LCOV - code coverage report
Current view: top level - third_party/openssl/crypto/evp - encode.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 68 142 47.9 %
Date: 2015-10-10 Functions: 4 8 50.0 %

          Line data    Source code
       1             : /* crypto/evp/encode.c */
       2             : /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
       3             :  * All rights reserved.
       4             :  *
       5             :  * This package is an SSL implementation written
       6             :  * by Eric Young (eay@cryptsoft.com).
       7             :  * The implementation was written so as to conform with Netscapes SSL.
       8             :  *
       9             :  * This library is free for commercial and non-commercial use as long as
      10             :  * the following conditions are aheared to.  The following conditions
      11             :  * apply to all code found in this distribution, be it the RC4, RSA,
      12             :  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
      13             :  * included with this distribution is covered by the same copyright terms
      14             :  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
      15             :  *
      16             :  * Copyright remains Eric Young's, and as such any Copyright notices in
      17             :  * the code are not to be removed.
      18             :  * If this package is used in a product, Eric Young should be given attribution
      19             :  * as the author of the parts of the library used.
      20             :  * This can be in the form of a textual message at program startup or
      21             :  * in documentation (online or textual) provided with the package.
      22             :  *
      23             :  * Redistribution and use in source and binary forms, with or without
      24             :  * modification, are permitted provided that the following conditions
      25             :  * are met:
      26             :  * 1. Redistributions of source code must retain the copyright
      27             :  *    notice, this list of conditions and the following disclaimer.
      28             :  * 2. Redistributions in binary form must reproduce the above copyright
      29             :  *    notice, this list of conditions and the following disclaimer in the
      30             :  *    documentation and/or other materials provided with the distribution.
      31             :  * 3. All advertising materials mentioning features or use of this software
      32             :  *    must display the following acknowledgement:
      33             :  *    "This product includes cryptographic software written by
      34             :  *     Eric Young (eay@cryptsoft.com)"
      35             :  *    The word 'cryptographic' can be left out if the rouines from the library
      36             :  *    being used are not cryptographic related :-).
      37             :  * 4. If you include any Windows specific code (or a derivative thereof) from
      38             :  *    the apps directory (application code) you must include an acknowledgement:
      39             :  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
      40             :  *
      41             :  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
      42             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      43             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      44             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      45             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      46             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      47             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      48             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      49             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      50             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      51             :  * SUCH DAMAGE.
      52             :  *
      53             :  * The licence and distribution terms for any publically available version or
      54             :  * derivative of this code cannot be changed.  i.e. this code cannot simply be
      55             :  * copied and put under another distribution licence
      56             :  * [including the GNU Public Licence.]
      57             :  */
      58             : 
      59             : #include <stdio.h>
      60             : #include "cryptlib.h"
      61             : #include <openssl/evp.h>
      62             : 
      63             : #ifndef CHARSET_EBCDIC
      64             : # define conv_bin2ascii(a)       (data_bin2ascii[(a)&0x3f])
      65             : # define conv_ascii2bin(a)       (data_ascii2bin[(a)&0x7f])
      66             : #else
      67             : /*
      68             :  * We assume that PEM encoded files are EBCDIC files (i.e., printable text
      69             :  * files). Convert them here while decoding. When encoding, output is EBCDIC
      70             :  * (text) format again. (No need for conversion in the conv_bin2ascii macro,
      71             :  * as the underlying textstring data_bin2ascii[] is already EBCDIC)
      72             :  */
      73             : # define conv_bin2ascii(a)       (data_bin2ascii[(a)&0x3f])
      74             : # define conv_ascii2bin(a)       (data_ascii2bin[os_toascii[a]&0x7f])
      75             : #endif
      76             : 
      77             : /*-
      78             :  * 64 char lines
      79             :  * pad input with 0
      80             :  * left over chars are set to =
      81             :  * 1 byte  => xx==
      82             :  * 2 bytes => xxx=
      83             :  * 3 bytes => xxxx
      84             :  */
      85             : #define BIN_PER_LINE    (64/4*3)
      86             : #define CHUNKS_PER_LINE (64/4)
      87             : #define CHAR_PER_LINE   (64+1)
      88             : 
      89             : static const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
      90             : abcdefghijklmnopqrstuvwxyz0123456789+/";
      91             : 
      92             : /*-
      93             :  * 0xF0 is a EOLN
      94             :  * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
      95             :  * 0xF2 is EOF
      96             :  * 0xE0 is ignore at start of line.
      97             :  * 0xFF is error
      98             :  */
      99             : 
     100             : #define B64_EOLN                0xF0
     101             : #define B64_CR                  0xF1
     102             : #define B64_EOF                 0xF2
     103             : #define B64_WS                  0xE0
     104             : #define B64_ERROR               0xFF
     105             : #define B64_NOT_BASE64(a)       (((a)|0x13) == 0xF3)
     106             : 
     107             : static const unsigned char data_ascii2bin[128] = {
     108             :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     109             :     0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
     110             :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     111             :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     112             :     0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     113             :     0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
     114             :     0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
     115             :     0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
     116             :     0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
     117             :     0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
     118             :     0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
     119             :     0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     120             :     0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
     121             :     0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
     122             :     0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
     123             :     0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     124             : };
     125             : 
     126           0 : void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
     127             : {
     128           0 :     ctx->length = 48;
     129           0 :     ctx->num = 0;
     130           0 :     ctx->line_num = 0;
     131           0 : }
     132             : 
     133           0 : void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
     134             :                       const unsigned char *in, int inl)
     135             : {
     136             :     int i, j;
     137             :     unsigned int total = 0;
     138             : 
     139           0 :     *outl = 0;
     140           0 :     if (inl <= 0)
     141             :         return;
     142           0 :     OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
     143           0 :     if ((ctx->num + inl) < ctx->length) {
     144           0 :         memcpy(&(ctx->enc_data[ctx->num]), in, inl);
     145           0 :         ctx->num += inl;
     146           0 :         return;
     147             :     }
     148           0 :     if (ctx->num != 0) {
     149           0 :         i = ctx->length - ctx->num;
     150           0 :         memcpy(&(ctx->enc_data[ctx->num]), in, i);
     151           0 :         in += i;
     152           0 :         inl -= i;
     153           0 :         j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
     154           0 :         ctx->num = 0;
     155           0 :         out += j;
     156           0 :         *(out++) = '\n';
     157           0 :         *out = '\0';
     158           0 :         total = j + 1;
     159             :     }
     160           0 :     while (inl >= ctx->length) {
     161           0 :         j = EVP_EncodeBlock(out, in, ctx->length);
     162           0 :         in += ctx->length;
     163           0 :         inl -= ctx->length;
     164           0 :         out += j;
     165           0 :         *(out++) = '\n';
     166           0 :         *out = '\0';
     167           0 :         total += j + 1;
     168             :     }
     169           0 :     if (inl != 0)
     170           0 :         memcpy(&(ctx->enc_data[0]), in, inl);
     171           0 :     ctx->num = inl;
     172           0 :     *outl = total;
     173             : }
     174             : 
     175           0 : void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
     176             : {
     177             :     unsigned int ret = 0;
     178             : 
     179           0 :     if (ctx->num != 0) {
     180           0 :         ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
     181           0 :         out[ret++] = '\n';
     182           0 :         out[ret] = '\0';
     183           0 :         ctx->num = 0;
     184             :     }
     185           0 :     *outl = ret;
     186           0 : }
     187             : 
     188           0 : int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
     189             : {
     190             :     int i, ret = 0;
     191             :     unsigned long l;
     192             : 
     193           0 :     for (i = dlen; i > 0; i -= 3) {
     194           0 :         if (i >= 3) {
     195           0 :             l = (((unsigned long)f[0]) << 16L) |
     196           0 :                 (((unsigned long)f[1]) << 8L) | f[2];
     197           0 :             *(t++) = conv_bin2ascii(l >> 18L);
     198           0 :             *(t++) = conv_bin2ascii(l >> 12L);
     199           0 :             *(t++) = conv_bin2ascii(l >> 6L);
     200           0 :             *(t++) = conv_bin2ascii(l);
     201             :         } else {
     202           0 :             l = ((unsigned long)f[0]) << 16L;
     203           0 :             if (i == 2)
     204           0 :                 l |= ((unsigned long)f[1] << 8L);
     205             : 
     206           0 :             *(t++) = conv_bin2ascii(l >> 18L);
     207           0 :             *(t++) = conv_bin2ascii(l >> 12L);
     208           0 :             *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L);
     209           0 :             *(t++) = '=';
     210             :         }
     211           0 :         ret += 4;
     212           0 :         f += 3;
     213             :     }
     214             : 
     215           0 :     *t = '\0';
     216           0 :     return (ret);
     217             : }
     218             : 
     219        1761 : void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
     220             : {
     221        1761 :     ctx->length = 30;
     222        1761 :     ctx->num = 0;
     223        1761 :     ctx->line_num = 0;
     224        1761 :     ctx->expect_nl = 0;
     225        1761 : }
     226             : 
     227             : /*-
     228             :  * -1 for error
     229             :  *  0 for last line
     230             :  *  1 for full line
     231             :  */
     232        1761 : int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
     233             :                      const unsigned char *in, int inl)
     234             : {
     235             :     int seof = -1, eof = 0, rv = -1, ret = 0, i, v, tmp, n, ln, exp_nl;
     236             :     unsigned char *d;
     237             : 
     238        1761 :     n = ctx->num;
     239        1761 :     d = ctx->enc_data;
     240        1761 :     ln = ctx->line_num;
     241        1761 :     exp_nl = ctx->expect_nl;
     242             : 
     243             :     /* last line of input. */
     244        1761 :     if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF))) {
     245             :         rv = 0;
     246             :         goto end;
     247             :     }
     248             : 
     249             :     /* We parse the input data */
     250     1491564 :     for (i = 0; i < inl; i++) {
     251             :         /* If the current line is > 80 characters, scream a lot */
     252     1493313 :         if (ln >= 80) {
     253             :             rv = -1;
     254             :             goto end;
     255             :         }
     256             : 
     257             :         /* Get char and put it into the buffer */
     258     1493313 :         tmp = *(in++);
     259     1493313 :         v = conv_ascii2bin(tmp);
     260             :         /* only save the good data :-) */
     261     1493313 :         if (!B64_NOT_BASE64(v)) {
     262     1470844 :             OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
     263     1470844 :             d[n++] = tmp;
     264     1470844 :             ln++;
     265       22469 :         } else if (v == B64_ERROR) {
     266             :             rv = -1;
     267             :             goto end;
     268             :         }
     269             : 
     270             :         /*
     271             :          * have we seen a '=' which is 'definitly' the last input line.  seof
     272             :          * will point to the character that holds it. and eof will hold how
     273             :          * many characters to chop off.
     274             :          */
     275     1493313 :         if (tmp == '=') {
     276        2188 :             if (seof == -1)
     277             :                 seof = n;
     278        2188 :             eof++;
     279             :         }
     280             : 
     281     1493313 :         if (v == B64_CR) {
     282             :             ln = 0;
     283           0 :             if (exp_nl)
     284           0 :                 continue;
     285             :         }
     286             : 
     287             :         /* eoln */
     288     1493313 :         if (v == B64_EOLN) {
     289             :             ln = 0;
     290       22469 :             if (exp_nl) {
     291             :                 exp_nl = 0;
     292       21584 :                 continue;
     293             :             }
     294             :         }
     295             :         exp_nl = 0;
     296             : 
     297             :         /*
     298             :          * If we are at the end of input and it looks like a line, process
     299             :          * it.
     300             :          */
     301     1471729 :         if (((i + 1) == inl) && (((n & 3) == 0) || eof)) {
     302             :             v = B64_EOF;
     303             :             /*
     304             :              * In case things were given us in really small records (so two
     305             :              * '=' were given in separate updates), eof may contain the
     306             :              * incorrect number of ending bytes to skip, so let's redo the
     307             :              * count
     308             :              */
     309             :             eof = 0;
     310         885 :             if (d[n - 1] == '=')
     311             :                 eof++;
     312         885 :             if (d[n - 2] == '=')
     313         439 :                 eof++;
     314             :             /* There will never be more than two '=' */
     315             :         }
     316             : 
     317     1471729 :         if ((v == B64_EOF && (n & 3) == 0) || (n >= 64)) {
     318             :             /*
     319             :              * This is needed to work correctly on 64 byte input lines.  We
     320             :              * process the line and then need to accept the '\n'
     321             :              */
     322       23345 :             if ((v != B64_EOF) && (n >= 64))
     323             :                 exp_nl = 1;
     324       23345 :             if (n > 0) {
     325       23345 :                 v = EVP_DecodeBlock(out, d, n);
     326             :                 n = 0;
     327       23345 :                 if (v < 0) {
     328             :                     rv = 0;
     329             :                     goto end;
     330             :                 }
     331       23345 :                 if (eof > v) {
     332             :                     rv = -1;
     333             :                     goto end;
     334             :                 }
     335       23345 :                 ret += (v - eof);
     336             :             } else {
     337             :                 eof = 1;
     338             :                 v = 0;
     339             :             }
     340             : 
     341             :             /*
     342             :              * This is the case where we have had a short but valid input
     343             :              * line
     344             :              */
     345       23345 :             if ((v < ctx->length) && eof) {
     346             :                 rv = 0;
     347             :                 goto end;
     348             :             } else
     349       22472 :                 ctx->length = v;
     350             : 
     351       22472 :             if (seof >= 0) {
     352             :                 rv = 0;
     353             :                 goto end;
     354             :             }
     355       21596 :             out += v;
     356             :         }
     357             :     }
     358             :     rv = 1;
     359             :  end:
     360        1761 :     *outl = ret;
     361        1761 :     ctx->num = n;
     362        1761 :     ctx->line_num = ln;
     363        1761 :     ctx->expect_nl = exp_nl;
     364        1761 :     return (rv);
     365             : }
     366             : 
     367       23345 : int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
     368             : {
     369             :     int i, ret = 0, a, b, c, d;
     370             :     unsigned long l;
     371             : 
     372             :     /* trim white space from the start of the line. */
     373       46690 :     while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) {
     374           0 :         f++;
     375           0 :         n--;
     376             :     }
     377             : 
     378             :     /*
     379             :      * strip off stuff at the end of the line ascii2bin values B64_WS,
     380             :      * B64_EOLN, B64_EOLN and B64_EOF
     381             :      */
     382       23345 :     while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1]))))
     383           0 :         n--;
     384             : 
     385       23345 :     if (n % 4 != 0)
     386             :         return (-1);
     387             : 
     388      367711 :     for (i = 0; i < n; i += 4) {
     389      367711 :         a = conv_ascii2bin(*(f++));
     390      367711 :         b = conv_ascii2bin(*(f++));
     391      367711 :         c = conv_ascii2bin(*(f++));
     392      367711 :         d = conv_ascii2bin(*(f++));
     393      367711 :         if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80))
     394             :             return (-1);
     395     1103133 :         l = ((((unsigned long)a) << 18L) |
     396      735422 :              (((unsigned long)b) << 12L) |
     397      735422 :              (((unsigned long)c) << 6L) | (((unsigned long)d)));
     398      367711 :         *(t++) = (unsigned char)(l >> 16L) & 0xff;
     399      367711 :         *(t++) = (unsigned char)(l >> 8L) & 0xff;
     400      367711 :         *(t++) = (unsigned char)(l) & 0xff;
     401      367711 :         ret += 3;
     402             :     }
     403             :     return (ret);
     404             : }
     405             : 
     406        1761 : int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
     407             : {
     408             :     int i;
     409             : 
     410        1761 :     *outl = 0;
     411        1761 :     if (ctx->num != 0) {
     412           0 :         i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
     413           0 :         if (i < 0)
     414             :             return (-1);
     415           0 :         ctx->num = 0;
     416           0 :         *outl = i;
     417           0 :         return (1);
     418             :     } else
     419             :         return (1);
     420             : }
     421             : 
     422             : #ifdef undef
     423             : int EVP_DecodeValid(unsigned char *buf, int len)
     424             : {
     425             :     int i, num = 0, bad = 0;
     426             : 
     427             :     if (len == 0)
     428             :         return (-1);
     429             :     while (conv_ascii2bin(*buf) == B64_WS) {
     430             :         buf++;
     431             :         len--;
     432             :         if (len == 0)
     433             :             return (-1);
     434             :     }
     435             : 
     436             :     for (i = len; i >= 4; i -= 4) {
     437             :         if ((conv_ascii2bin(buf[0]) >= 0x40) ||
     438             :             (conv_ascii2bin(buf[1]) >= 0x40) ||
     439             :             (conv_ascii2bin(buf[2]) >= 0x40) ||
     440             :             (conv_ascii2bin(buf[3]) >= 0x40))
     441             :             return (-1);
     442             :         buf += 4;
     443             :         num += 1 + (buf[2] != '=') + (buf[3] != '=');
     444             :     }
     445             :     if ((i == 1) && (conv_ascii2bin(buf[0]) == B64_EOLN))
     446             :         return (num);
     447             :     if ((i == 2) && (conv_ascii2bin(buf[0]) == B64_EOLN) &&
     448             :         (conv_ascii2bin(buf[0]) == B64_EOLN))
     449             :         return (num);
     450             :     return (1);
     451             : }
     452             : #endif

Generated by: LCOV version 1.10