This is a port of cyaSSL 2.7.0.

Dependents:   CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers coding.c Source File

coding.c

00001 /* coding.c
00002  *
00003  * Copyright (C) 2006-2013 wolfSSL Inc.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * CyaSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023     #include <config.h>
00024 #endif
00025 
00026 #include <cyassl/ctaocrypt/settings.h>
00027 
00028 #ifndef NO_CODING
00029 
00030 #include <cyassl/ctaocrypt/coding.h>
00031 #include <cyassl/ctaocrypt/ctaoerror2.h>
00032 #include <cyassl/ctaocrypt/logging.h>
00033 
00034 
00035 enum {
00036     BAD         = 0xFF,  /* invalid encoding */
00037     PAD         = '=',
00038     PEM_LINE_SZ = 64
00039 };
00040 
00041 
00042 static
00043 const byte base64Decode[] = { 62, BAD, BAD, BAD, 63,   /* + starts at 0x2B */
00044                               52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
00045                               BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00046                               0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
00047                               10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
00048                               20, 21, 22, 23, 24, 25,
00049                               BAD, BAD, BAD, BAD, BAD, BAD,
00050                               26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
00051                               36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
00052                               46, 47, 48, 49, 50, 51
00053                             };
00054 
00055 
00056 int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
00057 {
00058     word32 i = 0;
00059     word32 j = 0;
00060     word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
00061     const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
00062 
00063     plainSz = (plainSz * 3 + 3) / 4;
00064     if (plainSz > *outLen) return BAD_FUNC_ARG;
00065 
00066     while (inLen > 3) {
00067         byte b1, b2, b3;
00068         byte e1 = in[j++];
00069         byte e2 = in[j++];
00070         byte e3 = in[j++];
00071         byte e4 = in[j++];
00072 
00073         int pad3 = 0;
00074         int pad4 = 0;
00075 
00076         if (e1 == 0)            /* end file 0's */
00077             break;
00078         if (e3 == PAD)
00079             pad3 = 1;
00080         if (e4 == PAD)
00081             pad4 = 1;
00082 
00083         if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
00084             CYASSL_MSG("Bad Base64 Decode data, too small");
00085             return ASN_INPUT_E;
00086         }
00087 
00088         if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
00089             CYASSL_MSG("Bad Base64 Decode data, too big");
00090             return ASN_INPUT_E;
00091         }
00092 
00093         e1 = base64Decode[e1 - 0x2B];
00094         e2 = base64Decode[e2 - 0x2B];
00095         e3 = (e3 == PAD) ? 0 : base64Decode[e3 - 0x2B];
00096         e4 = (e4 == PAD) ? 0 : base64Decode[e4 - 0x2B];
00097 
00098         b1 = (e1 << 2) | (e2 >> 4);
00099         b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
00100         b3 = ((e3 & 0x3) << 6) | e4;
00101 
00102         out[i++] = b1;
00103         if (!pad3)
00104             out[i++] = b2;
00105         if (!pad4)
00106             out[i++] = b3;
00107         else
00108             break;
00109         
00110         inLen -= 4;
00111         if (inLen && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) {
00112             byte endLine = in[j++];
00113             inLen--;
00114             while (inLen && endLine == ' ') {   /* allow trailing whitespace */
00115                 endLine = in[j++];
00116                 inLen--;
00117             }
00118             if (endLine == '\r') {
00119                 if (inLen) {
00120                     endLine = in[j++];
00121                     inLen--;
00122                 }
00123             }
00124             if (endLine != '\n') {
00125                 CYASSL_MSG("Bad end of line in Base64 Decode");
00126                 return ASN_INPUT_E;
00127             }
00128         }
00129     }
00130     *outLen = i;
00131 
00132     return 0;
00133 }
00134 
00135 
00136 #if defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER)
00137 
00138 static
00139 const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
00140                               'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
00141                               'U', 'V', 'W', 'X', 'Y', 'Z',
00142                               'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
00143                               'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
00144                               'u', 'v', 'w', 'x', 'y', 'z',
00145                               '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00146                               '+', '/'
00147                             };
00148 
00149 
00150 /* porting assistance from yaSSL by Raphael HUCK */
00151 int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
00152 {
00153     word32 i = 0,
00154            j = 0,
00155            n = 0;   /* new line counter */
00156 
00157     word32 outSz = (inLen + 3 - 1) / 3 * 4;
00158     outSz += (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ;  /* new lines */
00159 
00160     if (outSz > *outLen) return BAD_FUNC_ARG;
00161     
00162     while (inLen > 2) {
00163         byte b1 = in[j++];
00164         byte b2 = in[j++];
00165         byte b3 = in[j++];
00166 
00167         /* encoded idx */
00168         byte e1 = b1 >> 2;
00169         byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
00170         byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
00171         byte e4 = b3 & 0x3F;
00172 
00173         /* store */
00174         out[i++] = base64Encode[e1];
00175         out[i++] = base64Encode[e2];
00176         out[i++] = base64Encode[e3];
00177         out[i++] = base64Encode[e4];
00178 
00179         inLen -= 3;
00180 
00181         if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen)
00182             out[i++] = '\n';
00183     }
00184 
00185     /* last integral */
00186     if (inLen) {
00187         int twoBytes = (inLen == 2);
00188 
00189         byte b1 = in[j++];
00190         byte b2 = (twoBytes) ? in[j++] : 0;
00191 
00192         byte e1 = b1 >> 2;
00193         byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
00194         byte e3 =  (b2 & 0xF) << 2;
00195 
00196         out[i++] = base64Encode[e1];
00197         out[i++] = base64Encode[e2];
00198         out[i++] = (twoBytes) ? base64Encode[e3] : PAD;
00199         out[i++] = PAD;
00200     } 
00201 
00202     out[i++] = '\n';
00203     if (i != outSz)
00204         return ASN_INPUT_E; 
00205     *outLen = outSz;
00206 
00207     return 0; 
00208 }
00209 
00210 
00211 static
00212 const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
00213                            BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00214                            10, 11, 12, 13, 14, 15 
00215                          };  /* A starts at 0x41 not 0x3A */
00216 
00217 int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
00218 {
00219     word32 inIdx  = 0;
00220     word32 outIdx = 0;
00221 
00222     if (inLen == 1 && *outLen && in) {
00223         byte b = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
00224 
00225         /* sanity check */
00226         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
00227             return ASN_INPUT_E;
00228 
00229         b  = hexDecode[b];
00230 
00231         if (b == BAD)
00232             return ASN_INPUT_E;
00233         
00234         out[outIdx++] = b;
00235 
00236         *outLen = outIdx;
00237         return 0;
00238     }
00239 
00240     if (inLen % 2)
00241         return BAD_FUNC_ARG;
00242 
00243     if (*outLen < (inLen / 2))
00244         return BAD_FUNC_ARG;
00245 
00246     while (inLen) {
00247         byte b  = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
00248         byte b2 = in[inIdx++] - 0x30;
00249 
00250         /* sanity checks */
00251         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
00252             return ASN_INPUT_E;
00253         if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
00254             return ASN_INPUT_E;
00255 
00256         b  = hexDecode[b];
00257         b2 = hexDecode[b2];
00258 
00259         if (b == BAD || b2 == BAD)
00260             return ASN_INPUT_E;
00261         
00262         out[outIdx++] = (b << 4) | b2;
00263         inLen -= 2;
00264     }
00265 
00266     *outLen = outIdx;
00267     return 0;
00268 }
00269 
00270 
00271 #endif  /* defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER) */
00272 #endif /* NO_CODING */