|
1 /* ssl/d1_lib.c */ |
|
2 /* |
|
3 * DTLS implementation written by Nagendra Modadugu |
|
4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. |
|
5 */ |
|
6 /* ==================================================================== |
|
7 * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. |
|
8 * |
|
9 * Redistribution and use in source and binary forms, with or without |
|
10 * modification, are permitted provided that the following conditions |
|
11 * are met: |
|
12 * |
|
13 * 1. Redistributions of source code must retain the above copyright |
|
14 * notice, this list of conditions and the following disclaimer. |
|
15 * |
|
16 * 2. Redistributions in binary form must reproduce the above copyright |
|
17 * notice, this list of conditions and the following disclaimer in |
|
18 * the documentation and/or other materials provided with the |
|
19 * distribution. |
|
20 * |
|
21 * 3. All advertising materials mentioning features or use of this |
|
22 * software must display the following acknowledgment: |
|
23 * "This product includes software developed by the OpenSSL Project |
|
24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" |
|
25 * |
|
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
|
27 * endorse or promote products derived from this software without |
|
28 * prior written permission. For written permission, please contact |
|
29 * openssl-core@OpenSSL.org. |
|
30 * |
|
31 * 5. Products derived from this software may not be called "OpenSSL" |
|
32 * nor may "OpenSSL" appear in their names without prior written |
|
33 * permission of the OpenSSL Project. |
|
34 * |
|
35 * 6. Redistributions of any form whatsoever must retain the following |
|
36 * acknowledgment: |
|
37 * "This product includes software developed by the OpenSSL Project |
|
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" |
|
39 * |
|
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
|
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
|
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
|
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
|
51 * OF THE POSSIBILITY OF SUCH DAMAGE. |
|
52 * ==================================================================== |
|
53 * |
|
54 * This product includes cryptographic software written by Eric Young |
|
55 * (eay@cryptsoft.com). This product includes software written by Tim |
|
56 * Hudson (tjh@cryptsoft.com). |
|
57 * |
|
58 */ |
|
59 /* |
|
60 © Portions copyright (c) 2006 Nokia Corporation. All rights reserved. |
|
61 */ |
|
62 |
|
63 #include <stdio.h> |
|
64 #include <openssl/objects.h> |
|
65 #include "ssl_locl.h" |
|
66 |
|
67 const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT; |
|
68 |
|
69 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__))) |
|
70 #include "libssl_wsd.h" |
|
71 #endif |
|
72 |
|
73 #ifdef EMULATOR |
|
74 |
|
75 GET_STATIC_VAR_FROM_TLS(dtlsv1_base_method_data,d1_lib,SSL_METHOD) |
|
76 |
|
77 #define dtlsv1_base_method_data (*GET_WSD_VAR_NAME(dtlsv1_base_method_data,d1_lib,s)()) |
|
78 |
|
79 |
|
80 GET_GLOBAL_VAR_FROM_TLS(DTLSv1_enc_data,d1_lib,SSL3_ENC_METHOD) |
|
81 |
|
82 #define DTLSv1_enc_data (GET_WSD_VAR_NAME(DTLSv1_enc_data,d1_lib,g)()) |
|
83 |
|
84 #endif |
|
85 |
|
86 #ifndef EMULATOR |
|
87 SSL3_ENC_METHOD DTLSv1_enc_data={ |
|
88 #else |
|
89 const SSL3_ENC_METHOD temp_DTLSv1_enc_data={ |
|
90 #endif |
|
91 dtls1_enc, |
|
92 tls1_mac, |
|
93 tls1_setup_key_block, |
|
94 tls1_generate_master_secret, |
|
95 tls1_change_cipher_state, |
|
96 tls1_final_finish_mac, |
|
97 TLS1_FINISH_MAC_LENGTH, |
|
98 tls1_cert_verify_mac, |
|
99 TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, |
|
100 TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, |
|
101 tls1_alert_code, |
|
102 }; |
|
103 |
|
104 long dtls1_default_timeout(void) |
|
105 { |
|
106 /* 2 hours, the 24 hours mentioned in the DTLSv1 spec |
|
107 * is way too long for http, the cache would over fill */ |
|
108 return(60*60*2); |
|
109 } |
|
110 |
|
111 IMPLEMENT_dtls1_meth_func(dtlsv1_base_method, |
|
112 ssl_undefined_function, |
|
113 ssl_undefined_function, |
|
114 ssl_bad_method) |
|
115 |
|
116 int dtls1_new(SSL *s) |
|
117 { |
|
118 DTLS1_STATE *d1; |
|
119 |
|
120 if (!ssl3_new(s)) return(0); |
|
121 if ((d1=OPENSSL_malloc(sizeof *d1)) == NULL) return (0); |
|
122 memset(d1,0, sizeof *d1); |
|
123 |
|
124 /* d1->handshake_epoch=0; */ |
|
125 #if defined(OPENSSL_SYS_VMS) || defined(VMS_TEST) |
|
126 d1->bitmap.length=64; |
|
127 #else |
|
128 d1->bitmap.length=sizeof(d1->bitmap.map) * 8; |
|
129 #endif |
|
130 pq_64bit_init(&(d1->bitmap.map)); |
|
131 pq_64bit_init(&(d1->bitmap.max_seq_num)); |
|
132 |
|
133 pq_64bit_init(&(d1->next_bitmap.map)); |
|
134 pq_64bit_init(&(d1->next_bitmap.max_seq_num)); |
|
135 |
|
136 d1->unprocessed_rcds.q=pqueue_new(); |
|
137 d1->processed_rcds.q=pqueue_new(); |
|
138 d1->buffered_messages = pqueue_new(); |
|
139 d1->sent_messages=pqueue_new(); |
|
140 |
|
141 if ( s->server) |
|
142 { |
|
143 d1->cookie_len = sizeof(s->d1->cookie); |
|
144 } |
|
145 |
|
146 if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q |
|
147 || ! d1->buffered_messages || ! d1->sent_messages) |
|
148 { |
|
149 if ( d1->unprocessed_rcds.q) pqueue_free(d1->unprocessed_rcds.q); |
|
150 if ( d1->processed_rcds.q) pqueue_free(d1->processed_rcds.q); |
|
151 if ( d1->buffered_messages) pqueue_free(d1->buffered_messages); |
|
152 if ( d1->sent_messages) pqueue_free(d1->sent_messages); |
|
153 OPENSSL_free(d1); |
|
154 return (0); |
|
155 } |
|
156 |
|
157 s->d1=d1; |
|
158 s->method->ssl_clear(s); |
|
159 return(1); |
|
160 } |
|
161 |
|
162 void dtls1_free(SSL *s) |
|
163 { |
|
164 pitem *item = NULL; |
|
165 hm_fragment *frag = NULL; |
|
166 |
|
167 ssl3_free(s); |
|
168 |
|
169 while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) |
|
170 { |
|
171 OPENSSL_free(item->data); |
|
172 pitem_free(item); |
|
173 } |
|
174 pqueue_free(s->d1->unprocessed_rcds.q); |
|
175 |
|
176 while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL) |
|
177 { |
|
178 OPENSSL_free(item->data); |
|
179 pitem_free(item); |
|
180 } |
|
181 pqueue_free(s->d1->processed_rcds.q); |
|
182 |
|
183 while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL) |
|
184 { |
|
185 frag = (hm_fragment *)item->data; |
|
186 OPENSSL_free(frag->fragment); |
|
187 OPENSSL_free(frag); |
|
188 pitem_free(item); |
|
189 } |
|
190 pqueue_free(s->d1->buffered_messages); |
|
191 |
|
192 while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL) |
|
193 { |
|
194 frag = (hm_fragment *)item->data; |
|
195 OPENSSL_free(frag->fragment); |
|
196 OPENSSL_free(frag); |
|
197 pitem_free(item); |
|
198 } |
|
199 pqueue_free(s->d1->sent_messages); |
|
200 |
|
201 pq_64bit_free(&(s->d1->bitmap.map)); |
|
202 pq_64bit_free(&(s->d1->bitmap.max_seq_num)); |
|
203 |
|
204 pq_64bit_free(&(s->d1->next_bitmap.map)); |
|
205 pq_64bit_free(&(s->d1->next_bitmap.max_seq_num)); |
|
206 |
|
207 OPENSSL_free(s->d1); |
|
208 } |
|
209 |
|
210 void dtls1_clear(SSL *s) |
|
211 { |
|
212 ssl3_clear(s); |
|
213 s->version=DTLS1_VERSION; |
|
214 } |
|
215 |
|
216 /* |
|
217 * As it's impossible to use stream ciphers in "datagram" mode, this |
|
218 * simple filter is designed to disengage them in DTLS. Unfortunately |
|
219 * there is no universal way to identify stream SSL_CIPHER, so we have |
|
220 * to explicitly list their SSL_* codes. Currently RC4 is the only one |
|
221 * available, but if new ones emerge, they will have to be added... |
|
222 */ |
|
223 SSL_CIPHER *dtls1_get_cipher(unsigned int u) |
|
224 { |
|
225 SSL_CIPHER *ciph = ssl3_get_cipher(u); |
|
226 |
|
227 if (ciph != NULL) |
|
228 { |
|
229 if ((ciph->algorithms&SSL_ENC_MASK) == SSL_RC4) |
|
230 return NULL; |
|
231 } |
|
232 |
|
233 return ciph; |
|
234 } |