2 * @file sipe-crypt-openssl.c
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
24 * Cipher routines implementation based on OpenSSL.
26 #include <openssl/evp.h>
27 #include <openssl/rsa.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
)
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 */
60 EVP_CIPHER_CTX_set_key_length(&ctx
, key_length
);
61 EVP_EncryptInit_ex(&ctx
, NULL
, NULL
, key
, NULL
);
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
);
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
,
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(),
92 plaintext
, plaintext_length
,
96 gboolean
sipe_crypt_rsa_encrypt(gpointer
public,
98 const guchar
*plaintext
,
99 guchar
*encrypted_text
)
101 return(RSA_public_encrypt(modulus_length
,
109 gboolean
sipe_crypt_rsa_decrypt(gpointer
private,
110 gsize modulus_length
,
111 const guchar
*encrypted_text
,
114 return(RSA_private_decrypt(modulus_length
,
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));
129 if (!RSA_sign(NID_md5_sha1
,
130 digest
, digest_length
,
137 *signature_length
= length
;
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
,
152 static gpointer
openssl_EVP_init(const EVP_CIPHER
*(*evp
)(),
156 EVP_CIPHER_CTX
*ctx
= g_malloc(sizeof(EVP_CIPHER_CTX
));
158 /* initialize context */
159 EVP_CIPHER_CTX_init(ctx
);
160 EVP_EncryptInit_ex(ctx
, (*evp
)(), NULL
, key
, NULL
);
162 /* set encryption parameters */
163 EVP_CIPHER_CTX_set_key_length(ctx
, key_length
);
164 EVP_EncryptInit_ex(ctx
, NULL
, NULL
, key
, NULL
);
169 /* Stream RC4 cipher for file transfer with fixed-length 128-bit key */
170 gpointer
sipe_crypt_ft_start(const guchar
*key
)
172 return(openssl_EVP_init(EVP_rc4
, key
, 16));
175 void sipe_crypt_ft_stream(gpointer context
,
176 const guchar
*in
, gsize length
,
180 EVP_EncryptUpdate(context
, out
, &tmp
, in
, length
);
183 void sipe_crypt_ft_destroy(gpointer context
)
185 EVP_CIPHER_CTX_cleanup(context
);
189 /* Stream cipher for TLS with variable key length */
190 gpointer
sipe_crypt_tls_start(guint type
, const guchar
*key
, gsize key_length
)
192 gpointer result
= NULL
;
195 case SIPE_CRYPT_STREAM_RC4
:
196 result
= openssl_EVP_init(EVP_rc4
, key
, key_length
);
199 case SIPE_CRYPT_STREAM_AES_CBC
:
200 switch (key_length
) {
202 result
= openssl_EVP_init(EVP_aes_128_cbc
, key
, key_length
);
205 result
= openssl_EVP_init(EVP_aes_192_cbc
, key
, key_length
);
208 result
= openssl_EVP_init(EVP_aes_256_cbc
, key
, key_length
);
211 SIPE_DEBUG_ERROR("sipe_crypt_tls_start: unsupported key length %" G_GSIZE_FORMAT
" bytes for AES CBC",
218 SIPE_DEBUG_ERROR("sipe_crypt_tls_start: unknown cipher type '%d'",
226 void sipe_crypt_tls_stream(gpointer context
,
227 const guchar
*in
, gsize length
,
231 EVP_EncryptUpdate(context
, out
, &tmp
, in
, length
);
234 void sipe_crypt_tls_destroy(gpointer context
)
236 EVP_CIPHER_CTX_cleanup(context
);