openssl: fix AES_CBC crash
[siplcs.git] / src / core / sipe-crypt-openssl.c
blob90b99ede42a94cdd16f996514120e82659bac779
1 /**
2 * @file sipe-crypt-openssl.c
4 * pidgin-sipe
6 * Copyright (C) 2013-2015 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 /**
24 * Cipher routines implementation based on OpenSSL.
26 #include <openssl/evp.h>
27 #include <openssl/rsa.h>
29 #include "glib.h"
31 #include "sipe-common.h"
32 #include "sipe-backend.h"
33 #include "sipe-crypt.h"
35 /* OpenSSL specific initialization/shutdown */
36 void sipe_crypto_init(SIPE_UNUSED_PARAMETER gboolean production_mode)
38 /* nothing to do here */
41 void sipe_crypto_shutdown(void)
43 /* nothing to do here */
46 static void openssl_oneshot_crypt(const EVP_CIPHER *type,
47 const guchar *key, gsize key_length,
48 const guchar *plaintext, gsize plaintext_length,
49 guchar *encrypted_text)
51 EVP_CIPHER_CTX ctx;
52 int encrypted_length = 0;
54 /* initialize context */
55 EVP_CIPHER_CTX_init(&ctx);
56 EVP_EncryptInit_ex(&ctx, type, NULL, key, NULL);
58 /* set encryption parameters */
59 if (key_length)
60 EVP_CIPHER_CTX_set_key_length(&ctx, key_length);
61 EVP_EncryptInit_ex(&ctx, NULL, NULL, key, NULL);
63 /* encrypt */
64 EVP_EncryptUpdate(&ctx,
65 encrypted_text, &encrypted_length,
66 plaintext, plaintext_length);
67 encrypted_text += encrypted_length;
68 EVP_EncryptFinal_ex(&ctx, encrypted_text, &encrypted_length);
70 /* cleanup */
71 EVP_CIPHER_CTX_cleanup(&ctx);
74 /* DES CBC with 56-bit key */
75 void sipe_crypt_des(const guchar *key,
76 const guchar *plaintext, gsize plaintext_length,
77 guchar *encrypted_text)
79 openssl_oneshot_crypt(EVP_des_cbc(),
80 key, 0 /* fixed length */,
81 plaintext, plaintext_length,
82 encrypted_text);
85 /* RC4 with variable length key */
86 void sipe_crypt_rc4(const guchar *key, gsize key_length,
87 const guchar *plaintext, gsize plaintext_length,
88 guchar *encrypted_text)
90 openssl_oneshot_crypt(EVP_rc4(),
91 key, key_length,
92 plaintext, plaintext_length,
93 encrypted_text);
96 gboolean sipe_crypt_rsa_encrypt(gpointer public,
97 gsize modulus_length,
98 const guchar *plaintext,
99 guchar *encrypted_text)
101 return(RSA_public_encrypt(modulus_length,
102 plaintext,
103 encrypted_text,
104 public,
105 RSA_NO_PADDING)
106 != -1);
109 gboolean sipe_crypt_rsa_decrypt(gpointer private,
110 gsize modulus_length,
111 const guchar *encrypted_text,
112 guchar *plaintext)
114 return(RSA_private_decrypt(modulus_length,
115 encrypted_text,
116 plaintext,
117 private,
118 RSA_NO_PADDING)
119 != -1);
122 guchar *sipe_crypt_rsa_sign(gpointer private,
123 const guchar *digest, gsize digest_length,
124 gsize *signature_length)
126 guchar *signature = g_malloc(RSA_size(private));
127 unsigned int length;
129 if (!RSA_sign(NID_md5_sha1,
130 digest, digest_length,
131 signature, &length,
132 private)) {
133 g_free(signature);
134 return(NULL);
137 *signature_length = length;
138 return(signature);
141 gboolean sipe_crypt_verify_rsa(gpointer public,
142 const guchar *digest, gsize digest_length,
143 const guchar *signature, gsize signature_length)
145 return(RSA_verify(NID_md5_sha1,
146 digest, digest_length,
147 /* older OpenSSL version don't have "const" here */
148 (guchar *) signature, signature_length,
149 public));
152 static gpointer openssl_EVP_init(const EVP_CIPHER *type,
153 const guchar *key,
154 gsize key_length,
155 const guchar *iv)
157 EVP_CIPHER_CTX *ctx = g_malloc(sizeof(EVP_CIPHER_CTX));
159 /* initialize context */
160 EVP_CIPHER_CTX_init(ctx);
161 EVP_EncryptInit_ex(ctx, type, NULL, key, iv);
163 /* set encryption parameters */
164 EVP_CIPHER_CTX_set_key_length(ctx, key_length);
165 EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv);
167 return(ctx);
170 /* Stream RC4 cipher for file transfer with fixed-length 128-bit key */
171 gpointer sipe_crypt_ft_start(const guchar *key)
173 return(openssl_EVP_init(EVP_rc4(), key, 16, NULL));
176 void sipe_crypt_ft_stream(gpointer context,
177 const guchar *in, gsize length,
178 guchar *out)
180 int tmp;
181 EVP_EncryptUpdate(context, out, &tmp, in, length);
184 void sipe_crypt_ft_destroy(gpointer context)
186 EVP_CIPHER_CTX_cleanup(context);
187 g_free(context);
190 /* Stream RC4 cipher for TLS with variable key length */
191 gpointer sipe_crypt_tls_start(const guchar *key, gsize key_length)
193 return(openssl_EVP_init(EVP_rc4(), key, key_length, NULL));
196 void sipe_crypt_tls_stream(gpointer context,
197 const guchar *in, gsize length,
198 guchar *out)
200 int tmp;
201 EVP_EncryptUpdate(context, out, &tmp, in, length);
204 void sipe_crypt_tls_destroy(gpointer context)
206 EVP_CIPHER_CTX_cleanup(context);
207 g_free(context);
210 /* Block AES-CBC cipher for TLS */
211 void sipe_crypt_tls_block(const guchar *key, gsize key_length,
212 const guchar *iv,
213 /* OpenSSL assumes that iv is of correct size */
214 SIPE_UNUSED_PARAMETER gsize iv_length,
215 const guchar *in, gsize length,
216 guchar *out)
218 const EVP_CIPHER *type = NULL;
220 switch (key_length) {
221 case 128 / 8:
222 type = EVP_aes_128_cbc();
223 break;
225 * TLS does not use AES-192
227 case 192 / 8:
228 type = EVP_aes_192_cbc();
229 break;
231 case 256 / 8:
232 type = EVP_aes_256_cbc();
233 break;
234 default:
235 SIPE_DEBUG_ERROR("sipe_crypt_tls_block: unsupported key length %" G_GSIZE_FORMAT " bytes for AES CBC",
236 key_length);
237 break;
240 if (type) {
241 EVP_CIPHER_CTX *context = openssl_EVP_init(type,
242 key, key_length,
243 iv);
245 if (context) {
246 int tmp;
247 EVP_EncryptUpdate(context, out, &tmp, in, length);
248 EVP_CIPHER_CTX_cleanup(context);
249 g_free(context);
255 Local Variables:
256 mode: c
257 c-file-style: "bsd"
258 indent-tabs-mode: t
259 tab-width: 8
260 End: