155714Skris/* ssl/s2_pkt.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296465Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296465Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296465Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296465Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296465Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5772616Skris */
5872616Skris/* ====================================================================
5989840Skris * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
6055949Skris *
6172616Skris * Redistribution and use in source and binary forms, with or without
6272616Skris * modification, are permitted provided that the following conditions
6372616Skris * are met:
6472616Skris *
6572616Skris * 1. Redistributions of source code must retain the above copyright
66296465Sdelphij *    notice, this list of conditions and the following disclaimer.
6772616Skris *
6872616Skris * 2. Redistributions in binary form must reproduce the above copyright
6972616Skris *    notice, this list of conditions and the following disclaimer in
7072616Skris *    the documentation and/or other materials provided with the
7172616Skris *    distribution.
7272616Skris *
7372616Skris * 3. All advertising materials mentioning features or use of this
7472616Skris *    software must display the following acknowledgment:
7572616Skris *    "This product includes software developed by the OpenSSL Project
7672616Skris *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
7772616Skris *
7872616Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
7972616Skris *    endorse or promote products derived from this software without
8072616Skris *    prior written permission. For written permission, please contact
8172616Skris *    openssl-core@openssl.org.
8272616Skris *
8372616Skris * 5. Products derived from this software may not be called "OpenSSL"
8472616Skris *    nor may "OpenSSL" appear in their names without prior written
8572616Skris *    permission of the OpenSSL Project.
8672616Skris *
8772616Skris * 6. Redistributions of any form whatsoever must retain the following
8872616Skris *    acknowledgment:
8972616Skris *    "This product includes software developed by the OpenSSL Project
9072616Skris *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
9172616Skris *
9272616Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
9372616Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9472616Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
9572616Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
9672616Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9772616Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
9872616Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
9972616Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10072616Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
10172616Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10272616Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10372616Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
10472616Skris * ====================================================================
10572616Skris *
10672616Skris * This product includes cryptographic software written by Eric Young
10772616Skris * (eay@cryptsoft.com).  This product includes software written by Tim
10872616Skris * Hudson (tjh@cryptsoft.com).
10972616Skris *
11055714Skris */
11155714Skris
11259194Skris#include "ssl_locl.h"
113110007Smarkm#ifndef OPENSSL_NO_SSL2
114296465Sdelphij# include <stdio.h>
115296465Sdelphij# include <errno.h>
116296465Sdelphij# define USE_SOCKETS
11755714Skris
118296465Sdelphijstatic int read_n(SSL *s, unsigned int n, unsigned int max,
119296465Sdelphij                  unsigned int extend);
12055714Skrisstatic int do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len);
12155714Skrisstatic int write_pending(SSL *s, const unsigned char *buf, unsigned int len);
12255714Skrisstatic int ssl_mt_error(int n);
12355714Skris
124296465Sdelphij/*
125296465Sdelphij * SSL 2.0 imlementation for SSL_read/SSL_peek - This routine will return 0
126296465Sdelphij * to len bytes, decrypted etc if required.
12755714Skris */
12872616Skrisstatic int ssl2_read_internal(SSL *s, void *buf, int len, int peek)
129296465Sdelphij{
130296465Sdelphij    int n;
131296465Sdelphij    unsigned char mac[MAX_MAC_SIZE];
132296465Sdelphij    unsigned char *p;
133296465Sdelphij    int i;
134296465Sdelphij    unsigned int mac_size;
13555714Skris
13672616Skris ssl2_read_again:
137296465Sdelphij    if (SSL_in_init(s) && !s->in_handshake) {
138296465Sdelphij        n = s->handshake_func(s);
139296465Sdelphij        if (n < 0)
140296465Sdelphij            return (n);
141296465Sdelphij        if (n == 0) {
142296465Sdelphij            SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_SSL_HANDSHAKE_FAILURE);
143296465Sdelphij            return (-1);
144296465Sdelphij        }
145296465Sdelphij    }
14655714Skris
147296465Sdelphij    clear_sys_error();
148296465Sdelphij    s->rwstate = SSL_NOTHING;
149296465Sdelphij    if (len <= 0)
150296465Sdelphij        return (len);
15155714Skris
152296465Sdelphij    if (s->s2->ract_data_length != 0) { /* read from buffer */
153296465Sdelphij        if (len > s->s2->ract_data_length)
154296465Sdelphij            n = s->s2->ract_data_length;
155296465Sdelphij        else
156296465Sdelphij            n = len;
15755714Skris
158296465Sdelphij        memcpy(buf, s->s2->ract_data, (unsigned int)n);
159296465Sdelphij        if (!peek) {
160296465Sdelphij            s->s2->ract_data_length -= n;
161296465Sdelphij            s->s2->ract_data += n;
162296465Sdelphij            if (s->s2->ract_data_length == 0)
163296465Sdelphij                s->rstate = SSL_ST_READ_HEADER;
164296465Sdelphij        }
16572616Skris
166296465Sdelphij        return (n);
167296465Sdelphij    }
16855714Skris
169296465Sdelphij    /*
170296465Sdelphij     * s->s2->ract_data_length == 0 Fill the buffer, then goto
171296465Sdelphij     * ssl2_read_again.
172296465Sdelphij     */
17372616Skris
174296465Sdelphij    if (s->rstate == SSL_ST_READ_HEADER) {
175296465Sdelphij        if (s->first_packet) {
176296465Sdelphij            n = read_n(s, 5, SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER + 2, 0);
177296465Sdelphij            if (n <= 0)
178296465Sdelphij                return (n);     /* error or non-blocking */
179296465Sdelphij            s->first_packet = 0;
180296465Sdelphij            p = s->packet;
181296465Sdelphij            if (!((p[0] & 0x80) && ((p[2] == SSL2_MT_CLIENT_HELLO) ||
182296465Sdelphij                                    (p[2] == SSL2_MT_SERVER_HELLO)))) {
183296465Sdelphij                SSLerr(SSL_F_SSL2_READ_INTERNAL,
184296465Sdelphij                       SSL_R_NON_SSLV2_INITIAL_PACKET);
185296465Sdelphij                return (-1);
186296465Sdelphij            }
187296465Sdelphij        } else {
188296465Sdelphij            n = read_n(s, 2, SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER + 2, 0);
189296465Sdelphij            if (n <= 0)
190296465Sdelphij                return (n);     /* error or non-blocking */
191296465Sdelphij        }
192296465Sdelphij        /* part read stuff */
19355714Skris
194296465Sdelphij        s->rstate = SSL_ST_READ_BODY;
195296465Sdelphij        p = s->packet;
196296465Sdelphij        /* Do header */
197296465Sdelphij        /*
198296465Sdelphij         * s->s2->padding=0;
199296465Sdelphij         */
200296465Sdelphij        s->s2->escape = 0;
201296465Sdelphij        s->s2->rlength = (((unsigned int)p[0]) << 8) | ((unsigned int)p[1]);
202296465Sdelphij        if ((p[0] & TWO_BYTE_BIT)) { /* Two byte header? */
203296465Sdelphij            s->s2->three_byte_header = 0;
204296465Sdelphij            s->s2->rlength &= TWO_BYTE_MASK;
205296465Sdelphij        } else {
206296465Sdelphij            s->s2->three_byte_header = 1;
207296465Sdelphij            s->s2->rlength &= THREE_BYTE_MASK;
20855714Skris
209296465Sdelphij            /* security >s2->escape */
210296465Sdelphij            s->s2->escape = ((p[0] & SEC_ESC_BIT)) ? 1 : 0;
211296465Sdelphij        }
212296465Sdelphij    }
21355714Skris
214296465Sdelphij    if (s->rstate == SSL_ST_READ_BODY) {
215296465Sdelphij        n = s->s2->rlength + 2 + s->s2->three_byte_header;
216296465Sdelphij        if (n > (int)s->packet_length) {
217296465Sdelphij            n -= s->packet_length;
218296465Sdelphij            i = read_n(s, (unsigned int)n, (unsigned int)n, 1);
219296465Sdelphij            if (i <= 0)
220296465Sdelphij                return (i);     /* ERROR */
221296465Sdelphij        }
22255714Skris
223296465Sdelphij        p = &(s->packet[2]);
224296465Sdelphij        s->rstate = SSL_ST_READ_HEADER;
225296465Sdelphij        if (s->s2->three_byte_header)
226296465Sdelphij            s->s2->padding = *(p++);
227296465Sdelphij        else
228296465Sdelphij            s->s2->padding = 0;
22955714Skris
230296465Sdelphij        /* Data portion */
231296465Sdelphij        if (s->s2->clear_text) {
232296465Sdelphij            mac_size = 0;
233296465Sdelphij            s->s2->mac_data = p;
234296465Sdelphij            s->s2->ract_data = p;
235296465Sdelphij            if (s->s2->padding) {
236296465Sdelphij                SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_ILLEGAL_PADDING);
237296465Sdelphij                return (-1);
238296465Sdelphij            }
239296465Sdelphij        } else {
240296465Sdelphij            mac_size = EVP_MD_size(s->read_hash);
241296465Sdelphij            OPENSSL_assert(mac_size <= MAX_MAC_SIZE);
242296465Sdelphij            s->s2->mac_data = p;
243296465Sdelphij            s->s2->ract_data = &p[mac_size];
244296465Sdelphij            if (s->s2->padding + mac_size > s->s2->rlength) {
245296465Sdelphij                SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_ILLEGAL_PADDING);
246296465Sdelphij                return (-1);
247296465Sdelphij            }
248296465Sdelphij        }
24955714Skris
250296465Sdelphij        s->s2->ract_data_length = s->s2->rlength;
251296465Sdelphij        /*
252296465Sdelphij         * added a check for length > max_size in case encryption was not
253296465Sdelphij         * turned on yet due to an error
254296465Sdelphij         */
255296465Sdelphij        if ((!s->s2->clear_text) && (s->s2->rlength >= mac_size)) {
256296465Sdelphij            ssl2_enc(s, 0);
257296465Sdelphij            s->s2->ract_data_length -= mac_size;
258296465Sdelphij            ssl2_mac(s, mac, 0);
259296465Sdelphij            s->s2->ract_data_length -= s->s2->padding;
260296465Sdelphij            if ((CRYPTO_memcmp(mac, s->s2->mac_data, mac_size) != 0) ||
261296465Sdelphij                (s->s2->rlength %
262296465Sdelphij                 EVP_CIPHER_CTX_block_size(s->enc_read_ctx) != 0)) {
263296465Sdelphij                SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_BAD_MAC_DECODE);
264296465Sdelphij                return (-1);
265296465Sdelphij            }
266296465Sdelphij        }
267296465Sdelphij        INC32(s->s2->read_sequence); /* expect next number */
268296465Sdelphij        /* s->s2->ract_data is now available for processing */
26955714Skris
270296465Sdelphij        /*
271296465Sdelphij         * Possibly the packet that we just read had 0 actual data bytes.
272296465Sdelphij         * (SSLeay/OpenSSL itself never sends such packets; see ssl2_write.)
273296465Sdelphij         * In this case, returning 0 would be interpreted by the caller as
274296465Sdelphij         * indicating EOF, so it's not a good idea.  Instead, we just
275296465Sdelphij         * continue reading; thus ssl2_read_internal may have to process
276296465Sdelphij         * multiple packets before it can return. [Note that using select()
277296465Sdelphij         * for blocking sockets *never* guarantees that the next SSL_read
278296465Sdelphij         * will not block -- the available data may contain incomplete
279296465Sdelphij         * packets, and except for SSL 2, renegotiation can confuse things
280296465Sdelphij         * even more.]
281296465Sdelphij         */
28255714Skris
283296465Sdelphij        goto ssl2_read_again;   /* This should really be "return
284296465Sdelphij                                 * ssl2_read(s,buf,len)", but that would
285296465Sdelphij                                 * allow for denial-of-service attacks if a C
286296465Sdelphij                                 * compiler is used that does not recognize
287296465Sdelphij                                 * end-recursion. */
288296465Sdelphij    } else {
289296465Sdelphij        SSLerr(SSL_F_SSL2_READ_INTERNAL, SSL_R_BAD_STATE);
290296465Sdelphij        return (-1);
291296465Sdelphij    }
292296465Sdelphij}
29355714Skris
29472616Skrisint ssl2_read(SSL *s, void *buf, int len)
295296465Sdelphij{
296296465Sdelphij    return ssl2_read_internal(s, buf, len, 0);
297296465Sdelphij}
29872616Skris
29976870Skrisint ssl2_peek(SSL *s, void *buf, int len)
300296465Sdelphij{
301296465Sdelphij    return ssl2_read_internal(s, buf, len, 1);
302296465Sdelphij}
30372616Skris
30455714Skrisstatic int read_n(SSL *s, unsigned int n, unsigned int max,
305296465Sdelphij                  unsigned int extend)
306296465Sdelphij{
307296465Sdelphij    int i, off, newb;
30855714Skris
309296465Sdelphij    /*
310296465Sdelphij     * if there is stuff still in the buffer from a previous read, and there
311296465Sdelphij     * is more than we want, take some.
312296465Sdelphij     */
313296465Sdelphij    if (s->s2->rbuf_left >= (int)n) {
314296465Sdelphij        if (extend)
315296465Sdelphij            s->packet_length += n;
316296465Sdelphij        else {
317296465Sdelphij            s->packet = &(s->s2->rbuf[s->s2->rbuf_offs]);
318296465Sdelphij            s->packet_length = n;
319296465Sdelphij        }
320296465Sdelphij        s->s2->rbuf_left -= n;
321296465Sdelphij        s->s2->rbuf_offs += n;
322296465Sdelphij        return (n);
323296465Sdelphij    }
32455714Skris
325296465Sdelphij    if (!s->read_ahead)
326296465Sdelphij        max = n;
327296465Sdelphij    if (max > (unsigned int)(SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER + 2))
328296465Sdelphij        max = SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER + 2;
32955714Skris
330296465Sdelphij    /*
331296465Sdelphij     * Else we want more than we have. First, if there is some left or we
332296465Sdelphij     * want to extend
333296465Sdelphij     */
334296465Sdelphij    off = 0;
335296465Sdelphij    if ((s->s2->rbuf_left != 0) || ((s->packet_length != 0) && extend)) {
336296465Sdelphij        newb = s->s2->rbuf_left;
337296465Sdelphij        if (extend) {
338296465Sdelphij            off = s->packet_length;
339296465Sdelphij            if (s->packet != s->s2->rbuf)
340296465Sdelphij                memcpy(s->s2->rbuf, s->packet, (unsigned int)newb + off);
341296465Sdelphij        } else if (s->s2->rbuf_offs != 0) {
342296465Sdelphij            memcpy(s->s2->rbuf, &(s->s2->rbuf[s->s2->rbuf_offs]),
343296465Sdelphij                   (unsigned int)newb);
344296465Sdelphij            s->s2->rbuf_offs = 0;
345296465Sdelphij        }
346296465Sdelphij        s->s2->rbuf_left = 0;
347296465Sdelphij    } else
348296465Sdelphij        newb = 0;
34955714Skris
350296465Sdelphij    /*
351296465Sdelphij     * off is the offset to start writing too. r->s2->rbuf_offs is the
352296465Sdelphij     * 'unread data', now 0. newb is the number of new bytes so far
353296465Sdelphij     */
354296465Sdelphij    s->packet = s->s2->rbuf;
355296465Sdelphij    while (newb < (int)n) {
356296465Sdelphij        clear_sys_error();
357296465Sdelphij        if (s->rbio != NULL) {
358296465Sdelphij            s->rwstate = SSL_READING;
359296465Sdelphij            i = BIO_read(s->rbio, (char *)&(s->s2->rbuf[off + newb]),
360296465Sdelphij                         max - newb);
361296465Sdelphij        } else {
362296465Sdelphij            SSLerr(SSL_F_READ_N, SSL_R_READ_BIO_NOT_SET);
363296465Sdelphij            i = -1;
364296465Sdelphij        }
365296465Sdelphij# ifdef PKT_DEBUG
366296465Sdelphij        if (s->debug & 0x01)
367296465Sdelphij            sleep(1);
368296465Sdelphij# endif
369296465Sdelphij        if (i <= 0) {
370296465Sdelphij            s->s2->rbuf_left += newb;
371296465Sdelphij            return (i);
372296465Sdelphij        }
373296465Sdelphij        newb += i;
374296465Sdelphij    }
37555714Skris
376296465Sdelphij    /* record unread data */
377296465Sdelphij    if (newb > (int)n) {
378296465Sdelphij        s->s2->rbuf_offs = n + off;
379296465Sdelphij        s->s2->rbuf_left = newb - n;
380296465Sdelphij    } else {
381296465Sdelphij        s->s2->rbuf_offs = 0;
382296465Sdelphij        s->s2->rbuf_left = 0;
383296465Sdelphij    }
384296465Sdelphij    if (extend)
385296465Sdelphij        s->packet_length += n;
386296465Sdelphij    else
387296465Sdelphij        s->packet_length = n;
388296465Sdelphij    s->rwstate = SSL_NOTHING;
389296465Sdelphij    return (n);
390296465Sdelphij}
39155714Skris
39255714Skrisint ssl2_write(SSL *s, const void *_buf, int len)
393296465Sdelphij{
394296465Sdelphij    const unsigned char *buf = _buf;
395296465Sdelphij    unsigned int n, tot;
396296465Sdelphij    int i;
39755714Skris
398296465Sdelphij    if (SSL_in_init(s) && !s->in_handshake) {
399296465Sdelphij        i = s->handshake_func(s);
400296465Sdelphij        if (i < 0)
401296465Sdelphij            return (i);
402296465Sdelphij        if (i == 0) {
403296465Sdelphij            SSLerr(SSL_F_SSL2_WRITE, SSL_R_SSL_HANDSHAKE_FAILURE);
404296465Sdelphij            return (-1);
405296465Sdelphij        }
406296465Sdelphij    }
40755714Skris
408296465Sdelphij    if (s->error) {
409296465Sdelphij        ssl2_write_error(s);
410296465Sdelphij        if (s->error)
411296465Sdelphij            return (-1);
412296465Sdelphij    }
41355714Skris
414296465Sdelphij    clear_sys_error();
415296465Sdelphij    s->rwstate = SSL_NOTHING;
416296465Sdelphij    if (len <= 0)
417296465Sdelphij        return (len);
41855714Skris
419296465Sdelphij    tot = s->s2->wnum;
420296465Sdelphij    s->s2->wnum = 0;
42155714Skris
422296465Sdelphij    n = (len - tot);
423296465Sdelphij    for (;;) {
424296465Sdelphij        i = do_ssl_write(s, &(buf[tot]), n);
425296465Sdelphij        if (i <= 0) {
426296465Sdelphij            s->s2->wnum = tot;
427296465Sdelphij            return (i);
428296465Sdelphij        }
429296465Sdelphij        if ((i == (int)n) || (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE)) {
430296465Sdelphij            return (tot + i);
431296465Sdelphij        }
43255714Skris
433296465Sdelphij        n -= i;
434296465Sdelphij        tot += i;
435296465Sdelphij    }
436296465Sdelphij}
437296465Sdelphij
43855714Skrisstatic int write_pending(SSL *s, const unsigned char *buf, unsigned int len)
439296465Sdelphij{
440296465Sdelphij    int i;
44155714Skris
442296465Sdelphij    /* s->s2->wpend_len != 0 MUST be true. */
44355714Skris
444296465Sdelphij    /*
445296465Sdelphij     * check that they have given us the same buffer to write
446296465Sdelphij     */
447296465Sdelphij    if ((s->s2->wpend_tot > (int)len) ||
448296465Sdelphij        ((s->s2->wpend_buf != buf) &&
449296465Sdelphij         !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER))) {
450296465Sdelphij        SSLerr(SSL_F_WRITE_PENDING, SSL_R_BAD_WRITE_RETRY);
451296465Sdelphij        return (-1);
452296465Sdelphij    }
45355714Skris
454296465Sdelphij    for (;;) {
455296465Sdelphij        clear_sys_error();
456296465Sdelphij        if (s->wbio != NULL) {
457296465Sdelphij            s->rwstate = SSL_WRITING;
458296465Sdelphij            i = BIO_write(s->wbio,
459296465Sdelphij                          (char *)&(s->s2->write_ptr[s->s2->wpend_off]),
460296465Sdelphij                          (unsigned int)s->s2->wpend_len);
461296465Sdelphij        } else {
462296465Sdelphij            SSLerr(SSL_F_WRITE_PENDING, SSL_R_WRITE_BIO_NOT_SET);
463296465Sdelphij            i = -1;
464296465Sdelphij        }
465296465Sdelphij# ifdef PKT_DEBUG
466296465Sdelphij        if (s->debug & 0x01)
467296465Sdelphij            sleep(1);
468296465Sdelphij# endif
469296465Sdelphij        if (i == s->s2->wpend_len) {
470296465Sdelphij            s->s2->wpend_len = 0;
471296465Sdelphij            s->rwstate = SSL_NOTHING;
472296465Sdelphij            return (s->s2->wpend_ret);
473296465Sdelphij        } else if (i <= 0)
474296465Sdelphij            return (i);
475296465Sdelphij        s->s2->wpend_off += i;
476296465Sdelphij        s->s2->wpend_len -= i;
477296465Sdelphij    }
478296465Sdelphij}
47955714Skris
48055714Skrisstatic int do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len)
481296465Sdelphij{
482296465Sdelphij    unsigned int j, k, olen, p, mac_size, bs;
483296465Sdelphij    register unsigned char *pp;
48455714Skris
485296465Sdelphij    olen = len;
48655714Skris
487296465Sdelphij    /*
488296465Sdelphij     * first check if there is data from an encryption waiting to be sent -
489296465Sdelphij     * it must be sent because the other end is waiting. This will happen
490296465Sdelphij     * with non-blocking IO.  We print it and then return.
491296465Sdelphij     */
492296465Sdelphij    if (s->s2->wpend_len != 0)
493296465Sdelphij        return (write_pending(s, buf, len));
49455714Skris
495296465Sdelphij    /* set mac_size to mac size */
496296465Sdelphij    if (s->s2->clear_text)
497296465Sdelphij        mac_size = 0;
498296465Sdelphij    else
499296465Sdelphij        mac_size = EVP_MD_size(s->write_hash);
50055714Skris
501296465Sdelphij    /* lets set the pad p */
502296465Sdelphij    if (s->s2->clear_text) {
503296465Sdelphij        if (len > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
504296465Sdelphij            len = SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
505296465Sdelphij        p = 0;
506296465Sdelphij        s->s2->three_byte_header = 0;
507296465Sdelphij        /* len=len; */
508296465Sdelphij    } else {
509296465Sdelphij        bs = EVP_CIPHER_CTX_block_size(s->enc_read_ctx);
510296465Sdelphij        j = len + mac_size;
511296465Sdelphij        /*
512296465Sdelphij         * Two-byte headers allow for a larger record length than three-byte
513296465Sdelphij         * headers, but we can't use them if we need padding or if we have to
514296465Sdelphij         * set the escape bit.
515296465Sdelphij         */
516296465Sdelphij        if ((j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER) && (!s->s2->escape)) {
517296465Sdelphij            if (j > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
518296465Sdelphij                j = SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER;
519296465Sdelphij            /*
520296465Sdelphij             * set k to the max number of bytes with 2 byte header
521296465Sdelphij             */
522296465Sdelphij            k = j - (j % bs);
523296465Sdelphij            /* how many data bytes? */
524296465Sdelphij            len = k - mac_size;
525296465Sdelphij            s->s2->three_byte_header = 0;
526296465Sdelphij            p = 0;
527296465Sdelphij        } else if ((bs <= 1) && (!s->s2->escape)) {
528296465Sdelphij            /*-
529296465Sdelphij             * j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER, thus
530296465Sdelphij             * j < SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER
531296465Sdelphij             */
532296465Sdelphij            s->s2->three_byte_header = 0;
533296465Sdelphij            p = 0;
534296465Sdelphij        } else {                /* we may have to use a 3 byte header */
53572616Skris
536296465Sdelphij            /*-
537296465Sdelphij             * If s->s2->escape is not set, then
538296465Sdelphij             * j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER, and thus
539296465Sdelphij             * j < SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER.
540296465Sdelphij             */
541296465Sdelphij            p = (j % bs);
542296465Sdelphij            p = (p == 0) ? 0 : (bs - p);
543296465Sdelphij            if (s->s2->escape) {
544296465Sdelphij                s->s2->three_byte_header = 1;
545296465Sdelphij                if (j > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
546296465Sdelphij                    j = SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER;
547296465Sdelphij            } else
548296465Sdelphij                s->s2->three_byte_header = (p == 0) ? 0 : 1;
549296465Sdelphij        }
550296465Sdelphij    }
55172616Skris
552296465Sdelphij    /*-
553296465Sdelphij     * Now
554296465Sdelphij     *      j <= SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER
555296465Sdelphij     * holds, and if s->s2->three_byte_header is set, then even
556296465Sdelphij     *      j <= SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER.
557296465Sdelphij     */
55855714Skris
559296465Sdelphij    /*
560296465Sdelphij     * mac_size is the number of MAC bytes len is the number of data bytes we
561296465Sdelphij     * are going to send p is the number of padding bytes (if it is a
562296465Sdelphij     * two-byte header, then p == 0)
563296465Sdelphij     */
56455714Skris
565296465Sdelphij    s->s2->wlength = len;
566296465Sdelphij    s->s2->padding = p;
567296465Sdelphij    s->s2->mac_data = &(s->s2->wbuf[3]);
568296465Sdelphij    s->s2->wact_data = &(s->s2->wbuf[3 + mac_size]);
569296465Sdelphij    /* we copy the data into s->s2->wbuf */
570296465Sdelphij    memcpy(s->s2->wact_data, buf, len);
571296465Sdelphij    if (p)
572296465Sdelphij        memset(&(s->s2->wact_data[len]), 0, p); /* arbitrary padding */
57355714Skris
574296465Sdelphij    if (!s->s2->clear_text) {
575296465Sdelphij        s->s2->wact_data_length = len + p;
576296465Sdelphij        ssl2_mac(s, s->s2->mac_data, 1);
577296465Sdelphij        s->s2->wlength += p + mac_size;
578296465Sdelphij        ssl2_enc(s, 1);
579296465Sdelphij    }
58055714Skris
581296465Sdelphij    /* package up the header */
582296465Sdelphij    s->s2->wpend_len = s->s2->wlength;
583296465Sdelphij    if (s->s2->three_byte_header) { /* 3 byte header */
584296465Sdelphij        pp = s->s2->mac_data;
585296465Sdelphij        pp -= 3;
586296465Sdelphij        pp[0] = (s->s2->wlength >> 8) & (THREE_BYTE_MASK >> 8);
587296465Sdelphij        if (s->s2->escape)
588296465Sdelphij            pp[0] |= SEC_ESC_BIT;
589296465Sdelphij        pp[1] = s->s2->wlength & 0xff;
590296465Sdelphij        pp[2] = s->s2->padding;
591296465Sdelphij        s->s2->wpend_len += 3;
592296465Sdelphij    } else {
593296465Sdelphij        pp = s->s2->mac_data;
594296465Sdelphij        pp -= 2;
595296465Sdelphij        pp[0] = ((s->s2->wlength >> 8) & (TWO_BYTE_MASK >> 8)) | TWO_BYTE_BIT;
596296465Sdelphij        pp[1] = s->s2->wlength & 0xff;
597296465Sdelphij        s->s2->wpend_len += 2;
598296465Sdelphij    }
599296465Sdelphij    s->s2->write_ptr = pp;
60055714Skris
601296465Sdelphij    INC32(s->s2->write_sequence); /* expect next number */
60255714Skris
603296465Sdelphij    /* lets try to actually write the data */
604296465Sdelphij    s->s2->wpend_tot = olen;
605296465Sdelphij    s->s2->wpend_buf = buf;
60655714Skris
607296465Sdelphij    s->s2->wpend_ret = len;
608296465Sdelphij
609296465Sdelphij    s->s2->wpend_off = 0;
610296465Sdelphij    return (write_pending(s, buf, olen));
611296465Sdelphij}
612296465Sdelphij
61355714Skrisint ssl2_part_read(SSL *s, unsigned long f, int i)
614296465Sdelphij{
615296465Sdelphij    unsigned char *p;
616296465Sdelphij    int j;
61755714Skris
618296465Sdelphij    if (i < 0) {
619296465Sdelphij        /* ssl2_return_error(s); */
620296465Sdelphij        /*
621296465Sdelphij         * for non-blocking io, this is not necessarily fatal
622296465Sdelphij         */
623296465Sdelphij        return (i);
624296465Sdelphij    } else {
625296465Sdelphij        s->init_num += i;
62689840Skris
627296465Sdelphij        /*
628296465Sdelphij         * Check for error.  While there are recoverable errors, this
629296465Sdelphij         * function is not called when those must be expected; any error
630296465Sdelphij         * detected here is fatal.
631296465Sdelphij         */
632296465Sdelphij        if (s->init_num >= 3) {
633296465Sdelphij            p = (unsigned char *)s->init_buf->data;
634296465Sdelphij            if (p[0] == SSL2_MT_ERROR) {
635296465Sdelphij                j = (p[1] << 8) | p[2];
636296465Sdelphij                SSLerr((int)f, ssl_mt_error(j));
637296465Sdelphij                s->init_num -= 3;
638296465Sdelphij                if (s->init_num > 0)
639296465Sdelphij                    memmove(p, p + 3, s->init_num);
640296465Sdelphij            }
641296465Sdelphij        }
64289840Skris
643296465Sdelphij        /*
644296465Sdelphij         * If it's not an error message, we have some error anyway -- the
645296465Sdelphij         * message was shorter than expected.  This too is treated as fatal
646296465Sdelphij         * (at least if SSL_get_error is asked for its opinion).
647296465Sdelphij         */
648296465Sdelphij        return (0);
649296465Sdelphij    }
650296465Sdelphij}
65155714Skris
65255714Skrisint ssl2_do_write(SSL *s)
653296465Sdelphij{
654296465Sdelphij    int ret;
65555714Skris
656296465Sdelphij    ret = ssl2_write(s, &s->init_buf->data[s->init_off], s->init_num);
657296465Sdelphij    if (ret == s->init_num) {
658296465Sdelphij        if (s->msg_callback)
659296465Sdelphij            s->msg_callback(1, s->version, 0, s->init_buf->data,
660296465Sdelphij                            (size_t)(s->init_off + s->init_num), s,
661296465Sdelphij                            s->msg_callback_arg);
662296465Sdelphij        return (1);
663296465Sdelphij    }
664296465Sdelphij    if (ret < 0)
665296465Sdelphij        return (-1);
666296465Sdelphij    s->init_off += ret;
667296465Sdelphij    s->init_num -= ret;
668296465Sdelphij    return (0);
669296465Sdelphij}
67055714Skris
67155714Skrisstatic int ssl_mt_error(int n)
672296465Sdelphij{
673296465Sdelphij    int ret;
67455714Skris
675296465Sdelphij    switch (n) {
676296465Sdelphij    case SSL2_PE_NO_CIPHER:
677296465Sdelphij        ret = SSL_R_PEER_ERROR_NO_CIPHER;
678296465Sdelphij        break;
679296465Sdelphij    case SSL2_PE_NO_CERTIFICATE:
680296465Sdelphij        ret = SSL_R_PEER_ERROR_NO_CERTIFICATE;
681296465Sdelphij        break;
682296465Sdelphij    case SSL2_PE_BAD_CERTIFICATE:
683296465Sdelphij        ret = SSL_R_PEER_ERROR_CERTIFICATE;
684296465Sdelphij        break;
685296465Sdelphij    case SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE:
686296465Sdelphij        ret = SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE;
687296465Sdelphij        break;
688296465Sdelphij    default:
689296465Sdelphij        ret = SSL_R_UNKNOWN_REMOTE_ERROR_TYPE;
690296465Sdelphij        break;
691296465Sdelphij    }
692296465Sdelphij    return (ret);
693296465Sdelphij}
694296465Sdelphij#else                           /* !OPENSSL_NO_SSL2 */
69555949Skris
69659194Skris# if PEDANTIC
697296465Sdelphijstatic void *dummy = &dummy;
69859194Skris# endif
69959194Skris
70055949Skris#endif
701