Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenbase64.c
Go to the documentation of this file.
00001 /* 00002 * base64 encoder/decoder 00003 * 00004 * Copyright 2005 by Kai Blin 00005 * Copyright 2006 Juan Lang 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library 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 GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include <stdarg.h> 00023 #include "windef.h" 00024 #include "winbase.h" 00025 #include "winerror.h" 00026 #include "wincrypt.h" 00027 #include "wine/debug.h" 00028 #include "wine/unicode.h" 00029 00030 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 00031 00032 #define CERT_HEADER "-----BEGIN CERTIFICATE-----" 00033 #define CERT_HEADER_START "-----BEGIN" 00034 #define CERT_DELIMITER "-----" 00035 #define CERT_TRAILER "-----END CERTIFICATE-----" 00036 #define CERT_TRAILER_START "-----END" 00037 #define CERT_REQUEST_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----" 00038 #define CERT_REQUEST_TRAILER "-----END NEW CERTIFICATE REQUEST-----" 00039 #define X509_HEADER "-----BEGIN X509 CRL-----" 00040 #define X509_TRAILER "-----END X509 CRL-----" 00041 00042 static const WCHAR CERT_HEADER_W[] = { 00043 '-','-','-','-','-','B','E','G','I','N',' ','C','E','R','T','I','F','I','C', 00044 'A','T','E','-','-','-','-','-',0 }; 00045 static const WCHAR CERT_HEADER_START_W[] = { 00046 '-','-','-','-','-','B','E','G','I','N',0 }; 00047 static const WCHAR CERT_DELIMITER_W[] = { 00048 '-','-','-','-','-',0 }; 00049 static const WCHAR CERT_TRAILER_W[] = { 00050 '-','-','-','-','-','E','N','D',0 }; 00051 static const WCHAR CERT_TRAILER_START_W[] = { 00052 '-','-','-','-','-','E','N','D',' ','C','E','R','T','I','F','I','C','A','T', 00053 'E','-','-','-','-','-',0 }; 00054 static const WCHAR CERT_REQUEST_HEADER_W[] = { 00055 '-','-','-','-','-','B','E','G','I','N',' ','N','E','W',' ','C','E','R','T', 00056 'I','F','I','C','A','T','E','R','E','Q','U','E','S','T','-','-','-','-','-',0 }; 00057 static const WCHAR CERT_REQUEST_TRAILER_W[] = { 00058 '-','-','-','-','-','E','N','D',' ','N','E','W',' ','C','E','R','T','I','F', 00059 'I','C','A','T','E','R','E','Q','U','E','S','T','-','-','-','-','-',0 }; 00060 static const WCHAR X509_HEADER_W[] = { 00061 '-','-','-','-','-','B','E','G','I','N',' ','X','5','0','9',' ','C','R','L', 00062 '-','-','-','-','-',0 }; 00063 static const WCHAR X509_TRAILER_W[] = { 00064 '-','-','-','-','-','E','N','D',' ','X','5','0','9',' ','C','R','L','-','-', 00065 '-','-','-',0 }; 00066 00067 static const char b64[] = 00068 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00069 00070 typedef BOOL (*BinaryToStringAFunc)(const BYTE *pbBinary, 00071 DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString); 00072 typedef BOOL (*BinaryToStringWFunc)(const BYTE *pbBinary, 00073 DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString); 00074 00075 static BOOL EncodeBinaryToBinaryA(const BYTE *pbBinary, 00076 DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString) 00077 { 00078 BOOL ret = TRUE; 00079 00080 if (*pcchString < cbBinary) 00081 { 00082 if (!pszString) 00083 *pcchString = cbBinary; 00084 else 00085 { 00086 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00087 *pcchString = cbBinary; 00088 ret = FALSE; 00089 } 00090 } 00091 else 00092 { 00093 if (cbBinary) 00094 memcpy(pszString, pbBinary, cbBinary); 00095 *pcchString = cbBinary; 00096 } 00097 return ret; 00098 } 00099 00100 static LONG encodeBase64A(const BYTE *in_buf, int in_len, LPCSTR sep, 00101 char* out_buf, DWORD *out_len) 00102 { 00103 int div, i; 00104 const BYTE *d = in_buf; 00105 int bytes = (in_len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0; 00106 DWORD needed; 00107 LPSTR ptr; 00108 00109 TRACE("bytes is %d, pad bytes is %d\n", bytes, pad_bytes); 00110 needed = bytes + pad_bytes + 1; 00111 needed += (needed / 64 + 1) * strlen(sep); 00112 00113 if (needed > *out_len) 00114 { 00115 *out_len = needed; 00116 return ERROR_INSUFFICIENT_BUFFER; 00117 } 00118 else 00119 *out_len = needed; 00120 00121 /* Three bytes of input give 4 chars of output */ 00122 div = in_len / 3; 00123 00124 ptr = out_buf; 00125 i = 0; 00126 while (div > 0) 00127 { 00128 if (i && i % 64 == 0) 00129 { 00130 strcpy(ptr, sep); 00131 ptr += strlen(sep); 00132 } 00133 /* first char is the first 6 bits of the first byte*/ 00134 *ptr++ = b64[ ( d[0] >> 2) & 0x3f ]; 00135 /* second char is the last 2 bits of the first byte and the first 4 00136 * bits of the second byte */ 00137 *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)]; 00138 /* third char is the last 4 bits of the second byte and the first 2 00139 * bits of the third byte */ 00140 *ptr++ = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)]; 00141 /* fourth char is the remaining 6 bits of the third byte */ 00142 *ptr++ = b64[ d[2] & 0x3f]; 00143 i += 4; 00144 d += 3; 00145 div--; 00146 } 00147 00148 switch(pad_bytes) 00149 { 00150 case 1: 00151 /* first char is the first 6 bits of the first byte*/ 00152 *ptr++ = b64[ ( d[0] >> 2) & 0x3f ]; 00153 /* second char is the last 2 bits of the first byte and the first 4 00154 * bits of the second byte */ 00155 *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)]; 00156 /* third char is the last 4 bits of the second byte padded with 00157 * two zeroes */ 00158 *ptr++ = b64[ ((d[1] << 2) & 0x3c) ]; 00159 /* fourth char is a = to indicate one byte of padding */ 00160 *ptr++ = '='; 00161 break; 00162 case 2: 00163 /* first char is the first 6 bits of the first byte*/ 00164 *ptr++ = b64[ ( d[0] >> 2) & 0x3f ]; 00165 /* second char is the last 2 bits of the first byte padded with 00166 * four zeroes*/ 00167 *ptr++ = b64[ ((d[0] << 4) & 0x30)]; 00168 /* third char is = to indicate padding */ 00169 *ptr++ = '='; 00170 /* fourth char is = to indicate padding */ 00171 *ptr++ = '='; 00172 break; 00173 } 00174 strcpy(ptr, sep); 00175 00176 return ERROR_SUCCESS; 00177 } 00178 00179 static BOOL BinaryToBase64A(const BYTE *pbBinary, 00180 DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString) 00181 { 00182 static const char crlf[] = "\r\n", lf[] = "\n"; 00183 BOOL ret = TRUE; 00184 LPCSTR header = NULL, trailer = NULL, sep; 00185 DWORD charsNeeded; 00186 00187 if (dwFlags & CRYPT_STRING_NOCR) 00188 sep = lf; 00189 else if (dwFlags & CRYPT_STRING_NOCRLF) 00190 sep = ""; 00191 else 00192 sep = crlf; 00193 switch (dwFlags & 0x0fffffff) 00194 { 00195 case CRYPT_STRING_BASE64: 00196 /* no header or footer */ 00197 break; 00198 case CRYPT_STRING_BASE64HEADER: 00199 header = CERT_HEADER; 00200 trailer = CERT_TRAILER; 00201 break; 00202 case CRYPT_STRING_BASE64REQUESTHEADER: 00203 header = CERT_REQUEST_HEADER; 00204 trailer = CERT_REQUEST_TRAILER; 00205 break; 00206 case CRYPT_STRING_BASE64X509CRLHEADER: 00207 header = X509_HEADER; 00208 trailer = X509_TRAILER; 00209 break; 00210 } 00211 00212 charsNeeded = 0; 00213 encodeBase64A(pbBinary, cbBinary, sep, NULL, &charsNeeded); 00214 if (header) 00215 charsNeeded += strlen(header) + strlen(sep); 00216 if (trailer) 00217 charsNeeded += strlen(trailer) + strlen(sep); 00218 if (charsNeeded <= *pcchString) 00219 { 00220 LPSTR ptr = pszString; 00221 DWORD size = charsNeeded; 00222 00223 if (header) 00224 { 00225 strcpy(ptr, header); 00226 ptr += strlen(ptr); 00227 strcpy(ptr, sep); 00228 ptr += strlen(sep); 00229 } 00230 encodeBase64A(pbBinary, cbBinary, sep, ptr, &size); 00231 ptr += size - 1; 00232 if (trailer) 00233 { 00234 strcpy(ptr, trailer); 00235 ptr += strlen(ptr); 00236 strcpy(ptr, sep); 00237 } 00238 *pcchString = charsNeeded - 1; 00239 } 00240 else if (pszString) 00241 { 00242 *pcchString = charsNeeded; 00243 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00244 ret = FALSE; 00245 } 00246 else 00247 *pcchString = charsNeeded; 00248 return ret; 00249 } 00250 00251 BOOL WINAPI CryptBinaryToStringA(const BYTE *pbBinary, 00252 DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString) 00253 { 00254 BinaryToStringAFunc encoder = NULL; 00255 00256 TRACE("(%p, %d, %08x, %p, %p)\n", pbBinary, cbBinary, dwFlags, pszString, 00257 pcchString); 00258 00259 if (!pbBinary) 00260 { 00261 SetLastError(ERROR_INVALID_PARAMETER); 00262 return FALSE; 00263 } 00264 if (!pcchString) 00265 { 00266 SetLastError(ERROR_INVALID_PARAMETER); 00267 return FALSE; 00268 } 00269 00270 switch (dwFlags & 0x0fffffff) 00271 { 00272 case CRYPT_STRING_BINARY: 00273 encoder = EncodeBinaryToBinaryA; 00274 break; 00275 case CRYPT_STRING_BASE64: 00276 case CRYPT_STRING_BASE64HEADER: 00277 case CRYPT_STRING_BASE64REQUESTHEADER: 00278 case CRYPT_STRING_BASE64X509CRLHEADER: 00279 encoder = BinaryToBase64A; 00280 break; 00281 case CRYPT_STRING_HEX: 00282 case CRYPT_STRING_HEXASCII: 00283 case CRYPT_STRING_HEXADDR: 00284 case CRYPT_STRING_HEXASCIIADDR: 00285 FIXME("Unimplemented type %d\n", dwFlags & 0x0fffffff); 00286 /* fall through */ 00287 default: 00288 SetLastError(ERROR_INVALID_PARAMETER); 00289 return FALSE; 00290 } 00291 return encoder(pbBinary, cbBinary, dwFlags, pszString, pcchString); 00292 } 00293 00294 static LONG encodeBase64W(const BYTE *in_buf, int in_len, LPCWSTR sep, 00295 WCHAR* out_buf, DWORD *out_len) 00296 { 00297 int div, i; 00298 const BYTE *d = in_buf; 00299 int bytes = (in_len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0; 00300 DWORD needed; 00301 LPWSTR ptr; 00302 00303 TRACE("bytes is %d, pad bytes is %d\n", bytes, pad_bytes); 00304 needed = bytes + pad_bytes + 1; 00305 needed += (needed / 64 + 1) * strlenW(sep); 00306 00307 if (needed > *out_len) 00308 { 00309 *out_len = needed; 00310 return ERROR_INSUFFICIENT_BUFFER; 00311 } 00312 else 00313 *out_len = needed; 00314 00315 /* Three bytes of input give 4 chars of output */ 00316 div = in_len / 3; 00317 00318 ptr = out_buf; 00319 i = 0; 00320 while (div > 0) 00321 { 00322 if (i && i % 64 == 0) 00323 { 00324 strcpyW(ptr, sep); 00325 ptr += strlenW(sep); 00326 } 00327 /* first char is the first 6 bits of the first byte*/ 00328 *ptr++ = b64[ ( d[0] >> 2) & 0x3f ]; 00329 /* second char is the last 2 bits of the first byte and the first 4 00330 * bits of the second byte */ 00331 *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)]; 00332 /* third char is the last 4 bits of the second byte and the first 2 00333 * bits of the third byte */ 00334 *ptr++ = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)]; 00335 /* fourth char is the remaining 6 bits of the third byte */ 00336 *ptr++ = b64[ d[2] & 0x3f]; 00337 i += 4; 00338 d += 3; 00339 div--; 00340 } 00341 00342 switch(pad_bytes) 00343 { 00344 case 1: 00345 /* first char is the first 6 bits of the first byte*/ 00346 *ptr++ = b64[ ( d[0] >> 2) & 0x3f ]; 00347 /* second char is the last 2 bits of the first byte and the first 4 00348 * bits of the second byte */ 00349 *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)]; 00350 /* third char is the last 4 bits of the second byte padded with 00351 * two zeroes */ 00352 *ptr++ = b64[ ((d[1] << 2) & 0x3c) ]; 00353 /* fourth char is a = to indicate one byte of padding */ 00354 *ptr++ = '='; 00355 break; 00356 case 2: 00357 /* first char is the first 6 bits of the first byte*/ 00358 *ptr++ = b64[ ( d[0] >> 2) & 0x3f ]; 00359 /* second char is the last 2 bits of the first byte padded with 00360 * four zeroes*/ 00361 *ptr++ = b64[ ((d[0] << 4) & 0x30)]; 00362 /* third char is = to indicate padding */ 00363 *ptr++ = '='; 00364 /* fourth char is = to indicate padding */ 00365 *ptr++ = '='; 00366 break; 00367 } 00368 strcpyW(ptr, sep); 00369 00370 return ERROR_SUCCESS; 00371 } 00372 00373 static BOOL BinaryToBase64W(const BYTE *pbBinary, 00374 DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString) 00375 { 00376 static const WCHAR crlf[] = { '\r','\n',0 }, lf[] = { '\n',0 }, empty[] = {0}; 00377 BOOL ret = TRUE; 00378 LPCWSTR header = NULL, trailer = NULL, sep; 00379 DWORD charsNeeded; 00380 00381 if (dwFlags & CRYPT_STRING_NOCR) 00382 sep = lf; 00383 else if (dwFlags & CRYPT_STRING_NOCRLF) 00384 sep = empty; 00385 else 00386 sep = crlf; 00387 switch (dwFlags & 0x0fffffff) 00388 { 00389 case CRYPT_STRING_BASE64: 00390 /* no header or footer */ 00391 break; 00392 case CRYPT_STRING_BASE64HEADER: 00393 header = CERT_HEADER_W; 00394 trailer = CERT_TRAILER_W; 00395 break; 00396 case CRYPT_STRING_BASE64REQUESTHEADER: 00397 header = CERT_REQUEST_HEADER_W; 00398 trailer = CERT_REQUEST_TRAILER_W; 00399 break; 00400 case CRYPT_STRING_BASE64X509CRLHEADER: 00401 header = X509_HEADER_W; 00402 trailer = X509_TRAILER_W; 00403 break; 00404 } 00405 00406 charsNeeded = 0; 00407 encodeBase64W(pbBinary, cbBinary, sep, NULL, &charsNeeded); 00408 if (header) 00409 charsNeeded += strlenW(header) + strlenW(sep); 00410 if (trailer) 00411 charsNeeded += strlenW(trailer) + strlenW(sep); 00412 if (charsNeeded <= *pcchString) 00413 { 00414 LPWSTR ptr = pszString; 00415 DWORD size = charsNeeded; 00416 00417 if (header) 00418 { 00419 strcpyW(ptr, header); 00420 ptr += strlenW(ptr); 00421 strcpyW(ptr, sep); 00422 ptr += strlenW(sep); 00423 } 00424 encodeBase64W(pbBinary, cbBinary, sep, ptr, &size); 00425 ptr += size - 1; 00426 if (trailer) 00427 { 00428 strcpyW(ptr, trailer); 00429 ptr += strlenW(ptr); 00430 strcpyW(ptr, sep); 00431 } 00432 *pcchString = charsNeeded - 1; 00433 } 00434 else if (pszString) 00435 { 00436 *pcchString = charsNeeded; 00437 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00438 ret = FALSE; 00439 } 00440 else 00441 *pcchString = charsNeeded; 00442 return ret; 00443 } 00444 00445 BOOL WINAPI CryptBinaryToStringW(const BYTE *pbBinary, 00446 DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString) 00447 { 00448 BinaryToStringWFunc encoder = NULL; 00449 00450 TRACE("(%p, %d, %08x, %p, %p)\n", pbBinary, cbBinary, dwFlags, pszString, 00451 pcchString); 00452 00453 if (!pbBinary) 00454 { 00455 SetLastError(ERROR_INVALID_PARAMETER); 00456 return FALSE; 00457 } 00458 if (!pcchString) 00459 { 00460 SetLastError(ERROR_INVALID_PARAMETER); 00461 return FALSE; 00462 } 00463 00464 switch (dwFlags & 0x0fffffff) 00465 { 00466 case CRYPT_STRING_BASE64: 00467 case CRYPT_STRING_BASE64HEADER: 00468 case CRYPT_STRING_BASE64REQUESTHEADER: 00469 case CRYPT_STRING_BASE64X509CRLHEADER: 00470 encoder = BinaryToBase64W; 00471 break; 00472 case CRYPT_STRING_BINARY: 00473 case CRYPT_STRING_HEX: 00474 case CRYPT_STRING_HEXASCII: 00475 case CRYPT_STRING_HEXADDR: 00476 case CRYPT_STRING_HEXASCIIADDR: 00477 FIXME("Unimplemented type %d\n", dwFlags & 0x0fffffff); 00478 /* fall through */ 00479 default: 00480 SetLastError(ERROR_INVALID_PARAMETER); 00481 return FALSE; 00482 } 00483 return encoder(pbBinary, cbBinary, dwFlags, pszString, pcchString); 00484 } 00485 00486 static inline BYTE decodeBase64Byte(int c) 00487 { 00488 BYTE ret; 00489 00490 if (c >= 'A' && c <= 'Z') 00491 ret = c - 'A'; 00492 else if (c >= 'a' && c <= 'z') 00493 ret = c - 'a' + 26; 00494 else if (c >= '0' && c <= '9') 00495 ret = c - '0' + 52; 00496 else if (c == '+') 00497 ret = 62; 00498 else if (c == '/') 00499 ret = 63; 00500 else 00501 ret = 64; 00502 return ret; 00503 } 00504 00505 static LONG decodeBase64Block(const char *in_buf, int in_len, 00506 const char **nextBlock, PBYTE out_buf, DWORD *out_len) 00507 { 00508 int len = in_len; 00509 const char *d = in_buf; 00510 int ip0, ip1, ip2, ip3; 00511 00512 if (len < 4) 00513 return ERROR_INVALID_DATA; 00514 00515 if (d[2] == '=') 00516 { 00517 if ((ip0 = decodeBase64Byte(d[0])) > 63) 00518 return ERROR_INVALID_DATA; 00519 if ((ip1 = decodeBase64Byte(d[1])) > 63) 00520 return ERROR_INVALID_DATA; 00521 00522 if (out_buf) 00523 out_buf[0] = (ip0 << 2) | (ip1 >> 4); 00524 *out_len = 1; 00525 } 00526 else if (d[3] == '=') 00527 { 00528 if ((ip0 = decodeBase64Byte(d[0])) > 63) 00529 return ERROR_INVALID_DATA; 00530 if ((ip1 = decodeBase64Byte(d[1])) > 63) 00531 return ERROR_INVALID_DATA; 00532 if ((ip2 = decodeBase64Byte(d[2])) > 63) 00533 return ERROR_INVALID_DATA; 00534 00535 if (out_buf) 00536 { 00537 out_buf[0] = (ip0 << 2) | (ip1 >> 4); 00538 out_buf[1] = (ip1 << 4) | (ip2 >> 2); 00539 } 00540 *out_len = 2; 00541 } 00542 else 00543 { 00544 if ((ip0 = decodeBase64Byte(d[0])) > 63) 00545 return ERROR_INVALID_DATA; 00546 if ((ip1 = decodeBase64Byte(d[1])) > 63) 00547 return ERROR_INVALID_DATA; 00548 if ((ip2 = decodeBase64Byte(d[2])) > 63) 00549 return ERROR_INVALID_DATA; 00550 if ((ip3 = decodeBase64Byte(d[3])) > 63) 00551 return ERROR_INVALID_DATA; 00552 00553 if (out_buf) 00554 { 00555 out_buf[0] = (ip0 << 2) | (ip1 >> 4); 00556 out_buf[1] = (ip1 << 4) | (ip2 >> 2); 00557 out_buf[2] = (ip2 << 6) | ip3; 00558 } 00559 *out_len = 3; 00560 } 00561 if (len >= 6 && d[4] == '\r' && d[5] == '\n') 00562 *nextBlock = d + 6; 00563 else if (len >= 5 && d[4] == '\n') 00564 *nextBlock = d + 5; 00565 else if (len >= 4 && d[4]) 00566 *nextBlock = d + 4; 00567 else 00568 *nextBlock = NULL; 00569 return ERROR_SUCCESS; 00570 } 00571 00572 /* Unlike CryptStringToBinaryA, cchString is guaranteed to be the length of the 00573 * string to convert. 00574 */ 00575 typedef LONG (*StringToBinaryAFunc)(LPCSTR pszString, DWORD cchString, 00576 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags); 00577 00578 static LONG Base64ToBinaryA(LPCSTR pszString, DWORD cchString, 00579 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 00580 { 00581 LONG ret = ERROR_SUCCESS; 00582 const char *nextBlock; 00583 DWORD outLen = 0; 00584 00585 nextBlock = pszString; 00586 while (nextBlock && !ret) 00587 { 00588 DWORD len = 0; 00589 00590 ret = decodeBase64Block(nextBlock, cchString - (nextBlock - pszString), 00591 &nextBlock, pbBinary ? pbBinary + outLen : NULL, &len); 00592 if (!ret) 00593 outLen += len; 00594 if (cchString - (nextBlock - pszString) <= 0) 00595 nextBlock = NULL; 00596 } 00597 *pcbBinary = outLen; 00598 if (!ret) 00599 { 00600 if (pdwSkip) 00601 *pdwSkip = 0; 00602 if (pdwFlags) 00603 *pdwFlags = CRYPT_STRING_BASE64; 00604 } 00605 else if (ret == ERROR_INSUFFICIENT_BUFFER) 00606 { 00607 if (!pbBinary) 00608 ret = ERROR_SUCCESS; 00609 } 00610 return ret; 00611 } 00612 00613 static LONG Base64WithHeaderAndTrailerToBinaryA(LPCSTR pszString, 00614 DWORD cchString, LPCSTR header, LPCSTR trailer, BYTE *pbBinary, 00615 DWORD *pcbBinary, DWORD *pdwSkip, BOOL exactHeaderAndTrailerMatch) 00616 { 00617 LONG ret; 00618 00619 LPCSTR headerBegins; 00620 LPCSTR dataBegins; 00621 LPCSTR trailerBegins; 00622 size_t dataLength; 00623 00624 if ((strlen(header) + strlen(trailer)) > cchString) 00625 { 00626 return ERROR_INVALID_DATA; 00627 } 00628 00629 if (!(headerBegins = strstr(pszString, header))) 00630 { 00631 TRACE("Can't find %s in %s.\n", header, pszString); 00632 return ERROR_INVALID_DATA; 00633 } 00634 00635 dataBegins = headerBegins + strlen(header); 00636 if (!exactHeaderAndTrailerMatch) 00637 { 00638 if ((dataBegins = strstr(dataBegins, CERT_DELIMITER))) 00639 { 00640 dataBegins += strlen(CERT_DELIMITER); 00641 } 00642 else 00643 { 00644 return ERROR_INVALID_DATA; 00645 } 00646 } 00647 if (*dataBegins == '\r') dataBegins++; 00648 if (*dataBegins == '\n') dataBegins++; 00649 00650 if (exactHeaderAndTrailerMatch) 00651 { 00652 trailerBegins = pszString + cchString - strlen(trailer); 00653 if (pszString[cchString - 1] == '\n') trailerBegins--; 00654 if (pszString[cchString - 2] == '\r') trailerBegins--; 00655 00656 if (*(trailerBegins-1) == '\n') trailerBegins--; 00657 if (*(trailerBegins-1) == '\r') trailerBegins--; 00658 00659 if (!strncmp(trailerBegins, trailer, strlen(trailer))) 00660 { 00661 return ERROR_INVALID_DATA; 00662 } 00663 } 00664 else 00665 { 00666 if (!(trailerBegins = strstr(dataBegins, trailer))) 00667 { 00668 return ERROR_INVALID_DATA; 00669 } 00670 if (*(trailerBegins-1) == '\n') trailerBegins--; 00671 if (*(trailerBegins-1) == '\r') trailerBegins--; 00672 } 00673 00674 if (pdwSkip) 00675 *pdwSkip = headerBegins - pszString; 00676 00677 dataLength = trailerBegins - dataBegins; 00678 00679 ret = Base64ToBinaryA(dataBegins, dataLength, pbBinary, pcbBinary, NULL, 00680 NULL); 00681 00682 return ret; 00683 } 00684 00685 static LONG Base64HeaderToBinaryA(LPCSTR pszString, DWORD cchString, 00686 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 00687 { 00688 LONG ret = Base64WithHeaderAndTrailerToBinaryA(pszString, cchString, 00689 CERT_HEADER_START, CERT_TRAILER_START, pbBinary, pcbBinary, pdwSkip, FALSE); 00690 00691 if (!ret && pdwFlags) 00692 *pdwFlags = CRYPT_STRING_BASE64HEADER; 00693 return ret; 00694 } 00695 00696 static LONG Base64RequestHeaderToBinaryA(LPCSTR pszString, DWORD cchString, 00697 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 00698 { 00699 LONG ret = Base64WithHeaderAndTrailerToBinaryA(pszString, cchString, 00700 CERT_REQUEST_HEADER, CERT_REQUEST_TRAILER, pbBinary, pcbBinary, pdwSkip, TRUE); 00701 00702 if (!ret && pdwFlags) 00703 *pdwFlags = CRYPT_STRING_BASE64REQUESTHEADER; 00704 return ret; 00705 } 00706 00707 static LONG Base64X509HeaderToBinaryA(LPCSTR pszString, DWORD cchString, 00708 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 00709 { 00710 LONG ret = Base64WithHeaderAndTrailerToBinaryA(pszString, cchString, 00711 X509_HEADER, X509_TRAILER, pbBinary, pcbBinary, pdwSkip, TRUE); 00712 00713 if (!ret && pdwFlags) 00714 *pdwFlags = CRYPT_STRING_BASE64X509CRLHEADER; 00715 return ret; 00716 } 00717 00718 static LONG Base64AnyToBinaryA(LPCSTR pszString, DWORD cchString, 00719 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 00720 { 00721 LONG ret; 00722 00723 ret = Base64HeaderToBinaryA(pszString, cchString, pbBinary, pcbBinary, 00724 pdwSkip, pdwFlags); 00725 if (ret == ERROR_INVALID_DATA) 00726 ret = Base64ToBinaryA(pszString, cchString, pbBinary, pcbBinary, 00727 pdwSkip, pdwFlags); 00728 return ret; 00729 } 00730 00731 static LONG DecodeBinaryToBinaryA(LPCSTR pszString, DWORD cchString, 00732 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 00733 { 00734 LONG ret = ERROR_SUCCESS; 00735 00736 if (*pcbBinary < cchString) 00737 { 00738 if (!pbBinary) 00739 *pcbBinary = cchString; 00740 else 00741 { 00742 ret = ERROR_INSUFFICIENT_BUFFER; 00743 *pcbBinary = cchString; 00744 } 00745 } 00746 else 00747 { 00748 if (cchString) 00749 memcpy(pbBinary, pszString, cchString); 00750 *pcbBinary = cchString; 00751 } 00752 return ret; 00753 } 00754 00755 static LONG DecodeAnyA(LPCSTR pszString, DWORD cchString, 00756 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 00757 { 00758 LONG ret; 00759 00760 ret = Base64HeaderToBinaryA(pszString, cchString, pbBinary, pcbBinary, 00761 pdwSkip, pdwFlags); 00762 if (ret == ERROR_INVALID_DATA) 00763 ret = Base64ToBinaryA(pszString, cchString, pbBinary, pcbBinary, 00764 pdwSkip, pdwFlags); 00765 if (ret == ERROR_INVALID_DATA) 00766 ret = DecodeBinaryToBinaryA(pszString, cchString, pbBinary, pcbBinary, 00767 pdwSkip, pdwFlags); 00768 return ret; 00769 } 00770 00771 BOOL WINAPI CryptStringToBinaryA(LPCSTR pszString, 00772 DWORD cchString, DWORD dwFlags, BYTE *pbBinary, DWORD *pcbBinary, 00773 DWORD *pdwSkip, DWORD *pdwFlags) 00774 { 00775 StringToBinaryAFunc decoder; 00776 LONG ret; 00777 00778 TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_a(pszString), 00779 cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags); 00780 00781 if (!pszString) 00782 { 00783 SetLastError(ERROR_INVALID_PARAMETER); 00784 return FALSE; 00785 } 00786 /* Only the bottom byte contains valid types */ 00787 if (dwFlags & 0xfffffff0) 00788 { 00789 SetLastError(ERROR_INVALID_DATA); 00790 return FALSE; 00791 } 00792 switch (dwFlags) 00793 { 00794 case CRYPT_STRING_BASE64_ANY: 00795 decoder = Base64AnyToBinaryA; 00796 break; 00797 case CRYPT_STRING_BASE64: 00798 decoder = Base64ToBinaryA; 00799 break; 00800 case CRYPT_STRING_BASE64HEADER: 00801 decoder = Base64HeaderToBinaryA; 00802 break; 00803 case CRYPT_STRING_BASE64REQUESTHEADER: 00804 decoder = Base64RequestHeaderToBinaryA; 00805 break; 00806 case CRYPT_STRING_BASE64X509CRLHEADER: 00807 decoder = Base64X509HeaderToBinaryA; 00808 break; 00809 case CRYPT_STRING_BINARY: 00810 decoder = DecodeBinaryToBinaryA; 00811 break; 00812 case CRYPT_STRING_ANY: 00813 decoder = DecodeAnyA; 00814 break; 00815 case CRYPT_STRING_HEX: 00816 case CRYPT_STRING_HEXASCII: 00817 case CRYPT_STRING_HEXADDR: 00818 case CRYPT_STRING_HEXASCIIADDR: 00819 FIXME("Unimplemented type %d\n", dwFlags & 0x7fffffff); 00820 /* fall through */ 00821 default: 00822 SetLastError(ERROR_INVALID_PARAMETER); 00823 return FALSE; 00824 } 00825 if (!cchString) 00826 cchString = strlen(pszString); 00827 ret = decoder(pszString, cchString, pbBinary, pcbBinary, pdwSkip, pdwFlags); 00828 if (ret) 00829 SetLastError(ret); 00830 return (ret == ERROR_SUCCESS) ? TRUE : FALSE; 00831 } 00832 00833 static LONG decodeBase64BlockW(const WCHAR *in_buf, int in_len, 00834 const WCHAR **nextBlock, PBYTE out_buf, DWORD *out_len) 00835 { 00836 int len = in_len, i; 00837 const WCHAR *d = in_buf; 00838 int ip0, ip1, ip2, ip3; 00839 00840 if (len < 4) 00841 return ERROR_INVALID_DATA; 00842 00843 i = 0; 00844 if (d[2] == '=') 00845 { 00846 if ((ip0 = decodeBase64Byte(d[0])) > 63) 00847 return ERROR_INVALID_DATA; 00848 if ((ip1 = decodeBase64Byte(d[1])) > 63) 00849 return ERROR_INVALID_DATA; 00850 00851 if (out_buf) 00852 out_buf[i] = (ip0 << 2) | (ip1 >> 4); 00853 i++; 00854 } 00855 else if (d[3] == '=') 00856 { 00857 if ((ip0 = decodeBase64Byte(d[0])) > 63) 00858 return ERROR_INVALID_DATA; 00859 if ((ip1 = decodeBase64Byte(d[1])) > 63) 00860 return ERROR_INVALID_DATA; 00861 if ((ip2 = decodeBase64Byte(d[2])) > 63) 00862 return ERROR_INVALID_DATA; 00863 00864 if (out_buf) 00865 { 00866 out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4); 00867 out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2); 00868 } 00869 i += 2; 00870 } 00871 else 00872 { 00873 if ((ip0 = decodeBase64Byte(d[0])) > 63) 00874 return ERROR_INVALID_DATA; 00875 if ((ip1 = decodeBase64Byte(d[1])) > 63) 00876 return ERROR_INVALID_DATA; 00877 if ((ip2 = decodeBase64Byte(d[2])) > 63) 00878 return ERROR_INVALID_DATA; 00879 if ((ip3 = decodeBase64Byte(d[3])) > 63) 00880 return ERROR_INVALID_DATA; 00881 00882 if (out_buf) 00883 { 00884 out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4); 00885 out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2); 00886 out_buf[i + 2] = (ip2 << 6) | ip3; 00887 } 00888 i += 3; 00889 } 00890 if (len >= 6 && d[4] == '\r' && d[5] == '\n') 00891 *nextBlock = d + 6; 00892 else if (len >= 5 && d[4] == '\n') 00893 *nextBlock = d + 5; 00894 else if (len >= 4 && d[4]) 00895 *nextBlock = d + 4; 00896 else 00897 *nextBlock = NULL; 00898 *out_len = i; 00899 return ERROR_SUCCESS; 00900 } 00901 00902 /* Unlike CryptStringToBinaryW, cchString is guaranteed to be the length of the 00903 * string to convert. 00904 */ 00905 typedef LONG (*StringToBinaryWFunc)(LPCWSTR pszString, DWORD cchString, 00906 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags); 00907 00908 static LONG Base64ToBinaryW(LPCWSTR pszString, DWORD cchString, 00909 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 00910 { 00911 LONG ret = ERROR_SUCCESS; 00912 const WCHAR *nextBlock; 00913 DWORD outLen = 0; 00914 00915 nextBlock = pszString; 00916 while (nextBlock && !ret) 00917 { 00918 DWORD len = 0; 00919 00920 ret = decodeBase64BlockW(nextBlock, cchString - (nextBlock - pszString), 00921 &nextBlock, pbBinary ? pbBinary + outLen : NULL, &len); 00922 if (!ret) 00923 outLen += len; 00924 if (cchString - (nextBlock - pszString) <= 0) 00925 nextBlock = NULL; 00926 } 00927 *pcbBinary = outLen; 00928 if (!ret) 00929 { 00930 if (pdwSkip) 00931 *pdwSkip = 0; 00932 if (pdwFlags) 00933 *pdwFlags = CRYPT_STRING_BASE64; 00934 } 00935 else if (ret == ERROR_INSUFFICIENT_BUFFER) 00936 { 00937 if (!pbBinary) 00938 ret = ERROR_SUCCESS; 00939 } 00940 return ret; 00941 } 00942 00943 static LONG Base64WithHeaderAndTrailerToBinaryW(LPCWSTR pszString, 00944 DWORD cchString, LPCWSTR header, LPCWSTR trailer, BYTE *pbBinary, 00945 DWORD *pcbBinary, DWORD *pdwSkip, BOOL exactHeaderAndTrailerMatch) 00946 { 00947 LONG ret; 00948 00949 LPCWSTR headerBegins; 00950 LPCWSTR dataBegins; 00951 LPCWSTR trailerBegins; 00952 size_t dataLength; 00953 00954 if ((strlenW(header) + strlenW(trailer)) > cchString) 00955 { 00956 return ERROR_INVALID_DATA; 00957 } 00958 00959 if (!(headerBegins = strstrW(pszString, header))) 00960 { 00961 TRACE("Can't find %s in %s.\n", debugstr_w(header), debugstr_w(pszString)); 00962 return ERROR_INVALID_DATA; 00963 } 00964 00965 dataBegins = headerBegins + strlenW(header); 00966 if (!exactHeaderAndTrailerMatch) 00967 { 00968 if ((dataBegins = strstrW(dataBegins, CERT_DELIMITER_W))) 00969 { 00970 dataBegins += strlenW(CERT_DELIMITER_W); 00971 } 00972 else 00973 { 00974 return ERROR_INVALID_DATA; 00975 } 00976 } 00977 if (*dataBegins == '\r') dataBegins++; 00978 if (*dataBegins == '\n') dataBegins++; 00979 00980 if (exactHeaderAndTrailerMatch) 00981 { 00982 trailerBegins = pszString + cchString - strlenW(trailer); 00983 if (pszString[cchString - 1] == '\n') trailerBegins--; 00984 if (pszString[cchString - 2] == '\r') trailerBegins--; 00985 00986 if (*(trailerBegins-1) == '\n') trailerBegins--; 00987 if (*(trailerBegins-1) == '\r') trailerBegins--; 00988 00989 if (!strncmpW(trailerBegins, trailer, strlenW(trailer))) 00990 { 00991 return ERROR_INVALID_DATA; 00992 } 00993 } 00994 else 00995 { 00996 if (!(trailerBegins = strstrW(dataBegins, trailer))) 00997 { 00998 return ERROR_INVALID_DATA; 00999 } 01000 if (*(trailerBegins-1) == '\n') trailerBegins--; 01001 if (*(trailerBegins-1) == '\r') trailerBegins--; 01002 } 01003 01004 if (pdwSkip) 01005 *pdwSkip = headerBegins - pszString; 01006 01007 dataLength = trailerBegins - dataBegins; 01008 01009 ret = Base64ToBinaryW(dataBegins, dataLength, pbBinary, pcbBinary, NULL, 01010 NULL); 01011 01012 return ret; 01013 } 01014 01015 static LONG Base64HeaderToBinaryW(LPCWSTR pszString, DWORD cchString, 01016 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 01017 { 01018 LONG ret = Base64WithHeaderAndTrailerToBinaryW(pszString, cchString, 01019 CERT_HEADER_START_W, CERT_TRAILER_START_W, pbBinary, pcbBinary, 01020 pdwSkip, FALSE); 01021 01022 if (!ret && pdwFlags) 01023 *pdwFlags = CRYPT_STRING_BASE64HEADER; 01024 return ret; 01025 } 01026 01027 static LONG Base64RequestHeaderToBinaryW(LPCWSTR pszString, DWORD cchString, 01028 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 01029 { 01030 LONG ret = Base64WithHeaderAndTrailerToBinaryW(pszString, cchString, 01031 CERT_REQUEST_HEADER_W, CERT_REQUEST_TRAILER_W, pbBinary, pcbBinary, 01032 pdwSkip, TRUE); 01033 01034 if (!ret && pdwFlags) 01035 *pdwFlags = CRYPT_STRING_BASE64REQUESTHEADER; 01036 return ret; 01037 } 01038 01039 static LONG Base64X509HeaderToBinaryW(LPCWSTR pszString, DWORD cchString, 01040 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 01041 { 01042 LONG ret = Base64WithHeaderAndTrailerToBinaryW(pszString, cchString, 01043 X509_HEADER_W, X509_TRAILER_W, pbBinary, pcbBinary, pdwSkip, TRUE); 01044 01045 if (!ret && pdwFlags) 01046 *pdwFlags = CRYPT_STRING_BASE64X509CRLHEADER; 01047 return ret; 01048 } 01049 01050 static LONG Base64AnyToBinaryW(LPCWSTR pszString, DWORD cchString, 01051 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 01052 { 01053 LONG ret; 01054 01055 ret = Base64HeaderToBinaryW(pszString, cchString, pbBinary, pcbBinary, 01056 pdwSkip, pdwFlags); 01057 if (ret == ERROR_INVALID_DATA) 01058 ret = Base64ToBinaryW(pszString, cchString, pbBinary, pcbBinary, 01059 pdwSkip, pdwFlags); 01060 return ret; 01061 } 01062 01063 static LONG DecodeBinaryToBinaryW(LPCWSTR pszString, DWORD cchString, 01064 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 01065 { 01066 LONG ret = ERROR_SUCCESS; 01067 01068 if (*pcbBinary < cchString) 01069 { 01070 if (!pbBinary) 01071 *pcbBinary = cchString; 01072 else 01073 { 01074 ret = ERROR_INSUFFICIENT_BUFFER; 01075 *pcbBinary = cchString; 01076 } 01077 } 01078 else 01079 { 01080 if (cchString) 01081 memcpy(pbBinary, pszString, cchString * sizeof(WCHAR)); 01082 *pcbBinary = cchString * sizeof(WCHAR); 01083 } 01084 return ret; 01085 } 01086 01087 static LONG DecodeAnyW(LPCWSTR pszString, DWORD cchString, 01088 BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags) 01089 { 01090 LONG ret; 01091 01092 ret = Base64HeaderToBinaryW(pszString, cchString, pbBinary, pcbBinary, 01093 pdwSkip, pdwFlags); 01094 if (ret == ERROR_INVALID_DATA) 01095 ret = Base64ToBinaryW(pszString, cchString, pbBinary, pcbBinary, 01096 pdwSkip, pdwFlags); 01097 if (ret == ERROR_INVALID_DATA) 01098 ret = DecodeBinaryToBinaryW(pszString, cchString, pbBinary, pcbBinary, 01099 pdwSkip, pdwFlags); 01100 return ret; 01101 } 01102 01103 BOOL WINAPI CryptStringToBinaryW(LPCWSTR pszString, 01104 DWORD cchString, DWORD dwFlags, BYTE *pbBinary, DWORD *pcbBinary, 01105 DWORD *pdwSkip, DWORD *pdwFlags) 01106 { 01107 StringToBinaryWFunc decoder; 01108 LONG ret; 01109 01110 TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_w(pszString), 01111 cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags); 01112 01113 if (!pszString) 01114 { 01115 SetLastError(ERROR_INVALID_PARAMETER); 01116 return FALSE; 01117 } 01118 /* Only the bottom byte contains valid types */ 01119 if (dwFlags & 0xfffffff0) 01120 { 01121 SetLastError(ERROR_INVALID_DATA); 01122 return FALSE; 01123 } 01124 switch (dwFlags) 01125 { 01126 case CRYPT_STRING_BASE64_ANY: 01127 decoder = Base64AnyToBinaryW; 01128 break; 01129 case CRYPT_STRING_BASE64: 01130 decoder = Base64ToBinaryW; 01131 break; 01132 case CRYPT_STRING_BASE64HEADER: 01133 decoder = Base64HeaderToBinaryW; 01134 break; 01135 case CRYPT_STRING_BASE64REQUESTHEADER: 01136 decoder = Base64RequestHeaderToBinaryW; 01137 break; 01138 case CRYPT_STRING_BASE64X509CRLHEADER: 01139 decoder = Base64X509HeaderToBinaryW; 01140 break; 01141 case CRYPT_STRING_BINARY: 01142 decoder = DecodeBinaryToBinaryW; 01143 break; 01144 case CRYPT_STRING_ANY: 01145 decoder = DecodeAnyW; 01146 break; 01147 case CRYPT_STRING_HEX: 01148 case CRYPT_STRING_HEXASCII: 01149 case CRYPT_STRING_HEXADDR: 01150 case CRYPT_STRING_HEXASCIIADDR: 01151 FIXME("Unimplemented type %d\n", dwFlags & 0x7fffffff); 01152 /* fall through */ 01153 default: 01154 SetLastError(ERROR_INVALID_PARAMETER); 01155 return FALSE; 01156 } 01157 if (!cchString) 01158 cchString = strlenW(pszString); 01159 ret = decoder(pszString, cchString, pbBinary, pcbBinary, pdwSkip, pdwFlags); 01160 if (ret) 01161 SetLastError(ret); 01162 return (ret == ERROR_SUCCESS) ? TRUE : FALSE; 01163 } Generated on Sun May 27 2012 04:23:10 for ReactOS by
1.7.6.1
|