1 /* wrapper.c */ 2 /* wrapping functions for crypto functions. */ 3 /* why a wrapper ? let's say you want to port libssh from libcrypto of openssl to libfoo */ 4 /* you are going to spend hours to remove every references to SHA1_Update() to libfoo_sha1_update */ 5 /* after the work is finished, you're going to have only this file to modify */ 6 /* it's not needed to say that your modifications are welcome */ 7 8 /* 9 Copyright 2003 Aris Adamantiadis 10 11 This file is part of the SSH Library 12 13 The SSH Library is free software; you can redistribute it and/or modify 14 it under the terms of the GNU Lesser General Public License as published by 15 the Free Software Foundation; either version 2.1 of the License, or (at your 16 option) any later version. 17 18 The SSH Library is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 20 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 21 License for more details. 22 23 You should have received a copy of the GNU Lesser General Public License 24 along with the SSH Library; see the file COPYING. If not, write to 25 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 26 MA 02111-1307, USA. */ 27 28 #include "libssh/priv.h" 29 #include "libssh/crypto.h" 30 #include <string.h> 31 #ifdef OPENSSL_CRYPTO 32 #include <openssl/sha.h> 33 #include <openssl/md5.h> 34 #include <openssl/dsa.h> 35 #include <openssl/rsa.h> 36 #include <openssl/hmac.h> 37 #include <openssl/opensslv.h> 38 #ifdef HAVE_OPENSSL_AES_H 39 #define HAS_AES 40 #include <openssl/aes.h> 41 #endif 42 #ifdef HAVE_OPENSSL_BLOWFISH_H 43 #define HAS_BLOWFISH 44 #include <openssl/blowfish.h> 45 #endif 46 #if (OPENSSL_VERSION_NUMBER<0x009070000) 47 #define OLD_CRYPTO 48 #endif 49 50 SHACTX *sha1_init(){ 51 SHACTX *c=malloc(sizeof(SHACTX)); 52 SHA1_Init(c); 53 return c; 54 } 55 void sha1_update(SHACTX *c, const void *data, unsigned long len){ 56 SHA1_Update(c,data,len); 57 } 58 void sha1_final(unsigned char *md,SHACTX *c){ 59 SHA1_Final(md,c); 60 free(c); 61 } 62 void sha1(unsigned char *digest,int len,unsigned char *hash){ 63 SHA1(digest,len,hash); 64 } 65 66 MD5CTX *md5_init(){ 67 MD5CTX *c=malloc(sizeof(MD5CTX)); 68 MD5_Init(c); 69 return c; 70 } 71 void md5_update(MD5CTX *c, const void *data, unsigned long len){ 72 MD5_Update(c,data,len); 73 } 74 void md5_final(unsigned char *md,MD5CTX *c){ 75 MD5_Final(md,c); 76 free(c); 77 } 78 79 HMACCTX *hmac_init(const void *key, int len,int type){ 80 HMAC_CTX *ctx; 81 ctx=malloc(sizeof(HMAC_CTX)); 82 #ifndef OLD_CRYPTO 83 HMAC_CTX_init(ctx); // openssl 0.9.7 requires it. 84 #endif 85 switch(type){ 86 case HMAC_SHA1: 87 HMAC_Init(ctx,key,len,EVP_sha1()); 88 break; 89 case HMAC_MD5: 90 HMAC_Init(ctx,key,len,EVP_md5()); 91 break; 92 default: 93 free(ctx); 94 ctx=NULL; 95 } 96 return ctx; 97 } 98 void hmac_update(HMACCTX *ctx,const void *data, unsigned long len){ 99 HMAC_Update(ctx,data,len); 100 } 101 void hmac_final(HMACCTX *ctx,unsigned char *hashmacbuf,int *len){ 102 HMAC_Final(ctx,hashmacbuf,len); 103 #ifndef OLD_CRYPTO 104 HMAC_CTX_cleanup(ctx); 105 #else 106 HMAC_cleanup(ctx); 107 #endif 108 free(ctx); 109 } 110 111 static void alloc_key(struct crypto_struct *cipher){ 112 cipher->key=malloc(cipher->keylen); 113 } 114 115 #ifdef HAS_BLOWFISH 116 /* the wrapper functions for blowfish */ 117 static void blowfish_set_key(struct crypto_struct *cipher, void *key){ 118 if(!cipher->key){ 119 alloc_key(cipher); 120 BF_set_key(cipher->key,16,key); 121 } 122 } 123 124 static void blowfish_encrypt(struct crypto_struct *cipher, void *in, void *out,unsigned long len,void *IV){ 125 BF_cbc_encrypt(in,out,len,cipher->key,IV,BF_ENCRYPT); 126 } 127 128 static void blowfish_decrypt(struct crypto_struct *cipher, void *in, void *out,unsigned long len,void *IV){ 129 BF_cbc_encrypt(in,out,len,cipher->key,IV,BF_DECRYPT); 130 } 131 #endif 132 #ifdef HAS_AES 133 static void aes_set_encrypt_key(struct crypto_struct *cipher, void *key){ 134 if(!cipher->key){ 135 alloc_key(cipher); 136 AES_set_encrypt_key(key,cipher->keysize,cipher->key); 137 } 138 } 139 static void aes_set_decrypt_key(struct crypto_struct *cipher, void *key){ 140 if(!cipher->key){ 141 alloc_key(cipher); 142 AES_set_decrypt_key(key,cipher->keysize,cipher->key); 143 } 144 } 145 static void aes_encrypt(struct crypto_struct *cipher, void *in, void *out, unsigned long len, void *IV){ 146 AES_cbc_encrypt(in,out,len,cipher->key,IV,AES_ENCRYPT); 147 } 148 static void aes_decrypt(struct crypto_struct *cipher, void *in, void *out, unsigned long len, void *IV){ 149 AES_cbc_encrypt(in,out,len,cipher->key,IV,AES_DECRYPT); 150 } 151 #endif 152 /* the table of supported ciphers */ 153 static struct crypto_struct ssh_ciphertab[]={ 154 #ifdef HAS_BLOWFISH 155 { "blowfish-cbc", 8 ,sizeof (BF_KEY),NULL,128,blowfish_set_key,blowfish_set_key,blowfish_encrypt, blowfish_decrypt}, 156 #endif 157 #ifdef HAS_AES 158 { "aes128-cbc",16,sizeof(AES_KEY),NULL,128,aes_set_encrypt_key,aes_set_decrypt_key,aes_encrypt,aes_decrypt}, 159 { "aes192-cbc",16,sizeof(AES_KEY),NULL,192,aes_set_encrypt_key,aes_set_decrypt_key,aes_encrypt,aes_decrypt}, 160 { "aes256-cbc",16,sizeof(AES_KEY),NULL,256,aes_set_encrypt_key,aes_set_decrypt_key,aes_encrypt,aes_decrypt}, 161 #endif 162 { NULL,0,0,NULL,0,NULL,NULL,NULL} 163 }; 164 #endif /* OPENSSL_CRYPTO */ 165 166 /* it allocates a new cipher structure based on its offset into the global table */ 167 struct crypto_struct *cipher_new(int offset){ 168 struct crypto_struct *cipher=malloc(sizeof(struct crypto_struct)); 169 /* note the memcpy will copy the pointers : so, you shouldn't free them */ 170 memcpy(cipher,&ssh_ciphertab[offset],sizeof(*cipher)); 171 return cipher; 172 } 173 174 void cipher_free(struct crypto_struct *cipher){ 175 if(cipher->key){ 176 // destroy the key 177 memset(cipher->key,0,cipher->keylen); 178 free(cipher->key); 179 } 180 free(cipher); 181 } 182 183 CRYPTO *crypto_new(){ 184 CRYPTO *crypto=malloc(sizeof (CRYPTO)); 185 memset(crypto,0,sizeof(*crypto)); 186 return crypto; 187 } 188 189 void crypto_free(CRYPTO *crypto){ 190 if(crypto->server_pubkey) 191 free(crypto->server_pubkey); 192 if(crypto->in_cipher) 193 cipher_free(crypto->in_cipher); 194 if(crypto->out_cipher) 195 cipher_free(crypto->out_cipher); 196 if(crypto->e) 197 bignum_free(crypto->e); 198 if(crypto->f) 199 bignum_free(crypto->f); 200 if(crypto->x) 201 bignum_free(crypto->x); 202 if(crypto->k) 203 bignum_free(crypto->k); 204 /* lot of other things */ 205 /* i'm lost in my own code. good work */ 206 memset(crypto,0,sizeof(*crypto)); 207 free(crypto); 208 } 209 210 int crypt_set_algorithms(SSH_SESSION *session){ 211 /* we must scan the kex entries to find crypto algorithms and set their appropriate structure */ 212 int i=0; 213 /* out */ 214 char *wanted=session->client_kex.methods[KEX_CRYPT_C_S]; 215 while(ssh_ciphertab[i].name && strcmp(wanted,ssh_ciphertab[i].name)) 216 i++; 217 if(!ssh_ciphertab[i].name){ 218 ssh_set_error((session->connected?session:NULL),SSH_FATAL,"Crypt_set_algorithms : no crypto algorithm function found for %s",wanted); 219 return -1; 220 } 221 ssh_say(2,"Set output algorithm %s\n",wanted); 222 session->next_crypto->out_cipher=cipher_new(i); 223 i=0; 224 /* in */ 225 wanted=session->client_kex.methods[KEX_CRYPT_S_C]; 226 while(ssh_ciphertab[i].name && strcmp(wanted,ssh_ciphertab[i].name)) 227 i++; 228 if(!ssh_ciphertab[i].name){ 229 ssh_set_error((session->connected?session:NULL),SSH_FATAL,"Crypt_set_algorithms : no crypto algorithm function found for %s",wanted); 230 return -1; 231 } 232 ssh_say(2,"Set input algorithm %s\n",wanted); 233 session->next_crypto->in_cipher=cipher_new(i); 234 235 /* compression */ 236 if(strstr(session->client_kex.methods[KEX_COMP_C_S],"zlib")) 237 session->next_crypto->do_compress_out=1; 238 if(strstr(session->client_kex.methods[KEX_COMP_S_C],"zlib")) 239 session->next_crypto->do_compress_in=1; 240 return 0; 241 } |