2 * base64 encoder/decoder
4 * Copyright 2005 by Kai Blin
5 * Copyright 2006 Juan Lang
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.
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.
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
27 #include "wine/debug.h"
28 #include "wine/unicode.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
32 #define CERT_HEADER "-----BEGIN CERTIFICATE-----"
33 #define CERT_TRAILER "-----END CERTIFICATE-----"
34 #define CERT_REQUEST_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----"
35 #define CERT_REQUEST_TRAILER "-----END NEW CERTIFICATE REQUEST-----"
36 #define X509_HEADER "-----BEGIN X509 CRL-----"
37 #define X509_TRAILER "-----END X509 CRL-----"
39 static const WCHAR CERT_HEADER_W
[] = {
40 '-','-','-','-','-','B','E','G','I','N',' ','C','E','R','T','I','F','I','C',
41 'A','T','E','-','-','-','-','-',0 };
42 static const WCHAR CERT_TRAILER_W
[] = {
43 '-','-','-','-','-','E','N','D',' ','C','E','R','T','I','F','I','C','A','T',
44 'E','-','-','-','-','-',0 };
45 static const WCHAR CERT_REQUEST_HEADER_W
[] = {
46 '-','-','-','-','-','B','E','G','I','N',' ','N','E','W',' ','C','E','R','T',
47 'I','F','I','C','A','T','E','R','E','Q','U','E','S','T','-','-','-','-','-',0 };
48 static const WCHAR CERT_REQUEST_TRAILER_W
[] = {
49 '-','-','-','-','-','E','N','D',' ','N','E','W',' ','C','E','R','T','I','F',
50 'I','C','A','T','E','R','E','Q','U','E','S','T','-','-','-','-','-',0 };
51 static const WCHAR X509_HEADER_W
[] = {
52 '-','-','-','-','-','B','E','G','I','N',' ','X','5','0','9',' ','C','R','L',
53 '-','-','-','-','-',0 };
54 static const WCHAR X509_TRAILER_W
[] = {
55 '-','-','-','-','-','E','N','D',' ','X','5','0','9',' ','C','R','L','-','-',
58 static const char b64
[] =
59 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
61 typedef BOOL (*BinaryToStringAFunc
)(const BYTE
*pbBinary
,
62 DWORD cbBinary
, DWORD dwFlags
, LPSTR pszString
, DWORD
*pcchString
);
64 static BOOL
EncodeBinaryToBinaryA(const BYTE
*pbBinary
,
65 DWORD cbBinary
, DWORD dwFlags
, LPSTR pszString
, DWORD
*pcchString
)
69 if (*pcchString
< cbBinary
)
72 *pcchString
= cbBinary
;
75 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
76 *pcchString
= cbBinary
;
83 memcpy(pszString
, pbBinary
, cbBinary
);
84 *pcchString
= cbBinary
;
89 static LONG
encodeBase64A(const BYTE
*in_buf
, int in_len
, LPCSTR sep
,
90 char* out_buf
, DWORD
*out_len
)
93 const BYTE
*d
= in_buf
;
94 int bytes
= (in_len
*8 + 5)/6, pad_bytes
= (bytes
% 4) ? 4 - (bytes
% 4) : 0;
98 TRACE("bytes is %d, pad bytes is %d\n", bytes
, pad_bytes
);
99 needed
= bytes
+ pad_bytes
+ 1;
100 needed
+= (needed
/ 64 + 1) * strlen(sep
);
102 if (needed
> *out_len
)
105 return ERROR_INSUFFICIENT_BUFFER
;
110 /* Three bytes of input give 4 chars of output */
117 if (i
&& i
% 64 == 0)
122 /* first char is the first 6 bits of the first byte*/
123 *ptr
++ = b64
[ ( d
[0] >> 2) & 0x3f ];
124 /* second char is the last 2 bits of the first byte and the first 4
125 * bits of the second byte */
126 *ptr
++ = b64
[ ((d
[0] << 4) & 0x30) | (d
[1] >> 4 & 0x0f)];
127 /* third char is the last 4 bits of the second byte and the first 2
128 * bits of the third byte */
129 *ptr
++ = b64
[ ((d
[1] << 2) & 0x3c) | (d
[2] >> 6 & 0x03)];
130 /* fourth char is the remaining 6 bits of the third byte */
131 *ptr
++ = b64
[ d
[2] & 0x3f];
140 /* first char is the first 6 bits of the first byte*/
141 *ptr
++ = b64
[ ( d
[0] >> 2) & 0x3f ];
142 /* second char is the last 2 bits of the first byte and the first 4
143 * bits of the second byte */
144 *ptr
++ = b64
[ ((d
[0] << 4) & 0x30) | (d
[1] >> 4 & 0x0f)];
145 /* third char is the last 4 bits of the second byte padded with
147 *ptr
++ = b64
[ ((d
[1] << 2) & 0x3c) ];
148 /* fourth char is a = to indicate one byte of padding */
152 /* first char is the first 6 bits of the first byte*/
153 *ptr
++ = b64
[ ( d
[0] >> 2) & 0x3f ];
154 /* second char is the last 2 bits of the first byte padded with
156 *ptr
++ = b64
[ ((d
[0] << 4) & 0x30)];
157 /* third char is = to indicate padding */
159 /* fourth char is = to indicate padding */
165 return ERROR_SUCCESS
;
168 static BOOL
BinaryToBase64A(const BYTE
*pbBinary
,
169 DWORD cbBinary
, DWORD dwFlags
, LPSTR pszString
, DWORD
*pcchString
)
171 static const char crlf
[] = "\r\n", lf
[] = "\n";
173 LPCSTR header
= NULL
, trailer
= NULL
, sep
= NULL
;
176 if (dwFlags
& CRYPT_STRING_NOCR
)
180 switch (dwFlags
& 0x7fffffff)
182 case CRYPT_STRING_BASE64
:
183 /* no header or footer */
185 case CRYPT_STRING_BASE64HEADER
:
186 header
= CERT_HEADER
;
187 trailer
= CERT_TRAILER
;
189 case CRYPT_STRING_BASE64REQUESTHEADER
:
190 header
= CERT_REQUEST_HEADER
;
191 trailer
= CERT_REQUEST_TRAILER
;
193 case CRYPT_STRING_BASE64X509CRLHEADER
:
194 header
= X509_HEADER
;
195 trailer
= X509_TRAILER
;
200 encodeBase64A(pbBinary
, cbBinary
, sep
, NULL
, &charsNeeded
);
201 charsNeeded
+= strlen(sep
);
203 charsNeeded
+= strlen(header
) + strlen(sep
);
205 charsNeeded
+= strlen(trailer
) + strlen(sep
);
206 if (charsNeeded
<= *pcchString
)
208 LPSTR ptr
= pszString
;
209 DWORD size
= charsNeeded
;
218 encodeBase64A(pbBinary
, cbBinary
, sep
, ptr
, &size
);
222 strcpy(ptr
, trailer
);
227 *pcchString
= charsNeeded
- 1;
231 *pcchString
= charsNeeded
;
232 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
236 *pcchString
= charsNeeded
;
240 BOOL WINAPI
CryptBinaryToStringA(const BYTE
*pbBinary
,
241 DWORD cbBinary
, DWORD dwFlags
, LPSTR pszString
, DWORD
*pcchString
)
243 BinaryToStringAFunc encoder
= NULL
;
245 TRACE("(%p, %d, %08x, %p, %p)\n", pbBinary
, cbBinary
, dwFlags
, pszString
,
250 SetLastError(ERROR_INVALID_PARAMETER
);
255 SetLastError(ERROR_INVALID_PARAMETER
);
259 switch (dwFlags
& 0x7fffffff)
261 case CRYPT_STRING_BINARY
:
262 encoder
= EncodeBinaryToBinaryA
;
264 case CRYPT_STRING_BASE64
:
265 case CRYPT_STRING_BASE64HEADER
:
266 case CRYPT_STRING_BASE64REQUESTHEADER
:
267 case CRYPT_STRING_BASE64X509CRLHEADER
:
268 encoder
= BinaryToBase64A
;
270 case CRYPT_STRING_HEX
:
271 case CRYPT_STRING_HEXASCII
:
272 case CRYPT_STRING_HEXADDR
:
273 case CRYPT_STRING_HEXASCIIADDR
:
274 FIXME("Unimplemented type %d\n", dwFlags
& 0x7fffffff);
277 SetLastError(ERROR_INVALID_PARAMETER
);
280 return encoder(pbBinary
, cbBinary
, dwFlags
, pszString
, pcchString
);
283 static inline BYTE
decodeBase64Byte(int c
)
287 if (c
>= 'A' && c
<= 'Z')
289 else if (c
>= 'a' && c
<= 'z')
291 else if (c
>= '0' && c
<= '9')
302 static LONG
decodeBase64Block(const char *in_buf
, int in_len
,
303 const char **nextBlock
, PBYTE out_buf
, DWORD
*out_len
)
306 const char *d
= in_buf
;
307 int ip0
, ip1
, ip2
, ip3
;
310 return ERROR_INVALID_DATA
;
315 if ((ip0
= decodeBase64Byte(d
[0])) > 63)
316 return ERROR_INVALID_DATA
;
317 if ((ip1
= decodeBase64Byte(d
[1])) > 63)
318 return ERROR_INVALID_DATA
;
321 out_buf
[i
] = (ip0
<< 2) | (ip1
>> 4);
324 else if (d
[3] == '=')
326 if ((ip0
= decodeBase64Byte(d
[0])) > 63)
327 return ERROR_INVALID_DATA
;
328 if ((ip1
= decodeBase64Byte(d
[1])) > 63)
329 return ERROR_INVALID_DATA
;
330 if ((ip2
= decodeBase64Byte(d
[2])) > 63)
331 return ERROR_INVALID_DATA
;
335 out_buf
[i
+ 0] = (ip0
<< 2) | (ip1
>> 4);
336 out_buf
[i
+ 1] = (ip1
<< 4) | (ip2
>> 2);
342 if ((ip0
= decodeBase64Byte(d
[0])) > 63)
343 return ERROR_INVALID_DATA
;
344 if ((ip1
= decodeBase64Byte(d
[1])) > 63)
345 return ERROR_INVALID_DATA
;
346 if ((ip2
= decodeBase64Byte(d
[2])) > 63)
347 return ERROR_INVALID_DATA
;
348 if ((ip3
= decodeBase64Byte(d
[3])) > 63)
349 return ERROR_INVALID_DATA
;
353 out_buf
[i
+ 0] = (ip0
<< 2) | (ip1
>> 4);
354 out_buf
[i
+ 1] = (ip1
<< 4) | (ip2
>> 2);
355 out_buf
[i
+ 2] = (ip2
<< 6) | ip3
;
359 if (len
>= 6 && d
[4] == '\r' && d
[5] == '\n')
361 else if (len
>= 5 && d
[4] == '\n')
363 else if (len
>= 4 && d
[4])
368 return ERROR_SUCCESS
;
371 /* Unlike CryptStringToBinaryA, cchString is guaranteed to be the length of the
374 typedef LONG (*StringToBinaryAFunc
)(LPCSTR pszString
, DWORD cchString
,
375 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
);
377 static LONG
Base64ToBinaryA(LPCSTR pszString
, DWORD cchString
,
378 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
380 LONG ret
= ERROR_SUCCESS
;
381 const char *nextBlock
;
384 nextBlock
= pszString
;
385 while (nextBlock
&& !ret
)
389 ret
= decodeBase64Block(nextBlock
, cchString
- (nextBlock
- pszString
),
390 &nextBlock
, pbBinary
? pbBinary
+ outLen
: NULL
, &len
);
393 if (cchString
- (nextBlock
- pszString
) <= 0)
402 *pdwFlags
= CRYPT_STRING_BASE64
;
404 else if (ret
== ERROR_INSUFFICIENT_BUFFER
)
412 static LONG
Base64WithHeaderAndTrailerToBinaryA(LPCSTR pszString
,
413 DWORD cchString
, LPCSTR header
, LPCSTR trailer
, BYTE
*pbBinary
,
414 DWORD
*pcbBinary
, DWORD
*pdwSkip
)
419 if (cchString
> strlen(header
) + strlen(trailer
)
420 && (ptr
= strstr(pszString
, header
)) != NULL
)
422 LPCSTR trailerSpot
= pszString
+ cchString
- strlen(trailer
);
424 if (pszString
[cchString
- 1] == '\n')
429 if (pszString
[cchString
- 1] == '\r')
434 if (!strncmp(trailerSpot
, trailer
, strlen(trailer
)))
437 *pdwSkip
= ptr
- pszString
;
438 ptr
+= strlen(header
);
439 if (*ptr
== '\r') ptr
++;
440 if (*ptr
== '\n') ptr
++;
441 cchString
-= ptr
- pszString
+ strlen(trailer
);
442 ret
= Base64ToBinaryA(ptr
, cchString
, pbBinary
, pcbBinary
, NULL
,
446 ret
= ERROR_INVALID_DATA
;
449 ret
= ERROR_INVALID_DATA
;
453 static LONG
Base64HeaderToBinaryA(LPCSTR pszString
, DWORD cchString
,
454 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
456 LONG ret
= Base64WithHeaderAndTrailerToBinaryA(pszString
, cchString
,
457 CERT_HEADER
, CERT_TRAILER
, pbBinary
, pcbBinary
, pdwSkip
);
459 if (!ret
&& pdwFlags
)
460 *pdwFlags
= CRYPT_STRING_BASE64HEADER
;
464 static LONG
Base64RequestHeaderToBinaryA(LPCSTR pszString
, DWORD cchString
,
465 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
467 LONG ret
= Base64WithHeaderAndTrailerToBinaryA(pszString
, cchString
,
468 CERT_REQUEST_HEADER
, CERT_REQUEST_TRAILER
, pbBinary
, pcbBinary
, pdwSkip
);
470 if (!ret
&& pdwFlags
)
471 *pdwFlags
= CRYPT_STRING_BASE64REQUESTHEADER
;
475 static LONG
Base64X509HeaderToBinaryA(LPCSTR pszString
, DWORD cchString
,
476 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
478 LONG ret
= Base64WithHeaderAndTrailerToBinaryA(pszString
, cchString
,
479 X509_HEADER
, X509_TRAILER
, pbBinary
, pcbBinary
, pdwSkip
);
481 if (!ret
&& pdwFlags
)
482 *pdwFlags
= CRYPT_STRING_BASE64X509CRLHEADER
;
486 static LONG
Base64AnyToBinaryA(LPCSTR pszString
, DWORD cchString
,
487 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
491 ret
= Base64HeaderToBinaryA(pszString
, cchString
, pbBinary
, pcbBinary
,
493 if (ret
== ERROR_INVALID_DATA
)
494 ret
= Base64ToBinaryA(pszString
, cchString
, pbBinary
, pcbBinary
,
499 static LONG
DecodeBinaryToBinaryA(LPCSTR pszString
, DWORD cchString
,
500 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
502 LONG ret
= ERROR_SUCCESS
;
504 if (*pcbBinary
< cchString
)
507 *pcbBinary
= cchString
;
510 ret
= ERROR_INSUFFICIENT_BUFFER
;
511 *pcbBinary
= cchString
;
517 memcpy(pbBinary
, pszString
, cchString
);
518 *pcbBinary
= cchString
;
523 static LONG
DecodeAnyA(LPCSTR pszString
, DWORD cchString
,
524 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
528 ret
= Base64HeaderToBinaryA(pszString
, cchString
, pbBinary
, pcbBinary
,
530 if (ret
== ERROR_INVALID_DATA
)
531 ret
= Base64ToBinaryA(pszString
, cchString
, pbBinary
, pcbBinary
,
533 if (ret
== ERROR_INVALID_DATA
)
534 ret
= DecodeBinaryToBinaryA(pszString
, cchString
, pbBinary
, pcbBinary
,
539 BOOL WINAPI
CryptStringToBinaryA(LPCSTR pszString
,
540 DWORD cchString
, DWORD dwFlags
, BYTE
*pbBinary
, DWORD
*pcbBinary
,
541 DWORD
*pdwSkip
, DWORD
*pdwFlags
)
543 StringToBinaryAFunc decoder
;
546 TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_a(pszString
),
547 cchString
, dwFlags
, pbBinary
, pcbBinary
, pdwSkip
, pdwFlags
);
551 SetLastError(ERROR_INVALID_PARAMETER
);
554 /* Only the bottom byte contains valid types */
555 if (dwFlags
& 0xfffffff0)
557 SetLastError(ERROR_INVALID_DATA
);
562 case CRYPT_STRING_BASE64_ANY
:
563 decoder
= Base64AnyToBinaryA
;
565 case CRYPT_STRING_BASE64
:
566 decoder
= Base64ToBinaryA
;
568 case CRYPT_STRING_BASE64HEADER
:
569 decoder
= Base64HeaderToBinaryA
;
571 case CRYPT_STRING_BASE64REQUESTHEADER
:
572 decoder
= Base64RequestHeaderToBinaryA
;
574 case CRYPT_STRING_BASE64X509CRLHEADER
:
575 decoder
= Base64X509HeaderToBinaryA
;
577 case CRYPT_STRING_BINARY
:
578 decoder
= DecodeBinaryToBinaryA
;
580 case CRYPT_STRING_ANY
:
581 decoder
= DecodeAnyA
;
583 case CRYPT_STRING_HEX
:
584 case CRYPT_STRING_HEXASCII
:
585 case CRYPT_STRING_HEXADDR
:
586 case CRYPT_STRING_HEXASCIIADDR
:
587 FIXME("Unimplemented type %d\n", dwFlags
& 0x7fffffff);
590 SetLastError(ERROR_INVALID_PARAMETER
);
594 cchString
= strlen(pszString
);
595 ret
= decoder(pszString
, cchString
, pbBinary
, pcbBinary
, pdwSkip
, pdwFlags
);
598 return (ret
== ERROR_SUCCESS
) ? TRUE
: FALSE
;
601 static LONG
decodeBase64BlockW(const WCHAR
*in_buf
, int in_len
,
602 const WCHAR
**nextBlock
, PBYTE out_buf
, DWORD
*out_len
)
605 const WCHAR
*d
= in_buf
;
606 int ip0
, ip1
, ip2
, ip3
;
609 return ERROR_INVALID_DATA
;
614 if ((ip0
= decodeBase64Byte(d
[0])) > 63)
615 return ERROR_INVALID_DATA
;
616 if ((ip1
= decodeBase64Byte(d
[1])) > 63)
617 return ERROR_INVALID_DATA
;
620 out_buf
[i
] = (ip0
<< 2) | (ip1
>> 4);
623 else if (d
[3] == '=')
625 if ((ip0
= decodeBase64Byte(d
[0])) > 63)
626 return ERROR_INVALID_DATA
;
627 if ((ip1
= decodeBase64Byte(d
[1])) > 63)
628 return ERROR_INVALID_DATA
;
629 if ((ip2
= decodeBase64Byte(d
[2])) > 63)
630 return ERROR_INVALID_DATA
;
634 out_buf
[i
+ 0] = (ip0
<< 2) | (ip1
>> 4);
635 out_buf
[i
+ 1] = (ip1
<< 4) | (ip2
>> 2);
641 if ((ip0
= decodeBase64Byte(d
[0])) > 63)
642 return ERROR_INVALID_DATA
;
643 if ((ip1
= decodeBase64Byte(d
[1])) > 63)
644 return ERROR_INVALID_DATA
;
645 if ((ip2
= decodeBase64Byte(d
[2])) > 63)
646 return ERROR_INVALID_DATA
;
647 if ((ip3
= decodeBase64Byte(d
[3])) > 63)
648 return ERROR_INVALID_DATA
;
652 out_buf
[i
+ 0] = (ip0
<< 2) | (ip1
>> 4);
653 out_buf
[i
+ 1] = (ip1
<< 4) | (ip2
>> 2);
654 out_buf
[i
+ 2] = (ip2
<< 6) | ip3
;
658 if (len
>= 6 && d
[4] == '\r' && d
[5] == '\n')
660 else if (len
>= 5 && d
[4] == '\n')
662 else if (len
>= 4 && d
[4])
667 return ERROR_SUCCESS
;
670 /* Unlike CryptStringToBinaryW, cchString is guaranteed to be the length of the
673 typedef LONG (*StringToBinaryWFunc
)(LPCWSTR pszString
, DWORD cchString
,
674 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
);
676 static LONG
Base64ToBinaryW(LPCWSTR pszString
, DWORD cchString
,
677 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
679 LONG ret
= ERROR_SUCCESS
;
680 const WCHAR
*nextBlock
;
683 nextBlock
= pszString
;
684 while (nextBlock
&& !ret
)
688 ret
= decodeBase64BlockW(nextBlock
, cchString
- (nextBlock
- pszString
),
689 &nextBlock
, pbBinary
? pbBinary
+ outLen
: NULL
, &len
);
692 if (cchString
- (nextBlock
- pszString
) <= 0)
701 *pdwFlags
= CRYPT_STRING_BASE64
;
703 else if (ret
== ERROR_INSUFFICIENT_BUFFER
)
711 static LONG
Base64WithHeaderAndTrailerToBinaryW(LPCWSTR pszString
,
712 DWORD cchString
, LPCWSTR header
, LPCWSTR trailer
, BYTE
*pbBinary
,
713 DWORD
*pcbBinary
, DWORD
*pdwSkip
)
718 if (cchString
> strlenW(header
) + strlenW(trailer
)
719 && (ptr
= strstrW(pszString
, header
)) != NULL
)
721 LPCWSTR trailerSpot
= pszString
+ cchString
- strlenW(trailer
);
723 if (pszString
[cchString
- 1] == '\n')
728 if (pszString
[cchString
- 1] == '\r')
733 if (!strncmpW(trailerSpot
, trailer
, strlenW(trailer
)))
736 *pdwSkip
= ptr
- pszString
;
737 ptr
+= strlenW(header
);
738 if (*ptr
== '\r') ptr
++;
739 if (*ptr
== '\n') ptr
++;
740 cchString
-= ptr
- pszString
+ strlenW(trailer
);
741 ret
= Base64ToBinaryW(ptr
, cchString
, pbBinary
, pcbBinary
, NULL
,
745 ret
= ERROR_INVALID_DATA
;
748 ret
= ERROR_INVALID_DATA
;
752 static LONG
Base64HeaderToBinaryW(LPCWSTR pszString
, DWORD cchString
,
753 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
755 LONG ret
= Base64WithHeaderAndTrailerToBinaryW(pszString
, cchString
,
756 CERT_HEADER_W
, CERT_TRAILER_W
, pbBinary
, pcbBinary
, pdwSkip
);
758 if (!ret
&& pdwFlags
)
759 *pdwFlags
= CRYPT_STRING_BASE64HEADER
;
763 static LONG
Base64RequestHeaderToBinaryW(LPCWSTR pszString
, DWORD cchString
,
764 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
766 LONG ret
= Base64WithHeaderAndTrailerToBinaryW(pszString
, cchString
,
767 CERT_REQUEST_HEADER_W
, CERT_REQUEST_TRAILER_W
, pbBinary
, pcbBinary
,
770 if (!ret
&& pdwFlags
)
771 *pdwFlags
= CRYPT_STRING_BASE64REQUESTHEADER
;
775 static LONG
Base64X509HeaderToBinaryW(LPCWSTR pszString
, DWORD cchString
,
776 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
778 LONG ret
= Base64WithHeaderAndTrailerToBinaryW(pszString
, cchString
,
779 X509_HEADER_W
, X509_TRAILER_W
, pbBinary
, pcbBinary
, pdwSkip
);
781 if (!ret
&& pdwFlags
)
782 *pdwFlags
= CRYPT_STRING_BASE64X509CRLHEADER
;
786 static LONG
Base64AnyToBinaryW(LPCWSTR pszString
, DWORD cchString
,
787 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
791 ret
= Base64HeaderToBinaryW(pszString
, cchString
, pbBinary
, pcbBinary
,
793 if (ret
== ERROR_INVALID_DATA
)
794 ret
= Base64ToBinaryW(pszString
, cchString
, pbBinary
, pcbBinary
,
799 static LONG
DecodeBinaryToBinaryW(LPCWSTR pszString
, DWORD cchString
,
800 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
802 LONG ret
= ERROR_SUCCESS
;
804 if (*pcbBinary
< cchString
)
807 *pcbBinary
= cchString
;
810 ret
= ERROR_INSUFFICIENT_BUFFER
;
811 *pcbBinary
= cchString
;
817 memcpy(pbBinary
, pszString
, cchString
* sizeof(WCHAR
));
818 *pcbBinary
= cchString
* sizeof(WCHAR
);
823 static LONG
DecodeAnyW(LPCWSTR pszString
, DWORD cchString
,
824 BYTE
*pbBinary
, DWORD
*pcbBinary
, DWORD
*pdwSkip
, DWORD
*pdwFlags
)
828 ret
= Base64HeaderToBinaryW(pszString
, cchString
, pbBinary
, pcbBinary
,
830 if (ret
== ERROR_INVALID_DATA
)
831 ret
= Base64ToBinaryW(pszString
, cchString
, pbBinary
, pcbBinary
,
833 if (ret
== ERROR_INVALID_DATA
)
834 ret
= DecodeBinaryToBinaryW(pszString
, cchString
, pbBinary
, pcbBinary
,
839 BOOL WINAPI
CryptStringToBinaryW(LPCWSTR pszString
,
840 DWORD cchString
, DWORD dwFlags
, BYTE
*pbBinary
, DWORD
*pcbBinary
,
841 DWORD
*pdwSkip
, DWORD
*pdwFlags
)
843 StringToBinaryWFunc decoder
;
846 TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_w(pszString
),
847 cchString
, dwFlags
, pbBinary
, pcbBinary
, pdwSkip
, pdwFlags
);
851 SetLastError(ERROR_INVALID_PARAMETER
);
854 /* Only the bottom byte contains valid types */
855 if (dwFlags
& 0xfffffff0)
857 SetLastError(ERROR_INVALID_DATA
);
862 case CRYPT_STRING_BASE64_ANY
:
863 decoder
= Base64AnyToBinaryW
;
865 case CRYPT_STRING_BASE64
:
866 decoder
= Base64ToBinaryW
;
868 case CRYPT_STRING_BASE64HEADER
:
869 decoder
= Base64HeaderToBinaryW
;
871 case CRYPT_STRING_BASE64REQUESTHEADER
:
872 decoder
= Base64RequestHeaderToBinaryW
;
874 case CRYPT_STRING_BASE64X509CRLHEADER
:
875 decoder
= Base64X509HeaderToBinaryW
;
877 case CRYPT_STRING_BINARY
:
878 decoder
= DecodeBinaryToBinaryW
;
880 case CRYPT_STRING_ANY
:
881 decoder
= DecodeAnyW
;
883 case CRYPT_STRING_HEX
:
884 case CRYPT_STRING_HEXASCII
:
885 case CRYPT_STRING_HEXADDR
:
886 case CRYPT_STRING_HEXASCIIADDR
:
887 FIXME("Unimplemented type %d\n", dwFlags
& 0x7fffffff);
890 SetLastError(ERROR_INVALID_PARAMETER
);
894 cchString
= strlenW(pszString
);
895 ret
= decoder(pszString
, cchString
, pbBinary
, pcbBinary
, pdwSkip
, pdwFlags
);
898 return (ret
== ERROR_SUCCESS
) ? TRUE
: FALSE
;