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
*type
,
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
);
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
,
181 EVP_EncryptUpdate(context
, out
, &tmp
, in
, length
);
184 void sipe_crypt_ft_destroy(gpointer context
)
186 EVP_CIPHER_CTX_cleanup(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
,
201 EVP_EncryptUpdate(context
, out
, &tmp
, in
, length
);
204 void sipe_crypt_tls_destroy(gpointer context
)
206 EVP_CIPHER_CTX_cleanup(context
);
210 /* Block AES-CBC cipher for TLS */
211 void sipe_crypt_tls_block(const guchar
*key
, gsize key_length
,
213 /* OpenSSL assumes that iv is of correct size */
214 SIPE_UNUSED_PARAMETER gsize iv_length
,
215 const guchar
*in
, gsize length
,
218 const EVP_CIPHER
*type
= NULL
;
220 switch (key_length
) {
222 type
= EVP_aes_128_cbc();
225 * TLS does not use AES-192
228 type = EVP_aes_192_cbc();
232 type
= EVP_aes_256_cbc();
235 SIPE_DEBUG_ERROR("sipe_crypt_tls_block: unsupported key length %" G_GSIZE_FORMAT
" bytes for AES CBC",
241 EVP_CIPHER_CTX
*context
= openssl_EVP_init(type
,
247 EVP_EncryptUpdate(context
, out
, &tmp
, in
, length
);
248 EVP_CIPHER_CTX_cleanup(context
);