2 * @file sipe-crypt-openssl.c
6 * Copyright (C) 2013-2017 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
)
51 EVP_CIPHER_CTX
*ctx
= EVP_CIPHER_CTX_new();
52 int encrypted_length
= 0;
54 /* initialize context */
55 EVP_EncryptInit_ex(ctx
, type
, NULL
, key
, NULL
);
57 /* set encryption parameters */
59 EVP_CIPHER_CTX_set_key_length(ctx
, key_length
);
60 EVP_EncryptInit_ex(ctx
, NULL
, NULL
, key
, NULL
);
63 EVP_EncryptUpdate(ctx
,
64 encrypted_text
, &encrypted_length
,
65 plaintext
, plaintext_length
);
66 encrypted_text
+= encrypted_length
;
67 EVP_EncryptFinal_ex(ctx
, encrypted_text
, &encrypted_length
);
70 EVP_CIPHER_CTX_free(ctx
);
73 /* DES CBC with 56-bit key */
74 void sipe_crypt_des(const guchar
*key
,
75 const guchar
*plaintext
, gsize plaintext_length
,
76 guchar
*encrypted_text
)
78 openssl_oneshot_crypt(EVP_des_cbc(),
79 key
, 0 /* fixed length */,
80 plaintext
, plaintext_length
,
84 /* RC4 with variable length key */
85 void sipe_crypt_rc4(const guchar
*key
, gsize key_length
,
86 const guchar
*plaintext
, gsize plaintext_length
,
87 guchar
*encrypted_text
)
89 openssl_oneshot_crypt(EVP_rc4(),
91 plaintext
, plaintext_length
,
95 gboolean
sipe_crypt_rsa_encrypt(gpointer
public,
97 const guchar
*plaintext
,
98 guchar
*encrypted_text
)
100 return(RSA_public_encrypt(modulus_length
,
108 gboolean
sipe_crypt_rsa_decrypt(gpointer
private,
109 gsize modulus_length
,
110 const guchar
*encrypted_text
,
113 return(RSA_private_decrypt(modulus_length
,
121 guchar
*sipe_crypt_rsa_sign(gpointer
private,
122 const guchar
*digest
, gsize digest_length
,
123 gsize
*signature_length
)
125 guchar
*signature
= g_malloc(RSA_size(private));
128 if (!RSA_sign(NID_md5_sha1
,
129 digest
, digest_length
,
136 *signature_length
= length
;
140 gboolean
sipe_crypt_verify_rsa(gpointer
public,
141 const guchar
*digest
, gsize digest_length
,
142 const guchar
*signature
, gsize signature_length
)
144 return(RSA_verify(NID_md5_sha1
,
145 digest
, digest_length
,
146 /* older OpenSSL version don't have "const" here */
147 (guchar
*) signature
, signature_length
,
151 static gpointer
openssl_EVP_init(const EVP_CIPHER
*type
,
156 EVP_CIPHER_CTX
*ctx
= EVP_CIPHER_CTX_new();
158 /* initialize context */
159 EVP_EncryptInit_ex(ctx
, type
, NULL
, key
, iv
);
161 /* set encryption parameters */
162 EVP_CIPHER_CTX_set_key_length(ctx
, key_length
);
163 EVP_EncryptInit_ex(ctx
, NULL
, NULL
, key
, iv
);
168 /* Stream RC4 cipher for file transfer with fixed-length 128-bit key */
169 gpointer
sipe_crypt_ft_start(const guchar
*key
)
171 return(openssl_EVP_init(EVP_rc4(), key
, 16, NULL
));
174 void sipe_crypt_ft_stream(gpointer context
,
175 const guchar
*in
, gsize length
,
179 EVP_EncryptUpdate(context
, out
, &tmp
, in
, length
);
182 void sipe_crypt_ft_destroy(gpointer context
)
184 EVP_CIPHER_CTX_free(context
);
187 /* Stream RC4 cipher for TLS with variable key length */
188 gpointer
sipe_crypt_tls_start(const guchar
*key
, gsize key_length
)
190 return(openssl_EVP_init(EVP_rc4(), key
, key_length
, NULL
));
193 void sipe_crypt_tls_stream(gpointer context
,
194 const guchar
*in
, gsize length
,
198 EVP_EncryptUpdate(context
, out
, &tmp
, in
, length
);
201 void sipe_crypt_tls_destroy(gpointer context
)
203 EVP_CIPHER_CTX_free(context
);
206 /* Block AES-CBC cipher for TLS */
207 void sipe_crypt_tls_block(const guchar
*key
, gsize key_length
,
209 /* OpenSSL assumes that iv is of correct size */
210 SIPE_UNUSED_PARAMETER gsize iv_length
,
211 const guchar
*in
, gsize length
,
214 const EVP_CIPHER
*type
= NULL
;
216 switch (key_length
) {
218 type
= EVP_aes_128_cbc();
221 * TLS does not use AES-192
224 type = EVP_aes_192_cbc();
228 type
= EVP_aes_256_cbc();
231 SIPE_DEBUG_ERROR("sipe_crypt_tls_block: unsupported key length %" G_GSIZE_FORMAT
" bytes for AES CBC",
237 EVP_CIPHER_CTX
*context
= openssl_EVP_init(type
,
243 EVP_EncryptUpdate(context
, out
, &tmp
, in
, length
);
244 EVP_CIPHER_CTX_free(context
);