ReactOS  0.4.14-dev-57-g333b8f1
base64.c
Go to the documentation of this file.
1 /*
2  * base64 encoder/decoder
3  *
4  * Copyright 2005 by Kai Blin
5  * Copyright 2006 Juan Lang
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "wincrypt.h"
27 #include "wine/debug.h"
28 #include "wine/unicode.h"
29 
31 
32 #define CERT_HEADER "-----BEGIN CERTIFICATE-----"
33 #define CERT_HEADER_START "-----BEGIN "
34 #define CERT_DELIMITER "-----"
35 #define CERT_TRAILER "-----END CERTIFICATE-----"
36 #define CERT_TRAILER_START "-----END "
37 #define CERT_REQUEST_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----"
38 #define CERT_REQUEST_TRAILER "-----END NEW CERTIFICATE REQUEST-----"
39 #define X509_HEADER "-----BEGIN X509 CRL-----"
40 #define X509_TRAILER "-----END X509 CRL-----"
41 
42 static const WCHAR CERT_HEADER_W[] = {
43 '-','-','-','-','-','B','E','G','I','N',' ','C','E','R','T','I','F','I','C',
44 'A','T','E','-','-','-','-','-',0 };
45 static const WCHAR CERT_HEADER_START_W[] = {
46 '-','-','-','-','-','B','E','G','I','N',' ',0 };
47 static const WCHAR CERT_DELIMITER_W[] = {
48 '-','-','-','-','-',0 };
49 static const WCHAR CERT_TRAILER_W[] = {
50 '-','-','-','-','-','E','N','D',' ','C','E','R','T','I','F','I','C','A','T',
51 'E','-','-','-','-','-',0 };
52 static const WCHAR CERT_TRAILER_START_W[] = {
53 '-','-','-','-','-','E','N','D',' ',0 };
54 static const WCHAR CERT_REQUEST_HEADER_W[] = {
55 '-','-','-','-','-','B','E','G','I','N',' ','N','E','W',' ','C','E','R','T',
56 'I','F','I','C','A','T','E',' ','R','E','Q','U','E','S','T','-','-','-','-','-',0 };
57 static const WCHAR CERT_REQUEST_TRAILER_W[] = {
58 '-','-','-','-','-','E','N','D',' ','N','E','W',' ','C','E','R','T','I','F',
59 'I','C','A','T','E',' ','R','E','Q','U','E','S','T','-','-','-','-','-',0 };
60 static const WCHAR X509_HEADER_W[] = {
61 '-','-','-','-','-','B','E','G','I','N',' ','X','5','0','9',' ','C','R','L',
62 '-','-','-','-','-',0 };
63 static const WCHAR X509_TRAILER_W[] = {
64 '-','-','-','-','-','E','N','D',' ','X','5','0','9',' ','C','R','L','-','-',
65 '-','-','-',0 };
66 
67 static const char b64[] =
68 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
69 
70 typedef BOOL (*BinaryToStringAFunc)(const BYTE *pbBinary,
72 typedef BOOL (*BinaryToStringWFunc)(const BYTE *pbBinary,
74 
75 static BOOL EncodeBinaryToBinaryA(const BYTE *pbBinary,
77 {
78  BOOL ret = TRUE;
79 
80  if (pszString)
81  {
82  if (*pcchString < cbBinary)
83  {
85  ret = FALSE;
86  }
87  else if (cbBinary)
88  memcpy(pszString, pbBinary, cbBinary);
89  }
90  else
92 
93  return ret;
94 }
95 
96 static LONG encodeBase64A(const BYTE *in_buf, int in_len, LPCSTR sep,
97  char* out_buf, DWORD *out_len)
98 {
99  int div, i;
100  const BYTE *d = in_buf;
101  int bytes = (in_len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
102  DWORD needed;
103  LPSTR ptr;
104 
105  TRACE("bytes is %d, pad bytes is %d\n", bytes, pad_bytes);
106  needed = bytes + pad_bytes;
107  needed += (needed / 64 + (needed % 64 ? 1 : 0)) * strlen(sep);
108  needed++;
109 
110  if (needed > *out_len)
111  {
112  *out_len = needed;
114  }
115  else
116  *out_len = needed;
117 
118  /* Three bytes of input give 4 chars of output */
119  div = in_len / 3;
120 
121  ptr = out_buf;
122  i = 0;
123  while (div > 0)
124  {
125  if (i && i % 64 == 0)
126  {
127  strcpy(ptr, sep);
128  ptr += strlen(sep);
129  }
130  /* first char is the first 6 bits of the first byte*/
131  *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
132  /* second char is the last 2 bits of the first byte and the first 4
133  * bits of the second byte */
134  *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
135  /* third char is the last 4 bits of the second byte and the first 2
136  * bits of the third byte */
137  *ptr++ = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)];
138  /* fourth char is the remaining 6 bits of the third byte */
139  *ptr++ = b64[ d[2] & 0x3f];
140  i += 4;
141  d += 3;
142  div--;
143  }
144 
145  switch(pad_bytes)
146  {
147  case 1:
148  /* first char is the first 6 bits of the first byte*/
149  *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
150  /* second char is the last 2 bits of the first byte and the first 4
151  * bits of the second byte */
152  *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
153  /* third char is the last 4 bits of the second byte padded with
154  * two zeroes */
155  *ptr++ = b64[ ((d[1] << 2) & 0x3c) ];
156  /* fourth char is a = to indicate one byte of padding */
157  *ptr++ = '=';
158  break;
159  case 2:
160  /* first char is the first 6 bits of the first byte*/
161  *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
162  /* second char is the last 2 bits of the first byte padded with
163  * four zeroes*/
164  *ptr++ = b64[ ((d[0] << 4) & 0x30)];
165  /* third char is = to indicate padding */
166  *ptr++ = '=';
167  /* fourth char is = to indicate padding */
168  *ptr++ = '=';
169  break;
170  }
171  strcpy(ptr, sep);
172 
173  return ERROR_SUCCESS;
174 }
175 
176 static BOOL BinaryToBase64A(const BYTE *pbBinary,
178 {
179  static const char crlf[] = "\r\n", lf[] = "\n";
180  BOOL ret = TRUE;
181  LPCSTR header = NULL, trailer = NULL, sep;
182  DWORD charsNeeded;
183 
185  sep = lf;
186  else if (dwFlags & CRYPT_STRING_NOCRLF)
187  sep = "";
188  else
189  sep = crlf;
190  switch (dwFlags & 0x0fffffff)
191  {
192  case CRYPT_STRING_BASE64:
193  /* no header or footer */
194  break;
197  trailer = CERT_TRAILER;
198  break;
201  trailer = CERT_REQUEST_TRAILER;
202  break;
205  trailer = X509_TRAILER;
206  break;
207  }
208 
209  charsNeeded = 0;
210  encodeBase64A(pbBinary, cbBinary, sep, NULL, &charsNeeded);
211  if (header)
212  charsNeeded += strlen(header) + strlen(sep);
213  if (trailer)
214  charsNeeded += strlen(trailer) + strlen(sep);
215 
216  if (pszString)
217  {
218  if (charsNeeded <= *pcchString)
219  {
220  LPSTR ptr = pszString;
221  DWORD size = charsNeeded;
222 
223  if (header)
224  {
225  strcpy(ptr, header);
226  ptr += strlen(ptr);
227  strcpy(ptr, sep);
228  ptr += strlen(sep);
229  }
230  encodeBase64A(pbBinary, cbBinary, sep, ptr, &size);
231  ptr += size - 1;
232  if (trailer)
233  {
234  strcpy(ptr, trailer);
235  ptr += strlen(ptr);
236  strcpy(ptr, sep);
237  }
238  *pcchString = charsNeeded - 1;
239  }
240  else
241  {
242  *pcchString = charsNeeded;
244  ret = FALSE;
245  }
246  }
247  else
248  *pcchString = charsNeeded;
249 
250  return ret;
251 }
252 
255 {
256  BinaryToStringAFunc encoder = NULL;
257 
258  TRACE("(%p, %d, %08x, %p, %p)\n", pbBinary, cbBinary, dwFlags, pszString,
259  pcchString);
260 
261  if (!pbBinary)
262  {
264  return FALSE;
265  }
266  if (!pcchString)
267  {
269  return FALSE;
270  }
271 
272  switch (dwFlags & 0x0fffffff)
273  {
274  case CRYPT_STRING_BINARY:
275  encoder = EncodeBinaryToBinaryA;
276  break;
277  case CRYPT_STRING_BASE64:
281  encoder = BinaryToBase64A;
282  break;
283  case CRYPT_STRING_HEX:
287  FIXME("Unimplemented type %d\n", dwFlags & 0x0fffffff);
288  /* fall through */
289  default:
291  return FALSE;
292  }
293  return encoder(pbBinary, cbBinary, dwFlags, pszString, pcchString);
294 }
295 
296 static BOOL EncodeBinaryToBinaryW(const BYTE *in_buf, DWORD in_len, DWORD flags, WCHAR *out_buf, DWORD *out_len)
297 {
298  BOOL ret = TRUE;
299 
300  if (out_buf)
301  {
302  if (*out_len < in_len)
303  {
305  ret = FALSE;
306  }
307  else if (in_len)
308  memcpy(out_buf, in_buf, in_len);
309  }
310  else
311  *out_len = in_len;
312 
313  return ret;
314 }
315 
316 static LONG encodeBase64W(const BYTE *in_buf, int in_len, LPCWSTR sep,
317  WCHAR* out_buf, DWORD *out_len)
318 {
319  int div, i;
320  const BYTE *d = in_buf;
321  int bytes = (in_len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
322  DWORD needed;
323  LPWSTR ptr;
324 
325  TRACE("bytes is %d, pad bytes is %d\n", bytes, pad_bytes);
326  needed = bytes + pad_bytes;
327  needed += (needed / 64 + (needed % 64 ? 1 : 0)) * strlenW(sep);
328  needed++;
329 
330  if (needed > *out_len)
331  {
332  *out_len = needed;
334  }
335  else
336  *out_len = needed;
337 
338  /* Three bytes of input give 4 chars of output */
339  div = in_len / 3;
340 
341  ptr = out_buf;
342  i = 0;
343  while (div > 0)
344  {
345  if (i && i % 64 == 0)
346  {
347  strcpyW(ptr, sep);
348  ptr += strlenW(sep);
349  }
350  /* first char is the first 6 bits of the first byte*/
351  *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
352  /* second char is the last 2 bits of the first byte and the first 4
353  * bits of the second byte */
354  *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
355  /* third char is the last 4 bits of the second byte and the first 2
356  * bits of the third byte */
357  *ptr++ = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)];
358  /* fourth char is the remaining 6 bits of the third byte */
359  *ptr++ = b64[ d[2] & 0x3f];
360  i += 4;
361  d += 3;
362  div--;
363  }
364 
365  switch(pad_bytes)
366  {
367  case 1:
368  /* first char is the first 6 bits of the first byte*/
369  *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
370  /* second char is the last 2 bits of the first byte and the first 4
371  * bits of the second byte */
372  *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
373  /* third char is the last 4 bits of the second byte padded with
374  * two zeroes */
375  *ptr++ = b64[ ((d[1] << 2) & 0x3c) ];
376  /* fourth char is a = to indicate one byte of padding */
377  *ptr++ = '=';
378  break;
379  case 2:
380  /* first char is the first 6 bits of the first byte*/
381  *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
382  /* second char is the last 2 bits of the first byte padded with
383  * four zeroes*/
384  *ptr++ = b64[ ((d[0] << 4) & 0x30)];
385  /* third char is = to indicate padding */
386  *ptr++ = '=';
387  /* fourth char is = to indicate padding */
388  *ptr++ = '=';
389  break;
390  }
391  strcpyW(ptr, sep);
392 
393  return ERROR_SUCCESS;
394 }
395 
396 static BOOL BinaryToBase64W(const BYTE *pbBinary,
398 {
399  static const WCHAR crlf[] = { '\r','\n',0 }, lf[] = { '\n',0 }, empty[] = {0};
400  BOOL ret = TRUE;
401  LPCWSTR header = NULL, trailer = NULL, sep;
402  DWORD charsNeeded;
403 
405  sep = lf;
406  else if (dwFlags & CRYPT_STRING_NOCRLF)
407  sep = empty;
408  else
409  sep = crlf;
410  switch (dwFlags & 0x0fffffff)
411  {
412  case CRYPT_STRING_BASE64:
413  /* no header or footer */
414  break;
417  trailer = CERT_TRAILER_W;
418  break;
421  trailer = CERT_REQUEST_TRAILER_W;
422  break;
425  trailer = X509_TRAILER_W;
426  break;
427  }
428 
429  charsNeeded = 0;
430  encodeBase64W(pbBinary, cbBinary, sep, NULL, &charsNeeded);
431  if (header)
432  charsNeeded += strlenW(header) + strlenW(sep);
433  if (trailer)
434  charsNeeded += strlenW(trailer) + strlenW(sep);
435 
436  if (pszString)
437  {
438  if (charsNeeded <= *pcchString)
439  {
440  LPWSTR ptr = pszString;
441  DWORD size = charsNeeded;
442 
443  if (header)
444  {
445  strcpyW(ptr, header);
446  ptr += strlenW(ptr);
447  strcpyW(ptr, sep);
448  ptr += strlenW(sep);
449  }
450  encodeBase64W(pbBinary, cbBinary, sep, ptr, &size);
451  ptr += size - 1;
452  if (trailer)
453  {
454  strcpyW(ptr, trailer);
455  ptr += strlenW(ptr);
456  strcpyW(ptr, sep);
457  }
458  *pcchString = charsNeeded - 1;
459  }
460  else
461  {
462  *pcchString = charsNeeded;
464  ret = FALSE;
465  }
466  }
467  else
468  *pcchString = charsNeeded;
469 
470  return ret;
471 }
472 
475 {
476  BinaryToStringWFunc encoder = NULL;
477 
478  TRACE("(%p, %d, %08x, %p, %p)\n", pbBinary, cbBinary, dwFlags, pszString,
479  pcchString);
480 
481  if (!pbBinary)
482  {
484  return FALSE;
485  }
486  if (!pcchString)
487  {
489  return FALSE;
490  }
491 
492  switch (dwFlags & 0x0fffffff)
493  {
494  case CRYPT_STRING_BINARY:
495  encoder = EncodeBinaryToBinaryW;
496  break;
497  case CRYPT_STRING_BASE64:
501  encoder = BinaryToBase64W;
502  break;
503  case CRYPT_STRING_HEX:
507  FIXME("Unimplemented type %d\n", dwFlags & 0x0fffffff);
508  /* fall through */
509  default:
511  return FALSE;
512  }
513  return encoder(pbBinary, cbBinary, dwFlags, pszString, pcchString);
514 }
515 
516 #define BASE64_DECODE_PADDING 0x100
517 #define BASE64_DECODE_WHITESPACE 0x200
518 #define BASE64_DECODE_INVALID 0x300
519 
520 static inline int decodeBase64Byte(int c)
521 {
523 
524  if (c >= 'A' && c <= 'Z')
525  ret = c - 'A';
526  else if (c >= 'a' && c <= 'z')
527  ret = c - 'a' + 26;
528  else if (c >= '0' && c <= '9')
529  ret = c - '0' + 52;
530  else if (c == '+')
531  ret = 62;
532  else if (c == '/')
533  ret = 63;
534  else if (c == '=')
536  else if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
538  return ret;
539 }
540 
541 /* Unlike CryptStringToBinaryA, cchString is guaranteed to be the length of the
542  * string to convert.
543  */
545  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags);
546 
547 static LONG Base64ToBinary(const void* pszString, BOOL wide, DWORD cchString,
548  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
549 {
550  DWORD cbIn, cbValid, cbOut, hasPadding;
551  BYTE block[4];
552  for (cbIn = cbValid = cbOut = hasPadding = 0; cbIn < cchString; ++cbIn)
553  {
554  int c = wide ? (int)((WCHAR*)pszString)[cbIn] : (int)((char*)pszString)[cbIn];
555  int d = decodeBase64Byte(c);
556  if (d == BASE64_DECODE_INVALID)
557  goto invalid;
559  continue;
560 
561  /* When padding starts, data is not acceptable */
562  if (hasPadding && d != BASE64_DECODE_PADDING)
563  goto invalid;
564 
565  /* Padding after a full block (like "VVVV=") is ok and stops decoding */
566  if (d == BASE64_DECODE_PADDING && (cbValid & 3) == 0)
567  break;
568 
569  cbValid += 1;
570 
571  if (d == BASE64_DECODE_PADDING)
572  {
573  hasPadding = 1;
574  /* When padding reaches a full block, stop decoding */
575  if ((cbValid & 3) == 0)
576  break;
577  continue;
578  }
579 
580  /* cbOut is incremented in the 4-char block as follows: "1-23" */
581  if ((cbValid & 3) != 2)
582  cbOut += 1;
583  }
584  /* Fail if the block has bad padding; omitting padding is fine */
585  if ((cbValid & 3) != 0 && hasPadding)
586  goto invalid;
587  /* Check available buffer size */
588  if (pbBinary && *pcbBinary && cbOut > *pcbBinary)
589  goto overflow;
590  /* Convert the data; this step depends on the validity checks above! */
591  if (pbBinary) for (cbIn = cbValid = cbOut = 0; cbIn < cchString; ++cbIn)
592  {
593  int c = wide ? (int)((WCHAR*)pszString)[cbIn] : (int)((char*)pszString)[cbIn];
594  int d = decodeBase64Byte(c);
596  continue;
597  if (d == BASE64_DECODE_PADDING)
598  break;
599  block[cbValid & 3] = d;
600  cbValid += 1;
601  switch (cbValid & 3) {
602  case 1:
603  pbBinary[cbOut++] = (block[0] << 2);
604  break;
605  case 2:
606  pbBinary[cbOut-1] = (block[0] << 2) | (block[1] >> 4);
607  break;
608  case 3:
609  pbBinary[cbOut++] = (block[1] << 4) | (block[2] >> 2);
610  break;
611  case 0:
612  pbBinary[cbOut++] = (block[2] << 6) | (block[3] >> 0);
613  break;
614  }
615  }
616  *pcbBinary = cbOut;
617  if (pdwSkip)
618  *pdwSkip = 0;
619  if (pdwFlags)
620  *pdwFlags = CRYPT_STRING_BASE64;
621  return ERROR_SUCCESS;
622 overflow:
624 invalid:
625  *pcbBinary = cbOut;
626  return ERROR_INVALID_DATA;
627 }
628 
630  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
631 {
632  return Base64ToBinary(pszString, FALSE, cchString, pbBinary, pcbBinary, pdwSkip, pdwFlags);
633 }
634 
636  DWORD cchString, BYTE *pbBinary,
637  DWORD *pcbBinary, DWORD *pdwSkip)
638 {
639  LONG ret;
641  LPCSTR trailer = CERT_TRAILER_START;
642 
643  LPCSTR headerBegins;
644  LPCSTR dataBegins;
645  LPCSTR trailerBegins;
646  size_t dataLength;
647 
648  if ((strlen(header) + strlen(trailer)) > cchString)
649  {
650  return ERROR_INVALID_DATA;
651  }
652 
653  if (!(headerBegins = strstr(pszString, header)))
654  {
655  TRACE("Can't find %s in %s.\n", header, debugstr_an(pszString, cchString));
656  return ERROR_INVALID_DATA;
657  }
658 
659  dataBegins = headerBegins + strlen(header);
660  if (!(dataBegins = strstr(dataBegins, CERT_DELIMITER)))
661  {
662  return ERROR_INVALID_DATA;
663  }
664  dataBegins += strlen(CERT_DELIMITER);
665  if (*dataBegins == '\r') dataBegins++;
666  if (*dataBegins == '\n') dataBegins++;
667 
668  if (!(trailerBegins = strstr(dataBegins, trailer)))
669  {
670  return ERROR_INVALID_DATA;
671  }
672  if (*(trailerBegins-1) == '\n') trailerBegins--;
673  if (*(trailerBegins-1) == '\r') trailerBegins--;
674 
675  if (pdwSkip)
676  *pdwSkip = headerBegins - pszString;
677 
678  dataLength = trailerBegins - dataBegins;
679 
680  ret = Base64ToBinaryA(dataBegins, dataLength, pbBinary, pcbBinary, NULL,
681  NULL);
682 
683  return ret;
684 }
685 
687  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
688 {
690  pbBinary, pcbBinary, pdwSkip);
691 
692  if (!ret && pdwFlags)
693  *pdwFlags = CRYPT_STRING_BASE64HEADER;
694  return ret;
695 }
696 
698  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
699 {
701  pbBinary, pcbBinary, pdwSkip);
702 
703  if (!ret && pdwFlags)
705  return ret;
706 }
707 
709  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
710 {
712  pbBinary, pcbBinary, pdwSkip);
713 
714  if (!ret && pdwFlags)
716  return ret;
717 }
718 
720  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
721 {
722  LONG ret;
723 
724  ret = Base64HeaderToBinaryA(pszString, cchString, pbBinary, pcbBinary,
725  pdwSkip, pdwFlags);
726  if (ret == ERROR_INVALID_DATA)
727  ret = Base64ToBinaryA(pszString, cchString, pbBinary, pcbBinary,
728  pdwSkip, pdwFlags);
729  return ret;
730 }
731 
733  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
734 {
736 
737  if (*pcbBinary < cchString)
738  {
739  if (!pbBinary)
740  *pcbBinary = cchString;
741  else
742  {
744  *pcbBinary = cchString;
745  }
746  }
747  else
748  {
749  if (cchString)
750  memcpy(pbBinary, pszString, cchString);
751  *pcbBinary = cchString;
752  }
753  return ret;
754 }
755 
757  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
758 {
759  LONG ret;
760 
761  ret = Base64HeaderToBinaryA(pszString, cchString, pbBinary, pcbBinary,
762  pdwSkip, pdwFlags);
763  if (ret == ERROR_INVALID_DATA)
764  ret = Base64ToBinaryA(pszString, cchString, pbBinary, pcbBinary,
765  pdwSkip, pdwFlags);
766  if (ret == ERROR_INVALID_DATA)
767  ret = DecodeBinaryToBinaryA(pszString, cchString, pbBinary, pcbBinary,
768  pdwSkip, pdwFlags);
769  return ret;
770 }
771 
773  DWORD cchString, DWORD dwFlags, BYTE *pbBinary, DWORD *pcbBinary,
774  DWORD *pdwSkip, DWORD *pdwFlags)
775 {
776  StringToBinaryAFunc decoder;
777  LONG ret;
778 
779  TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_an(pszString, cchString ? cchString : -1),
780  cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags);
781 
782  if (!pszString)
783  {
785  return FALSE;
786  }
787  /* Only the bottom byte contains valid types */
788  if (dwFlags & 0xfffffff0)
789  {
791  return FALSE;
792  }
793  switch (dwFlags)
794  {
796  decoder = Base64AnyToBinaryA;
797  break;
798  case CRYPT_STRING_BASE64:
799  decoder = Base64ToBinaryA;
800  break;
802  decoder = Base64HeaderToBinaryA;
803  break;
806  break;
808  decoder = Base64X509HeaderToBinaryA;
809  break;
810  case CRYPT_STRING_BINARY:
811  decoder = DecodeBinaryToBinaryA;
812  break;
813  case CRYPT_STRING_ANY:
814  decoder = DecodeAnyA;
815  break;
816  case CRYPT_STRING_HEX:
820  FIXME("Unimplemented type %d\n", dwFlags & 0x7fffffff);
821  /* fall through */
822  default:
824  return FALSE;
825  }
826  if (!cchString)
827  cchString = strlen(pszString);
828  ret = decoder(pszString, cchString, pbBinary, pcbBinary, pdwSkip, pdwFlags);
829  if (ret)
830  SetLastError(ret);
831  return ret == ERROR_SUCCESS;
832 }
833 
834 /* Unlike CryptStringToBinaryW, cchString is guaranteed to be the length of the
835  * string to convert.
836  */
838  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags);
839 
841  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
842 {
843  return Base64ToBinary(pszString, TRUE, cchString, pbBinary, pcbBinary, pdwSkip, pdwFlags);
844 }
845 
847  DWORD cchString, BYTE *pbBinary,
848  DWORD *pcbBinary, DWORD *pdwSkip)
849 {
850  LONG ret;
852  LPCWSTR trailer = CERT_TRAILER_START_W;
853 
854  LPCWSTR headerBegins;
855  LPCWSTR dataBegins;
856  LPCWSTR trailerBegins;
857  size_t dataLength;
858 
859  if ((strlenW(header) + strlenW(trailer)) > cchString)
860  {
861  return ERROR_INVALID_DATA;
862  }
863 
864  if (!(headerBegins = strstrW(pszString, header)))
865  {
866  TRACE("Can't find %s in %s.\n", debugstr_w(header), debugstr_wn(pszString, cchString));
867  return ERROR_INVALID_DATA;
868  }
869 
870  dataBegins = headerBegins + strlenW(header);
871  if (!(dataBegins = strstrW(dataBegins, CERT_DELIMITER_W)))
872  {
873  return ERROR_INVALID_DATA;
874  }
875  dataBegins += strlenW(CERT_DELIMITER_W);
876  if (*dataBegins == '\r') dataBegins++;
877  if (*dataBegins == '\n') dataBegins++;
878 
879  if (!(trailerBegins = strstrW(dataBegins, trailer)))
880  {
881  return ERROR_INVALID_DATA;
882  }
883  if (*(trailerBegins-1) == '\n') trailerBegins--;
884  if (*(trailerBegins-1) == '\r') trailerBegins--;
885 
886  if (pdwSkip)
887  *pdwSkip = headerBegins - pszString;
888 
889  dataLength = trailerBegins - dataBegins;
890 
891  ret = Base64ToBinaryW(dataBegins, dataLength, pbBinary, pcbBinary, NULL,
892  NULL);
893 
894  return ret;
895 }
896 
898  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
899 {
901  pbBinary, pcbBinary, pdwSkip);
902 
903  if (!ret && pdwFlags)
904  *pdwFlags = CRYPT_STRING_BASE64HEADER;
905  return ret;
906 }
907 
909  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
910 {
912  pbBinary, pcbBinary, pdwSkip);
913 
914  if (!ret && pdwFlags)
916  return ret;
917 }
918 
920  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
921 {
923  pbBinary, pcbBinary, pdwSkip);
924 
925  if (!ret && pdwFlags)
927  return ret;
928 }
929 
931  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
932 {
933  LONG ret;
934 
935  ret = Base64HeaderToBinaryW(pszString, cchString, pbBinary, pcbBinary,
936  pdwSkip, pdwFlags);
937  if (ret == ERROR_INVALID_DATA)
938  ret = Base64ToBinaryW(pszString, cchString, pbBinary, pcbBinary,
939  pdwSkip, pdwFlags);
940  return ret;
941 }
942 
944  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
945 {
947 
948  if (*pcbBinary < cchString)
949  {
950  if (!pbBinary)
951  *pcbBinary = cchString;
952  else
953  {
955  *pcbBinary = cchString;
956  }
957  }
958  else
959  {
960  if (cchString)
961  memcpy(pbBinary, pszString, cchString * sizeof(WCHAR));
962  *pcbBinary = cchString * sizeof(WCHAR);
963  }
964  return ret;
965 }
966 
968  BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
969 {
970  LONG ret;
971 
972  ret = Base64HeaderToBinaryW(pszString, cchString, pbBinary, pcbBinary,
973  pdwSkip, pdwFlags);
974  if (ret == ERROR_INVALID_DATA)
975  ret = Base64ToBinaryW(pszString, cchString, pbBinary, pcbBinary,
976  pdwSkip, pdwFlags);
977  if (ret == ERROR_INVALID_DATA)
978  ret = DecodeBinaryToBinaryW(pszString, cchString, pbBinary, pcbBinary,
979  pdwSkip, pdwFlags);
980  return ret;
981 }
982 
984  DWORD cchString, DWORD dwFlags, BYTE *pbBinary, DWORD *pcbBinary,
985  DWORD *pdwSkip, DWORD *pdwFlags)
986 {
987  StringToBinaryWFunc decoder;
988  LONG ret;
989 
990  TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_wn(pszString, cchString ? cchString : -1),
991  cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags);
992 
993  if (!pszString)
994  {
996  return FALSE;
997  }
998  /* Only the bottom byte contains valid types */
999  if (dwFlags & 0xfffffff0)
1000  {
1002  return FALSE;
1003  }
1004  switch (dwFlags)
1005  {
1007  decoder = Base64AnyToBinaryW;
1008  break;
1009  case CRYPT_STRING_BASE64:
1010  decoder = Base64ToBinaryW;
1011  break;
1013  decoder = Base64HeaderToBinaryW;
1014  break;
1016  decoder = Base64RequestHeaderToBinaryW;
1017  break;
1019  decoder = Base64X509HeaderToBinaryW;
1020  break;
1021  case CRYPT_STRING_BINARY:
1022  decoder = DecodeBinaryToBinaryW;
1023  break;
1024  case CRYPT_STRING_ANY:
1025  decoder = DecodeAnyW;
1026  break;
1027  case CRYPT_STRING_HEX:
1028  case CRYPT_STRING_HEXASCII:
1029  case CRYPT_STRING_HEXADDR:
1031  FIXME("Unimplemented type %d\n", dwFlags & 0x7fffffff);
1032  /* fall through */
1033  default:
1035  return FALSE;
1036  }
1037  if (!cchString)
1038  cchString = strlenW(pszString);
1039  ret = decoder(pszString, cchString, pbBinary, pcbBinary, pdwSkip, pdwFlags);
1040  if (ret)
1041  SetLastError(ret);
1042  return ret == ERROR_SUCCESS;
1043 }
static unsigned int block
Definition: xmlmemory.c:118
static LONG Base64AnyToBinaryW(LPCWSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:930
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
static LONG Base64WithHeaderAndTrailerToBinaryA(LPCSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip)
Definition: base64.c:635
BOOL WINAPI CryptBinaryToStringW(const BYTE *pbBinary, DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString)
Definition: base64.c:473
static const WCHAR invalid[]
Definition: assoc.c:39
#define CRYPT_STRING_BASE64X509CRLHEADER
Definition: wincrypt.h:2993
LONG(* StringToBinaryWFunc)(LPCWSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:837
static const WCHAR CERT_HEADER_START_W[]
Definition: base64.c:45
#define CRYPT_STRING_HEXASCIIADDR
Definition: wincrypt.h:2995
static LONG Base64AnyToBinaryA(LPCSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:719
#define CERT_REQUEST_TRAILER
Definition: base64.c:38
#define TRUE
Definition: types.h:120
_In_ DWORD cbBinary
Definition: wincrypt.h:4507
static const WCHAR CERT_TRAILER_W[]
Definition: base64.c:49
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define ERROR_SUCCESS
Definition: deptool.c:10
#define CRYPT_STRING_HEXADDR
Definition: wincrypt.h:2994
static int decodeBase64Byte(int c)
Definition: base64.c:520
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
static LONG Base64HeaderToBinaryW(LPCWSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:897
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define CRYPT_STRING_BASE64_ANY
Definition: wincrypt.h:2990
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
static BOOL BinaryToBase64W(const BYTE *pbBinary, DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString)
Definition: base64.c:396
static const WCHAR empty[]
Definition: main.c:49
static const WCHAR CERT_REQUEST_TRAILER_W[]
Definition: base64.c:57
#define CERT_HEADER
Definition: base64.c:32
static BOOL BinaryToBase64A(const BYTE *pbBinary, DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString)
Definition: base64.c:176
#define BASE64_DECODE_INVALID
Definition: base64.c:518
static LONG DecodeBinaryToBinaryW(LPCWSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:943
#define CERT_HEADER_START
Definition: base64.c:33
static LONG Base64ToBinary(const void *pszString, BOOL wide, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:547
static const WCHAR CERT_HEADER_W[]
Definition: base64.c:42
#define CRYPT_STRING_BASE64REQUESTHEADER
Definition: wincrypt.h:2987
static LONG Base64RequestHeaderToBinaryW(LPCWSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:908
char * LPSTR
Definition: xmlstorage.h:182
#define BOOL
Definition: nt_native.h:43
static const WCHAR CERT_DELIMITER_W[]
Definition: base64.c:47
BOOL(* BinaryToStringWFunc)(const BYTE *pbBinary, DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString)
Definition: base64.c:72
_In_ DWORD _In_ DWORD _Out_writes_to_opt_ pcchString LPSTR _Inout_ DWORD * pcchString
Definition: wincrypt.h:4509
static const char b64[]
Definition: base64.c:67
static LONG Base64ToBinaryW(LPCWSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:840
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define CERT_TRAILER
Definition: base64.c:35
static const WCHAR CERT_TRAILER_START_W[]
Definition: base64.c:52
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
static LONG Base64ToBinaryA(LPCSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:629
BOOL WINAPI CryptStringToBinaryW(LPCWSTR pszString, DWORD cchString, DWORD dwFlags, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:983
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
WINE_DEFAULT_DEBUG_CHANNEL(crypt)
static LONG DecodeAnyA(LPCSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:756
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:110
static PVOID ptr
Definition: dispmode.c:27
#define CERT_REQUEST_HEADER
Definition: base64.c:37
#define strstrW(d, s)
Definition: unicode.h:32
smooth NULL
Definition: ftsmooth.c:416
#define CRYPT_STRING_BINARY
Definition: wincrypt.h:2986
#define CRYPT_STRING_ANY
Definition: wincrypt.h:2991
const char * LPCSTR
Definition: xmlstorage.h:183
static LONG Base64X509HeaderToBinaryA(LPCSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:708
#define CRYPT_STRING_HEXASCII
Definition: wincrypt.h:2989
static LONG DecodeBinaryToBinaryA(LPCSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:732
static LONG Base64RequestHeaderToBinaryA(LPCSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:697
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define d
Definition: ke_i.h:81
BOOL WINAPI CryptStringToBinaryA(LPCSTR pszString, DWORD cchString, DWORD dwFlags, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:772
__wchar_t WCHAR
Definition: xmlstorage.h:180
_STLP_VENDOR_CSTD::ldiv_t div(long __x, long __y)
Definition: _cstdlib.h:137
#define CRYPT_STRING_BASE64
Definition: wincrypt.h:2985
static LONG Base64WithHeaderAndTrailerToBinaryW(LPCWSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip)
Definition: base64.c:846
#define WINAPI
Definition: msvc.h:8
const GLubyte * c
Definition: glext.h:8905
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:409
static LONG encodeBase64W(const BYTE *in_buf, int in_len, LPCWSTR sep, WCHAR *out_buf, DWORD *out_len)
Definition: base64.c:316
GLbitfield flags
Definition: glext.h:7161
#define BASE64_DECODE_WHITESPACE
Definition: base64.c:517
int ret
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:47
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned char BYTE
Definition: mem.h:68
BOOL(* BinaryToStringAFunc)(const BYTE *pbBinary, DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString)
Definition: base64.c:70
#define X509_TRAILER
Definition: base64.c:40
#define debugstr_wn
Definition: kernel32.h:33
static LONG Base64HeaderToBinaryA(LPCSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:686
#define ERROR_INVALID_DATA
Definition: winerror.h:116
LONG(* StringToBinaryAFunc)(LPCSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:544
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
static LONG Base64X509HeaderToBinaryW(LPCWSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:919
#define CRYPT_STRING_HEX
Definition: wincrypt.h:2988
#define CRYPT_STRING_NOCR
Definition: wincrypt.h:2997
#define CERT_TRAILER_START
Definition: base64.c:36
static LONG DecodeAnyW(LPCWSTR pszString, DWORD cchString, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
Definition: base64.c:967
static LONG encodeBase64A(const BYTE *in_buf, int in_len, LPCSTR sep, char *out_buf, DWORD *out_len)
Definition: base64.c:96
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define CRYPT_STRING_BASE64HEADER
Definition: wincrypt.h:2984
static const WCHAR X509_TRAILER_W[]
Definition: base64.c:63
BOOL WINAPI CryptBinaryToStringA(const BYTE *pbBinary, DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString)
Definition: base64.c:253
#define X509_HEADER
Definition: base64.c:39
static BOOL EncodeBinaryToBinaryW(const BYTE *in_buf, DWORD in_len, DWORD flags, WCHAR *out_buf, DWORD *out_len)
Definition: base64.c:296
static const WCHAR crlf[]
Definition: object.c:1018
static BOOL EncodeBinaryToBinaryA(const BYTE *pbBinary, DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString)
Definition: base64.c:75
#define CRYPT_STRING_NOCRLF
Definition: wincrypt.h:2996
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define BASE64_DECODE_PADDING
Definition: base64.c:516
static const WCHAR CERT_REQUEST_HEADER_W[]
Definition: base64.c:54
struct CFHEADER header
Definition: fdi.c:109
#define CERT_DELIMITER
Definition: base64.c:34
_In_ DWORD _In_ DWORD _Out_writes_to_opt_ pcchString LPSTR pszString
Definition: wincrypt.h:4509
static const WCHAR X509_HEADER_W[]
Definition: base64.c:60
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10