wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

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-2016 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL 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  * wolfSSL 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfssl/wolfcrypt/settings.h>
00028 
00029 #ifndef NO_CODING
00030 
00031 #include <wolfssl/wolfcrypt/coding.h>
00032 #include <wolfssl/wolfcrypt/error-crypt.h>
00033 #include <wolfssl/wolfcrypt/logging.h>
00034 
00035 
00036 enum {
00037     BAD         = 0xFF,  /* invalid encoding */
00038     PAD         = '=',
00039     PEM_LINE_SZ = 64
00040 };
00041 
00042 
00043 static
00044 const byte base64Decode[] = { 62, BAD, BAD, BAD, 63,   /* + starts at 0x2B */
00045                               52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
00046                               BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00047                               0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
00048                               10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
00049                               20, 21, 22, 23, 24, 25,
00050                               BAD, BAD, BAD, BAD, BAD, BAD,
00051                               26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
00052                               36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
00053                               46, 47, 48, 49, 50, 51
00054                             };
00055 
00056 
00057 int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
00058 {
00059     word32 i = 0;
00060     word32 j = 0;
00061     word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
00062     const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
00063 
00064     plainSz = (plainSz * 3 + 3) / 4;
00065     if (plainSz > *outLen) return BAD_FUNC_ARG;
00066 
00067     while (inLen > 3) {
00068         byte b1, b2, b3;
00069         byte e1 = in[j++];
00070         byte e2 = in[j++];
00071         byte e3 = in[j++];
00072         byte e4 = in[j++];
00073 
00074         int pad3 = 0;
00075         int pad4 = 0;
00076 
00077         if (e1 == 0)            /* end file 0's */
00078             break;
00079         if (e3 == PAD)
00080             pad3 = 1;
00081         if (e4 == PAD)
00082             pad4 = 1;
00083 
00084         if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
00085             WOLFSSL_MSG("Bad Base64 Decode data, too small");
00086             return ASN_INPUT_E;
00087         }
00088 
00089         if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
00090             WOLFSSL_MSG("Bad Base64 Decode data, too big");
00091             return ASN_INPUT_E;
00092         }
00093 
00094         e1 = base64Decode[e1 - 0x2B];
00095         e2 = base64Decode[e2 - 0x2B];
00096         e3 = (e3 == PAD) ? 0 : base64Decode[e3 - 0x2B];
00097         e4 = (e4 == PAD) ? 0 : base64Decode[e4 - 0x2B];
00098 
00099         b1 = (byte)((e1 << 2) | (e2 >> 4));
00100         b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
00101         b3 = (byte)(((e3 & 0x3) << 6) | e4);
00102 
00103         out[i++] = b1;
00104         if (!pad3)
00105             out[i++] = b2;
00106         if (!pad4)
00107             out[i++] = b3;
00108         else
00109             break;
00110 
00111         inLen -= 4;
00112         if (inLen && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) {
00113             byte endLine = in[j++];
00114             inLen--;
00115             while (inLen && endLine == ' ') {   /* allow trailing whitespace */
00116                 endLine = in[j++];
00117                 inLen--;
00118             }
00119             if (endLine == '\r') {
00120                 if (inLen) {
00121                     endLine = in[j++];
00122                     inLen--;
00123                 }
00124             }
00125             if (endLine != '\n') {
00126                 WOLFSSL_MSG("Bad end of line in Base64 Decode");
00127                 return ASN_INPUT_E;
00128             }
00129         }
00130     }
00131     *outLen = i;
00132 
00133     return 0;
00134 }
00135 
00136 
00137 #if defined(WOLFSSL_BASE64_ENCODE)
00138 
00139 static
00140 const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
00141                               'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
00142                               'U', 'V', 'W', 'X', 'Y', 'Z',
00143                               'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
00144                               'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
00145                               'u', 'v', 'w', 'x', 'y', 'z',
00146                               '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00147                               '+', '/'
00148                             };
00149 
00150 
00151 /* make sure *i (idx) won't exceed max, store and possibly escape to out,
00152  * raw means use e w/o decode,  0 on success */
00153 static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max,
00154                   int raw, int getSzOnly)
00155 {
00156     int    doEscape = 0;
00157     word32 needed = 1;
00158     word32 idx = *i;
00159 
00160     byte basic;
00161     byte plus    = 0;
00162     byte equals  = 0;
00163     byte newline = 0;
00164 
00165     if (raw)
00166         basic = e;
00167     else
00168         basic = base64Encode[e];
00169 
00170     /* check whether to escape. Only escape for EncodeEsc */
00171     if (escaped == WC_ESC_NL_ENC) {
00172         switch ((char)basic) {
00173             case '+' :
00174                 plus     = 1;
00175                 doEscape = 1;
00176                 needed  += 2;
00177                 break;
00178             case '=' :
00179                 equals   = 1;
00180                 doEscape = 1;
00181                 needed  += 2;
00182                 break;
00183             case '\n' :
00184                 newline  = 1;
00185                 doEscape = 1;
00186                 needed  += 2;
00187                 break;
00188             default:
00189                 /* do nothing */
00190                 break;
00191         }
00192     }
00193 
00194     /* check size */
00195     if ( (idx+needed) > max && !getSzOnly) {
00196         WOLFSSL_MSG("Escape buffer max too small");
00197         return BUFFER_E;
00198     }
00199 
00200     /* store it */
00201     if (doEscape == 0) {
00202         if(getSzOnly)
00203             idx++;
00204         else
00205             out[idx++] = basic;
00206     }
00207     else {
00208         if(getSzOnly)
00209             idx+=3;
00210         else {
00211             out[idx++] = '%';  /* start escape */
00212 
00213             if (plus) {
00214                 out[idx++] = '2';
00215                 out[idx++] = 'B';
00216             }
00217             else if (equals) {
00218                 out[idx++] = '3';
00219                 out[idx++] = 'D';
00220             }
00221             else if (newline) {
00222                 out[idx++] = '0';
00223                 out[idx++] = 'A';
00224             }
00225         }
00226     }
00227     *i = idx;
00228 
00229     return 0;
00230 }
00231 
00232 
00233 /* internal worker, handles both escaped and normal line endings.
00234    If out buffer is NULL, will return sz needed in outLen */
00235 static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
00236                            word32* outLen, int escaped)
00237 {
00238     int    ret = 0;
00239     word32 i = 0,
00240            j = 0,
00241            n = 0;   /* new line counter */
00242 
00243     int    getSzOnly = (out == NULL);
00244 
00245     word32 outSz = (inLen + 3 - 1) / 3 * 4;
00246     word32 addSz = (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ;  /* new lines */
00247 
00248     if (escaped == WC_ESC_NL_ENC)
00249         addSz *= 3;   /* instead of just \n, we're doing %0A triplet */
00250     else if (escaped == WC_NO_NL_ENC)
00251         addSz = 0;    /* encode without \n */
00252 
00253     outSz += addSz;
00254 
00255     /* if escaped we can't predetermine size for one pass encoding, but
00256      * make sure we have enough if no escapes are in input
00257      * Also need to ensure outLen valid before dereference */
00258     if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG;
00259 
00260     while (inLen > 2) {
00261         byte b1 = in[j++];
00262         byte b2 = in[j++];
00263         byte b3 = in[j++];
00264 
00265         /* encoded idx */
00266         byte e1 = b1 >> 2;
00267         byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
00268         byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
00269         byte e4 = b3 & 0x3F;
00270 
00271         /* store */
00272         ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
00273         if (ret != 0) break;
00274         ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
00275         if (ret != 0) break;
00276         ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
00277         if (ret != 0) break;
00278         ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly);
00279         if (ret != 0) break;
00280 
00281         inLen -= 3;
00282 
00283         /* Insert newline after PEM_LINE_SZ, unless no \n requested */
00284         if (escaped != WC_NO_NL_ENC && (++n % (PEM_LINE_SZ/4)) == 0 && inLen){
00285             ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
00286             if (ret != 0) break;
00287         }
00288     }
00289 
00290     /* last integral */
00291     if (inLen && ret == 0) {
00292         int twoBytes = (inLen == 2);
00293 
00294         byte b1 = in[j++];
00295         byte b2 = (twoBytes) ? in[j++] : 0;
00296 
00297         byte e1 = b1 >> 2;
00298         byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
00299         byte e3 = (byte)((b2 & 0xF) << 2);
00300 
00301         ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
00302         if (ret == 0)
00303             ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
00304         if (ret == 0) {
00305             /* third */
00306             if (twoBytes)
00307                 ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
00308             else
00309                 ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
00310         }
00311         /* fourth always pad */
00312         if (ret == 0)
00313             ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
00314     }
00315 
00316     if (ret == 0 && escaped != WC_NO_NL_ENC)
00317         ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
00318 
00319     if (i != outSz && escaped != 1 && ret == 0)
00320         return ASN_INPUT_E;
00321 
00322     *outLen = i;
00323     if(ret == 0)
00324         return getSzOnly ? LENGTH_ONLY_E : 0;
00325     return ret;
00326 }
00327 
00328 
00329 /* Base64 Encode, PEM style, with \n line endings */
00330 int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
00331 {
00332     return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC);
00333 }
00334 
00335 
00336 /* Base64 Encode, with %0A escaped line endings instead of \n */
00337 int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen)
00338 {
00339     return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC);
00340 }
00341 
00342 int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen)
00343 {
00344     return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC);
00345 }
00346 
00347 #endif  /* defined(WOLFSSL_BASE64_ENCODE) */
00348 
00349 
00350 #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) \
00351                            || defined(HAVE_ECC_CDH)
00352 
00353 static
00354 const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
00355                            BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00356                            10, 11, 12, 13, 14, 15,  /* upper case A-F */
00357                            BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00358                            BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00359                            BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
00360                            BAD, BAD,  /* G - ` */
00361                            10, 11, 12, 13, 14, 15   /* lower case a-f */
00362                          };  /* A starts at 0x41 not 0x3A */
00363 
00364 int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
00365 {
00366     word32 inIdx  = 0;
00367     word32 outIdx = 0;
00368 
00369     if (in == NULL || out == NULL || outLen == NULL)
00370         return BAD_FUNC_ARG;
00371 
00372     if (inLen == 1 && *outLen && in) {
00373         byte b = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
00374 
00375         /* sanity check */
00376         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
00377             return ASN_INPUT_E;
00378 
00379         b  = hexDecode[b];
00380 
00381         if (b == BAD)
00382             return ASN_INPUT_E;
00383 
00384         out[outIdx++] = b;
00385 
00386         *outLen = outIdx;
00387         return 0;
00388     }
00389 
00390     if (inLen % 2)
00391         return BAD_FUNC_ARG;
00392 
00393     if (*outLen < (inLen / 2))
00394         return BAD_FUNC_ARG;
00395 
00396     while (inLen) {
00397         byte b  = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
00398         byte b2 = in[inIdx++] - 0x30;
00399 
00400         /* sanity checks */
00401         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
00402             return ASN_INPUT_E;
00403         if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
00404             return ASN_INPUT_E;
00405 
00406         b  = hexDecode[b];
00407         b2 = hexDecode[b2];
00408 
00409         if (b == BAD || b2 == BAD)
00410             return ASN_INPUT_E;
00411 
00412         out[outIdx++] = (byte)((b << 4) | b2);
00413         inLen -= 2;
00414     }
00415 
00416     *outLen = outIdx;
00417     return 0;
00418 }
00419 
00420 int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
00421 {
00422     word32 outIdx = 0;
00423     word32 i;
00424     byte   hb, lb;
00425 
00426     if (in == NULL || out == NULL || outLen == NULL)
00427         return BAD_FUNC_ARG;
00428 
00429     if (*outLen < (2 * inLen + 1))
00430         return BAD_FUNC_ARG;
00431 
00432     for (i = 0; i < inLen; i++) {
00433         hb = in[i] >> 4;
00434         lb = in[i] & 0x0f;
00435 
00436         /* ASCII value */
00437         hb += '0';
00438         if (hb > '9')
00439             hb += 7;
00440 
00441         /* ASCII value */
00442         lb += '0';
00443         if (lb>'9')
00444             lb += 7;
00445 
00446         out[outIdx++] = hb;
00447         out[outIdx++] = lb;
00448     }
00449 
00450     /* force 0 at this end */
00451     out[outIdx++] = 0;
00452 
00453     *outLen = outIdx;
00454     return 0;
00455 }
00456 
00457 #endif /* (OPENSSL_EXTRA) || (HAVE_WEBSERVER) || (HAVE_FIPS) */
00458 
00459 #endif /* NO_CODING */
00460