From f7842e3a4b9acea2126ff725f993c299aef0e6db Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 6 Sep 2010 14:28:38 +0200 Subject: misc: Rename libssh/ to src/ --- src/libcrypto.c | 443 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 443 insertions(+) create mode 100644 src/libcrypto.c (limited to 'src/libcrypto.c') diff --git a/src/libcrypto.c b/src/libcrypto.c new file mode 100644 index 00000000..f43a91eb --- /dev/null +++ b/src/libcrypto.c @@ -0,0 +1,443 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2009 by Aris Adamantiadis + * + * The SSH Library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the SSH Library; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + + +#include +#include +#include + +#include "libssh/priv.h" +#include "libssh/session.h" +#include "libssh/crypto.h" +#include "libssh/wrapper.h" +#include "libssh/libcrypto.h" + +#ifdef HAVE_LIBCRYPTO + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_OPENSSL_AES_H +#define HAS_AES +#include +#endif +#ifdef HAVE_OPENSSL_BLOWFISH_H +#define HAS_BLOWFISH +#include +#endif +#ifdef HAVE_OPENSSL_DES_H +#define HAS_DES +#include +#endif + +#if (OPENSSL_VERSION_NUMBER<0x00907000L) +#define OLD_CRYPTO +#endif + +#include "libssh/crypto.h" + +static int alloc_key(struct crypto_struct *cipher) { + cipher->key = malloc(cipher->keylen); + if (cipher->key == NULL) { + return -1; + } + + return 0; +} + +SHACTX sha1_init(void) { + SHACTX c = malloc(sizeof(*c)); + if (c == NULL) { + return NULL; + } + SHA1_Init(c); + + return c; +} + +void sha1_update(SHACTX c, const void *data, unsigned long len) { + SHA1_Update(c,data,len); +} + +void sha1_final(unsigned char *md, SHACTX c) { + SHA1_Final(md, c); + SAFE_FREE(c); +} + +void sha1(unsigned char *digest, int len, unsigned char *hash) { + SHA1(digest, len, hash); +} + +MD5CTX md5_init(void) { + MD5CTX c = malloc(sizeof(*c)); + if (c == NULL) { + return NULL; + } + + MD5_Init(c); + + return c; +} + +void md5_update(MD5CTX c, const void *data, unsigned long len) { + MD5_Update(c, data, len); +} + +void md5_final(unsigned char *md, MD5CTX c) { + MD5_Final(md,c); + SAFE_FREE(c); +} + +HMACCTX hmac_init(const void *key, int len, int type) { + HMACCTX ctx = NULL; + + ctx = malloc(sizeof(*ctx)); + if (ctx == NULL) { + return NULL; + } + +#ifndef OLD_CRYPTO + HMAC_CTX_init(ctx); // openssl 0.9.7 requires it. +#endif + + switch(type) { + case HMAC_SHA1: + HMAC_Init(ctx, key, len, EVP_sha1()); + break; + case HMAC_MD5: + HMAC_Init(ctx, key, len, EVP_md5()); + break; + default: + SAFE_FREE(ctx); + ctx = NULL; + } + + return ctx; +} + +void hmac_update(HMACCTX ctx, const void *data, unsigned long len) { + HMAC_Update(ctx, data, len); +} + +void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len) { + HMAC_Final(ctx,hashmacbuf,len); + +#ifndef OLD_CRYPTO + HMAC_CTX_cleanup(ctx); +#else + HMAC_cleanup(ctx); +#endif + + SAFE_FREE(ctx); +} + +#ifdef HAS_BLOWFISH +/* the wrapper functions for blowfish */ +static int blowfish_set_key(struct crypto_struct *cipher, void *key){ + if (cipher->key == NULL) { + if (alloc_key(cipher) < 0) { + return -1; + } + BF_set_key(cipher->key, 16, key); + } + + return 0; +} + +static void blowfish_encrypt(struct crypto_struct *cipher, void *in, + void *out, unsigned long len, void *IV) { + BF_cbc_encrypt(in, out, len, cipher->key, IV, BF_ENCRYPT); +} + +static void blowfish_decrypt(struct crypto_struct *cipher, void *in, + void *out, unsigned long len, void *IV) { + BF_cbc_encrypt(in, out, len, cipher->key, IV, BF_DECRYPT); +} +#endif /* HAS_BLOWFISH */ + +#ifdef HAS_AES +static int aes_set_encrypt_key(struct crypto_struct *cipher, void *key) { + if (cipher->key == NULL) { + if (alloc_key(cipher) < 0) { + return -1; + } + if (AES_set_encrypt_key(key,cipher->keysize,cipher->key) < 0) { + SAFE_FREE(cipher->key); + return -1; + } + } + + return 0; +} +static int aes_set_decrypt_key(struct crypto_struct *cipher, void *key) { + if (cipher->key == NULL) { + if (alloc_key(cipher) < 0) { + return -1; + } + if (AES_set_decrypt_key(key,cipher->keysize,cipher->key) < 0) { + SAFE_FREE(cipher->key); + return -1; + } + } + + return 0; +} + +static void aes_encrypt(struct crypto_struct *cipher, void *in, void *out, + unsigned long len, void *IV) { + AES_cbc_encrypt(in, out, len, cipher->key, IV, AES_ENCRYPT); +} + +static void aes_decrypt(struct crypto_struct *cipher, void *in, void *out, + unsigned long len, void *IV) { + AES_cbc_encrypt(in, out, len, cipher->key, IV, AES_DECRYPT); +} + +#ifndef BROKEN_AES_CTR +/* OpenSSL until 0.9.7c has a broken AES_ctr128_encrypt implementation which + * increments the counter from 2^64 instead of 1. It's better not to use it + */ + +/** @internal + * @brief encrypts/decrypts data with stream cipher AES_ctr128. 128 bits is actually + * the size of the CTR counter and incidentally the blocksize, but not the keysize. + * @param len[in] must be a multiple of AES128 block size. + */ +static void aes_ctr128_encrypt(struct crypto_struct *cipher, void *in, void *out, + unsigned long len, void *IV) { + unsigned char tmp_buffer[128/8]; + unsigned int num=0; + /* Some things are special with ctr128 : + * In this case, tmp_buffer is not being used, because it is used to store temporary data + * when an encryption is made on lengths that are not multiple of blocksize. + * Same for num, which is being used to store the current offset in blocksize in CTR + * function. + */ + AES_ctr128_encrypt(in, out, len, cipher->key, IV, tmp_buffer, &num); +} +#endif /* BROKEN_AES_CTR */ +#endif /* HAS_AES */ + +#ifdef HAS_DES +static int des3_set_key(struct crypto_struct *cipher, void *key) { + if (cipher->key == NULL) { + if (alloc_key(cipher) < 0) { + return -1; + } + + DES_set_odd_parity(key); + DES_set_odd_parity((void*)((uint8_t*)key + 8)); + DES_set_odd_parity((void*)((uint8_t*)key + 16)); + DES_set_key_unchecked(key, cipher->key); + DES_set_key_unchecked((void*)((uint8_t*)key + 8), (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule))); + DES_set_key_unchecked((void*)((uint8_t*)key + 16), (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule))); + } + + return 0; +} + +static void des3_encrypt(struct crypto_struct *cipher, void *in, + void *out, unsigned long len, void *IV) { + DES_ede3_cbc_encrypt(in, out, len, cipher->key, + (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)), + (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)), + IV, 1); +} + +static void des3_decrypt(struct crypto_struct *cipher, void *in, + void *out, unsigned long len, void *IV) { + DES_ede3_cbc_encrypt(in, out, len, cipher->key, + (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)), + (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)), + IV, 0); +} + +static void des3_1_encrypt(struct crypto_struct *cipher, void *in, + void *out, unsigned long len, void *IV) { +#ifdef DEBUG_CRYPTO + ssh_print_hexa("Encrypt IV before", IV, 24); +#endif + DES_ncbc_encrypt(in, out, len, cipher->key, IV, 1); + DES_ncbc_encrypt(out, in, len, (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)), + (void*)((uint8_t*)IV + 8), 0); + DES_ncbc_encrypt(in, out, len, (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)), + (void*)((uint8_t*)IV + 16), 1); +#ifdef DEBUG_CRYPTO + ssh_print_hexa("Encrypt IV after", IV, 24); +#endif +} + +static void des3_1_decrypt(struct crypto_struct *cipher, void *in, + void *out, unsigned long len, void *IV) { +#ifdef DEBUG_CRYPTO + ssh_print_hexa("Decrypt IV before", IV, 24); +#endif + + DES_ncbc_encrypt(in, out, len, (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)), + IV, 0); + DES_ncbc_encrypt(out, in, len, (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)), + (void*)((uint8_t*)IV + 8), 1); + DES_ncbc_encrypt(in, out, len, cipher->key, (void*)((uint8_t*)IV + 16), 0); + +#ifdef DEBUG_CRYPTO + ssh_print_hexa("Decrypt IV after", IV, 24); +#endif +} + +#endif /* HAS_DES */ + +/* + * The table of supported ciphers + * + * WARNING: If you modify crypto_struct, you must make sure the order is + * correct! + */ +static struct crypto_struct ssh_ciphertab[] = { +#ifdef HAS_BLOWFISH + { + "blowfish-cbc", + 8, + sizeof (BF_KEY), + NULL, + 128, + blowfish_set_key, + blowfish_set_key, + blowfish_encrypt, + blowfish_decrypt + }, +#endif /* HAS_BLOWFISH */ +#ifdef HAS_AES +#ifndef BROKEN_AES_CTR + { + "aes128-ctr", + 16, + sizeof(AES_KEY), + NULL, + 128, + aes_set_encrypt_key, + aes_set_encrypt_key, + aes_ctr128_encrypt, + aes_ctr128_encrypt + }, + { + "aes192-ctr", + 16, + sizeof(AES_KEY), + NULL, + 192, + aes_set_encrypt_key, + aes_set_encrypt_key, + aes_ctr128_encrypt, + aes_ctr128_encrypt + }, + { + "aes256-ctr", + 16, + sizeof(AES_KEY), + NULL, + 256, + aes_set_encrypt_key, + aes_set_encrypt_key, + aes_ctr128_encrypt, + aes_ctr128_encrypt + }, +#endif /* BROKEN_AES_CTR */ + { + "aes128-cbc", + 16, + sizeof(AES_KEY), + NULL, + 128, + aes_set_encrypt_key, + aes_set_decrypt_key, + aes_encrypt, + aes_decrypt + }, + { + "aes192-cbc", + 16, + sizeof(AES_KEY), + NULL, + 192, + aes_set_encrypt_key, + aes_set_decrypt_key, + aes_encrypt, + aes_decrypt + }, + { + "aes256-cbc", + 16, + sizeof(AES_KEY), + NULL, + 256, + aes_set_encrypt_key, + aes_set_decrypt_key, + aes_encrypt, + aes_decrypt + }, +#endif /* HAS_AES */ +#ifdef HAS_DES + { + "3des-cbc", + 8, + sizeof(DES_key_schedule) * 3, + NULL, + 192, + des3_set_key, + des3_set_key, + des3_encrypt, + des3_decrypt + }, + { + "3des-cbc-ssh1", + 8, + sizeof(DES_key_schedule) * 3, + NULL, + 192, + des3_set_key, + des3_set_key, + des3_1_encrypt, + des3_1_decrypt + }, +#endif /* HAS_DES */ + { + NULL, + 0, + 0, + NULL, + 0, + NULL, + NULL, + NULL, + NULL + } +}; + + +struct crypto_struct *ssh_get_ciphertab(){ + return ssh_ciphertab; +} + +#endif /* LIBCRYPTO */ + -- cgit