Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 00352 static 00353 const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 00354 BAD, BAD, BAD, BAD, BAD, BAD, BAD, 00355 10, 11, 12, 13, 14, 15, /* upper case A-F */ 00356 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 00357 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 00358 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 00359 BAD, BAD, /* G - ` */ 00360 10, 11, 12, 13, 14, 15 /* lower case a-f */ 00361 }; /* A starts at 0x41 not 0x3A */ 00362 00363 int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) 00364 { 00365 word32 inIdx = 0; 00366 word32 outIdx = 0; 00367 00368 if (inLen == 1 && *outLen && in) { 00369 byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */ 00370 00371 /* sanity check */ 00372 if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) 00373 return ASN_INPUT_E; 00374 00375 b = hexDecode[b]; 00376 00377 if (b == BAD) 00378 return ASN_INPUT_E; 00379 00380 out[outIdx++] = b; 00381 00382 *outLen = outIdx; 00383 return 0; 00384 } 00385 00386 if (inLen % 2) 00387 return BAD_FUNC_ARG; 00388 00389 if (*outLen < (inLen / 2)) 00390 return BAD_FUNC_ARG; 00391 00392 while (inLen) { 00393 byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */ 00394 byte b2 = in[inIdx++] - 0x30; 00395 00396 /* sanity checks */ 00397 if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) 00398 return ASN_INPUT_E; 00399 if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0])) 00400 return ASN_INPUT_E; 00401 00402 b = hexDecode[b]; 00403 b2 = hexDecode[b2]; 00404 00405 if (b == BAD || b2 == BAD) 00406 return ASN_INPUT_E; 00407 00408 out[outIdx++] = (byte)((b << 4) | b2); 00409 inLen -= 2; 00410 } 00411 00412 *outLen = outIdx; 00413 return 0; 00414 } 00415 00416 int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen) 00417 { 00418 word32 outIdx = 0; 00419 word32 i; 00420 byte hb, lb; 00421 00422 if (*outLen < (2 * inLen + 1)) 00423 return BAD_FUNC_ARG; 00424 00425 for (i = 0; i < inLen; i++) { 00426 hb = in[i] >> 4; 00427 lb = in[i] & 0x0f; 00428 00429 /* ASCII value */ 00430 hb += '0'; 00431 if (hb > '9') 00432 hb += 7; 00433 00434 /* ASCII value */ 00435 lb += '0'; 00436 if (lb>'9') 00437 lb += 7; 00438 00439 out[outIdx++] = hb; 00440 out[outIdx++] = lb; 00441 } 00442 00443 /* force 0 at this end */ 00444 out[outIdx++] = 0; 00445 00446 *outLen = outIdx; 00447 return 0; 00448 } 00449 00450 #endif /* (OPENSSL_EXTRA) || (HAVE_WEBSERVER) || (HAVE_FIPS) */ 00451 00452 #endif /* NO_CODING */ 00453
Generated on Tue Jul 12 2022 15:55:18 by
1.7.2