wolfSSL SSL/TLS library, support up to TLS1.3

Dependents:   CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more

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