From ed05255e183f5a1c5466b96140d7729960845f89 Mon Sep 17 00:00:00 2001 From: Stefan Becker Date: Mon, 24 Aug 2015 14:45:54 +0300 Subject: [PATCH] crypt: add TLS stream cipher type sipe-crypt implementations now support RC4 and AES CBC stream ciphers for TLS. --- src/core/sipe-crypt-nss.c | 26 +++++++++++++++++++---- src/core/sipe-crypt-openssl.c | 49 ++++++++++++++++++++++++++++++++++++------- src/core/sipe-crypt.h | 10 ++++++--- src/core/sipe-tls.c | 8 ++++++- 4 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/core/sipe-crypt-nss.c b/src/core/sipe-crypt-nss.c index aef50f04..e642265b 100755 --- a/src/core/sipe-crypt-nss.c +++ b/src/core/sipe-crypt-nss.c @@ -3,7 +3,7 @@ * * pidgin-sipe * - * Copyright (C) 2011 SIPE Project + * Copyright (C) 2011-2015 SIPE Project * Copyright (C) 2010 pier11 * * This program is free software; you can redistribute it and/or modify @@ -247,13 +247,31 @@ sipe_crypt_ft_destroy(gpointer context) } /* - * Stream RC4 cipher for TLS + * Stream cipher for TLS * * basically the same as for FT, but with variable key length */ -gpointer sipe_crypt_tls_start(const guchar *key, gsize key_length) +gpointer sipe_crypt_tls_start(guint type, const guchar *key, gsize key_length) { - return sipe_crypt_ctx_create(CKM_RC4, key, key_length); + CK_MECHANISM_TYPE mech; + + switch (type) { + case SIPE_CRYPT_STREAM_RC4: + mech = CKM_RC4; + break; + + case SIPE_CRYPT_STREAM_AES_CBC: + mech = CKM_AES_CBC; + break; + + default: + SIPE_DEBUG_ERROR("sipe_crypt_tls_start: unknown cipher type '%d'", + type); + return(NULL); + break; + } + + return sipe_crypt_ctx_create(mech, key, key_length); } void sipe_crypt_tls_stream(gpointer context, diff --git a/src/core/sipe-crypt-openssl.c b/src/core/sipe-crypt-openssl.c index 969fa87a..3c94be9d 100755 --- a/src/core/sipe-crypt-openssl.c +++ b/src/core/sipe-crypt-openssl.c @@ -3,7 +3,7 @@ * * pidgin-sipe * - * Copyright (C) 2013 SIPE Project + * Copyright (C) 2013-2015 SIPE Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -149,13 +149,15 @@ gboolean sipe_crypt_verify_rsa(gpointer public, public)); } -static gpointer openssl_rc4_init(const guchar *key, gsize key_length) +static gpointer openssl_EVP_init(const EVP_CIPHER *(*evp)(), + const guchar *key, + gsize key_length) { EVP_CIPHER_CTX *ctx = g_malloc(sizeof(EVP_CIPHER_CTX)); /* initialize context */ EVP_CIPHER_CTX_init(ctx); - EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, key, NULL); + EVP_EncryptInit_ex(ctx, (*evp)(), NULL, key, NULL); /* set encryption parameters */ EVP_CIPHER_CTX_set_key_length(ctx, key_length); @@ -167,7 +169,7 @@ static gpointer openssl_rc4_init(const guchar *key, gsize key_length) /* Stream RC4 cipher for file transfer with fixed-length 128-bit key */ gpointer sipe_crypt_ft_start(const guchar *key) { - return(openssl_rc4_init(key, 16)); + return(openssl_EVP_init(EVP_rc4, key, 16)); } void sipe_crypt_ft_stream(gpointer context, @@ -184,10 +186,41 @@ void sipe_crypt_ft_destroy(gpointer context) g_free(context); } -/* Stream RC4 cipher for TLS with variable key length */ -gpointer sipe_crypt_tls_start(const guchar *key, gsize key_length) -{ - return(openssl_rc4_init(key, key_length)); +/* Stream cipher for TLS with variable key length */ +gpointer sipe_crypt_tls_start(guint type, const guchar *key, gsize key_length) +{ + gpointer result = NULL; + + switch (type) { + case SIPE_CRYPT_STREAM_RC4: + result = openssl_EVP_init(EVP_rc4, key, key_length); + break; + + case SIPE_CRYPT_STREAM_AES_CBC: + switch (key_length) { + case 16: + result = openssl_EVP_init(EVP_aes_128_cbc, key, key_length); + break; + case 24: + result = openssl_EVP_init(EVP_aes_192_cbc, key, key_length); + break; + case 32: + result = openssl_EVP_init(EVP_aes_256_cbc, key, key_length); + break; + default: + SIPE_DEBUG_ERROR("sipe_crypt_tls_start: unsupported key length %" G_GSIZE_FORMAT " bytes for AES CBC", + key_length); + break; + } + break; + + default: + SIPE_DEBUG_ERROR("sipe_crypt_tls_start: unknown cipher type '%d'", + type); + break; + } + + return(result); } void sipe_crypt_tls_stream(gpointer context, diff --git a/src/core/sipe-crypt.h b/src/core/sipe-crypt.h index 596324d6..9af20976 100644 --- a/src/core/sipe-crypt.h +++ b/src/core/sipe-crypt.h @@ -3,7 +3,7 @@ * * pidgin-sipe * - * Copyright (C) 2010-11 SIPE Project + * Copyright (C) 2010-2015 SIPE Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,8 +59,12 @@ void sipe_crypt_ft_stream(gpointer context, guchar *out); void sipe_crypt_ft_destroy(gpointer context); -/* Stream RC4 cipher for TLS */ -gpointer sipe_crypt_tls_start(const guchar *key, gsize key_length); +/* Stream cipher for TLS */ +#define SIPE_CRYPT_STREAM_UNKNOWN 0 +#define SIPE_CRYPT_STREAM_RC4 1 +#define SIPE_CRYPT_STREAM_AES_CBC 2 + +gpointer sipe_crypt_tls_start(guint type, const guchar *key, gsize key_length); void sipe_crypt_tls_stream(gpointer context, const guchar *in, gsize length, guchar *out); diff --git a/src/core/sipe-tls.c b/src/core/sipe-tls.c index e7a51ef0..f8e48393 100644 --- a/src/core/sipe-tls.c +++ b/src/core/sipe-tls.c @@ -66,6 +66,7 @@ struct tls_internal_state { gsize msg_remainder; GHashTable *data; GString *debug; + guint cipher_type; gpointer md5_context; gpointer sha1_context; gpointer server_certificate; @@ -1202,6 +1203,7 @@ static gboolean check_cipher_suite(struct tls_internal_state *state) state->mac_func = sipe_digest_hmac_md5; label = "MD5"; state->common.algorithm = SIPE_TLS_DIGEST_ALGORITHM_MD5; + state->cipher_type = SIPE_CRYPT_STREAM_RC4; break; case TLS_RSA_WITH_RC4_128_MD5: @@ -1210,6 +1212,7 @@ static gboolean check_cipher_suite(struct tls_internal_state *state) state->mac_func = sipe_digest_hmac_md5; label = "MD5"; state->common.algorithm = SIPE_TLS_DIGEST_ALGORITHM_MD5; + state->cipher_type = SIPE_CRYPT_STREAM_RC4; break; case TLS_RSA_WITH_RC4_128_SHA: @@ -1218,6 +1221,7 @@ static gboolean check_cipher_suite(struct tls_internal_state *state) state->mac_func = sipe_digest_hmac_sha1; label = "SHA-1"; state->common.algorithm = SIPE_TLS_DIGEST_ALGORITHM_SHA1; + state->cipher_type = SIPE_CRYPT_STREAM_RC4; break; case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: @@ -1228,6 +1232,7 @@ static gboolean check_cipher_suite(struct tls_internal_state *state) state->mac_func = sipe_digest_hmac_sha1; label = "SHA-1"; state->common.algorithm = SIPE_TLS_DIGEST_ALGORITHM_SHA1; + state->cipher_type = SIPE_CRYPT_STREAM_AES_CBC; break; default: @@ -1317,7 +1322,8 @@ static void tls_calculate_secrets(struct tls_internal_state *state) state->server_write_secret = state->key_block + 2 * state->mac_length + state->key_length; /* initialize cipher context */ - state->cipher_context = sipe_crypt_tls_start(state->client_write_secret, + state->cipher_context = sipe_crypt_tls_start(state->cipher_type, + state->client_write_secret, state->key_length); } -- 2.11.4.GIT