enc_writ.c revision 306195
10SN/A/* crypto/des/enc_writ.c */
20SN/A/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30SN/A * All rights reserved.
40SN/A *
57636SN/A * This package is an SSL implementation written
67636SN/A * by Eric Young (eay@cryptsoft.com).
77636SN/A * The implementation was written so as to conform with Netscapes SSL.
87636SN/A *
97636SN/A * This library is free for commercial and non-commercial use as long as
107636SN/A * the following conditions are aheared to.  The following conditions
117636SN/A * apply to all code found in this distribution, be it the RC4, RSA,
127636SN/A * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
130SN/A * included with this distribution is covered by the same copyright terms
147636SN/A * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150SN/A *
167636SN/A * Copyright remains Eric Young's, and as such any Copyright notices in
177636SN/A * the code are not to be removed.
187636SN/A * If this package is used in a product, Eric Young should be given attribution
197636SN/A * as the author of the parts of the library used.
207636SN/A * This can be in the form of a textual message at program startup or
217636SN/A * in documentation (online or textual) provided with the package.
220SN/A *
230SN/A * Redistribution and use in source and binary forms, with or without
240SN/A * modification, are permitted provided that the following conditions
250SN/A * are met:
260SN/A * 1. Redistributions of source code must retain the copyright
270SN/A *    notice, this list of conditions and the following disclaimer.
280SN/A * 2. Redistributions in binary form must reproduce the above copyright
290SN/A *    notice, this list of conditions and the following disclaimer in the
300SN/A *    documentation and/or other materials provided with the distribution.
310SN/A * 3. All advertising materials mentioning features or use of this software
320SN/A *    must display the following acknowledgement:
330SN/A *    "This product includes cryptographic software written by
340SN/A *     Eric Young (eay@cryptsoft.com)"
350SN/A *    The word 'cryptographic' can be left out if the rouines from the library
360SN/A *    being used are not cryptographic related :-).
370SN/A * 4. If you include any Windows specific code (or a derivative thereof) from
380SN/A *    the apps directory (application code) you must include an acknowledgement:
390SN/A *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400SN/A *
410SN/A * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440SN/A * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
517475SN/A * SUCH DAMAGE.
520SN/A *
530SN/A * The licence and distribution terms for any publically available version or
540SN/A * derivative of this code cannot be changed.  i.e. this code cannot simply be
557475SN/A * copied and put under another distribution licence
560SN/A * [including the GNU Public Licence.]
570SN/A */
580SN/A
590SN/A#include <errno.h>
600SN/A#include <time.h>
610SN/A#include <stdio.h>
620SN/A#include "cryptlib.h"
630SN/A#include "des_locl.h"
640SN/A#include <openssl/rand.h>
657636SN/A
660SN/A/*-
670SN/A * WARNINGS:
680SN/A *
690SN/A *  -  The data format used by DES_enc_write() and DES_enc_read()
700SN/A *     has a cryptographic weakness: When asked to write more
710SN/A *     than MAXWRITE bytes, DES_enc_write will split the data
720SN/A *     into several chunks that are all encrypted
730SN/A *     using the same IV.  So don't use these functions unless you
740SN/A *     are sure you know what you do (in which case you might
750SN/A *     not want to use them anyway).
760SN/A *
770SN/A *  -  This code cannot handle non-blocking sockets.
780SN/A */
790SN/A
807636SN/Aint DES_enc_write(int fd, const void *_buf, int len,
817636SN/A                  DES_key_schedule *sched, DES_cblock *iv)
827636SN/A{
837636SN/A#if defined(OPENSSL_NO_POSIX_IO)
847636SN/A    return (-1);
857636SN/A#else
867636SN/A# ifdef _LIBC
877636SN/A    extern unsigned long time();
889883SN/A    extern int write();
899883SN/A# endif
909883SN/A    const unsigned char *buf = _buf;
919883SN/A    long rnum;
927636SN/A    int i, j, k, outnum;
937636SN/A    static unsigned char *outbuf = NULL;
947636SN/A    unsigned char shortbuf[8];
957636SN/A    unsigned char *p;
967636SN/A    const unsigned char *cp;
977636SN/A    static int start = 1;
987636SN/A
997636SN/A    if (len < 0)
1007636SN/A        return -1;
1017636SN/A
1027636SN/A    if (outbuf == NULL) {
1037636SN/A        outbuf = OPENSSL_malloc(BSIZE + HDRSIZE);
1047636SN/A        if (outbuf == NULL)
1057636SN/A            return (-1);
1067636SN/A    }
1077636SN/A    /*
1087636SN/A     * If we are sending less than 8 bytes, the same char will look the same
1097636SN/A     * if we don't pad it out with random bytes
1107636SN/A     */
1117636SN/A    if (start) {
1127636SN/A        start = 0;
1137636SN/A    }
1147636SN/A
1157636SN/A    /* lets recurse if we want to send the data in small chunks */
1167636SN/A    if (len > MAXWRITE) {
1177636SN/A        j = 0;
1187636SN/A        for (i = 0; i < len; i += k) {
1197636SN/A            k = DES_enc_write(fd, &(buf[i]),
1207636SN/A                              ((len - i) > MAXWRITE) ? MAXWRITE : (len - i),
1217636SN/A                              sched, iv);
1227636SN/A            if (k < 0)
1237636SN/A                return (k);
1247636SN/A            else
1257636SN/A                j += k;
1267636SN/A        }
1277636SN/A        return (j);
1287636SN/A    }
1297636SN/A
1307636SN/A    /* write length first */
1317636SN/A    p = outbuf;
1327636SN/A    l2n(len, p);
1337636SN/A
1347636SN/A    /* pad short strings */
1357636SN/A    if (len < 8) {
1367636SN/A        cp = shortbuf;
1377636SN/A        memcpy(shortbuf, buf, len);
1387636SN/A        if (RAND_bytes(shortbuf + len, 8 - len) <= 0) {
1397636SN/A            return -1;
1407636SN/A        }
1417636SN/A        rnum = 8;
1427636SN/A    } else {
1437636SN/A        cp = buf;
1447636SN/A        rnum = ((len + 7) / 8 * 8); /* round up to nearest eight */
1457636SN/A    }
1467636SN/A
1477636SN/A    if (DES_rw_mode & DES_PCBC_MODE)
1487636SN/A        DES_pcbc_encrypt(cp, &(outbuf[HDRSIZE]), (len < 8) ? 8 : len, sched,
1497636SN/A                         iv, DES_ENCRYPT);
1507636SN/A    else
1517636SN/A        DES_cbc_encrypt(cp, &(outbuf[HDRSIZE]), (len < 8) ? 8 : len, sched,
1527636SN/A                        iv, DES_ENCRYPT);
1537636SN/A
1547636SN/A    /* output */
1557636SN/A    outnum = rnum + HDRSIZE;
1567636SN/A
1577636SN/A    for (j = 0; j < outnum; j += i) {
1580SN/A        /*
1590SN/A         * eay 26/08/92 I was not doing writing from where we got up to.
1607636SN/A         */
1617636SN/A# ifndef _WIN32
1627636SN/A        i = write(fd, (void *)&(outbuf[j]), outnum - j);
1637636SN/A# else
1647636SN/A        i = _write(fd, (void *)&(outbuf[j]), outnum - j);
1650SN/A# endif
1667636SN/A        if (i == -1) {
1677636SN/A# ifdef EINTR
1687636SN/A            if (errno == EINTR)
1697636SN/A                i = 0;
1707636SN/A            else
1717636SN/A# endif
1727636SN/A                /*
1737636SN/A                 * This is really a bad error - very bad It will stuff-up
1740SN/A                 * both ends.
1757636SN/A                 */
1767636SN/A                return (-1);
1777636SN/A        }
1780SN/A    }
1797636SN/A
1807636SN/A    return (len);
1817636SN/A#endif                          /* OPENSSL_NO_POSIX_IO */
1827636SN/A}
1837636SN/A