1/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to.  The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 *    notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 *    notice, this list of conditions and the following disclaimer in the
29 *    documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 *    must display the following acknowledgement:
32 *    "This product includes cryptographic software written by
33 *     Eric Young (eay@cryptsoft.com)"
34 *    The word 'cryptographic' can be left out if the rouines from the library
35 *    being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 *    the apps directory (application code) you must include an acknowledgement:
38 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed.  i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
56 */
57/* ====================================================================
58 * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
59 *
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
62 * are met:
63 *
64 * 1. Redistributions of source code must retain the above copyright
65 *    notice, this list of conditions and the following disclaimer.
66 *
67 * 2. Redistributions in binary form must reproduce the above copyright
68 *    notice, this list of conditions and the following disclaimer in
69 *    the documentation and/or other materials provided with the
70 *    distribution.
71 *
72 * 3. All advertising materials mentioning features or use of this
73 *    software must display the following acknowledgment:
74 *    "This product includes software developed by the OpenSSL Project
75 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76 *
77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78 *    endorse or promote products derived from this software without
79 *    prior written permission. For written permission, please contact
80 *    openssl-core@openssl.org.
81 *
82 * 5. Products derived from this software may not be called "OpenSSL"
83 *    nor may "OpenSSL" appear in their names without prior written
84 *    permission of the OpenSSL Project.
85 *
86 * 6. Redistributions of any form whatsoever must retain the following
87 *    acknowledgment:
88 *    "This product includes software developed by the OpenSSL Project
89 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90 *
91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102 * OF THE POSSIBILITY OF SUCH DAMAGE.
103 * ====================================================================
104 *
105 * This product includes cryptographic software written by Eric Young
106 * (eay@cryptsoft.com).  This product includes software written by Tim
107 * Hudson (tjh@cryptsoft.com). */
108/* ====================================================================
109 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
110 * ECC cipher suite support in OpenSSL originally developed by
111 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */
112
113#include <assert.h>
114#include <limits.h>
115#include <stdio.h>
116#include <string.h>
117
118#include <openssl/buf.h>
119#include <openssl/evp.h>
120#include <openssl/mem.h>
121#include <openssl/md5.h>
122#include <openssl/obj.h>
123#include <openssl/rand.h>
124#include <openssl/sha.h>
125#include <openssl/x509.h>
126
127#include "ssl_locl.h"
128
129/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
130int ssl3_do_write(SSL *s, int type)
131	{
132	int ret;
133
134	ret=ssl3_write_bytes(s,type,&s->init_buf->data[s->init_off],
135	                     s->init_num);
136	if (ret < 0) return(-1);
137	if (type == SSL3_RT_HANDSHAKE)
138		/* should not be done for 'Hello Request's, but in that case
139		 * we'll ignore the result anyway */
140		ssl3_finish_mac(s,(unsigned char *)&s->init_buf->data[s->init_off],ret);
141
142	if (ret == s->init_num)
143		{
144		if (s->msg_callback)
145			s->msg_callback(1, s->version, type, s->init_buf->data, (size_t)(s->init_off + s->init_num), s, s->msg_callback_arg);
146		return(1);
147		}
148	s->init_off+=ret;
149	s->init_num-=ret;
150	return(0);
151	}
152
153int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
154	{
155	unsigned char *p;
156	int i;
157	unsigned long l;
158
159	if (s->state == a)
160		{
161		p = ssl_handshake_start(s);
162
163		i=s->method->ssl3_enc->final_finish_mac(s,
164			sender,slen,s->s3->tmp.finish_md);
165		if (i == 0)
166			return 0;
167		s->s3->tmp.finish_md_len = i;
168		memcpy(p, s->s3->tmp.finish_md, i);
169		l=i;
170
171                /* Log the master secret, if logging is enabled. */
172                if (!ssl_ctx_log_master_secret(s->ctx,
173				s->s3->client_random, SSL3_RANDOM_SIZE,
174				s->session->master_key, s->session->master_key_length))
175			{
176			return 0;
177			}
178
179                /* Copy the finished so we can use it for
180                   renegotiation checks */
181                if(s->type == SSL_ST_CONNECT)
182                        {
183                         assert(i <= EVP_MAX_MD_SIZE);
184                         memcpy(s->s3->previous_client_finished,
185                             s->s3->tmp.finish_md, i);
186                         s->s3->previous_client_finished_len=i;
187                        }
188                else
189                        {
190                        assert(i <= EVP_MAX_MD_SIZE);
191                        memcpy(s->s3->previous_server_finished,
192                            s->s3->tmp.finish_md, i);
193                        s->s3->previous_server_finished_len=i;
194                        }
195
196		ssl_set_handshake_header(s, SSL3_MT_FINISHED, l);
197		s->state=b;
198		}
199
200	/* SSL3_ST_SEND_xxxxxx_HELLO_B */
201	return ssl_do_write(s);
202	}
203
204/* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen to far. */
205static void ssl3_take_mac(SSL *s)
206	{
207	const char *sender;
208	int slen;
209	/* If no new cipher setup return immediately: other functions will
210	 * set the appropriate error.
211	 */
212	if (s->s3->tmp.new_cipher == NULL)
213		return;
214	if (s->state & SSL_ST_CONNECT)
215		{
216		sender=s->method->ssl3_enc->server_finished_label;
217		slen=s->method->ssl3_enc->server_finished_label_len;
218		}
219	else
220		{
221		sender=s->method->ssl3_enc->client_finished_label;
222		slen=s->method->ssl3_enc->client_finished_label_len;
223		}
224
225	s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
226		sender,slen,s->s3->tmp.peer_finish_md);
227	}
228
229int ssl3_get_finished(SSL *s, int a, int b)
230	{
231	int al,i,ok;
232	long n;
233	unsigned char *p;
234
235	n=s->method->ssl_get_message(s,
236		a,
237		b,
238		SSL3_MT_FINISHED,
239		64, /* should actually be 36+4 :-) */
240		SSL_GET_MESSAGE_DONT_HASH_MESSAGE,
241		&ok);
242
243	if (!ok) return((int)n);
244
245	/* Snapshot the finished hash before incorporating the new message. */
246	ssl3_take_mac(s);
247	ssl3_hash_current_message(s);
248
249	/* If this occurs, we have missed a message.
250	 * TODO(davidben): Is this check now redundant with
251	 * SSL3_FLAGS_EXPECT_CCS? */
252	if (!s->s3->change_cipher_spec)
253		{
254		al=SSL_AD_UNEXPECTED_MESSAGE;
255		OPENSSL_PUT_ERROR(SSL, ssl3_get_finished, SSL_R_GOT_A_FIN_BEFORE_A_CCS);
256		goto f_err;
257		}
258	s->s3->change_cipher_spec=0;
259
260	p = s->init_msg;
261	i = s->s3->tmp.peer_finish_md_len;
262
263	if (i != n)
264		{
265		al=SSL_AD_DECODE_ERROR;
266		OPENSSL_PUT_ERROR(SSL, ssl3_get_finished, SSL_R_BAD_DIGEST_LENGTH);
267		goto f_err;
268		}
269
270	if (CRYPTO_memcmp(p, s->s3->tmp.peer_finish_md, i) != 0)
271		{
272		al=SSL_AD_DECRYPT_ERROR;
273		OPENSSL_PUT_ERROR(SSL, ssl3_get_finished, SSL_R_DIGEST_CHECK_FAILED);
274		goto f_err;
275		}
276
277        /* Copy the finished so we can use it for
278           renegotiation checks */
279        if(s->type == SSL_ST_ACCEPT)
280                {
281                assert(i <= EVP_MAX_MD_SIZE);
282                memcpy(s->s3->previous_client_finished,
283                    s->s3->tmp.peer_finish_md, i);
284                s->s3->previous_client_finished_len=i;
285                }
286        else
287                {
288                assert(i <= EVP_MAX_MD_SIZE);
289                memcpy(s->s3->previous_server_finished,
290                    s->s3->tmp.peer_finish_md, i);
291                s->s3->previous_server_finished_len=i;
292                }
293
294	return(1);
295f_err:
296	ssl3_send_alert(s,SSL3_AL_FATAL,al);
297	return(0);
298	}
299
300/* for these 2 messages, we need to
301 * ssl->enc_read_ctx			re-init
302 * ssl->s3->read_sequence		zero
303 * ssl->s3->read_mac_secret		re-init
304 * ssl->session->read_sym_enc		assign
305 * ssl->session->read_compression	assign
306 * ssl->session->read_hash		assign
307 */
308int ssl3_send_change_cipher_spec(SSL *s, int a, int b)
309	{
310	unsigned char *p;
311
312	if (s->state == a)
313		{
314		p=(unsigned char *)s->init_buf->data;
315		*p=SSL3_MT_CCS;
316		s->init_num=1;
317		s->init_off=0;
318
319		s->state=b;
320		}
321
322	/* SSL3_ST_CW_CHANGE_B */
323	return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
324	}
325
326unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
327	{
328	unsigned char *p;
329	unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s);
330
331	if (!ssl_add_cert_chain(s, cpk, &l))
332		return 0;
333
334	l -= 3 + SSL_HM_HEADER_LENGTH(s);
335	p = ssl_handshake_start(s);
336	l2n3(l,p);
337	l += 3;
338	ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l);
339	return l + SSL_HM_HEADER_LENGTH(s);
340	}
341
342/* Obtain handshake message of message type 'mt' (any if mt == -1),
343 * maximum acceptable body length 'max'.
344 * The first four bytes (msg_type and length) are read in state 'st1',
345 * the body is read in state 'stn'.
346 */
347long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int hash_message, int *ok)
348	{
349	unsigned char *p;
350	unsigned long l;
351	long n;
352	int i,al;
353
354	if (s->s3->tmp.reuse_message)
355		{
356		/* A SSL_GET_MESSAGE_DONT_HASH_MESSAGE call cannot be combined
357		 * with reuse_message; the SSL_GET_MESSAGE_DONT_HASH_MESSAGE
358		 * would have to have been applied to the previous call. */
359		assert(hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE);
360		s->s3->tmp.reuse_message=0;
361		if ((mt >= 0) && (s->s3->tmp.message_type != mt))
362			{
363			al=SSL_AD_UNEXPECTED_MESSAGE;
364			OPENSSL_PUT_ERROR(SSL, ssl3_get_message, SSL_R_UNEXPECTED_MESSAGE);
365			goto f_err;
366			}
367		*ok=1;
368		s->init_msg = (uint8_t*)s->init_buf->data + 4;
369		s->init_num = (int)s->s3->tmp.message_size;
370		return s->init_num;
371		}
372
373	p=(unsigned char *)s->init_buf->data;
374
375	if (s->state == st1) /* s->init_num < 4 */
376		{
377		int skip_message;
378
379		do
380			{
381			while (s->init_num < 4)
382				{
383				i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
384					&p[s->init_num],4 - s->init_num, 0);
385				if (i <= 0)
386					{
387					s->rwstate=SSL_READING;
388					*ok = 0;
389					return i;
390					}
391				s->init_num+=i;
392				}
393
394			skip_message = 0;
395			if (!s->server)
396				if (p[0] == SSL3_MT_HELLO_REQUEST)
397					/* The server may always send 'Hello Request' messages --
398					 * we are doing a handshake anyway now, so ignore them
399					 * if their format is correct. Does not count for
400					 * 'Finished' MAC. */
401					if (p[1] == 0 && p[2] == 0 &&p[3] == 0)
402						{
403						s->init_num = 0;
404						skip_message = 1;
405
406						if (s->msg_callback)
407							s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, 4, s, s->msg_callback_arg);
408						}
409			}
410		while (skip_message);
411
412		/* s->init_num == 4 */
413
414		if ((mt >= 0) && (*p != mt))
415			{
416			al=SSL_AD_UNEXPECTED_MESSAGE;
417			OPENSSL_PUT_ERROR(SSL, ssl3_get_message, SSL_R_UNEXPECTED_MESSAGE);
418			goto f_err;
419			}
420		if ((mt < 0) && (*p == SSL3_MT_CLIENT_HELLO) &&
421					(st1 == SSL3_ST_SR_CERT_A) &&
422					(stn == SSL3_ST_SR_CERT_B))
423			{
424			/* At this point we have got an MS SGC second client
425			 * hello (maybe we should always allow the client to
426			 * start a new handshake?). We need to restart the mac.
427			 * Don't increment {num,total}_renegotiations because
428			 * we have not completed the handshake. */
429			ssl3_init_finished_mac(s);
430			}
431
432		s->s3->tmp.message_type= *(p++);
433
434		n2l3(p,l);
435		if (l > (unsigned long)max)
436			{
437			al=SSL_AD_ILLEGAL_PARAMETER;
438			OPENSSL_PUT_ERROR(SSL, ssl3_get_message, SSL_R_EXCESSIVE_MESSAGE_SIZE);
439			goto f_err;
440			}
441		if (l > (INT_MAX-4)) /* BUF_MEM_grow takes an 'int' parameter */
442			{
443			al=SSL_AD_ILLEGAL_PARAMETER;
444			OPENSSL_PUT_ERROR(SSL, ssl3_get_message, SSL_R_EXCESSIVE_MESSAGE_SIZE);
445			goto f_err;
446			}
447		if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l+4))
448			{
449			OPENSSL_PUT_ERROR(SSL, ssl3_get_message, ERR_R_BUF_LIB);
450			goto err;
451			}
452		s->s3->tmp.message_size=l;
453		s->state=stn;
454
455		s->init_msg = (uint8_t*)s->init_buf->data + 4;
456		s->init_num = 0;
457		}
458
459	/* next state (stn) */
460	p = s->init_msg;
461	n = s->s3->tmp.message_size - s->init_num;
462	while (n > 0)
463		{
464		i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],n,0);
465		if (i <= 0)
466			{
467			s->rwstate=SSL_READING;
468			*ok = 0;
469			return i;
470			}
471		s->init_num += i;
472		n -= i;
473		}
474
475	/* Feed this message into MAC computation. */
476	if (hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE)
477		ssl3_hash_current_message(s);
478	if (s->msg_callback)
479		s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, s->msg_callback_arg);
480	*ok=1;
481	return s->init_num;
482f_err:
483	ssl3_send_alert(s,SSL3_AL_FATAL,al);
484err:
485	*ok=0;
486	return(-1);
487	}
488
489void ssl3_hash_current_message(SSL *s)
490	{
491	/* The handshake header (different size between DTLS and TLS) is included in the hash. */
492	size_t header_len = s->init_msg - (uint8_t *)s->init_buf->data;
493	ssl3_finish_mac(s, (uint8_t *)s->init_buf->data, s->init_num + header_len);
494	}
495
496/* ssl3_cert_verify_hash is documented as needing EVP_MAX_MD_SIZE because that
497 * is sufficient pre-TLS1.2 as well. */
498OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE > MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
499	combined_tls_hash_fits_in_max);
500
501int ssl3_cert_verify_hash(SSL *s, uint8_t *out, size_t *out_len, const EVP_MD **out_md, EVP_PKEY *pkey)
502	{
503	/* For TLS v1.2 send signature algorithm and signature using
504	 * agreed digest and cached handshake records. Otherwise, use
505	 * SHA1 or MD5 + SHA1 depending on key type.  */
506	if (SSL_USE_SIGALGS(s))
507		{
508		const uint8_t *hdata;
509		size_t hdatalen;
510		EVP_MD_CTX mctx;
511		unsigned len;
512
513		if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen))
514			{
515			OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_INTERNAL_ERROR);
516			return 0;
517			}
518		EVP_MD_CTX_init(&mctx);
519		if (!EVP_DigestInit_ex(&mctx, *out_md, NULL)
520			|| !EVP_DigestUpdate(&mctx, hdata, hdatalen)
521			|| !EVP_DigestFinal(&mctx, out, &len))
522			{
523			OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_EVP_LIB);
524			EVP_MD_CTX_cleanup(&mctx);
525			return 0;
526			}
527		*out_len = len;
528		}
529	else if (pkey->type == EVP_PKEY_RSA)
530		{
531		if (s->method->ssl3_enc->cert_verify_mac(s, NID_md5, out) == 0 ||
532			s->method->ssl3_enc->cert_verify_mac(s,
533				NID_sha1, out + MD5_DIGEST_LENGTH) == 0)
534			return 0;
535		*out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
536		/* Using a NULL signature MD makes EVP_PKEY_sign perform
537		 * a raw RSA signature, rather than wrapping in a
538		 * DigestInfo. */
539		*out_md = NULL;
540		}
541	else if (pkey->type == EVP_PKEY_EC)
542		{
543		if (s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, out) == 0)
544			return 0;
545		*out_len = SHA_DIGEST_LENGTH;
546		*out_md = EVP_sha1();
547		}
548	else
549		{
550		OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_INTERNAL_ERROR);
551		return 0;
552		}
553	return 1;
554	}
555
556int ssl_cert_type(X509 *x, EVP_PKEY *pkey)
557	{
558	EVP_PKEY *pk;
559	int ret= -1,i;
560
561	if (pkey == NULL)
562		pk=X509_get_pubkey(x);
563	else
564		pk=pkey;
565	if (pk == NULL) goto err;
566
567	i=pk->type;
568	if (i == EVP_PKEY_RSA)
569		{
570		ret=SSL_PKEY_RSA_ENC;
571		}
572	else if (i == EVP_PKEY_EC)
573		{
574		ret = SSL_PKEY_ECC;
575		}
576
577err:
578	if(!pkey) EVP_PKEY_free(pk);
579	return(ret);
580	}
581
582int ssl_verify_alarm_type(long type)
583	{
584	int al;
585
586	switch(type)
587		{
588	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
589	case X509_V_ERR_UNABLE_TO_GET_CRL:
590	case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
591		al=SSL_AD_UNKNOWN_CA;
592		break;
593	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
594	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
595	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
596	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
597	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
598	case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
599	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
600	case X509_V_ERR_CERT_NOT_YET_VALID:
601	case X509_V_ERR_CRL_NOT_YET_VALID:
602	case X509_V_ERR_CERT_UNTRUSTED:
603	case X509_V_ERR_CERT_REJECTED:
604		al=SSL_AD_BAD_CERTIFICATE;
605		break;
606	case X509_V_ERR_CERT_SIGNATURE_FAILURE:
607	case X509_V_ERR_CRL_SIGNATURE_FAILURE:
608		al=SSL_AD_DECRYPT_ERROR;
609		break;
610	case X509_V_ERR_CERT_HAS_EXPIRED:
611	case X509_V_ERR_CRL_HAS_EXPIRED:
612		al=SSL_AD_CERTIFICATE_EXPIRED;
613		break;
614	case X509_V_ERR_CERT_REVOKED:
615		al=SSL_AD_CERTIFICATE_REVOKED;
616		break;
617	case X509_V_ERR_OUT_OF_MEM:
618		al=SSL_AD_INTERNAL_ERROR;
619		break;
620	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
621	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
622	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
623	case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
624	case X509_V_ERR_CERT_CHAIN_TOO_LONG:
625	case X509_V_ERR_PATH_LENGTH_EXCEEDED:
626	case X509_V_ERR_INVALID_CA:
627		al=SSL_AD_UNKNOWN_CA;
628		break;
629	case X509_V_ERR_APPLICATION_VERIFICATION:
630		al=SSL_AD_HANDSHAKE_FAILURE;
631		break;
632	case X509_V_ERR_INVALID_PURPOSE:
633		al=SSL_AD_UNSUPPORTED_CERTIFICATE;
634		break;
635	default:
636		al=SSL_AD_CERTIFICATE_UNKNOWN;
637		break;
638		}
639	return(al);
640	}
641
642int ssl3_setup_read_buffer(SSL *s)
643	{
644	unsigned char *p;
645	size_t len,align=0,headerlen;
646
647	if (SSL_IS_DTLS(s))
648		headerlen = DTLS1_RT_HEADER_LENGTH;
649	else
650		headerlen = SSL3_RT_HEADER_LENGTH;
651
652#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
653	align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1);
654#endif
655
656	if (s->s3->rbuf.buf == NULL)
657		{
658		len = SSL3_RT_MAX_PLAIN_LENGTH
659			+ SSL3_RT_MAX_ENCRYPTED_OVERHEAD
660			+ headerlen + align;
661		if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
662			{
663			s->s3->init_extra = 1;
664			len += SSL3_RT_MAX_EXTRA;
665			}
666		if ((p=OPENSSL_malloc(len)) == NULL)
667			goto err;
668		s->s3->rbuf.buf = p;
669		s->s3->rbuf.len = len;
670		}
671
672	s->packet= &(s->s3->rbuf.buf[0]);
673	return 1;
674
675err:
676	OPENSSL_PUT_ERROR(SSL, ssl3_setup_read_buffer, ERR_R_MALLOC_FAILURE);
677	return 0;
678	}
679
680int ssl3_setup_write_buffer(SSL *s)
681	{
682	unsigned char *p;
683	size_t len,align=0,headerlen;
684
685	if (SSL_IS_DTLS(s))
686		headerlen = DTLS1_RT_HEADER_LENGTH + 1;
687	else
688		headerlen = SSL3_RT_HEADER_LENGTH;
689
690#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
691	align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1);
692#endif
693
694	if (s->s3->wbuf.buf == NULL)
695		{
696		len = s->max_send_fragment
697			+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
698			+ headerlen + align;
699		/* Account for 1/n-1 record splitting. */
700		if (s->mode & SSL_MODE_CBC_RECORD_SPLITTING)
701			len += headerlen + align + 1
702				+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
703
704		if ((p=OPENSSL_malloc(len)) == NULL)
705			goto err;
706		s->s3->wbuf.buf = p;
707		s->s3->wbuf.len = len;
708		}
709
710	return 1;
711
712err:
713	OPENSSL_PUT_ERROR(SSL, ssl3_setup_write_buffer, ERR_R_MALLOC_FAILURE);
714	return 0;
715	}
716
717
718int ssl3_setup_buffers(SSL *s)
719	{
720	if (!ssl3_setup_read_buffer(s))
721		return 0;
722	if (!ssl3_setup_write_buffer(s))
723		return 0;
724	return 1;
725	}
726
727int ssl3_release_write_buffer(SSL *s)
728	{
729	if (s->s3->wbuf.buf != NULL)
730		{
731		OPENSSL_free(s->s3->wbuf.buf);
732		s->s3->wbuf.buf = NULL;
733		}
734	return 1;
735	}
736
737int ssl3_release_read_buffer(SSL *s)
738	{
739	if (s->s3->rbuf.buf != NULL)
740		{
741		OPENSSL_free(s->s3->rbuf.buf);
742		s->s3->rbuf.buf = NULL;
743		}
744	return 1;
745	}
746
747