- Crypto library
- SSL library
- PKCS#11 support
For missing features, please see README.polarssl
Signed-off-by: Adriaan de Jong <dejong@fox-it.com>
Acked-by: James Yonan <james@openvpn.net>
Acked-by: Gert Doering <gert@greenie.muc.de>
Signed-off-by: David Sommerseth <davids@redhat.com>
... | ... |
@@ -160,6 +160,13 @@ openvpn_SOURCES += \ |
160 | 160 |
ssl_openssl.c ssl_openssl.h \ |
161 | 161 |
ssl_verify_openssl.c ssl_verify_openssl.h |
162 | 162 |
endif |
163 |
+if USE_POLARSSL |
|
164 |
+openvpn_SOURCES += \ |
|
165 |
+ crypto_polarssl.c crypto_polarssl.h \ |
|
166 |
+ pkcs11_polarssl.c \ |
|
167 |
+ ssl_polarssl.c ssl_polarssl.h \ |
|
168 |
+ ssl_verify_polarssl.c ssl_verify_polarssl.h |
|
169 |
+endif |
|
163 | 170 |
|
164 | 171 |
dist-hook: |
165 | 172 |
cd $(distdir) && for i in $(EXTRA_DIST) $(SUBDIRS) ; do find $$i -name .svn -type d -prune -exec rm -rf '{}' ';' ; rm -f `find $$i -type f | grep -E '(^|\/)\.?\#|\~$$|\.s?o$$'` ; done |
166 | 173 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,23 @@ |
0 |
+This version of OpenVPN has PolarSSL support. To enable follow the following |
|
1 |
+instructions: |
|
2 |
+ |
|
3 |
+To Build and Install, |
|
4 |
+ |
|
5 |
+ ./configure --with-ssl-type=polarssl |
|
6 |
+ make |
|
7 |
+ make install |
|
8 |
+ |
|
9 |
+************************************************************************* |
|
10 |
+ |
|
11 |
+The following features are missing in the PolarSSL version of OpenVPN: |
|
12 |
+ |
|
13 |
+ * ca_path support - Loading certificate authorities from a directory |
|
14 |
+ * PKCS#12 file support |
|
15 |
+ * Windows CryptoAPI support |
|
16 |
+ * Management external key support |
|
17 |
+ * X509 alternative username fields (must be "CN") |
|
18 |
+ |
|
19 |
+ TODO: |
|
20 |
+ * serial is in Hex |
|
21 |
+ * X509 certificate export |
|
22 |
+ * X.509 tracking |
... | ... |
@@ -291,14 +291,16 @@ AC_ARG_WITH(mem-check, |
291 | 291 |
) |
292 | 292 |
|
293 | 293 |
AC_ARG_WITH([ssl-type], |
294 |
- [ --with-ssl-type=TYPE Build with the given SSL library, TYPE = openssl ], |
|
294 |
+ [ --with-ssl-type=TYPE Build with the given SSL library, TYPE = openssl or polarssl ], |
|
295 | 295 |
[case "${withval}" in |
296 | 296 |
openssl) SSL_LIB=openssl ;; |
297 |
+ polarssl) SSL_LIB=polarssl ;; |
|
297 | 298 |
*) AC_MSG_ERROR([bad value ${withval} for --with-ssl-type]) ;; |
298 | 299 |
esac], |
299 | 300 |
[SSL_LIB="openssl"] |
300 | 301 |
) |
301 | 302 |
AM_CONDITIONAL([USE_OPENSSL], [test x$SSL_LIB = xopenssl]) |
303 |
+AM_CONDITIONAL([USE_POLARSSL], [test x$SSL_LIB = xpolarssl]) |
|
302 | 304 |
|
303 | 305 |
dnl fix search path, to allow compilers to find syshead.h |
304 | 306 |
CPPFLAGS="$CPPFLAGS -I${srcdir}" |
... | ... |
@@ -710,6 +712,24 @@ if test "$LZO_STUB" = "yes"; then |
710 | 710 |
fi |
711 | 711 |
|
712 | 712 |
dnl |
713 |
+dnl enable pkcs11 capability |
|
714 |
+dnl |
|
715 |
+ |
|
716 |
+if test "$PKCS11" = "yes"; then |
|
717 |
+ AC_CHECKING([for pkcs11-helper Library and Header files]) |
|
718 |
+ AC_CHECK_HEADER(pkcs11-helper-1.0/pkcs11h-core.h, |
|
719 |
+ [AC_CHECK_LIB(pkcs11-helper, pkcs11h_initialize, |
|
720 |
+ [ |
|
721 |
+ AC_DEFINE(USE_PKCS11, 1, [Enable PKCS11 capability]) |
|
722 |
+ OPENVPN_ADD_LIBS(-lpkcs11-helper) |
|
723 |
+ ], |
|
724 |
+ [AC_MSG_RESULT([pkcs11-helper library not found.])] |
|
725 |
+ )], |
|
726 |
+ [AC_MSG_RESULT([pkcs11-helper headers not found.])] |
|
727 |
+ ) |
|
728 |
+fi |
|
729 |
+ |
|
730 |
+dnl |
|
713 | 731 |
dnl check for SSL-crypto library |
714 | 732 |
dnl |
715 | 733 |
|
... | ... |
@@ -752,7 +772,20 @@ if test "$CRYPTO" = "yes"; then |
752 | 752 |
[AC_MSG_ERROR([OpenSSL crypto Library is too old.])] |
753 | 753 |
) |
754 | 754 |
fi |
755 |
- |
|
755 |
+ if test "$SSL_LIB" = "polarssl"; then |
|
756 |
+ AC_CHECKING([for PolarSSL Crypto Library and Header files]) |
|
757 |
+ AC_CHECK_HEADER(polarssl/aes.h, |
|
758 |
+ [AC_CHECK_LIB(polarssl, aes_crypt_cbc, |
|
759 |
+ [ |
|
760 |
+ OPENVPN_ADD_LIBS(-lpolarssl) |
|
761 |
+ AC_DEFINE(USE_CRYPTO, 1, [Use crypto library]) |
|
762 |
+ AC_DEFINE(USE_POLARSSL, 1, [Use PolarSSL library]) |
|
763 |
+ ], |
|
764 |
+ [AC_MSG_ERROR([PolarSSL Crypto library not found.])] |
|
765 |
+ )], |
|
766 |
+ [AC_MSG_ERROR([PolarSSL Crypto headers not found.])] |
|
767 |
+ ) |
|
768 |
+ fi |
|
756 | 769 |
dnl |
757 | 770 |
dnl check for OpenSSL-SSL library |
758 | 771 |
dnl |
... | ... |
@@ -788,6 +821,20 @@ if test "$CRYPTO" = "yes"; then |
788 | 788 |
|
789 | 789 |
AC_DEFINE(USE_SSL, 1, [Use OpenSSL SSL library]) |
790 | 790 |
fi |
791 |
+ if test "$SSL_LIB" = "polarssl"; then |
|
792 |
+ AC_CHECKING([for PolarSSL SSL Library and Header files]) |
|
793 |
+ AC_CHECK_HEADER(polarssl/ssl.h, |
|
794 |
+ [AC_CHECK_LIB(polarssl, ssl_init, |
|
795 |
+ [ |
|
796 |
+ OPENVPN_ADD_LIBS(-lpolarssl) |
|
797 |
+ AC_DEFINE(USE_SSL, 1, [Use SSL library]) |
|
798 |
+ AC_DEFINE(USE_POLARSSL, 1, [Use PolarSSL library]) |
|
799 |
+ ], |
|
800 |
+ [AC_MSG_ERROR([PolarSSL SSL library not found.])] |
|
801 |
+ )], |
|
802 |
+ [AC_MSG_ERROR([PolarSSL SSL headers not found.])] |
|
803 |
+ ) |
|
804 |
+ fi |
|
791 | 805 |
fi |
792 | 806 |
fi |
793 | 807 |
|
... | ... |
@@ -796,22 +843,6 @@ if test "$X509ALTUSERNAME" = "yes"; then |
796 | 796 |
AC_DEFINE(ENABLE_X509ALTUSERNAME, 1, [Enable --x509-username-field feature]) |
797 | 797 |
fi |
798 | 798 |
|
799 |
-dnl enable pkcs11 capability |
|
800 |
- |
|
801 |
-if test "$PKCS11" = "yes"; then |
|
802 |
- AC_CHECKING([for pkcs11-helper Library and Header files]) |
|
803 |
- AC_CHECK_HEADER(pkcs11-helper-1.0/pkcs11h-core.h, |
|
804 |
- [AC_CHECK_LIB(pkcs11-helper, pkcs11h_initialize, |
|
805 |
- [ |
|
806 |
- AC_DEFINE(USE_PKCS11, 1, [Enable PKCS11 capability]) |
|
807 |
- OPENVPN_ADD_LIBS(-lpkcs11-helper) |
|
808 |
- ], |
|
809 |
- [AC_MSG_RESULT([pkcs11-helper library not found.])] |
|
810 |
- )], |
|
811 |
- [AC_MSG_RESULT([pkcs11-helper headers not found.])] |
|
812 |
- ) |
|
813 |
-fi |
|
814 |
- |
|
815 | 799 |
dnl enable multi-client mode |
816 | 800 |
if test "$MULTI" = "yes"; then |
817 | 801 |
AC_DEFINE(ENABLE_CLIENT_SERVER, 1, [Enable client/server capability]) |
42 | 44 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,577 @@ |
0 |
+/* |
|
1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
3 |
+ * session authentication and key exchange, |
|
4 |
+ * packet encryption, packet authentication, and |
|
5 |
+ * packet compression. |
|
6 |
+ * |
|
7 |
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> |
|
8 |
+ * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com> |
|
9 |
+ * |
|
10 |
+ * This program is free software; you can redistribute it and/or modify |
|
11 |
+ * it under the terms of the GNU General Public License version 2 |
|
12 |
+ * as published by the Free Software Foundation. |
|
13 |
+ * |
|
14 |
+ * This program is distributed in the hope that it will be useful, |
|
15 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
+ * GNU General Public License for more details. |
|
18 |
+ * |
|
19 |
+ * You should have received a copy of the GNU General Public License |
|
20 |
+ * along with this program (see the file COPYING included with this |
|
21 |
+ * distribution); if not, write to the Free Software Foundation, Inc., |
|
22 |
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
23 |
+ */ |
|
24 |
+ |
|
25 |
+/** |
|
26 |
+ * @file Data Channel Cryptography PolarSSL-specific backend interface |
|
27 |
+ */ |
|
28 |
+ |
|
29 |
+#include "syshead.h" |
|
30 |
+ |
|
31 |
+#include "errlevel.h" |
|
32 |
+#include "basic.h" |
|
33 |
+#include "buffer.h" |
|
34 |
+#include "integer.h" |
|
35 |
+#include "crypto_backend.h" |
|
36 |
+ |
|
37 |
+#include <polarssl/des.h> |
|
38 |
+#include <polarssl/md5.h> |
|
39 |
+#include <polarssl/cipher.h> |
|
40 |
+#include <polarssl/havege.h> |
|
41 |
+ |
|
42 |
+/* |
|
43 |
+ * |
|
44 |
+ * Hardware engine support. Allows loading/unloading of engines. |
|
45 |
+ * |
|
46 |
+ */ |
|
47 |
+ |
|
48 |
+void |
|
49 |
+crypto_init_lib_engine (const char *engine_name) |
|
50 |
+{ |
|
51 |
+ msg (M_WARN, "Note: PolarSSL hardware crypto engine functionality is not " |
|
52 |
+ "available"); |
|
53 |
+} |
|
54 |
+ |
|
55 |
+/* |
|
56 |
+ * |
|
57 |
+ * Functions related to the core crypto library |
|
58 |
+ * |
|
59 |
+ */ |
|
60 |
+ |
|
61 |
+void |
|
62 |
+crypto_init_lib (void) |
|
63 |
+{ |
|
64 |
+} |
|
65 |
+ |
|
66 |
+void |
|
67 |
+crypto_uninit_lib (void) |
|
68 |
+{ |
|
69 |
+ prng_uninit(); |
|
70 |
+} |
|
71 |
+ |
|
72 |
+void |
|
73 |
+crypto_clear_error (void) |
|
74 |
+{ |
|
75 |
+} |
|
76 |
+ |
|
77 |
+#ifdef DMALLOC |
|
78 |
+void |
|
79 |
+crypto_init_dmalloc (void) |
|
80 |
+{ |
|
81 |
+ msg (M_ERR, "Error: dmalloc support is not available for PolarSSL."); |
|
82 |
+} |
|
83 |
+#endif /* DMALLOC */ |
|
84 |
+ |
|
85 |
+void |
|
86 |
+show_available_ciphers () |
|
87 |
+{ |
|
88 |
+ const int *ciphers = cipher_list(); |
|
89 |
+ |
|
90 |
+#ifndef ENABLE_SMALL |
|
91 |
+ printf ("The following ciphers and cipher modes are available\n" |
|
92 |
+ "for use with " PACKAGE_NAME ". Each cipher shown below may be\n" |
|
93 |
+ "used as a parameter to the --cipher option. The default\n" |
|
94 |
+ "key size is shown as well as whether or not it can be\n" |
|
95 |
+ "changed with the --keysize directive. Using a CBC mode\n" |
|
96 |
+ "is recommended.\n\n"); |
|
97 |
+#endif |
|
98 |
+ |
|
99 |
+ while (*ciphers != 0) |
|
100 |
+ { |
|
101 |
+ const cipher_info_t *info = cipher_info_from_type(*ciphers); |
|
102 |
+ |
|
103 |
+ if (info && info->mode == POLARSSL_MODE_CBC) |
|
104 |
+ printf ("%s %d bit default key\n", |
|
105 |
+ info->name, info->key_length); |
|
106 |
+ |
|
107 |
+ ciphers++; |
|
108 |
+ } |
|
109 |
+ printf ("\n"); |
|
110 |
+} |
|
111 |
+ |
|
112 |
+void |
|
113 |
+show_available_digests () |
|
114 |
+{ |
|
115 |
+ const int *digests = md_list(); |
|
116 |
+ |
|
117 |
+#ifndef ENABLE_SMALL |
|
118 |
+ printf ("The following message digests are available for use with\n" |
|
119 |
+ PACKAGE_NAME ". A message digest is used in conjunction with\n" |
|
120 |
+ "the HMAC function, to authenticate received packets.\n" |
|
121 |
+ "You can specify a message digest as parameter to\n" |
|
122 |
+ "the --auth option.\n\n"); |
|
123 |
+#endif |
|
124 |
+ |
|
125 |
+ while (*digests != 0) |
|
126 |
+ { |
|
127 |
+ const md_info_t *info = md_info_from_type(*digests); |
|
128 |
+ |
|
129 |
+ if (info) |
|
130 |
+ printf ("%s %d bit default key\n", |
|
131 |
+ info->name, info->size * 8); |
|
132 |
+ digests++; |
|
133 |
+ } |
|
134 |
+ printf ("\n"); |
|
135 |
+} |
|
136 |
+ |
|
137 |
+void |
|
138 |
+show_available_engines () |
|
139 |
+{ |
|
140 |
+ printf ("Sorry, PolarSSL hardware crypto engine functionality is not " |
|
141 |
+ "available\n"); |
|
142 |
+} |
|
143 |
+ |
|
144 |
+ |
|
145 |
+/* |
|
146 |
+ * |
|
147 |
+ * Random number functions, used in cases where we want |
|
148 |
+ * reasonably strong cryptographic random number generation |
|
149 |
+ * without depleting our entropy pool. Used for random |
|
150 |
+ * IV values and a number of other miscellaneous tasks. |
|
151 |
+ * |
|
152 |
+ */ |
|
153 |
+ |
|
154 |
+int |
|
155 |
+rand_bytes (uint8_t *output, int len) |
|
156 |
+{ |
|
157 |
+ static havege_state hs = {0}; |
|
158 |
+ static bool hs_initialised = false; |
|
159 |
+ const int int_size = sizeof(int); |
|
160 |
+ |
|
161 |
+ if (!hs_initialised) |
|
162 |
+ { |
|
163 |
+ /* Initialise PolarSSL RNG */ |
|
164 |
+ havege_init(&hs); |
|
165 |
+ hs_initialised = true; |
|
166 |
+ } |
|
167 |
+ |
|
168 |
+ while (len > 0) |
|
169 |
+ { |
|
170 |
+ const int blen = min_int (len, int_size); |
|
171 |
+ const int rand_int = havege_rand(&hs); |
|
172 |
+ |
|
173 |
+ memcpy (output, &rand_int, blen); |
|
174 |
+ output += blen; |
|
175 |
+ len -= blen; |
|
176 |
+ } |
|
177 |
+ return 1; |
|
178 |
+} |
|
179 |
+ |
|
180 |
+/* |
|
181 |
+ * |
|
182 |
+ * Key functions, allow manipulation of keys. |
|
183 |
+ * |
|
184 |
+ */ |
|
185 |
+ |
|
186 |
+ |
|
187 |
+int |
|
188 |
+key_des_num_cblocks (const cipher_info_t *kt) |
|
189 |
+{ |
|
190 |
+ int ret = 0; |
|
191 |
+ if (kt->type == POLARSSL_CIPHER_DES_CBC) |
|
192 |
+ ret = 1; |
|
193 |
+ if (kt->type == POLARSSL_CIPHER_DES_EDE_CBC) |
|
194 |
+ ret = 2; |
|
195 |
+ if (kt->type == POLARSSL_CIPHER_DES_EDE3_CBC) |
|
196 |
+ ret = 3; |
|
197 |
+ |
|
198 |
+ dmsg (D_CRYPTO_DEBUG, "CRYPTO INFO: n_DES_cblocks=%d", ret); |
|
199 |
+ return ret; |
|
200 |
+} |
|
201 |
+ |
|
202 |
+bool |
|
203 |
+key_des_check (uint8_t *key, int key_len, int ndc) |
|
204 |
+{ |
|
205 |
+ int i; |
|
206 |
+ struct buffer b; |
|
207 |
+ |
|
208 |
+ buf_set_read (&b, key, key_len); |
|
209 |
+ |
|
210 |
+ for (i = 0; i < ndc; ++i) |
|
211 |
+ { |
|
212 |
+ unsigned char *key = buf_read_alloc(&b, DES_KEY_SIZE); |
|
213 |
+ if (!key) |
|
214 |
+ { |
|
215 |
+ msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: insufficient key material"); |
|
216 |
+ goto err; |
|
217 |
+ } |
|
218 |
+ if (0 != des_key_check_weak(key)) |
|
219 |
+ { |
|
220 |
+ msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: weak key detected"); |
|
221 |
+ goto err; |
|
222 |
+ } |
|
223 |
+ if (0 != des_key_check_key_parity(key)) |
|
224 |
+ { |
|
225 |
+ msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: bad parity detected"); |
|
226 |
+ goto err; |
|
227 |
+ } |
|
228 |
+ } |
|
229 |
+ return true; |
|
230 |
+ |
|
231 |
+ err: |
|
232 |
+ return false; |
|
233 |
+} |
|
234 |
+ |
|
235 |
+void |
|
236 |
+key_des_fixup (uint8_t *key, int key_len, int ndc) |
|
237 |
+{ |
|
238 |
+ int i; |
|
239 |
+ struct buffer b; |
|
240 |
+ |
|
241 |
+ buf_set_read (&b, key, key_len); |
|
242 |
+ for (i = 0; i < ndc; ++i) |
|
243 |
+ { |
|
244 |
+ unsigned char *key = buf_read_alloc(&b, DES_KEY_SIZE); |
|
245 |
+ if (!key) |
|
246 |
+ { |
|
247 |
+ msg (D_CRYPT_ERRORS, "CRYPTO INFO: fixup_key_DES: insufficient key material"); |
|
248 |
+ return; |
|
249 |
+ } |
|
250 |
+ des_key_set_parity(key); |
|
251 |
+ } |
|
252 |
+} |
|
253 |
+ |
|
254 |
+/* |
|
255 |
+ * |
|
256 |
+ * Generic cipher key type functions |
|
257 |
+ * |
|
258 |
+ */ |
|
259 |
+ |
|
260 |
+ |
|
261 |
+const cipher_info_t * |
|
262 |
+cipher_kt_get (const char *ciphername) |
|
263 |
+{ |
|
264 |
+ const cipher_info_t *cipher = NULL; |
|
265 |
+ |
|
266 |
+ ASSERT (ciphername); |
|
267 |
+ |
|
268 |
+ cipher = cipher_info_from_string(ciphername); |
|
269 |
+ |
|
270 |
+ if (NULL == cipher) |
|
271 |
+ msg (M_FATAL, "Cipher algorithm '%s' not found", ciphername); |
|
272 |
+ |
|
273 |
+ if (cipher->key_length/8 > MAX_CIPHER_KEY_LENGTH) |
|
274 |
+ msg (M_FATAL, "Cipher algorithm '%s' uses a default key size (%d bytes) which is larger than " PACKAGE_NAME "'s current maximum key size (%d bytes)", |
|
275 |
+ ciphername, |
|
276 |
+ cipher->key_length/8, |
|
277 |
+ MAX_CIPHER_KEY_LENGTH); |
|
278 |
+ |
|
279 |
+ return cipher; |
|
280 |
+} |
|
281 |
+ |
|
282 |
+const char * |
|
283 |
+cipher_kt_name (const cipher_info_t *cipher_kt) |
|
284 |
+{ |
|
285 |
+ if (NULL == cipher_kt) |
|
286 |
+ return "[null-cipher]"; |
|
287 |
+ return cipher_kt->name; |
|
288 |
+} |
|
289 |
+ |
|
290 |
+int |
|
291 |
+cipher_kt_key_size (const cipher_info_t *cipher_kt) |
|
292 |
+{ |
|
293 |
+ if (NULL == cipher_kt) |
|
294 |
+ return 0; |
|
295 |
+ return cipher_kt->key_length/8; |
|
296 |
+} |
|
297 |
+ |
|
298 |
+int |
|
299 |
+cipher_kt_iv_size (const cipher_info_t *cipher_kt) |
|
300 |
+{ |
|
301 |
+ if (NULL == cipher_kt) |
|
302 |
+ return 0; |
|
303 |
+ return cipher_kt->iv_size; |
|
304 |
+} |
|
305 |
+ |
|
306 |
+int |
|
307 |
+cipher_kt_block_size (const cipher_info_t *cipher_kt) |
|
308 |
+{ |
|
309 |
+ if (NULL == cipher_kt) |
|
310 |
+ return 0; |
|
311 |
+ return cipher_kt->block_size; |
|
312 |
+} |
|
313 |
+ |
|
314 |
+bool |
|
315 |
+cipher_kt_mode (const cipher_info_t *cipher_kt) |
|
316 |
+{ |
|
317 |
+ ASSERT(NULL != cipher_kt); |
|
318 |
+ return cipher_kt->mode; |
|
319 |
+} |
|
320 |
+ |
|
321 |
+ |
|
322 |
+/* |
|
323 |
+ * |
|
324 |
+ * Generic cipher context functions |
|
325 |
+ * |
|
326 |
+ */ |
|
327 |
+ |
|
328 |
+ |
|
329 |
+void |
|
330 |
+cipher_ctx_init (cipher_context_t *ctx, uint8_t *key, int key_len, |
|
331 |
+ const cipher_info_t *kt, int enc, const char *prefix) |
|
332 |
+{ |
|
333 |
+ struct gc_arena gc = gc_new (); |
|
334 |
+ |
|
335 |
+ ASSERT(NULL != kt && NULL != ctx); |
|
336 |
+ |
|
337 |
+ CLEAR (*ctx); |
|
338 |
+ |
|
339 |
+ if (0 != cipher_init_ctx(ctx, kt)) |
|
340 |
+ msg (M_FATAL, "PolarSSL cipher context init #1"); |
|
341 |
+ |
|
342 |
+ if (0 != cipher_setkey(ctx, key, key_len*8, enc)) |
|
343 |
+ msg (M_FATAL, "PolarSSL cipher set key"); |
|
344 |
+ |
|
345 |
+ msg (D_HANDSHAKE, "%s: Cipher '%s' initialized with %d bit key", |
|
346 |
+ prefix, |
|
347 |
+ cipher_kt_name(kt), |
|
348 |
+ cipher_get_key_size(ctx)); |
|
349 |
+ |
|
350 |
+ /* make sure we used a big enough key */ |
|
351 |
+ ASSERT (ctx->key_length <= key_len*8); |
|
352 |
+ |
|
353 |
+ dmsg (D_SHOW_KEYS, "%s: CIPHER KEY: %s", prefix, |
|
354 |
+ format_hex (key, key_len, 0, &gc)); |
|
355 |
+ dmsg (D_CRYPTO_DEBUG, "%s: CIPHER block_size=%d iv_size=%d", |
|
356 |
+ prefix, |
|
357 |
+ cipher_get_block_size(ctx), |
|
358 |
+ cipher_get_iv_size(ctx)); |
|
359 |
+ |
|
360 |
+ gc_free (&gc); |
|
361 |
+} |
|
362 |
+ |
|
363 |
+void cipher_ctx_cleanup (cipher_context_t *ctx) |
|
364 |
+{ |
|
365 |
+ cipher_free_ctx(ctx); |
|
366 |
+} |
|
367 |
+ |
|
368 |
+int cipher_ctx_iv_length (const cipher_context_t *ctx) |
|
369 |
+{ |
|
370 |
+ return cipher_get_iv_size(ctx); |
|
371 |
+} |
|
372 |
+ |
|
373 |
+int cipher_ctx_block_size(const cipher_context_t *ctx) |
|
374 |
+{ |
|
375 |
+ return cipher_get_block_size(ctx); |
|
376 |
+} |
|
377 |
+ |
|
378 |
+int cipher_ctx_mode (const cipher_context_t *ctx) |
|
379 |
+{ |
|
380 |
+ ASSERT(NULL != ctx); |
|
381 |
+ |
|
382 |
+ return cipher_kt_mode(ctx->cipher_info); |
|
383 |
+} |
|
384 |
+ |
|
385 |
+int cipher_ctx_reset (cipher_context_t *ctx, uint8_t *iv_buf) |
|
386 |
+{ |
|
387 |
+ return 0 == cipher_reset(ctx, iv_buf); |
|
388 |
+} |
|
389 |
+ |
|
390 |
+int cipher_ctx_update (cipher_context_t *ctx, uint8_t *dst, int *dst_len, |
|
391 |
+ uint8_t *src, int src_len) |
|
392 |
+{ |
|
393 |
+ return 0 == cipher_update(ctx, src, src_len, dst, dst_len); |
|
394 |
+} |
|
395 |
+ |
|
396 |
+int cipher_ctx_final (cipher_context_t *ctx, uint8_t *dst, int *dst_len) |
|
397 |
+{ |
|
398 |
+ return 0 == cipher_finish(ctx, dst, dst_len); |
|
399 |
+} |
|
400 |
+ |
|
401 |
+void |
|
402 |
+cipher_des_encrypt_ecb (const unsigned char key[DES_KEY_SIZE], |
|
403 |
+ unsigned char *src, |
|
404 |
+ unsigned char *dst) |
|
405 |
+{ |
|
406 |
+ des_context ctx; |
|
407 |
+ |
|
408 |
+ des_setkey_enc(&ctx, key); |
|
409 |
+ des_crypt_ecb(&ctx, src, dst); |
|
410 |
+} |
|
411 |
+ |
|
412 |
+ |
|
413 |
+ |
|
414 |
+/* |
|
415 |
+ * |
|
416 |
+ * Generic message digest information functions |
|
417 |
+ * |
|
418 |
+ */ |
|
419 |
+ |
|
420 |
+ |
|
421 |
+const md_info_t * |
|
422 |
+md_kt_get (const char *digest) |
|
423 |
+{ |
|
424 |
+ const md_info_t *md = NULL; |
|
425 |
+ ASSERT (digest); |
|
426 |
+ |
|
427 |
+ md = md_info_from_string(digest); |
|
428 |
+ if (!md) |
|
429 |
+ msg (M_FATAL, "Message hash algorithm '%s' not found", digest); |
|
430 |
+ if (md->size > MAX_HMAC_KEY_LENGTH) |
|
431 |
+ msg (M_FATAL, "Message hash algorithm '%s' uses a default hash size (%d bytes) which is larger than " PACKAGE_NAME "'s current maximum hash size (%d bytes)", |
|
432 |
+ digest, |
|
433 |
+ md->size, |
|
434 |
+ MAX_HMAC_KEY_LENGTH); |
|
435 |
+ return md; |
|
436 |
+} |
|
437 |
+ |
|
438 |
+const char * |
|
439 |
+md_kt_name (const md_info_t *kt) |
|
440 |
+{ |
|
441 |
+ if (NULL == kt) |
|
442 |
+ return "[null-digest]"; |
|
443 |
+ return md_get_name (kt); |
|
444 |
+} |
|
445 |
+ |
|
446 |
+int |
|
447 |
+md_kt_size (const md_info_t *kt) |
|
448 |
+{ |
|
449 |
+ if (NULL == kt) |
|
450 |
+ return 0; |
|
451 |
+ return md_get_size(kt); |
|
452 |
+} |
|
453 |
+ |
|
454 |
+/* |
|
455 |
+ * |
|
456 |
+ * Generic message digest functions |
|
457 |
+ * |
|
458 |
+ */ |
|
459 |
+ |
|
460 |
+int |
|
461 |
+md_full (const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst) |
|
462 |
+{ |
|
463 |
+ return 0 == md(kt, src, src_len, dst); |
|
464 |
+} |
|
465 |
+ |
|
466 |
+ |
|
467 |
+void |
|
468 |
+md_ctx_init (md_context_t *ctx, const md_info_t *kt) |
|
469 |
+{ |
|
470 |
+ ASSERT(NULL != ctx && NULL != kt); |
|
471 |
+ |
|
472 |
+ CLEAR(*ctx); |
|
473 |
+ |
|
474 |
+ ASSERT(0 == md_starts(kt, ctx)); |
|
475 |
+} |
|
476 |
+ |
|
477 |
+void |
|
478 |
+md_ctx_cleanup(md_context_t *ctx) |
|
479 |
+{ |
|
480 |
+ ASSERT(0 == md_free_ctx(ctx)); |
|
481 |
+} |
|
482 |
+ |
|
483 |
+int |
|
484 |
+md_ctx_size (const md_context_t *ctx) |
|
485 |
+{ |
|
486 |
+ if (NULL == ctx) |
|
487 |
+ return 0; |
|
488 |
+ return md_get_size(ctx->md_info); |
|
489 |
+} |
|
490 |
+ |
|
491 |
+void |
|
492 |
+md_ctx_update (md_context_t *ctx, const uint8_t *src, int src_len) |
|
493 |
+{ |
|
494 |
+ ASSERT(0 == md_update(ctx, src, src_len)); |
|
495 |
+} |
|
496 |
+ |
|
497 |
+void |
|
498 |
+md_ctx_final (md_context_t *ctx, uint8_t *dst) |
|
499 |
+{ |
|
500 |
+ ASSERT(0 == md_finish(ctx, dst)); |
|
501 |
+} |
|
502 |
+ |
|
503 |
+ |
|
504 |
+/* |
|
505 |
+ * |
|
506 |
+ * Generic HMAC functions |
|
507 |
+ * |
|
508 |
+ */ |
|
509 |
+ |
|
510 |
+ |
|
511 |
+/* |
|
512 |
+ * TODO: re-enable dmsg for crypto debug |
|
513 |
+ */ |
|
514 |
+void |
|
515 |
+hmac_ctx_init (md_context_t *ctx, const uint8_t *key, int key_len, const md_info_t *kt, |
|
516 |
+ const char *prefix) |
|
517 |
+{ |
|
518 |
+ struct gc_arena gc = gc_new (); |
|
519 |
+ |
|
520 |
+ ASSERT(NULL != kt && NULL != ctx); |
|
521 |
+ |
|
522 |
+ CLEAR(*ctx); |
|
523 |
+ |
|
524 |
+ ASSERT(0 == md_hmac_starts(kt, ctx, key, key_len)); |
|
525 |
+ |
|
526 |
+ if (prefix) |
|
527 |
+ msg (D_HANDSHAKE, |
|
528 |
+ "%s: Using %d bit message hash '%s' for HMAC authentication", |
|
529 |
+ prefix, md_get_size(kt) * 8, md_get_name(kt)); |
|
530 |
+ |
|
531 |
+ /* make sure we used a big enough key */ |
|
532 |
+ ASSERT (md_get_size(kt) <= key_len); |
|
533 |
+ |
|
534 |
+ if (prefix) |
|
535 |
+ dmsg (D_SHOW_KEYS, "%s: HMAC KEY: %s", prefix, |
|
536 |
+ format_hex (key, key_len, 0, &gc)); |
|
537 |
+// if (prefix) |
|
538 |
+// dmsg (D_CRYPTO_DEBUG, "%s: HMAC size=%d block_size=%d", |
|
539 |
+// prefix, |
|
540 |
+// md_get_size(md_info), |
|
541 |
+// EVP_MD_block_size (md_info)); |
|
542 |
+ |
|
543 |
+ gc_free (&gc); |
|
544 |
+} |
|
545 |
+ |
|
546 |
+void |
|
547 |
+hmac_ctx_cleanup(md_context_t *ctx) |
|
548 |
+{ |
|
549 |
+ ASSERT(0 == md_free_ctx(ctx)); |
|
550 |
+} |
|
551 |
+ |
|
552 |
+int |
|
553 |
+hmac_ctx_size (const md_context_t *ctx) |
|
554 |
+{ |
|
555 |
+ if (NULL == ctx) |
|
556 |
+ return 0; |
|
557 |
+ return md_get_size(ctx->md_info); |
|
558 |
+} |
|
559 |
+ |
|
560 |
+void |
|
561 |
+hmac_ctx_reset (md_context_t *ctx) |
|
562 |
+{ |
|
563 |
+ ASSERT(0 == md_hmac_reset(ctx)); |
|
564 |
+} |
|
565 |
+ |
|
566 |
+void |
|
567 |
+hmac_ctx_update (md_context_t *ctx, const uint8_t *src, int src_len) |
|
568 |
+{ |
|
569 |
+ ASSERT(0 == md_hmac_update(ctx, src, src_len)); |
|
570 |
+} |
|
571 |
+ |
|
572 |
+void |
|
573 |
+hmac_ctx_final (md_context_t *ctx, uint8_t *dst) |
|
574 |
+{ |
|
575 |
+ ASSERT(0 == md_hmac_finish(ctx, dst)); |
|
576 |
+} |
0 | 577 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,71 @@ |
0 |
+/* |
|
1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
3 |
+ * session authentication and key exchange, |
|
4 |
+ * packet encryption, packet authentication, and |
|
5 |
+ * packet compression. |
|
6 |
+ * |
|
7 |
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> |
|
8 |
+ * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com> |
|
9 |
+ * |
|
10 |
+ * This program is free software; you can redistribute it and/or modify |
|
11 |
+ * it under the terms of the GNU General Public License version 2 |
|
12 |
+ * as published by the Free Software Foundation. |
|
13 |
+ * |
|
14 |
+ * This program is distributed in the hope that it will be useful, |
|
15 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
+ * GNU General Public License for more details. |
|
18 |
+ * |
|
19 |
+ * You should have received a copy of the GNU General Public License |
|
20 |
+ * along with this program (see the file COPYING included with this |
|
21 |
+ * distribution); if not, write to the Free Software Foundation, Inc., |
|
22 |
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
23 |
+ */ |
|
24 |
+ |
|
25 |
+/** |
|
26 |
+ * @file Data Channel Cryptography PolarSSL-specific backend interface |
|
27 |
+ */ |
|
28 |
+ |
|
29 |
+#ifndef CRYPTO_POLARSSL_H_ |
|
30 |
+#define CRYPTO_POLARSSL_H_ |
|
31 |
+ |
|
32 |
+#include <polarssl/cipher.h> |
|
33 |
+#include <polarssl/md.h> |
|
34 |
+ |
|
35 |
+/** Generic cipher key type %context. */ |
|
36 |
+typedef cipher_info_t cipher_kt_t; |
|
37 |
+ |
|
38 |
+/** Generic message digest key type %context. */ |
|
39 |
+typedef md_info_t md_kt_t; |
|
40 |
+ |
|
41 |
+/** Generic cipher %context. */ |
|
42 |
+typedef cipher_context_t cipher_ctx_t; |
|
43 |
+ |
|
44 |
+/** Generic message digest %context. */ |
|
45 |
+typedef md_context_t md_ctx_t; |
|
46 |
+ |
|
47 |
+/** Generic HMAC %context. */ |
|
48 |
+typedef md_context_t hmac_ctx_t; |
|
49 |
+ |
|
50 |
+/** Maximum length of an IV */ |
|
51 |
+#define OPENVPN_MAX_IV_LENGTH POLARSSL_MAX_IV_LENGTH |
|
52 |
+ |
|
53 |
+/** Cipher is in CBC mode */ |
|
54 |
+#define OPENVPN_MODE_CBC POLARSSL_MODE_CBC |
|
55 |
+ |
|
56 |
+/** Cipher is in OFB mode */ |
|
57 |
+#define OPENVPN_MODE_OFB POLARSSL_MODE_OFB |
|
58 |
+ |
|
59 |
+/** Cipher is in CFB mode */ |
|
60 |
+#define OPENVPN_MODE_CFB POLARSSL_MODE_CFB |
|
61 |
+ |
|
62 |
+/** Cipher should encrypt */ |
|
63 |
+#define OPENVPN_OP_ENCRYPT POLARSSL_ENCRYPT |
|
64 |
+ |
|
65 |
+/** Cipher should decrypt */ |
|
66 |
+#define OPENVPN_OP_DECRYPT POLARSSL_DECRYPT |
|
67 |
+ |
|
68 |
+#define MD5_DIGEST_LENGTH 16 |
|
69 |
+ |
|
70 |
+#endif /* CRYPTO_POLARSSL_H_ */ |
... | ... |
@@ -79,9 +79,11 @@ |
79 | 79 |
* |
80 | 80 |
* @subsection key_generation_random Source of random material |
81 | 81 |
* |
82 |
- * OpenVPN uses the OpenSSL library as its source of random material. More |
|
83 |
- * specifically, the \c RAND_bytes() function is called to supply |
|
84 |
- * cryptographically strong pseudo-random data. The following links |
|
82 |
+ * OpenVPN uses the either the OpenSSL library or the PolarSSL library as its |
|
83 |
+ * source of random material. |
|
84 |
+ * |
|
85 |
+ * In OpenSSL, the \c RAND_bytes() function is called |
|
86 |
+ * to supply cryptographically strong pseudo-random data. The following links |
|
85 | 87 |
* contain more information on this subject: |
86 | 88 |
* - For OpenSSL's \c RAND_bytes() function: |
87 | 89 |
* http://www.openssl.org/docs/crypto/RAND_bytes.html |
... | ... |
@@ -90,6 +92,9 @@ |
90 | 90 |
* - For OpenSSL's support for external crypto modules: |
91 | 91 |
* http://www.openssl.org/docs/crypto/engine.html |
92 | 92 |
* |
93 |
+ * In PolarSSL, the Havege random number generator is used. For details, see |
|
94 |
+ * the PolarSSL documentation. |
|
95 |
+ * |
|
93 | 96 |
* @section key_generation_exchange Key exchange: |
94 | 97 |
* |
95 | 98 |
* The %key exchange process is initiated by the OpenVPN process running |
... | ... |
@@ -508,7 +508,9 @@ static const char usage_message[] = |
508 | 508 |
"--keysize n : Size of cipher key in bits (optional).\n" |
509 | 509 |
" If unspecified, defaults to cipher-specific default.\n" |
510 | 510 |
#endif |
511 |
+#ifndef USE_POLARSSL |
|
511 | 512 |
"--engine [name] : Enable OpenSSL hardware crypto engine functionality.\n" |
513 |
+#endif |
|
512 | 514 |
"--no-replay : Disable replay protection.\n" |
513 | 515 |
"--mute-replay-warnings : Silence the output of replay warnings to log file.\n" |
514 | 516 |
"--replay-window n [t] : Use a replay protection sliding window of size n\n" |
... | ... |
@@ -529,13 +531,15 @@ static const char usage_message[] = |
529 | 529 |
" number, such as 1 (default), 2, etc.\n" |
530 | 530 |
"--ca file : Certificate authority file in .pem format containing\n" |
531 | 531 |
" root certificate.\n" |
532 |
+#ifndef USE_POLARSSL |
|
532 | 533 |
"--capath dir : A directory of trusted certificates (CAs" |
533 | 534 |
#if OPENSSL_VERSION_NUMBER >= 0x00907000L |
534 | 535 |
" and CRLs).\n" |
535 |
-#else |
|
536 |
+#else /* OPENSSL_VERSION_NUMBER >= 0x00907000L */ |
|
536 | 537 |
").\n" |
537 | 538 |
" WARNING: no support of CRL available with this version.\n" |
538 |
-#endif |
|
539 |
+#endif /* OPENSSL_VERSION_NUMBER >= 0x00907000L */ |
|
540 |
+#endif /* USE_POLARSSL */ |
|
539 | 541 |
"--dh file : File containing Diffie Hellman parameters\n" |
540 | 542 |
" in .pem format (for --tls-server only).\n" |
541 | 543 |
" Use \"openssl dhparam -out dh1024.pem 1024\" to generate.\n" |
... | ... |
@@ -590,7 +594,7 @@ static const char usage_message[] = |
590 | 590 |
" nsCertType designation t = 'client' | 'server'.\n" |
591 | 591 |
"--x509-track x : Save peer X509 attribute x in environment for use by\n" |
592 | 592 |
" plugins and management interface.\n" |
593 |
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L |
|
593 |
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L || USE_POLARSSL |
|
594 | 594 |
"--remote-cert-ku v ... : Require that the peer certificate was signed with\n" |
595 | 595 |
" explicit key usage, you can specify more than one value.\n" |
596 | 596 |
" value should be given in hex format.\n" |
... | ... |
@@ -600,7 +604,7 @@ static const char usage_message[] = |
600 | 600 |
"--remote-cert-tls t: Require that peer certificate was signed with explicit\n" |
601 | 601 |
" key usage and extended key usage based on RFC3280 TLS rules.\n" |
602 | 602 |
" t = 'client' | 'server'.\n" |
603 |
-#endif /* OPENSSL_VERSION_NUMBER */ |
|
603 |
+#endif /* OPENSSL_VERSION_NUMBER || USE_POLARSSL */ |
|
604 | 604 |
#endif /* USE_SSL */ |
605 | 605 |
#ifdef ENABLE_PKCS11 |
606 | 606 |
"\n" |
... | ... |
@@ -1537,7 +1541,9 @@ show_settings (const struct options *o) |
1537 | 1537 |
SHOW_STR (prng_hash); |
1538 | 1538 |
SHOW_INT (prng_nonce_secret_len); |
1539 | 1539 |
SHOW_INT (keysize); |
1540 |
+#ifndef USE_POLARSSL |
|
1540 | 1541 |
SHOW_BOOL (engine); |
1542 |
+#endif /* USE_POLARSSL */ |
|
1541 | 1543 |
SHOW_BOOL (replay); |
1542 | 1544 |
SHOW_BOOL (mute_replay_warnings); |
1543 | 1545 |
SHOW_INT (replay_window); |
... | ... |
@@ -2268,8 +2274,13 @@ options_postprocess_verify_ce (const struct options *options, const struct conne |
2268 | 2268 |
} |
2269 | 2269 |
else |
2270 | 2270 |
{ |
2271 |
+#ifdef USE_POLARSSL |
|
2272 |
+ if (!(options->ca_file)) |
|
2273 |
+ msg(M_USAGE, "You must define CA file (--ca)"); |
|
2274 |
+#else |
|
2271 | 2275 |
if ((!(options->ca_file)) && (!(options->ca_path))) |
2272 | 2276 |
msg(M_USAGE, "You must define CA file (--ca) or CA path (--capath)"); |
2277 |
+#endif |
|
2273 | 2278 |
if (pull) |
2274 | 2279 |
{ |
2275 | 2280 |
const int sum = (options->cert_file != NULL) + (options->priv_key_file != NULL); |
... | ... |
@@ -6114,6 +6125,7 @@ add_option (struct options *options, |
6114 | 6114 |
VERIFY_PERMISSION (OPT_P_GENERAL); |
6115 | 6115 |
options->test_crypto = true; |
6116 | 6116 |
} |
6117 |
+#ifndef USE_POLARSSL |
|
6117 | 6118 |
else if (streq (p[0], "engine")) |
6118 | 6119 |
{ |
6119 | 6120 |
VERIFY_PERMISSION (OPT_P_GENERAL); |
... | ... |
@@ -6124,6 +6136,7 @@ add_option (struct options *options, |
6124 | 6124 |
else |
6125 | 6125 |
options->engine = "auto"; |
6126 | 6126 |
} |
6127 |
+#endif /* USE_POLARSSL */ |
|
6127 | 6128 |
#ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH |
6128 | 6129 |
else if (streq (p[0], "keysize") && p[1]) |
6129 | 6130 |
{ |
... | ... |
@@ -6166,11 +6179,13 @@ add_option (struct options *options, |
6166 | 6166 |
} |
6167 | 6167 |
#endif |
6168 | 6168 |
} |
6169 |
+#ifndef USE_POLARSSL |
|
6169 | 6170 |
else if (streq (p[0], "capath") && p[1]) |
6170 | 6171 |
{ |
6171 | 6172 |
VERIFY_PERMISSION (OPT_P_GENERAL); |
6172 | 6173 |
options->ca_path = p[1]; |
6173 | 6174 |
} |
6175 |
+#endif /* USE_POLARSSL */ |
|
6174 | 6176 |
else if (streq (p[0], "dh") && p[1]) |
6175 | 6177 |
{ |
6176 | 6178 |
VERIFY_PERMISSION (OPT_P_GENERAL); |
... | ... |
@@ -6322,7 +6337,7 @@ add_option (struct options *options, |
6322 | 6322 |
goto err; |
6323 | 6323 |
} |
6324 | 6324 |
} |
6325 |
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L |
|
6325 |
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L || USE_POLARSSL |
|
6326 | 6326 |
else if (streq (p[0], "remote-cert-ku")) |
6327 | 6327 |
{ |
6328 | 6328 |
int j; |
6329 | 6329 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,121 @@ |
0 |
+/* |
|
1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
3 |
+ * session authentication and key exchange, |
|
4 |
+ * packet encryption, packet authentication, and |
|
5 |
+ * packet compression. |
|
6 |
+ * |
|
7 |
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> |
|
8 |
+ * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com> |
|
9 |
+ * |
|
10 |
+ * This program is free software; you can redistribute it and/or modify |
|
11 |
+ * it under the terms of the GNU General Public License version 2 |
|
12 |
+ * as published by the Free Software Foundation. |
|
13 |
+ * |
|
14 |
+ * This program is distributed in the hope that it will be useful, |
|
15 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
+ * GNU General Public License for more details. |
|
18 |
+ * |
|
19 |
+ * You should have received a copy of the GNU General Public License |
|
20 |
+ * along with this program (see the file COPYING included with this |
|
21 |
+ * distribution); if not, write to the Free Software Foundation, Inc., |
|
22 |
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
23 |
+ */ |
|
24 |
+ |
|
25 |
+/** |
|
26 |
+ * @file PKCS #11 PolarSSL backend |
|
27 |
+ */ |
|
28 |
+ |
|
29 |
+#include "syshead.h" |
|
30 |
+ |
|
31 |
+#if defined(ENABLE_PKCS11) |
|
32 |
+ |
|
33 |
+#include "errlevel.h" |
|
34 |
+#include "pkcs11_backend.h" |
|
35 |
+#include <polarssl/pkcs11.h> |
|
36 |
+ |
|
37 |
+int |
|
38 |
+pkcs11_init_tls_session(pkcs11h_certificate_t certificate, |
|
39 |
+ struct tls_root_ctx * const ssl_ctx) |
|
40 |
+{ |
|
41 |
+ int ret = 1; |
|
42 |
+ pkcs11_context pkcs11_ctx; |
|
43 |
+ |
|
44 |
+ ASSERT (NULL != ssl_ctx); |
|
45 |
+ |
|
46 |
+ if (pkcs11_x509_cert_init(ssl_ctx->crt_chain, certificate)) { |
|
47 |
+ msg (M_FATAL, "PKCS#11: Cannot retrieve PolarSSL certificate object"); |
|
48 |
+ goto cleanup; |
|
49 |
+ } |
|
50 |
+ |
|
51 |
+ ssl_ctx->priv_key_pkcs11 = malloc(sizeof(pkcs11_context)); |
|
52 |
+ |
|
53 |
+ if (ssl_ctx->priv_key_pkcs11 == NULL) { |
|
54 |
+ msg (M_FATAL, "PKCS#11: Cannot allocate PolarSSL private key object"); |
|
55 |
+ goto cleanup; |
|
56 |
+ } |
|
57 |
+ |
|
58 |
+ if (pkcs11_priv_key_init(ssl_ctx->priv_key_pkcs11, certificate)) { |
|
59 |
+ msg (M_FATAL, "PKCS#11: Cannot initialize PolarSSL private key object"); |
|
60 |
+ goto cleanup; |
|
61 |
+ } |
|
62 |
+ |
|
63 |
+ ret = 0; |
|
64 |
+ |
|
65 |
+cleanup: |
|
66 |
+ return ret; |
|
67 |
+} |
|
68 |
+ |
|
69 |
+int |
|
70 |
+pkcs11_certificate_dn (pkcs11h_certificate_t cert, char *dn, |
|
71 |
+ size_t dn_len) |
|
72 |
+{ |
|
73 |
+ int ret = 1; |
|
74 |
+ |
|
75 |
+ x509_cert polar_cert = {0}; |
|
76 |
+ |
|
77 |
+ if (pkcs11_x509_cert_init(&polar_cert, cert)) { |
|
78 |
+ msg (M_FATAL, "PKCS#11: Cannot retrieve PolarSSL certificate object"); |
|
79 |
+ goto cleanup; |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ if (-1 == x509parse_dn_gets (dn, dn_len, &polar_cert.subject)) { |
|
83 |
+ msg (M_FATAL, "PKCS#11: PolarSSL cannot parse subject"); |
|
84 |
+ goto cleanup; |
|
85 |
+ } |
|
86 |
+ |
|
87 |
+ ret = 0; |
|
88 |
+ |
|
89 |
+cleanup: |
|
90 |
+ x509_free(&polar_cert); |
|
91 |
+ |
|
92 |
+ return ret; |
|
93 |
+} |
|
94 |
+ |
|
95 |
+int |
|
96 |
+pkcs11_certificate_serial (pkcs11h_certificate_t cert, char *serial, |
|
97 |
+ size_t serial_len) |
|
98 |
+{ |
|
99 |
+ int ret = 1; |
|
100 |
+ |
|
101 |
+ x509_cert polar_cert = {0}; |
|
102 |
+ |
|
103 |
+ if (pkcs11_x509_cert_init(&polar_cert, cert)) { |
|
104 |
+ msg (M_FATAL, "PKCS#11: Cannot retrieve PolarSSL certificate object"); |
|
105 |
+ goto cleanup; |
|
106 |
+ } |
|
107 |
+ |
|
108 |
+ if (-1 == x509parse_serial_gets (serial, serial_len, &polar_cert.serial)) { |
|
109 |
+ msg (M_FATAL, "PKCS#11: PolarSSL cannot parse serial"); |
|
110 |
+ goto cleanup; |
|
111 |
+ } |
|
112 |
+ |
|
113 |
+ ret = 0; |
|
114 |
+ |
|
115 |
+cleanup: |
|
116 |
+ x509_free(&polar_cert); |
|
117 |
+ |
|
118 |
+ return ret; |
|
119 |
+} |
|
120 |
+#endif /* defined(ENABLE_PKCS11) */ |
42 | 46 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,848 @@ |
0 |
+/* |
|
1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
3 |
+ * session authentication and key exchange, |
|
4 |
+ * packet encryption, packet authentication, and |
|
5 |
+ * packet compression. |
|
6 |
+ * |
|
7 |
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> |
|
8 |
+ * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com> |
|
9 |
+ * |
|
10 |
+ * This program is free software; you can redistribute it and/or modify |
|
11 |
+ * it under the terms of the GNU General Public License version 2 |
|
12 |
+ * as published by the Free Software Foundation. |
|
13 |
+ * |
|
14 |
+ * This program is distributed in the hope that it will be useful, |
|
15 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
+ * GNU General Public License for more details. |
|
18 |
+ * |
|
19 |
+ * You should have received a copy of the GNU General Public License |
|
20 |
+ * along with this program (see the file COPYING included with this |
|
21 |
+ * distribution); if not, write to the Free Software Foundation, Inc., |
|
22 |
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
23 |
+ */ |
|
24 |
+ |
|
25 |
+/** |
|
26 |
+ * @file Control Channel PolarSSL Backend |
|
27 |
+ */ |
|
28 |
+ |
|
29 |
+#include "syshead.h" |
|
30 |
+#include "errlevel.h" |
|
31 |
+#include "ssl_backend.h" |
|
32 |
+#include "buffer.h" |
|
33 |
+#include "misc.h" |
|
34 |
+#include "manage.h" |
|
35 |
+#include "ssl_common.h" |
|
36 |
+ |
|
37 |
+#include "ssl_verify_polarssl.h" |
|
38 |
+ |
|
39 |
+void |
|
40 |
+tls_init_lib() |
|
41 |
+{ |
|
42 |
+} |
|
43 |
+ |
|
44 |
+void |
|
45 |
+tls_free_lib() |
|
46 |
+{ |
|
47 |
+} |
|
48 |
+ |
|
49 |
+void |
|
50 |
+tls_clear_error() |
|
51 |
+{ |
|
52 |
+} |
|
53 |
+ |
|
54 |
+static int default_ciphers[] = |
|
55 |
+{ |
|
56 |
+ SSL_EDH_RSA_AES_256_SHA, |
|
57 |
+ SSL_EDH_RSA_CAMELLIA_256_SHA, |
|
58 |
+ SSL_EDH_RSA_AES_128_SHA, |
|
59 |
+ SSL_EDH_RSA_CAMELLIA_128_SHA, |
|
60 |
+ SSL_EDH_RSA_DES_168_SHA, |
|
61 |
+ SSL_RSA_AES_256_SHA, |
|
62 |
+ SSL_RSA_CAMELLIA_256_SHA, |
|
63 |
+ SSL_RSA_AES_128_SHA, |
|
64 |
+ SSL_RSA_CAMELLIA_128_SHA, |
|
65 |
+ SSL_RSA_DES_168_SHA, |
|
66 |
+ SSL_RSA_RC4_128_SHA, |
|
67 |
+ SSL_RSA_RC4_128_MD5, |
|
68 |
+ 0 |
|
69 |
+}; |
|
70 |
+ |
|
71 |
+void |
|
72 |
+tls_ctx_server_new(struct tls_root_ctx *ctx) |
|
73 |
+{ |
|
74 |
+ ASSERT(NULL != ctx); |
|
75 |
+ CLEAR(*ctx); |
|
76 |
+ |
|
77 |
+ ALLOC_OBJ_CLEAR(ctx->hs, havege_state); |
|
78 |
+ havege_init(ctx->hs); |
|
79 |
+ |
|
80 |
+ ALLOC_OBJ_CLEAR(ctx->dhm_ctx, dhm_context); |
|
81 |
+ ALLOC_OBJ_CLEAR(ctx->priv_key, rsa_context); |
|
82 |
+ |
|
83 |
+ ALLOC_OBJ_CLEAR(ctx->ca_chain, x509_cert); |
|
84 |
+ ALLOC_OBJ_CLEAR(ctx->crt_chain, x509_cert); |
|
85 |
+ |
|
86 |
+ |
|
87 |
+ ctx->endpoint = SSL_IS_SERVER; |
|
88 |
+ ctx->initialised = true; |
|
89 |
+} |
|
90 |
+ |
|
91 |
+void |
|
92 |
+tls_ctx_client_new(struct tls_root_ctx *ctx) |
|
93 |
+{ |
|
94 |
+ ASSERT(NULL != ctx); |
|
95 |
+ |
|
96 |
+ CLEAR(*ctx); |
|
97 |
+ |
|
98 |
+ ALLOC_OBJ_CLEAR(ctx->hs, havege_state); |
|
99 |
+ havege_init(ctx->hs); |
|
100 |
+ |
|
101 |
+ ALLOC_OBJ_CLEAR(ctx->dhm_ctx, dhm_context); |
|
102 |
+ ALLOC_OBJ_CLEAR(ctx->priv_key, rsa_context); |
|
103 |
+ |
|
104 |
+ ALLOC_OBJ_CLEAR(ctx->ca_chain, x509_cert); |
|
105 |
+ ALLOC_OBJ_CLEAR(ctx->crt_chain, x509_cert); |
|
106 |
+ |
|
107 |
+ ctx->endpoint = SSL_IS_CLIENT; |
|
108 |
+ ctx->initialised = true; |
|
109 |
+} |
|
110 |
+ |
|
111 |
+void |
|
112 |
+tls_ctx_free(struct tls_root_ctx *ctx) |
|
113 |
+{ |
|
114 |
+ if (ctx) |
|
115 |
+ { |
|
116 |
+ rsa_free(ctx->priv_key); |
|
117 |
+ free(ctx->priv_key); |
|
118 |
+ |
|
119 |
+ x509_free(ctx->ca_chain); |
|
120 |
+ free(ctx->ca_chain); |
|
121 |
+ |
|
122 |
+ x509_free(ctx->crt_chain); |
|
123 |
+ free(ctx->crt_chain); |
|
124 |
+ |
|
125 |
+ dhm_free(ctx->dhm_ctx); |
|
126 |
+ free(ctx->dhm_ctx); |
|
127 |
+ |
|
128 |
+#if defined(ENABLE_PKCS11) |
|
129 |
+ if (ctx->priv_key_pkcs11 != NULL) { |
|
130 |
+ pkcs11_priv_key_free(ctx->priv_key_pkcs11); |
|
131 |
+ free(ctx->priv_key_pkcs11); |
|
132 |
+ } |
|
133 |
+#endif |
|
134 |
+ |
|
135 |
+ free(ctx->hs); |
|
136 |
+ |
|
137 |
+ if (ctx->allowed_ciphers) |
|
138 |
+ free(ctx->allowed_ciphers); |
|
139 |
+ |
|
140 |
+ CLEAR(*ctx); |
|
141 |
+ |
|
142 |
+ ctx->initialised = false; |
|
143 |
+ |
|
144 |
+ } |
|
145 |
+} |
|
146 |
+ |
|
147 |
+bool |
|
148 |
+tls_ctx_initialised(struct tls_root_ctx *ctx) |
|
149 |
+{ |
|
150 |
+ ASSERT(NULL != ctx); |
|
151 |
+ return ctx->initialised; |
|
152 |
+} |
|
153 |
+ |
|
154 |
+void |
|
155 |
+tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags) |
|
156 |
+{ |
|
157 |
+} |
|
158 |
+ |
|
159 |
+void |
|
160 |
+tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) |
|
161 |
+{ |
|
162 |
+ char *tmp_ciphers, *tmp_ciphers_orig; |
|
163 |
+ int i, cipher_count; |
|
164 |
+ int ciphers_len = strlen (ciphers); |
|
165 |
+ |
|
166 |
+ ASSERT (NULL != ctx); |
|
167 |
+ ASSERT (0 != ciphers_len); |
|
168 |
+ |
|
169 |
+ /* Get number of ciphers */ |
|
170 |
+ for (i = 0, cipher_count = 1; i < ciphers_len; i++) |
|
171 |
+ if (ciphers[i] == ':') |
|
172 |
+ cipher_count++; |
|
173 |
+ |
|
174 |
+ /* Allocate an array for them */ |
|
175 |
+ ALLOC_ARRAY_CLEAR(ctx->allowed_ciphers, int, cipher_count+1) |
|
176 |
+ |
|
177 |
+ /* Parse allowed ciphers, getting IDs */ |
|
178 |
+ i = 0; |
|
179 |
+ tmp_ciphers_orig = tmp_ciphers = strdup(ciphers); |
|
180 |
+ while(tmp_ciphers) { |
|
181 |
+ ctx->allowed_ciphers[i] = ssl_get_cipher_id (strsep (&tmp_ciphers, ":")); |
|
182 |
+ if (ctx->allowed_ciphers[i] != 0) |
|
183 |
+ i++; |
|
184 |
+ } |
|
185 |
+ free(tmp_ciphers_orig); |
|
186 |
+} |
|
187 |
+ |
|
188 |
+void |
|
189 |
+tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const char *dh_file |
|
190 |
+#if ENABLE_INLINE_FILES |
|
191 |
+ , const char *dh_file_inline |
|
192 |
+#endif /* ENABLE_INLINE_FILES */ |
|
193 |
+ ) |
|
194 |
+{ |
|
195 |
+#if ENABLE_INLINE_FILES |
|
196 |
+ if (!strcmp (dh_file, INLINE_FILE_TAG) && dh_file_inline) |
|
197 |
+ { |
|
198 |
+ if (0 != x509parse_dhm(ctx->dhm_ctx, dh_file_inline, strlen(dh_file_inline))) |
|
199 |
+ msg (M_FATAL, "Cannot read inline DH parameters"); |
|
200 |
+ } |
|
201 |
+else |
|
202 |
+#endif /* ENABLE_INLINE_FILES */ |
|
203 |
+ { |
|
204 |
+ if (0 != x509parse_dhmfile(ctx->dhm_ctx, dh_file)) |
|
205 |
+ msg (M_FATAL, "Cannot read DH parameters from file %s", dh_file); |
|
206 |
+ } |
|
207 |
+ |
|
208 |
+ msg (D_TLS_DEBUG_LOW, "Diffie-Hellman initialized with %d bit key", |
|
209 |
+ 8 * mpi_size(&ctx->dhm_ctx->P)); |
|
210 |
+} |
|
211 |
+ |
|
212 |
+int |
|
213 |
+tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, |
|
214 |
+#if ENABLE_INLINE_FILES |
|
215 |
+ const char *pkcs12_file_inline, |
|
216 |
+#endif /* ENABLE_INLINE_FILES */ |
|
217 |
+ bool load_ca_file |
|
218 |
+ ) |
|
219 |
+{ |
|
220 |
+ msg(M_FATAL, "PKCS #12 files not yet supported for PolarSSL."); |
|
221 |
+} |
|
222 |
+ |
|
223 |
+#ifdef WIN32 |
|
224 |
+void |
|
225 |
+tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert) |
|
226 |
+{ |
|
227 |
+ msg(M_FATAL, "Windows CryptoAPI not yet supported for PolarSSL."); |
|
228 |
+} |
|
229 |
+#endif /* WIN32 */ |
|
230 |
+ |
|
231 |
+void |
|
232 |
+tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, |
|
233 |
+#if ENABLE_INLINE_FILES |
|
234 |
+ const char *cert_file_inline, |
|
235 |
+#endif |
|
236 |
+ x509_cert_t **x509 |
|
237 |
+ ) |
|
238 |
+{ |
|
239 |
+ ASSERT(NULL != ctx); |
|
240 |
+ if (NULL != x509) |
|
241 |
+ ASSERT(NULL == *x509); |
|
242 |
+ |
|
243 |
+#if ENABLE_INLINE_FILES |
|
244 |
+ if (!strcmp (cert_file, INLINE_FILE_TAG) && cert_file_inline) |
|
245 |
+ { |
|
246 |
+ if (0 != x509parse_crt(ctx->crt_chain, cert_file_inline, |
|
247 |
+ strlen(cert_file_inline))) |
|
248 |
+ msg (M_FATAL, "Cannot load inline certificate file"); |
|
249 |
+ } |
|
250 |
+ else |
|
251 |
+#endif /* ENABLE_INLINE_FILES */ |
|
252 |
+ { |
|
253 |
+ if (0 != x509parse_crtfile(ctx->crt_chain, cert_file)) |
|
254 |
+ msg (M_FATAL, "Cannot load certificate file %s", cert_file); |
|
255 |
+ } |
|
256 |
+ if (x509) |
|
257 |
+ { |
|
258 |
+ *x509 = ctx->crt_chain; |
|
259 |
+ } |
|
260 |
+} |
|
261 |
+ |
|
262 |
+int |
|
263 |
+tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file |
|
264 |
+#if ENABLE_INLINE_FILES |
|
265 |
+ , const char *priv_key_file_inline |
|
266 |
+#endif /* ENABLE_INLINE_FILES */ |
|
267 |
+ ) |
|
268 |
+{ |
|
269 |
+ int status; |
|
270 |
+ ASSERT(NULL != ctx); |
|
271 |
+ |
|
272 |
+#if ENABLE_INLINE_FILES |
|
273 |
+ if (!strcmp (priv_key_file, INLINE_FILE_TAG) && priv_key_file_inline) |
|
274 |
+ { |
|
275 |
+ status = x509parse_key(ctx->priv_key, |
|
276 |
+ priv_key_file_inline, strlen(priv_key_file_inline), |
|
277 |
+ NULL, 0); |
|
278 |
+ if (POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED == status) |
|
279 |
+ { |
|
280 |
+ char passbuf[512] = {0}; |
|
281 |
+ pem_password_callback(passbuf, 512, 0, NULL); |
|
282 |
+ status = x509parse_key(ctx->priv_key, |
|
283 |
+ priv_key_file_inline, strlen(priv_key_file_inline), |
|
284 |
+ passbuf, strlen(passbuf)); |
|
285 |
+ } |
|
286 |
+ } |
|
287 |
+ else |
|
288 |
+#endif /* ENABLE_INLINE_FILES */ |
|
289 |
+ { |
|
290 |
+ status = x509parse_keyfile(ctx->priv_key, priv_key_file, NULL); |
|
291 |
+ if (POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED == status) |
|
292 |
+ { |
|
293 |
+ char passbuf[512] = {0}; |
|
294 |
+ pem_password_callback(passbuf, 512, 0, NULL); |
|
295 |
+ status = x509parse_keyfile(ctx->priv_key, priv_key_file, passbuf); |
|
296 |
+ } |
|
297 |
+ } |
|
298 |
+ if (0 != status) |
|
299 |
+ { |
|
300 |
+#ifdef ENABLE_MANAGEMENT |
|
301 |
+ if (management && (POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH == status)) |
|
302 |
+ management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); |
|
303 |
+#endif |
|
304 |
+ msg (M_WARN, "Cannot load private key file %s", priv_key_file); |
|
305 |
+ return 1; |
|
306 |
+ } |
|
307 |
+ |
|
308 |
+ warn_if_group_others_accessible (priv_key_file); |
|
309 |
+ |
|
310 |
+ /* TODO: Check Private Key */ |
|
311 |
+// if (!SSL_CTX_check_private_key (ctx)) |
|
312 |
+// msg (M_SSLERR, "Private key does not match the certificate"); |
|
313 |
+ return 0; |
|
314 |
+} |
|
315 |
+ |
|
316 |
+#ifdef MANAGMENT_EXTERNAL_KEY |
|
317 |
+ |
|
318 |
+int |
|
319 |
+tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, x509_cert_t *cert) |
|
320 |
+{ |
|
321 |
+ msg(M_FATAL, "Use of management external keys not yet supported for PolarSSL."); |
|
322 |
+ |
|
323 |
+} |
|
324 |
+ |
|
325 |
+#endif |
|
326 |
+ |
|
327 |
+void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, |
|
328 |
+#if ENABLE_INLINE_FILES |
|
329 |
+ const char *ca_file_inline, |
|
330 |
+#endif |
|
331 |
+ const char *ca_path, bool tls_server |
|
332 |
+ ) |
|
333 |
+{ |
|
334 |
+ int status; |
|
335 |
+ |
|
336 |
+ if (ca_path) |
|
337 |
+ msg(M_FATAL, "ERROR: PolarSSL cannot handle the capath directive"); |
|
338 |
+ |
|
339 |
+#if ENABLE_INLINE_FILES |
|
340 |
+ if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline) |
|
341 |
+ { |
|
342 |
+ if (0 != x509parse_crt(ctx->ca_chain, ca_file_inline, strlen(ca_file_inline))); |
|
343 |
+ msg (M_FATAL, "Cannot load inline CA certificates"); |
|
344 |
+ } |
|
345 |
+ else |
|
346 |
+#endif |
|
347 |
+ { |
|
348 |
+ /* Load CA file for verifying peer supplied certificate */ |
|
349 |
+ if (0 != x509parse_crtfile(ctx->ca_chain, ca_file)) |
|
350 |
+ msg (M_FATAL, "Cannot load CA certificate file %s", ca_file); |
|
351 |
+ } |
|
352 |
+} |
|
353 |
+ |
|
354 |
+void |
|
355 |
+tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file |
|
356 |
+#if ENABLE_INLINE_FILES |
|
357 |
+ , const char *extra_certs_file_inline |
|
358 |
+#endif |
|
359 |
+ ) |
|
360 |
+{ |
|
361 |
+ ASSERT(NULL != ctx); |
|
362 |
+ |
|
363 |
+#if ENABLE_INLINE_FILES |
|
364 |
+ if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_file_inline) |
|
365 |
+ { |
|
366 |
+ if (0 != x509parse_crt(ctx->crt_chain, extra_certs_file_inline, |
|
367 |
+ strlen(extra_certs_file_inline))) |
|
368 |
+ msg (M_FATAL, "Cannot load inline extra-certs file"); |
|
369 |
+ } |
|
370 |
+ else |
|
371 |
+#endif /* ENABLE_INLINE_FILES */ |
|
372 |
+ { |
|
373 |
+ if (0 != x509parse_crtfile(ctx->crt_chain, extra_certs_file)) |
|
374 |
+ msg (M_FATAL, "Cannot load extra-certs file: %s", extra_certs_file); |
|
375 |
+ } |
|
376 |
+} |
|
377 |
+ |
|
378 |
+/* ************************************** |
|
379 |
+ * |
|
380 |
+ * Key-state specific functions |
|
381 |
+ * |
|
382 |
+ ***************************************/ |
|
383 |
+ |
|
384 |
+/* |
|
385 |
+ * "Endless buffer" |
|
386 |
+ */ |
|
387 |
+ |
|
388 |
+static inline void buf_free_entry(buffer_entry *entry) |
|
389 |
+{ |
|
390 |
+ if (NULL != entry) |
|
391 |
+ { |
|
392 |
+ free(entry->data); |
|
393 |
+ free(entry); |
|
394 |
+ } |
|
395 |
+} |
|
396 |
+ |
|
397 |
+static void buf_free_entries(endless_buffer *buf) |
|
398 |
+{ |
|
399 |
+ while(buf->first_block) |
|
400 |
+ { |
|
401 |
+ buffer_entry *cur_block = buf->first_block; |
|
402 |
+ buf->first_block = cur_block->next_block; |
|
403 |
+ buf_free_entry(cur_block); |
|
404 |
+ } |
|
405 |
+ buf->last_block = NULL; |
|
406 |
+} |
|
407 |
+ |
|
408 |
+static int endless_buf_read( void * ctx, unsigned char * out, int out_len ) |
|
409 |
+{ |
|
410 |
+ endless_buffer *in = (endless_buffer *) ctx; |
|
411 |
+ int read_len = 0; |
|
412 |
+ |
|
413 |
+ if (in->first_block == NULL) |
|
414 |
+ return POLARSSL_ERR_NET_TRY_AGAIN; |
|
415 |
+ |
|
416 |
+ while (in->first_block != NULL && read_len < out_len) |
|
417 |
+ { |
|
418 |
+ int block_len = in->first_block->length - in->data_start; |
|
419 |
+ if (block_len <= out_len - read_len) |
|
420 |
+ { |
|
421 |
+ buffer_entry *cur_entry = in->first_block; |
|
422 |
+ memcpy(out + read_len, cur_entry->data + in->data_start, |
|
423 |
+ block_len); |
|
424 |
+ |
|
425 |
+ read_len += block_len; |
|
426 |
+ |
|
427 |
+ in->first_block = cur_entry->next_block; |
|
428 |
+ in->data_start = 0; |
|
429 |
+ |
|
430 |
+ if (in->first_block == NULL) |
|
431 |
+ in->last_block = NULL; |
|
432 |
+ |
|
433 |
+ buf_free_entry(cur_entry); |
|
434 |
+ } |
|
435 |
+ else |
|
436 |
+ { |
|
437 |
+ memcpy(out + read_len, in->first_block->data + in->data_start, |
|
438 |
+ out_len - read_len); |
|
439 |
+ in->data_start += out_len - read_len; |
|
440 |
+ read_len = out_len; |
|
441 |
+ } |
|
442 |
+ } |
|
443 |
+ |
|
444 |
+ return read_len; |
|
445 |
+} |
|
446 |
+ |
|
447 |
+static int endless_buf_write( void *ctx, unsigned char *in, int len ) |
|
448 |
+{ |
|
449 |
+ endless_buffer *out = (endless_buffer *) ctx; |
|
450 |
+ buffer_entry *new_block = malloc(sizeof(buffer_entry)); |
|
451 |
+ if (NULL == new_block) |
|
452 |
+ return POLARSSL_ERR_NET_SEND_FAILED; |
|
453 |
+ |
|
454 |
+ new_block->data = malloc(len); |
|
455 |
+ if (NULL == new_block->data) |
|
456 |
+ { |
|
457 |
+ free(new_block); |
|
458 |
+ return POLARSSL_ERR_NET_SEND_FAILED; |
|
459 |
+ } |
|
460 |
+ |
|
461 |
+ new_block->length = len; |
|
462 |
+ new_block->next_block = NULL; |
|
463 |
+ |
|
464 |
+ memcpy(new_block->data, in, len); |
|
465 |
+ |
|
466 |
+ if (NULL == out->first_block) |
|
467 |
+ out->first_block = new_block; |
|
468 |
+ |
|
469 |
+ if (NULL != out->last_block) |
|
470 |
+ out->last_block->next_block = new_block; |
|
471 |
+ |
|
472 |
+ out->last_block = new_block; |
|
473 |
+ |
|
474 |
+ return len; |
|
475 |
+} |
|
476 |
+ |
|
477 |
+static void my_debug( void *ctx, int level, const char *str ) |
|
478 |
+{ |
|
479 |
+ if (level == 1) |
|
480 |
+ { |
|
481 |
+ dmsg (D_HANDSHAKE_VERBOSE, "PolarSSL alert: %s", str); |
|
482 |
+ } |
|
483 |
+} |
|
484 |
+ |
|
485 |
+void key_state_ssl_init(struct key_state_ssl *ks_ssl, |
|
486 |
+ const struct tls_root_ctx *ssl_ctx, bool is_server, void *session) |
|
487 |
+{ |
|
488 |
+ ASSERT(NULL != ssl_ctx); |
|
489 |
+ ASSERT(ks_ssl); |
|
490 |
+ CLEAR(*ks_ssl); |
|
491 |
+ |
|
492 |
+ ALLOC_OBJ_CLEAR(ks_ssl->ctx, ssl_context); |
|
493 |
+ if (0 == ssl_init(ks_ssl->ctx)) |
|
494 |
+ { |
|
495 |
+ /* Initialise SSL context */ |
|
496 |
+ ssl_set_dbg (ks_ssl->ctx, my_debug, NULL); |
|
497 |
+ ssl_set_endpoint (ks_ssl->ctx, ssl_ctx->endpoint); |
|
498 |
+ ssl_set_rng (ks_ssl->ctx, havege_rand, ssl_ctx->hs); |
|
499 |
+ ALLOC_OBJ_CLEAR (ks_ssl->ssn, ssl_session); |
|
500 |
+ ssl_set_session (ks_ssl->ctx, 0, 0, ks_ssl->ssn ); |
|
501 |
+ if (ssl_ctx->allowed_ciphers) |
|
502 |
+ ssl_set_ciphers (ks_ssl->ctx, ssl_ctx->allowed_ciphers); |
|
503 |
+ else |
|
504 |
+ ssl_set_ciphers (ks_ssl->ctx, default_ciphers); |
|
505 |
+ |
|
506 |
+ /* Initialise authentication information */ |
|
507 |
+ ssl_set_dh_param_ctx (ks_ssl->ctx, ssl_ctx->dhm_ctx ); |
|
508 |
+ if (ssl_ctx->priv_key_pkcs11 != NULL) |
|
509 |
+ ssl_set_own_cert_pkcs11( ks_ssl->ctx, ssl_ctx->crt_chain, |
|
510 |
+ ssl_ctx->priv_key_pkcs11 ); |
|
511 |
+ else |
|
512 |
+ ssl_set_own_cert( ks_ssl->ctx, ssl_ctx->crt_chain, ssl_ctx->priv_key ); |
|
513 |
+ |
|
514 |
+ /* Initialise SSL verification */ |
|
515 |
+ ssl_set_authmode (ks_ssl->ctx, SSL_VERIFY_REQUIRED); |
|
516 |
+ ssl_set_verify (ks_ssl->ctx, verify_callback, session); |
|
517 |
+ /* TODO: PolarSSL does not currently support sending the CA chain to the client */ |
|
518 |
+ ssl_set_ca_chain (ks_ssl->ctx, ssl_ctx->ca_chain, NULL, NULL ); |
|
519 |
+ |
|
520 |
+ /* Initialise BIOs */ |
|
521 |
+ ALLOC_OBJ_CLEAR (ks_ssl->ct_in, endless_buffer); |
|
522 |
+ ALLOC_OBJ_CLEAR (ks_ssl->ct_out, endless_buffer); |
|
523 |
+ ssl_set_bio (ks_ssl->ctx, endless_buf_read, ks_ssl->ct_in, |
|
524 |
+ endless_buf_write, ks_ssl->ct_out); |
|
525 |
+ |
|
526 |
+ } |
|
527 |
+} |
|
528 |
+ |
|
529 |
+void |
|
530 |
+key_state_ssl_free(struct key_state_ssl *ks_ssl) |
|
531 |
+{ |
|
532 |
+ if (ks_ssl) { |
|
533 |
+ if (ks_ssl->ctx) |
|
534 |
+ { |
|
535 |
+ ssl_free(ks_ssl->ctx); |
|
536 |
+ free(ks_ssl->ctx); |
|
537 |
+ } |
|
538 |
+ if (ks_ssl->ssn) |
|
539 |
+ free(ks_ssl->ssn); |
|
540 |
+ if (ks_ssl->ct_in) { |
|
541 |
+ buf_free_entries(ks_ssl->ct_in); |
|
542 |
+ free(ks_ssl->ct_in); |
|
543 |
+ } |
|
544 |
+ if (ks_ssl->ct_out) { |
|
545 |
+ buf_free_entries(ks_ssl->ct_out); |
|
546 |
+ free(ks_ssl->ct_out); |
|
547 |
+ } |
|
548 |
+ CLEAR(*ks_ssl); |
|
549 |
+ } |
|
550 |
+} |
|
551 |
+ |
|
552 |
+int |
|
553 |
+key_state_write_plaintext (struct key_state_ssl *ks, struct buffer *buf) |
|
554 |
+{ |
|
555 |
+ int retval = 0; |
|
556 |
+ perf_push (PERF_BIO_WRITE_PLAINTEXT); |
|
557 |
+ |
|
558 |
+ ASSERT (NULL != ks); |
|
559 |
+ ASSERT (buf); |
|
560 |
+ ASSERT (buf->len >= 0); |
|
561 |
+ |
|
562 |
+ if (0 == buf->len) |
|
563 |
+ { |
|
564 |
+ return 0; |
|
565 |
+ perf_pop (); |
|
566 |
+ } |
|
567 |
+ |
|
568 |
+ retval = ssl_write(ks->ctx, BPTR(buf), buf->len); |
|
569 |
+ |
|
570 |
+ if (retval < 0) |
|
571 |
+ { |
|
572 |
+ perf_pop (); |
|
573 |
+ if (POLARSSL_ERR_NET_TRY_AGAIN == retval ) |
|
574 |
+ return 0; |
|
575 |
+ msg (D_TLS_ERRORS, "TLS ERROR: write tls_write_plaintext error"); |
|
576 |
+ return -1; |
|
577 |
+ } |
|
578 |
+ |
|
579 |
+ if (retval != buf->len) |
|
580 |
+ { |
|
581 |
+ msg (D_TLS_ERRORS, |
|
582 |
+ "TLS ERROR: write tls_write_plaintext incomplete %d/%d", |
|
583 |
+ retval, buf->len); |
|
584 |
+ perf_pop (); |
|
585 |
+ return -1; |
|
586 |
+ } |
|
587 |
+ |
|
588 |
+ /* successful write */ |
|
589 |
+ dmsg (D_HANDSHAKE_VERBOSE, "write tls_write_plaintext %d bytes", retval); |
|
590 |
+ |
|
591 |
+ memset (BPTR (buf), 0, BLEN (buf)); /* erase data just written */ |
|
592 |
+ buf->len = 0; |
|
593 |
+ |
|
594 |
+ perf_pop (); |
|
595 |
+ return 1; |
|
596 |
+} |
|
597 |
+ |
|
598 |
+int |
|
599 |
+key_state_write_plaintext_const (struct key_state_ssl *ks, const uint8_t *data, int len) |
|
600 |
+{ |
|
601 |
+ int retval = 0; |
|
602 |
+ perf_push (PERF_BIO_WRITE_PLAINTEXT); |
|
603 |
+ |
|
604 |
+ ASSERT (NULL != ks); |
|
605 |
+ ASSERT (len >= 0); |
|
606 |
+ |
|
607 |
+ if (0 == len) |
|
608 |
+ { |
|
609 |
+ perf_pop (); |
|
610 |
+ return 0; |
|
611 |
+ } |
|
612 |
+ |
|
613 |
+ ASSERT (data); |
|
614 |
+ |
|
615 |
+ retval = ssl_write(ks->ctx, data, len); |
|
616 |
+ |
|
617 |
+ if (retval < 0) |
|
618 |
+ { |
|
619 |
+ perf_pop (); |
|
620 |
+ if (POLARSSL_ERR_NET_TRY_AGAIN == retval ) |
|
621 |
+ return 0; |
|
622 |
+ msg (D_TLS_ERRORS, "TLS ERROR: write tls_write_plaintext_const error"); |
|
623 |
+ return -1; |
|
624 |
+ } |
|
625 |
+ |
|
626 |
+ if (retval != len) |
|
627 |
+ { |
|
628 |
+ msg (D_TLS_ERRORS, |
|
629 |
+ "TLS ERROR: write tls_write_plaintext_const incomplete %d/%d", |
|
630 |
+ retval, len); |
|
631 |
+ perf_pop (); |
|
632 |
+ return -1; |
|
633 |
+ } |
|
634 |
+ |
|
635 |
+ /* successful write */ |
|
636 |
+ dmsg (D_HANDSHAKE_VERBOSE, "write tls_write_plaintext_const %d bytes", retval); |
|
637 |
+ |
|
638 |
+ perf_pop (); |
|
639 |
+ return 1; |
|
640 |
+} |
|
641 |
+ |
|
642 |
+int |
|
643 |
+key_state_read_ciphertext (struct key_state_ssl *ks, struct buffer *buf, |
|
644 |
+ int maxlen) |
|
645 |
+{ |
|
646 |
+ int retval = 0; |
|
647 |
+ int len = 0; |
|
648 |
+ |
|
649 |
+ perf_push (PERF_BIO_READ_CIPHERTEXT); |
|
650 |
+ |
|
651 |
+ ASSERT (NULL != ks); |
|
652 |
+ ASSERT (buf); |
|
653 |
+ ASSERT (buf->len >= 0); |
|
654 |
+ |
|
655 |
+ if (buf->len) |
|
656 |
+ { |
|
657 |
+ perf_pop (); |
|
658 |
+ return 0; |
|
659 |
+ } |
|
660 |
+ |
|
661 |
+ len = buf_forward_capacity (buf); |
|
662 |
+ if (maxlen < len) |
|
663 |
+ len = maxlen; |
|
664 |
+ |
|
665 |
+ retval = endless_buf_read(ks->ct_out, BPTR(buf), len); |
|
666 |
+ |
|
667 |
+ /* Error during read, check for retry error */ |
|
668 |
+ if (retval < 0) |
|
669 |
+ { |
|
670 |
+ perf_pop (); |
|
671 |
+ if (POLARSSL_ERR_NET_TRY_AGAIN == retval ) |
|
672 |
+ return 0; |
|
673 |
+ msg (D_TLS_ERRORS, "TLS_ERROR: read tls_read_plaintext error"); |
|
674 |
+ buf->len = 0; |
|
675 |
+ return -1; |
|
676 |
+ } |
|
677 |
+ /* Nothing read, try again */ |
|
678 |
+ if (0 == retval) |
|
679 |
+ { |
|
680 |
+ buf->len = 0; |
|
681 |
+ perf_pop (); |
|
682 |
+ return 0; |
|
683 |
+ } |
|
684 |
+ |
|
685 |
+ /* successful read */ |
|
686 |
+ dmsg (D_HANDSHAKE_VERBOSE, "read tls_read_ciphertext %d bytes", retval); |
|
687 |
+ buf->len = retval; |
|
688 |
+ perf_pop (); |
|
689 |
+ return 1; |
|
690 |
+} |
|
691 |
+ |
|
692 |
+int |
|
693 |
+key_state_write_ciphertext (struct key_state_ssl *ks, struct buffer *buf) |
|
694 |
+{ |
|
695 |
+ int retval = 0; |
|
696 |
+ perf_push (PERF_BIO_WRITE_CIPHERTEXT); |
|
697 |
+ |
|
698 |
+ ASSERT (NULL != ks); |
|
699 |
+ ASSERT (buf); |
|
700 |
+ ASSERT (buf->len >= 0); |
|
701 |
+ |
|
702 |
+ if (0 == buf->len) |
|
703 |
+ { |
|
704 |
+ perf_pop (); |
|
705 |
+ return 0; |
|
706 |
+ } |
|
707 |
+ |
|
708 |
+ retval = endless_buf_write(ks->ct_in, BPTR(buf), buf->len); |
|
709 |
+ |
|
710 |
+ if (retval < 0) |
|
711 |
+ { |
|
712 |
+ perf_pop (); |
|
713 |
+ |
|
714 |
+ if (POLARSSL_ERR_NET_TRY_AGAIN == retval ) |
|
715 |
+ return 0; |
|
716 |
+ msg (D_TLS_ERRORS, "TLS ERROR: write tls_write_ciphertext error"); |
|
717 |
+ return -1; |
|
718 |
+ } |
|
719 |
+ |
|
720 |
+ if (retval != buf->len) |
|
721 |
+ { |
|
722 |
+ msg (D_TLS_ERRORS, |
|
723 |
+ "TLS ERROR: write tls_write_ciphertext incomplete %d/%d", |
|
724 |
+ retval, buf->len); |
|
725 |
+ perf_pop (); |
|
726 |
+ return -1; |
|
727 |
+ } |
|
728 |
+ |
|
729 |
+ /* successful write */ |
|
730 |
+ dmsg (D_HANDSHAKE_VERBOSE, "write tls_write_ciphertext %d bytes", retval); |
|
731 |
+ |
|
732 |
+ memset (BPTR (buf), 0, BLEN (buf)); /* erase data just written */ |
|
733 |
+ buf->len = 0; |
|
734 |
+ |
|
735 |
+ perf_pop (); |
|
736 |
+ return 1; |
|
737 |
+} |
|
738 |
+ |
|
739 |
+int |
|
740 |
+key_state_read_plaintext (struct key_state_ssl *ks, struct buffer *buf, |
|
741 |
+ int maxlen) |
|
742 |
+{ |
|
743 |
+ int retval = 0; |
|
744 |
+ int len = 0; |
|
745 |
+ |
|
746 |
+ perf_push (PERF_BIO_READ_PLAINTEXT); |
|
747 |
+ |
|
748 |
+ ASSERT (NULL != ks); |
|
749 |
+ ASSERT (buf); |
|
750 |
+ ASSERT (buf->len >= 0); |
|
751 |
+ |
|
752 |
+ if (buf->len) |
|
753 |
+ { |
|
754 |
+ perf_pop (); |
|
755 |
+ return 0; |
|
756 |
+ } |
|
757 |
+ |
|
758 |
+ len = buf_forward_capacity (buf); |
|
759 |
+ if (maxlen < len) |
|
760 |
+ len = maxlen; |
|
761 |
+ |
|
762 |
+ retval = ssl_read(ks->ctx, BPTR(buf), len); |
|
763 |
+ |
|
764 |
+ /* Error during read, check for retry error */ |
|
765 |
+ if (retval < 0) |
|
766 |
+ { |
|
767 |
+ if (POLARSSL_ERR_NET_TRY_AGAIN == retval ) |
|
768 |
+ return 0; |
|
769 |
+ msg (D_TLS_ERRORS, "TLS_ERROR: read tls_read_plaintext error"); |
|
770 |
+ buf->len = 0; |
|
771 |
+ perf_pop (); |
|
772 |
+ return -1; |
|
773 |
+ } |
|
774 |
+ /* Nothing read, try again */ |
|
775 |
+ if (0 == retval) |
|
776 |
+ { |
|
777 |
+ buf->len = 0; |
|
778 |
+ perf_pop (); |
|
779 |
+ return 0; |
|
780 |
+ } |
|
781 |
+ |
|
782 |
+ /* successful read */ |
|
783 |
+ dmsg (D_HANDSHAKE_VERBOSE, "read tls_read_plaintext %d bytes", retval); |
|
784 |
+ buf->len = retval; |
|
785 |
+ |
|
786 |
+ perf_pop (); |
|
787 |
+ return 1; |
|
788 |
+} |
|
789 |
+ |
|
790 |
+/* ************************************** |
|
791 |
+ * |
|
792 |
+ * Information functions |
|
793 |
+ * |
|
794 |
+ * Print information for the end user. |
|
795 |
+ * |
|
796 |
+ ***************************************/ |
|
797 |
+void |
|
798 |
+print_details (struct key_state_ssl * ks_ssl, const char *prefix) |
|
799 |
+{ |
|
800 |
+ x509_cert *cert; |
|
801 |
+ char s1[256]; |
|
802 |
+ char s2[256]; |
|
803 |
+ |
|
804 |
+ s1[0] = s2[0] = 0; |
|
805 |
+ openvpn_snprintf (s1, sizeof (s1), "%s %s, cipher %s", |
|
806 |
+ prefix, |
|
807 |
+ ssl_get_version (ks_ssl->ctx), |
|
808 |
+ ssl_get_cipher(ks_ssl->ctx)); |
|
809 |
+ |
|
810 |
+ cert = ks_ssl->ctx->peer_cert; |
|
811 |
+ if (cert != NULL) |
|
812 |
+ { |
|
813 |
+ openvpn_snprintf (s2, sizeof (s2), ", %d bit RSA", cert->rsa.len * 8); |
|
814 |
+ } |
|
815 |
+ |
|
816 |
+ msg (D_HANDSHAKE, "%s%s", s1, s2); |
|
817 |
+} |
|
818 |
+ |
|
819 |
+void |
|
820 |
+show_available_tls_ciphers () |
|
821 |
+{ |
|
822 |
+ const int *ciphers = ssl_list_ciphers(); |
|
823 |
+ |
|
824 |
+#ifndef ENABLE_SMALL |
|
825 |
+ printf ("Available TLS Ciphers,\n"); |
|
826 |
+ printf ("listed in order of preference:\n\n"); |
|
827 |
+#endif |
|
828 |
+ |
|
829 |
+ while (*ciphers != 0) |
|
830 |
+ { |
|
831 |
+ printf ("%s\n", ssl_get_cipher_name(*ciphers)); |
|
832 |
+ ciphers++; |
|
833 |
+ } |
|
834 |
+ printf ("\n"); |
|
835 |
+} |
|
836 |
+ |
|
837 |
+void |
|
838 |
+get_highest_preference_tls_cipher (char *buf, int size) |
|
839 |
+{ |
|
840 |
+ const char *cipher_name; |
|
841 |
+ const int *ciphers = ssl_list_ciphers(); |
|
842 |
+ if (*ciphers == 0) |
|
843 |
+ msg (M_FATAL, "Cannot retrieve list of supported SSL ciphers."); |
|
844 |
+ |
|
845 |
+ cipher_name = ssl_get_cipher_name(*ciphers); |
|
846 |
+ strncpynt (buf, cipher_name, size); |
|
847 |
+} |
0 | 848 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,85 @@ |
0 |
+/* |
|
1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
3 |
+ * session authentication and key exchange, |
|
4 |
+ * packet encryption, packet authentication, and |
|
5 |
+ * packet compression. |
|
6 |
+ * |
|
7 |
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> |
|
8 |
+ * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com> |
|
9 |
+ * |
|
10 |
+ * This program is free software; you can redistribute it and/or modify |
|
11 |
+ * it under the terms of the GNU General Public License version 2 |
|
12 |
+ * as published by the Free Software Foundation. |
|
13 |
+ * |
|
14 |
+ * This program is distributed in the hope that it will be useful, |
|
15 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
+ * GNU General Public License for more details. |
|
18 |
+ * |
|
19 |
+ * You should have received a copy of the GNU General Public License |
|
20 |
+ * along with this program (see the file COPYING included with this |
|
21 |
+ * distribution); if not, write to the Free Software Foundation, Inc., |
|
22 |
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
23 |
+ */ |
|
24 |
+ |
|
25 |
+/** |
|
26 |
+ * @file Control Channel PolarSSL Backend |
|
27 |
+ */ |
|
28 |
+ |
|
29 |
+#ifndef SSL_POLARSSL_H_ |
|
30 |
+#define SSL_POLARSSL_H_ |
|
31 |
+ |
|
32 |
+#include <polarssl/havege.h> |
|
33 |
+#include <polarssl/ssl.h> |
|
34 |
+#include "config.h" |
|
35 |
+ |
|
36 |
+#if defined(ENABLE_PKCS11) |
|
37 |
+#include <polarssl/pkcs11.h> |
|
38 |
+#endif |
|
39 |
+ |
|
40 |
+typedef struct _buffer_entry buffer_entry; |
|
41 |
+ |
|
42 |
+struct _buffer_entry { |
|
43 |
+ size_t length; |
|
44 |
+ uint8_t *data; |
|
45 |
+ buffer_entry *next_block; |
|
46 |
+}; |
|
47 |
+ |
|
48 |
+typedef struct { |
|
49 |
+ size_t data_start; |
|
50 |
+ buffer_entry *first_block; |
|
51 |
+ buffer_entry *last_block; |
|
52 |
+} endless_buffer; |
|
53 |
+ |
|
54 |
+/** |
|
55 |
+ * Structure that wraps the TLS context. Contents differ depending on the |
|
56 |
+ * SSL library used. |
|
57 |
+ * |
|
58 |
+ * Either \c priv_key_pkcs11 or \c priv_key must be filled in. |
|
59 |
+ */ |
|
60 |
+struct tls_root_ctx { |
|
61 |
+ bool initialised; /**< True if the context has been initialised */ |
|
62 |
+ |
|
63 |
+ int endpoint; /**< Whether or not this is a server or a client */ |
|
64 |
+ |
|
65 |
+ havege_state *hs; /**< HAVEGE random number state */ |
|
66 |
+ dhm_context *dhm_ctx; /**< Diffie-Helmann-Merkle context */ |
|
67 |
+ x509_cert *crt_chain; /**< Local Certificate chain */ |
|
68 |
+ x509_cert *ca_chain; /**< CA chain for remote verification */ |
|
69 |
+ rsa_context *priv_key; /**< Local private key */ |
|
70 |
+#if defined(ENABLE_PKCS11) |
|
71 |
+ pkcs11_context *priv_key_pkcs11; /**< PKCS11 private key */ |
|
72 |
+#endif |
|
73 |
+ int * allowed_ciphers; /**< List of allowed ciphers for this connection */ |
|
74 |
+}; |
|
75 |
+ |
|
76 |
+struct key_state_ssl { |
|
77 |
+ ssl_context *ctx; |
|
78 |
+ ssl_session *ssn; |
|
79 |
+ endless_buffer *ct_in; |
|
80 |
+ endless_buffer *ct_out; |
|
81 |
+}; |
|
82 |
+ |
|
83 |
+ |
|
84 |
+#endif /* SSL_POLARSSL_H_ */ |
... | ... |
@@ -326,7 +326,7 @@ verify_peer_cert(const struct tls_options *opt, x509_cert_t *peer_cert, |
326 | 326 |
} |
327 | 327 |
} |
328 | 328 |
|
329 |
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L |
|
329 |
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L || USE_POLARSSL |
|
330 | 330 |
|
331 | 331 |
/* verify certificate ku */ |
332 | 332 |
if (opt->remote_cert_ku[0] != 0) |
45 | 48 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,446 @@ |
0 |
+/* |
|
1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
3 |
+ * session authentication and key exchange, |
|
4 |
+ * packet encryption, packet authentication, and |
|
5 |
+ * packet compression. |
|
6 |
+ * |
|
7 |
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> |
|
8 |
+ * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com> |
|
9 |
+ * |
|
10 |
+ * This program is free software; you can redistribute it and/or modify |
|
11 |
+ * it under the terms of the GNU General Public License version 2 |
|
12 |
+ * as published by the Free Software Foundation. |
|
13 |
+ * |
|
14 |
+ * This program is distributed in the hope that it will be useful, |
|
15 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
+ * GNU General Public License for more details. |
|
18 |
+ * |
|
19 |
+ * You should have received a copy of the GNU General Public License |
|
20 |
+ * along with this program (see the file COPYING included with this |
|
21 |
+ * distribution); if not, write to the Free Software Foundation, Inc., |
|
22 |
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
23 |
+ */ |
|
24 |
+ |
|
25 |
+/** |
|
26 |
+ * @file Control Channel Verification Module PolarSSL backend |
|
27 |
+ */ |
|
28 |
+ |
|
29 |
+#include "ssl_verify.h" |
|
30 |
+#include <polarssl/sha1.h> |
|
31 |
+ |
|
32 |
+#define MAX_SUBJECT_LENGTH 256 |
|
33 |
+ |
|
34 |
+int |
|
35 |
+verify_callback (void *session_obj, x509_cert *cert, int cert_depth, |
|
36 |
+ int preverify_ok) |
|
37 |
+{ |
|
38 |
+ struct tls_session *session = (struct tls_session *) session_obj; |
|
39 |
+ unsigned char *sha1_hash = NULL; |
|
40 |
+ |
|
41 |
+ ASSERT (cert); |
|
42 |
+ ASSERT (session); |
|
43 |
+ |
|
44 |
+ session->verified = false; |
|
45 |
+ |
|
46 |
+ /* Remember certificate hash */ |
|
47 |
+ sha1_hash = x509_get_sha1_hash(cert); |
|
48 |
+ cert_hash_remember (session, cert_depth, sha1_hash); |
|
49 |
+ x509_free_sha1_hash(sha1_hash); |
|
50 |
+ |
|
51 |
+ /* did peer present cert which was signed by our root cert? */ |
|
52 |
+ if (!preverify_ok) |
|
53 |
+ { |
|
54 |
+ char subject[MAX_SUBJECT_LENGTH] = {0}; |
|
55 |
+ |
|
56 |
+ /* get the X509 name */ |
|
57 |
+ if (x509parse_dn_gets( subject, MAX_SUBJECT_LENGTH, &cert->subject ) < 0) |
|
58 |
+ msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, could not extract X509 " |
|
59 |
+ "subject string from certificate", cert_depth); |
|
60 |
+ else |
|
61 |
+ msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, %s", cert_depth, subject); |
|
62 |
+ |
|
63 |
+ return 1; |
|
64 |
+ } |
|
65 |
+ |
|
66 |
+ /* |
|
67 |
+ * verify_cert() returns 1 on success, 0 on failure. |
|
68 |
+ * PolarSSL expects the opposite. |
|
69 |
+ */ |
|
70 |
+ return 0 == verify_cert(session, cert, cert_depth); |
|
71 |
+} |
|
72 |
+ |
|
73 |
+#ifdef ENABLE_X509ALTUSERNAME |
|
74 |
+# warning "X509 alt user name not yet supported for PolarSSL" |
|
75 |
+#endif |
|
76 |
+ |
|
77 |
+bool |
|
78 |
+x509_get_username (char *cn, int cn_len, |
|
79 |
+ char *x509_username_field, x509_cert *cert) |
|
80 |
+{ |
|
81 |
+ x509_name *name; |
|
82 |
+ |
|
83 |
+ ASSERT( cn != NULL ); |
|
84 |
+ |
|
85 |
+ name = &cert->subject; |
|
86 |
+ |
|
87 |
+ /* Find common name */ |
|
88 |
+ while( name != NULL ) |
|
89 |
+ { |
|
90 |
+ if( memcmp( name->oid.p, OID_CN, OID_SIZE(OID_CN) ) == 0) |
|
91 |
+ break; |
|
92 |
+ |
|
93 |
+ name = name->next; |
|
94 |
+ } |
|
95 |
+ |
|
96 |
+ /* Not found, return an error if this is the peer's certificate */ |
|
97 |
+ if( name == NULL ) |
|
98 |
+ return 1; |
|
99 |
+ |
|
100 |
+ /* Found, extract CN */ |
|
101 |
+ if (cn_len > name->val.len) |
|
102 |
+ memcpy( cn, name->val.p, name->val.len ); |
|
103 |
+ else |
|
104 |
+ { |
|
105 |
+ memcpy( cn, name->val.p, cn_len); |
|
106 |
+ cn[cn_len-1] = '\0'; |
|
107 |
+ } |
|
108 |
+ |
|
109 |
+ return 0; |
|
110 |
+} |
|
111 |
+ |
|
112 |
+char * |
|
113 |
+x509_get_serial (x509_cert *cert) |
|
114 |
+{ |
|
115 |
+ int ret = 0; |
|
116 |
+ int i = 0; |
|
117 |
+ char *buf = NULL; |
|
118 |
+ size_t len = cert->serial.len * 3; |
|
119 |
+ |
|
120 |
+ buf = malloc(len); |
|
121 |
+ ASSERT(buf); |
|
122 |
+ |
|
123 |
+ if(x509parse_serial_gets(buf, len-1, &cert->serial) < 0) |
|
124 |
+ { |
|
125 |
+ free(buf); |
|
126 |
+ buf = NULL; |
|
127 |
+ } |
|
128 |
+ |
|
129 |
+ return buf; |
|
130 |
+} |
|
131 |
+ |
|
132 |
+void |
|
133 |
+x509_free_serial (char *serial) |
|
134 |
+{ |
|
135 |
+ if (serial) |
|
136 |
+ free(serial); |
|
137 |
+} |
|
138 |
+ |
|
139 |
+unsigned char * |
|
140 |
+x509_get_sha1_hash (x509_cert *cert) |
|
141 |
+{ |
|
142 |
+ unsigned char *sha1_hash = malloc(SHA_DIGEST_LENGTH); |
|
143 |
+ sha1(cert->tbs.p, cert->tbs.len, sha1_hash); |
|
144 |
+ return sha1_hash; |
|
145 |
+} |
|
146 |
+ |
|
147 |
+void |
|
148 |
+x509_free_sha1_hash (unsigned char *hash) |
|
149 |
+{ |
|
150 |
+ if (hash) |
|
151 |
+ free(hash); |
|
152 |
+} |
|
153 |
+ |
|
154 |
+char * |
|
155 |
+x509_get_subject(x509_cert *cert) |
|
156 |
+{ |
|
157 |
+ char tmp_subject[MAX_SUBJECT_LENGTH] = {0}; |
|
158 |
+ char *subject = NULL; |
|
159 |
+ |
|
160 |
+ int ret = 0; |
|
161 |
+ |
|
162 |
+ ret = x509parse_dn_gets( tmp_subject, MAX_SUBJECT_LENGTH-1, &cert->subject ); |
|
163 |
+ if (ret > 0) |
|
164 |
+ { |
|
165 |
+ /* Allocate the required space for the subject */ |
|
166 |
+ subject = malloc(ret + 1); |
|
167 |
+ strncpy(subject, tmp_subject, ret+1); |
|
168 |
+ } |
|
169 |
+ |
|
170 |
+ return subject; |
|
171 |
+} |
|
172 |
+ |
|
173 |
+void |
|
174 |
+x509_free_subject (char *subject) |
|
175 |
+{ |
|
176 |
+ if (subject) |
|
177 |
+ free(subject); |
|
178 |
+} |
|
179 |
+ |
|
180 |
+/* |
|
181 |
+ * Save X509 fields to environment, using the naming convention: |
|
182 |
+ * |
|
183 |
+ * X509_{cert_depth}_{name}={value} |
|
184 |
+ */ |
|
185 |
+void |
|
186 |
+x509_setenv (struct env_set *es, int cert_depth, x509_cert_t *cert) |
|
187 |
+{ |
|
188 |
+ int i, ret; |
|
189 |
+ unsigned char c; |
|
190 |
+ const x509_name *name; |
|
191 |
+ char s[128]; |
|
192 |
+ |
|
193 |
+ name = &cert->subject; |
|
194 |
+ |
|
195 |
+ memset( s, 0, sizeof( s ) ); |
|
196 |
+ |
|
197 |
+ while( name != NULL ) |
|
198 |
+ { |
|
199 |
+ char name_expand[64+8]; |
|
200 |
+ |
|
201 |
+ if( name->oid.len == 2 && memcmp( name->oid.p, OID_X520, 2 ) == 0 ) |
|
202 |
+ { |
|
203 |
+ switch( name->oid.p[2] ) |
|
204 |
+ { |
|
205 |
+ case X520_COMMON_NAME: |
|
206 |
+ openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_CN", |
|
207 |
+ cert_depth); break; |
|
208 |
+ |
|
209 |
+ case X520_COUNTRY: |
|
210 |
+ openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_C", |
|
211 |
+ cert_depth); break; |
|
212 |
+ |
|
213 |
+ case X520_LOCALITY: |
|
214 |
+ openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_L", |
|
215 |
+ cert_depth); break; |
|
216 |
+ |
|
217 |
+ case X520_STATE: |
|
218 |
+ openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_ST", |
|
219 |
+ cert_depth); break; |
|
220 |
+ |
|
221 |
+ case X520_ORGANIZATION: |
|
222 |
+ openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_O", |
|
223 |
+ cert_depth); break; |
|
224 |
+ |
|
225 |
+ case X520_ORG_UNIT: |
|
226 |
+ openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_OU", |
|
227 |
+ cert_depth); break; |
|
228 |
+ |
|
229 |
+ default: |
|
230 |
+ openvpn_snprintf (name_expand, sizeof(name_expand), |
|
231 |
+ "X509_%d_0x%02X", cert_depth, name->oid.p[2]); |
|
232 |
+ break; |
|
233 |
+ } |
|
234 |
+ } |
|
235 |
+ else if( name->oid.len == 8 && memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 ) |
|
236 |
+ { |
|
237 |
+ switch( name->oid.p[8] ) |
|
238 |
+ { |
|
239 |
+ case PKCS9_EMAIL: |
|
240 |
+ openvpn_snprintf (name_expand, sizeof(name_expand), |
|
241 |
+ "X509_%d_emailAddress", cert_depth); break; |
|
242 |
+ |
|
243 |
+ default: |
|
244 |
+ openvpn_snprintf (name_expand, sizeof(name_expand), |
|
245 |
+ "X509_%d_0x%02X", cert_depth, name->oid.p[8]); |
|
246 |
+ break; |
|
247 |
+ } |
|
248 |
+ } |
|
249 |
+ else |
|
250 |
+ { |
|
251 |
+ openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_\?\?", |
|
252 |
+ cert_depth); |
|
253 |
+ } |
|
254 |
+ |
|
255 |
+ for( i = 0; i < name->val.len; i++ ) |
|
256 |
+ { |
|
257 |
+ if( i >= (int) sizeof( s ) - 1 ) |
|
258 |
+ break; |
|
259 |
+ |
|
260 |
+ c = name->val.p[i]; |
|
261 |
+ if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) |
|
262 |
+ s[i] = '?'; |
|
263 |
+ else s[i] = c; |
|
264 |
+ } |
|
265 |
+ s[i] = '\0'; |
|
266 |
+ |
|
267 |
+ /* Check both strings, set environment variable */ |
|
268 |
+ string_mod (name_expand, CC_PRINT, CC_CRLF, '_'); |
|
269 |
+ string_mod ((char*)s, CC_PRINT, CC_CRLF, '_'); |
|
270 |
+ setenv_str (es, name_expand, (char*)s); |
|
271 |
+ |
|
272 |
+ name = name->next; |
|
273 |
+ } |
|
274 |
+} |
|
275 |
+ |
|
276 |
+bool |
|
277 |
+x509_verify_ns_cert_type(const x509_cert *cert, const int usage) |
|
278 |
+{ |
|
279 |
+ if (usage == NS_CERT_CHECK_NONE) |
|
280 |
+ return true; |
|
281 |
+ if (usage == NS_CERT_CHECK_CLIENT) |
|
282 |
+ return ((cert->ext_types & EXT_NS_CERT_TYPE) |
|
283 |
+ && (cert->ns_cert_type & NS_CERT_TYPE_SSL_CLIENT)); |
|
284 |
+ if (usage == NS_CERT_CHECK_SERVER) |
|
285 |
+ return ((cert->ext_types & EXT_NS_CERT_TYPE) |
|
286 |
+ && (cert->ns_cert_type & NS_CERT_TYPE_SSL_SERVER)); |
|
287 |
+ |
|
288 |
+ return false; |
|
289 |
+} |
|
290 |
+ |
|
291 |
+bool |
|
292 |
+x509_verify_cert_ku (x509_cert *cert, const unsigned * const expected_ku, |
|
293 |
+ int expected_len) |
|
294 |
+{ |
|
295 |
+ bool fFound = false; |
|
296 |
+ |
|
297 |
+ if(!(cert->ext_types & EXT_KEY_USAGE)) |
|
298 |
+ { |
|
299 |
+ msg (D_HANDSHAKE, "Certificate does not have key usage extension"); |
|
300 |
+ } |
|
301 |
+ else |
|
302 |
+ { |
|
303 |
+ int i; |
|
304 |
+ unsigned nku = cert->key_usage; |
|
305 |
+ |
|
306 |
+ msg (D_HANDSHAKE, "Validating certificate key usage"); |
|
307 |
+ for (i=0;!fFound && i<expected_len;i++) |
|
308 |
+ { |
|
309 |
+ if (expected_ku[i] != 0) |
|
310 |
+ { |
|
311 |
+ msg (D_HANDSHAKE, "++ Certificate has key usage %04x, expects " |
|
312 |
+ "%04x", nku, expected_ku[i]); |
|
313 |
+ |
|
314 |
+ if (nku == expected_ku[i]) |
|
315 |
+ { |
|
316 |
+ fFound = true; |
|
317 |
+ } |
|
318 |
+ } |
|
319 |
+ } |
|
320 |
+ } |
|
321 |
+ return fFound; |
|
322 |
+} |
|
323 |
+ |
|
324 |
+bool |
|
325 |
+x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) |
|
326 |
+{ |
|
327 |
+ bool fFound = false; |
|
328 |
+ |
|
329 |
+ if (!(cert->ext_types & EXT_EXTENDED_KEY_USAGE)) |
|
330 |
+ { |
|
331 |
+ msg (D_HANDSHAKE, "Certificate does not have extended key usage extension"); |
|
332 |
+ } |
|
333 |
+ else |
|
334 |
+ { |
|
335 |
+ x509_sequence *oid_seq = &(cert->ext_key_usage); |
|
336 |
+ |
|
337 |
+ msg (D_HANDSHAKE, "Validating certificate extended key usage"); |
|
338 |
+ while (oid_seq != NULL) |
|
339 |
+ { |
|
340 |
+ x509_buf *oid = &oid_seq->buf; |
|
341 |
+ char oid_num_str[1024]; |
|
342 |
+ const char *oid_str; |
|
343 |
+ |
|
344 |
+ oid_str = x509_oid_get_description(oid); |
|
345 |
+ if (oid_str != NULL) |
|
346 |
+ { |
|
347 |
+ msg (D_HANDSHAKE, "++ Certificate has EKU (str) %s, expects %s", |
|
348 |
+ oid_str, expected_oid); |
|
349 |
+ if (!strcmp (expected_oid, oid_str)) |
|
350 |
+ { |
|
351 |
+ fFound = true; |
|
352 |
+ break; |
|
353 |
+ } |
|
354 |
+ } |
|
355 |
+ |
|
356 |
+ if (0 == x509_oid_get_numeric_string( oid_num_str, |
|
357 |
+ sizeof (oid_num_str), oid)) |
|
358 |
+ { |
|
359 |
+ msg (D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s", |
|
360 |
+ oid_num_str, expected_oid); |
|
361 |
+ if (!strcmp (expected_oid, oid_num_str)) |
|
362 |
+ { |
|
363 |
+ fFound = true; |
|
364 |
+ break; |
|
365 |
+ } |
|
366 |
+ } |
|
367 |
+ oid_seq = oid_seq->next; |
|
368 |
+ } |
|
369 |
+ } |
|
370 |
+ |
|
371 |
+ return fFound; |
|
372 |
+} |
|
373 |
+ |
|
374 |
+const char * |
|
375 |
+x509_write_cert(x509_cert *peercert, const char *tmp_dir, struct gc_arena *gc) |
|
376 |
+{ |
|
377 |
+ FILE *peercert_file; |
|
378 |
+ const char *peercert_filename=""; |
|
379 |
+ |
|
380 |
+ if(!tmp_dir) |
|
381 |
+ return NULL; |
|
382 |
+ |
|
383 |
+ /* create tmp file to store peer cert */ |
|
384 |
+ peercert_filename = create_temp_file (tmp_dir, "pcf", gc); |
|
385 |
+ |
|
386 |
+ /* write peer-cert in tmp-file */ |
|
387 |
+ peercert_file = fopen(peercert_filename, "w+"); |
|
388 |
+ if(!peercert_file) |
|
389 |
+ { |
|
390 |
+ msg (M_ERR, "Failed to open temporary file : %s", peercert_filename); |
|
391 |
+ return NULL; |
|
392 |
+ } |
|
393 |
+ |
|
394 |
+// if(PEM_write_X509(peercert_file,peercert)<0) |
|
395 |
+// { |
|
396 |
+ msg (M_ERR, "PolarSSL does not support writing peer certificate in PEM format"); |
|
397 |
+ fclose(peercert_file); |
|
398 |
+ return NULL; |
|
399 |
+// } |
|
400 |
+ |
|
401 |
+ fclose(peercert_file); |
|
402 |
+ return peercert_filename; |
|
403 |
+} |
|
404 |
+ |
|
405 |
+/* |
|
406 |
+ * check peer cert against CRL |
|
407 |
+ */ |
|
408 |
+bool |
|
409 |
+x509_verify_crl(const char *crl_file, x509_cert *cert, const char *subject) |
|
410 |
+{ |
|
411 |
+ int retval = 0; |
|
412 |
+ x509_crl crl = {0}; |
|
413 |
+ |
|
414 |
+ if (x509parse_crlfile(&crl, crl_file) != 0) |
|
415 |
+ { |
|
416 |
+ msg (M_ERR, "CRL: cannot read CRL from file %s", crl_file); |
|
417 |
+ goto end; |
|
418 |
+ } |
|
419 |
+ |
|
420 |
+ if(cert->issuer_raw.len != crl.issuer_raw.len || |
|
421 |
+ memcmp(crl.issuer_raw.p, cert->issuer_raw.p, crl.issuer_raw.len) != 0) |
|
422 |
+ { |
|
423 |
+ msg (M_WARN, "CRL: CRL %s is from a different issuer than the issuer of " |
|
424 |
+ "certificate %s", crl_file, subject); |
|
425 |
+ retval = 1; |
|
426 |
+ goto end; |
|
427 |
+ } |
|
428 |
+ |
|
429 |
+ if (0 != x509parse_revoked(cert, &crl)) |
|
430 |
+ { |
|
431 |
+ msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED", subject); |
|
432 |
+ goto end; |
|
433 |
+ } |
|
434 |
+ |
|
435 |
+ retval = 1; |
|
436 |
+ msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject); |
|
437 |
+ |
|
438 |
+end: |
|
439 |
+ x509_crl_free(&crl); |
|
440 |
+ |
|
441 |
+ if (!retval) |
|
442 |
+ return true; |
|
443 |
+ |
|
444 |
+ return false; |
|
445 |
+} |
0 | 446 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,79 @@ |
0 |
+/* |
|
1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
3 |
+ * session authentication and key exchange, |
|
4 |
+ * packet encryption, packet authentication, and |
|
5 |
+ * packet compression. |
|
6 |
+ * |
|
7 |
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> |
|
8 |
+ * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com> |
|
9 |
+ * |
|
10 |
+ * This program is free software; you can redistribute it and/or modify |
|
11 |
+ * it under the terms of the GNU General Public License version 2 |
|
12 |
+ * as published by the Free Software Foundation. |
|
13 |
+ * |
|
14 |
+ * This program is distributed in the hope that it will be useful, |
|
15 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
+ * GNU General Public License for more details. |
|
18 |
+ * |
|
19 |
+ * You should have received a copy of the GNU General Public License |
|
20 |
+ * along with this program (see the file COPYING included with this |
|
21 |
+ * distribution); if not, write to the Free Software Foundation, Inc., |
|
22 |
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
23 |
+ */ |
|
24 |
+ |
|
25 |
+/** |
|
26 |
+ * @file Control Channel Verification Module PolarSSL backend |
|
27 |
+ */ |
|
28 |
+ |
|
29 |
+#ifndef SSL_VERIFY_POLARSSL_H_ |
|
30 |
+#define SSL_VERIFY_POLARSSL_H_ |
|
31 |
+ |
|
32 |
+#include "syshead.h" |
|
33 |
+#include "misc.h" |
|
34 |
+#include "manage.h" |
|
35 |
+#include <polarssl/x509.h> |
|
36 |
+ |
|
37 |
+typedef x509_cert x509_cert_t; |
|
38 |
+ |
|
39 |
+/** @name Function for authenticating a new connection from a remote OpenVPN peer |
|
40 |
+ * @{ */ |
|
41 |
+ |
|
42 |
+/** |
|
43 |
+ * Verify that the remote OpenVPN peer's certificate allows setting up a |
|
44 |
+ * VPN tunnel. |
|
45 |
+ * @ingroup control_tls |
|
46 |
+ * |
|
47 |
+ * This callback function is called when a new TLS session is being setup to |
|
48 |
+ * determine whether the remote OpenVPN peer's certificate is allowed to |
|
49 |
+ * connect. It is called for once for every certificate in the chain. The |
|
50 |
+ * callback functionality is configured in the \c init_ssl() function, which |
|
51 |
+ * calls the PolarSSL library's \c ssl_set_verify_callback() function with \c |
|
52 |
+ * verify_callback() as its callback argument. |
|
53 |
+ * |
|
54 |
+ * It checks preverify_ok, and registers the certificate hash. If these steps |
|
55 |
+ * succeed, it calls the \c verify_cert() function, which performs |
|
56 |
+ * OpenVPN-specific verification. |
|
57 |
+ * |
|
58 |
+ * @param session_obj - The OpenVPN \c tls_session associated with this object, |
|
59 |
+ * as set during SSL session setup. |
|
60 |
+ * @param cert - The certificate used by PolarSSL. |
|
61 |
+ * @param cert_depth - The depth of the current certificate in the chain, with |
|
62 |
+ * 0 being the actual certificate. |
|
63 |
+ * @param preverify_ok - Whether the remote OpenVPN peer's certificate |
|
64 |
+ * past verification. A value of 1 means it |
|
65 |
+ * verified successfully, 0 means it failed. |
|
66 |
+ * |
|
67 |
+ * @return The return value indicates whether the supplied certificate is |
|
68 |
+ * allowed to set up a VPN tunnel. The following values can be |
|
69 |
+ * returned: |
|
70 |
+ * - \c 0: failure, this certificate is not allowed to connect. |
|
71 |
+ * - \c 1: success, this certificate is allowed to connect. |
|
72 |
+ */ |
|
73 |
+int verify_callback (void *session_obj, x509_cert *cert, int cert_depth, |
|
74 |
+ int preverify_ok); |
|
75 |
+ |
|
76 |
+/** @} name Function for authenticating a new connection from a remote OpenVPN peer */ |
|
77 |
+ |
|
78 |
+#endif /* SSL_VERIFY_POLARSSL_H_ */ |