wolfSSL SSL/TLS library, support up to TLS1.3
Dependents: CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more
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
Generated on Tue Jul 12 2022 20:58:34 by 1.7.2