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.
Dependents: HTTPClient-SSL HTTPClient HTTPClient-SSL http_access ... more
coding.c
00001 /* coding.c 00002 * 00003 * Copyright (C) 2006-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/error-crypt.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 = (byte)((e1 << 2) | (e2 >> 4)); 00099 b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2)); 00100 b3 = (byte)(((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 /* make sure *i (idx) won't exceed max, store and possibly escape to out, 00151 * raw means use e w/o decode, 0 on success */ 00152 static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max, 00153 int raw) 00154 { 00155 int doEscape = 0; 00156 word32 needed = 1; 00157 word32 idx = *i; 00158 00159 byte basic; 00160 byte plus = 0; 00161 byte equals = 0; 00162 byte newline = 0; 00163 00164 if (raw) 00165 basic = e; 00166 else 00167 basic = base64Encode[e]; 00168 00169 /* check whether to escape */ 00170 if (escaped) { 00171 switch ((char)basic) { 00172 case '+' : 00173 plus = 1; 00174 doEscape = 1; 00175 needed += 2; 00176 break; 00177 case '=' : 00178 equals = 1; 00179 doEscape = 1; 00180 needed += 2; 00181 break; 00182 case '\n' : 00183 newline = 1; 00184 doEscape = 1; 00185 needed += 2; 00186 break; 00187 default: 00188 /* do nothing */ 00189 break; 00190 } 00191 } 00192 00193 /* check size */ 00194 if ( (idx+needed) > max) { 00195 CYASSL_MSG("Escape buffer max too small"); 00196 return BUFFER_E; 00197 } 00198 00199 /* store it */ 00200 if (doEscape == 0) { 00201 out[idx++] = basic; 00202 } 00203 else { 00204 out[idx++] = '%'; /* start escape */ 00205 00206 if (plus) { 00207 out[idx++] = '2'; 00208 out[idx++] = 'B'; 00209 } 00210 else if (equals) { 00211 out[idx++] = '3'; 00212 out[idx++] = 'D'; 00213 } 00214 else if (newline) { 00215 out[idx++] = '0'; 00216 out[idx++] = 'A'; 00217 } 00218 00219 } 00220 *i = idx; 00221 00222 return 0; 00223 } 00224 00225 00226 /* internal worker, handles both escaped and normal line endings */ 00227 static int DoBase64_Encode(const byte* in, word32 inLen, byte* out, 00228 word32* outLen, int escaped) 00229 { 00230 int ret = 0; 00231 word32 i = 0, 00232 j = 0, 00233 n = 0; /* new line counter */ 00234 00235 word32 outSz = (inLen + 3 - 1) / 3 * 4; 00236 word32 addSz = (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ; /* new lines */ 00237 00238 if (escaped) 00239 addSz *= 3; /* instead of just \n, we're doing %0A triplet */ 00240 00241 outSz += addSz; 00242 00243 /* if escaped we can't predetermine size for one pass encoding, but 00244 * make sure we have enough if no escapes are in input */ 00245 if (outSz > *outLen) return BAD_FUNC_ARG; 00246 00247 while (inLen > 2) { 00248 byte b1 = in[j++]; 00249 byte b2 = in[j++]; 00250 byte b3 = in[j++]; 00251 00252 /* encoded idx */ 00253 byte e1 = b1 >> 2; 00254 byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4)); 00255 byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6)); 00256 byte e4 = b3 & 0x3F; 00257 00258 /* store */ 00259 ret = CEscape(escaped, e1, out, &i, *outLen, 0); 00260 if (ret != 0) break; 00261 ret = CEscape(escaped, e2, out, &i, *outLen, 0); 00262 if (ret != 0) break; 00263 ret = CEscape(escaped, e3, out, &i, *outLen, 0); 00264 if (ret != 0) break; 00265 ret = CEscape(escaped, e4, out, &i, *outLen, 0); 00266 if (ret != 0) break; 00267 00268 inLen -= 3; 00269 00270 if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen) { 00271 ret = CEscape(escaped, '\n', out, &i, *outLen, 1); 00272 if (ret != 0) break; 00273 } 00274 } 00275 00276 /* last integral */ 00277 if (inLen && ret == 0) { 00278 int twoBytes = (inLen == 2); 00279 00280 byte b1 = in[j++]; 00281 byte b2 = (twoBytes) ? in[j++] : 0; 00282 00283 byte e1 = b1 >> 2; 00284 byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4)); 00285 byte e3 = (byte)((b2 & 0xF) << 2); 00286 00287 ret = CEscape(escaped, e1, out, &i, *outLen, 0); 00288 if (ret == 0) 00289 ret = CEscape(escaped, e2, out, &i, *outLen, 0); 00290 if (ret == 0) { 00291 /* third */ 00292 if (twoBytes) 00293 ret = CEscape(escaped, e3, out, &i, *outLen, 0); 00294 else 00295 ret = CEscape(escaped, '=', out, &i, *outLen, 1); 00296 } 00297 /* fourth always pad */ 00298 if (ret == 0) 00299 ret = CEscape(escaped, '=', out, &i, *outLen, 1); 00300 } 00301 00302 if (ret == 0) 00303 ret = CEscape(escaped, '\n', out, &i, *outLen, 1); 00304 00305 if (i != outSz && escaped == 0 && ret == 0) 00306 return ASN_INPUT_E; 00307 00308 *outLen = i; 00309 return ret; 00310 } 00311 00312 00313 /* Base64 Encode, PEM style, with \n line endings */ 00314 int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen) 00315 { 00316 return DoBase64_Encode(in, inLen, out, outLen, 0); 00317 } 00318 00319 00320 /* Base64 Encode, with %0A esacped line endings instead of \n */ 00321 int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen) 00322 { 00323 return DoBase64_Encode(in, inLen, out, outLen, 1); 00324 } 00325 00326 00327 #endif /* defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER) */ 00328 00329 00330 #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) 00331 00332 static 00333 const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 00334 BAD, BAD, BAD, BAD, BAD, BAD, BAD, 00335 10, 11, 12, 13, 14, 15, /* upper case A-F */ 00336 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 00337 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 00338 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 00339 BAD, BAD, /* G - ` */ 00340 10, 11, 12, 13, 14, 15 /* lower case a-f */ 00341 }; /* A starts at 0x41 not 0x3A */ 00342 00343 int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) 00344 { 00345 word32 inIdx = 0; 00346 word32 outIdx = 0; 00347 00348 if (inLen == 1 && *outLen && in) { 00349 byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */ 00350 00351 /* sanity check */ 00352 if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) 00353 return ASN_INPUT_E; 00354 00355 b = hexDecode[b]; 00356 00357 if (b == BAD) 00358 return ASN_INPUT_E; 00359 00360 out[outIdx++] = b; 00361 00362 *outLen = outIdx; 00363 return 0; 00364 } 00365 00366 if (inLen % 2) 00367 return BAD_FUNC_ARG; 00368 00369 if (*outLen < (inLen / 2)) 00370 return BAD_FUNC_ARG; 00371 00372 while (inLen) { 00373 byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */ 00374 byte b2 = in[inIdx++] - 0x30; 00375 00376 /* sanity checks */ 00377 if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) 00378 return ASN_INPUT_E; 00379 if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0])) 00380 return ASN_INPUT_E; 00381 00382 b = hexDecode[b]; 00383 b2 = hexDecode[b2]; 00384 00385 if (b == BAD || b2 == BAD) 00386 return ASN_INPUT_E; 00387 00388 out[outIdx++] = (byte)((b << 4) | b2); 00389 inLen -= 2; 00390 } 00391 00392 *outLen = outIdx; 00393 return 0; 00394 } 00395 00396 00397 #endif /* (OPENSSL_EXTRA) || (HAVE_WEBSERVER) || (HAVE_FIPS) */ 00398 00399 #endif /* NO_CODING */ 00400
Generated on Wed Jul 13 2022 02:18:39 by
 1.7.2
 1.7.2