crypt32: Implement CryptStringToBinaryW.
This commit is contained in:
parent
909a81839b
commit
a104479da1
@ -7,7 +7,7 @@
|
|||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 2 of the License, or (at your option) any later version.
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@ -25,6 +25,7 @@
|
|||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "wincrypt.h"
|
#include "wincrypt.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
||||||
|
|
||||||
@ -35,6 +36,25 @@ WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
|||||||
#define X509_HEADER "-----BEGIN X509 CRL-----"
|
#define X509_HEADER "-----BEGIN X509 CRL-----"
|
||||||
#define X509_TRAILER "-----END X509 CRL-----"
|
#define X509_TRAILER "-----END X509 CRL-----"
|
||||||
|
|
||||||
|
static const WCHAR CERT_HEADER_W[] = {
|
||||||
|
'-','-','-','-','-','B','E','G','I','N',' ','C','E','R','T','I','F','I','C',
|
||||||
|
'A','T','E','-','-','-','-','-',0 };
|
||||||
|
static const WCHAR CERT_TRAILER_W[] = {
|
||||||
|
'-','-','-','-','-','E','N','D',' ','C','E','R','T','I','F','I','C','A','T',
|
||||||
|
'E','-','-','-','-','-',0 };
|
||||||
|
static const WCHAR CERT_REQUEST_HEADER_W[] = {
|
||||||
|
'-','-','-','-','-','B','E','G','I','N',' ','N','E','W',' ','C','E','R','T',
|
||||||
|
'I','F','I','C','A','T','E','R','E','Q','U','E','S','T','-','-','-','-','-',0 };
|
||||||
|
static const WCHAR CERT_REQUEST_TRAILER_W[] = {
|
||||||
|
'-','-','-','-','-','E','N','D',' ','N','E','W',' ','C','E','R','T','I','F',
|
||||||
|
'I','C','A','T','E','R','E','Q','U','E','S','T','-','-','-','-','-',0 };
|
||||||
|
static const WCHAR X509_HEADER_W[] = {
|
||||||
|
'-','-','-','-','-','B','E','G','I','N',' ','X','5','0','9',' ','C','R','L',
|
||||||
|
'-','-','-','-','-',0 };
|
||||||
|
static const WCHAR X509_TRAILER_W[] = {
|
||||||
|
'-','-','-','-','-','E','N','D',' ','X','5','0','9',' ','C','R','L','-','-',
|
||||||
|
'-','-','-',0 };
|
||||||
|
|
||||||
static const char b64[] =
|
static const char b64[] =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
@ -260,7 +280,7 @@ BOOL WINAPI CryptBinaryToStringA(const BYTE *pbBinary,
|
|||||||
return encoder(pbBinary, cbBinary, dwFlags, pszString, pcchString);
|
return encoder(pbBinary, cbBinary, dwFlags, pszString, pcchString);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline BYTE decodeBase64Byte(char c)
|
static inline BYTE decodeBase64Byte(int c)
|
||||||
{
|
{
|
||||||
BYTE ret;
|
BYTE ret;
|
||||||
|
|
||||||
@ -577,3 +597,303 @@ BOOL WINAPI CryptStringToBinaryA(LPCSTR pszString,
|
|||||||
SetLastError(ret);
|
SetLastError(ret);
|
||||||
return (ret == ERROR_SUCCESS) ? TRUE : FALSE;
|
return (ret == ERROR_SUCCESS) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LONG decodeBase64BlockW(const WCHAR *in_buf, int in_len,
|
||||||
|
const WCHAR **nextBlock, PBYTE out_buf, DWORD *out_len)
|
||||||
|
{
|
||||||
|
int len = in_len, i;
|
||||||
|
const WCHAR *d = in_buf;
|
||||||
|
int ip0, ip1, ip2, ip3;
|
||||||
|
|
||||||
|
if (len < 4)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
if (d[2] == '=')
|
||||||
|
{
|
||||||
|
if ((ip0 = decodeBase64Byte(d[0])) > 63)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
if ((ip1 = decodeBase64Byte(d[1])) > 63)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
|
if (out_buf)
|
||||||
|
out_buf[i] = (ip0 << 2) | (ip1 >> 4);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (d[3] == '=')
|
||||||
|
{
|
||||||
|
if ((ip0 = decodeBase64Byte(d[0])) > 63)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
if ((ip1 = decodeBase64Byte(d[1])) > 63)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
if ((ip2 = decodeBase64Byte(d[2])) > 63)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
|
if (out_buf)
|
||||||
|
{
|
||||||
|
out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4);
|
||||||
|
out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2);
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((ip0 = decodeBase64Byte(d[0])) > 63)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
if ((ip1 = decodeBase64Byte(d[1])) > 63)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
if ((ip2 = decodeBase64Byte(d[2])) > 63)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
if ((ip3 = decodeBase64Byte(d[3])) > 63)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
|
if (out_buf)
|
||||||
|
{
|
||||||
|
out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4);
|
||||||
|
out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2);
|
||||||
|
out_buf[i + 2] = (ip2 << 6) | ip3;
|
||||||
|
}
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
if (len >= 6 && d[4] == '\r' && d[5] == '\n')
|
||||||
|
*nextBlock = d + 6;
|
||||||
|
else if (len >= 5 && d[4] == '\n')
|
||||||
|
*nextBlock = d + 5;
|
||||||
|
else if (len >= 4 && d[4])
|
||||||
|
*nextBlock = d + 4;
|
||||||
|
else
|
||||||
|
*nextBlock = NULL;
|
||||||
|
*out_len = i;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlike CryptStringToBinaryW, cchString is guaranteed to be the length of the
|
||||||
|
* string to convert.
|
||||||
|
*/
|
||||||
|
typedef LONG (*StringToBinaryWFunc)(LPCWSTR pszString, DWORD cchString,
|
||||||
|
BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags);
|
||||||
|
|
||||||
|
static LONG Base64ToBinaryW(LPCWSTR pszString, DWORD cchString,
|
||||||
|
BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
|
||||||
|
{
|
||||||
|
LONG ret = ERROR_SUCCESS;
|
||||||
|
const WCHAR *nextBlock;
|
||||||
|
DWORD outLen = 0;
|
||||||
|
|
||||||
|
nextBlock = pszString;
|
||||||
|
while (nextBlock && !ret)
|
||||||
|
{
|
||||||
|
DWORD len = 0;
|
||||||
|
|
||||||
|
ret = decodeBase64BlockW(nextBlock, cchString - (nextBlock - pszString),
|
||||||
|
&nextBlock, pbBinary ? pbBinary + outLen : NULL, &len);
|
||||||
|
if (!ret)
|
||||||
|
outLen += len;
|
||||||
|
if (cchString - (nextBlock - pszString) <= 0)
|
||||||
|
nextBlock = NULL;
|
||||||
|
}
|
||||||
|
*pcbBinary = outLen;
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
if (pdwSkip)
|
||||||
|
*pdwSkip = 0;
|
||||||
|
if (pdwFlags)
|
||||||
|
*pdwFlags = CRYPT_STRING_BASE64;
|
||||||
|
}
|
||||||
|
else if (ret == ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
{
|
||||||
|
if (!pbBinary)
|
||||||
|
ret = ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG Base64WithHeaderAndTrailerToBinaryW(LPCWSTR pszString,
|
||||||
|
DWORD cchString, LPCWSTR header, LPCWSTR trailer, BYTE *pbBinary,
|
||||||
|
DWORD *pcbBinary, DWORD *pdwSkip)
|
||||||
|
{
|
||||||
|
LONG ret;
|
||||||
|
LPCWSTR ptr;
|
||||||
|
|
||||||
|
if (cchString > strlenW(header) + strlenW(trailer)
|
||||||
|
&& (ptr = strstrW(pszString, header)) != NULL)
|
||||||
|
{
|
||||||
|
LPCWSTR trailerSpot = pszString + cchString - strlenW(trailer);
|
||||||
|
|
||||||
|
if (pszString[cchString - 1] == '\n')
|
||||||
|
{
|
||||||
|
cchString--;
|
||||||
|
trailerSpot--;
|
||||||
|
}
|
||||||
|
if (pszString[cchString - 1] == '\r')
|
||||||
|
{
|
||||||
|
cchString--;
|
||||||
|
trailerSpot--;
|
||||||
|
}
|
||||||
|
if (!strncmpW(trailerSpot, trailer, strlenW(trailer)))
|
||||||
|
{
|
||||||
|
if (pdwSkip)
|
||||||
|
*pdwSkip = ptr - pszString;
|
||||||
|
ptr += strlenW(header);
|
||||||
|
if (*ptr == '\r') ptr++;
|
||||||
|
if (*ptr == '\n') ptr++;
|
||||||
|
cchString -= ptr - pszString + strlenW(trailer);
|
||||||
|
ret = Base64ToBinaryW(ptr, cchString, pbBinary, pcbBinary, NULL,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = ERROR_INVALID_DATA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = ERROR_INVALID_DATA;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG Base64HeaderToBinaryW(LPCWSTR pszString, DWORD cchString,
|
||||||
|
BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
|
||||||
|
{
|
||||||
|
LONG ret = Base64WithHeaderAndTrailerToBinaryW(pszString, cchString,
|
||||||
|
CERT_HEADER_W, CERT_TRAILER_W, pbBinary, pcbBinary, pdwSkip);
|
||||||
|
|
||||||
|
if (!ret && pdwFlags)
|
||||||
|
*pdwFlags = CRYPT_STRING_BASE64HEADER;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG Base64RequestHeaderToBinaryW(LPCWSTR pszString, DWORD cchString,
|
||||||
|
BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
|
||||||
|
{
|
||||||
|
LONG ret = Base64WithHeaderAndTrailerToBinaryW(pszString, cchString,
|
||||||
|
CERT_REQUEST_HEADER_W, CERT_REQUEST_TRAILER_W, pbBinary, pcbBinary,
|
||||||
|
pdwSkip);
|
||||||
|
|
||||||
|
if (!ret && pdwFlags)
|
||||||
|
*pdwFlags = CRYPT_STRING_BASE64REQUESTHEADER;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG Base64X509HeaderToBinaryW(LPCWSTR pszString, DWORD cchString,
|
||||||
|
BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
|
||||||
|
{
|
||||||
|
LONG ret = Base64WithHeaderAndTrailerToBinaryW(pszString, cchString,
|
||||||
|
X509_HEADER_W, X509_TRAILER_W, pbBinary, pcbBinary, pdwSkip);
|
||||||
|
|
||||||
|
if (!ret && pdwFlags)
|
||||||
|
*pdwFlags = CRYPT_STRING_BASE64X509CRLHEADER;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG Base64AnyToBinaryW(LPCWSTR pszString, DWORD cchString,
|
||||||
|
BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
|
||||||
|
{
|
||||||
|
LONG ret;
|
||||||
|
|
||||||
|
ret = Base64HeaderToBinaryW(pszString, cchString, pbBinary, pcbBinary,
|
||||||
|
pdwSkip, pdwFlags);
|
||||||
|
if (ret == ERROR_INVALID_DATA)
|
||||||
|
ret = Base64ToBinaryW(pszString, cchString, pbBinary, pcbBinary,
|
||||||
|
pdwSkip, pdwFlags);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG DecodeBinaryToBinaryW(LPCWSTR pszString, DWORD cchString,
|
||||||
|
BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
|
||||||
|
{
|
||||||
|
LONG ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (*pcbBinary < cchString)
|
||||||
|
{
|
||||||
|
if (!pbBinary)
|
||||||
|
*pcbBinary = cchString;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = ERROR_INSUFFICIENT_BUFFER;
|
||||||
|
*pcbBinary = cchString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cchString)
|
||||||
|
memcpy(pbBinary, pszString, cchString * sizeof(WCHAR));
|
||||||
|
*pcbBinary = cchString * sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG DecodeAnyW(LPCWSTR pszString, DWORD cchString,
|
||||||
|
BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags)
|
||||||
|
{
|
||||||
|
LONG ret;
|
||||||
|
|
||||||
|
ret = Base64HeaderToBinaryW(pszString, cchString, pbBinary, pcbBinary,
|
||||||
|
pdwSkip, pdwFlags);
|
||||||
|
if (ret == ERROR_INVALID_DATA)
|
||||||
|
ret = Base64ToBinaryW(pszString, cchString, pbBinary, pcbBinary,
|
||||||
|
pdwSkip, pdwFlags);
|
||||||
|
if (ret == ERROR_INVALID_DATA)
|
||||||
|
ret = DecodeBinaryToBinaryW(pszString, cchString, pbBinary, pcbBinary,
|
||||||
|
pdwSkip, pdwFlags);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI CryptStringToBinaryW(LPCWSTR pszString,
|
||||||
|
DWORD cchString, DWORD dwFlags, BYTE *pbBinary, DWORD *pcbBinary,
|
||||||
|
DWORD *pdwSkip, DWORD *pdwFlags)
|
||||||
|
{
|
||||||
|
StringToBinaryWFunc decoder;
|
||||||
|
LONG ret;
|
||||||
|
|
||||||
|
TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_w(pszString),
|
||||||
|
cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags);
|
||||||
|
|
||||||
|
if (!pszString)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
/* Only the bottom byte contains valid types */
|
||||||
|
if (dwFlags & 0xfffffff0)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_DATA);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
switch (dwFlags)
|
||||||
|
{
|
||||||
|
case CRYPT_STRING_BASE64_ANY:
|
||||||
|
decoder = Base64AnyToBinaryW;
|
||||||
|
break;
|
||||||
|
case CRYPT_STRING_BASE64:
|
||||||
|
decoder = Base64ToBinaryW;
|
||||||
|
break;
|
||||||
|
case CRYPT_STRING_BASE64HEADER:
|
||||||
|
decoder = Base64HeaderToBinaryW;
|
||||||
|
break;
|
||||||
|
case CRYPT_STRING_BASE64REQUESTHEADER:
|
||||||
|
decoder = Base64RequestHeaderToBinaryW;
|
||||||
|
break;
|
||||||
|
case CRYPT_STRING_BASE64X509CRLHEADER:
|
||||||
|
decoder = Base64X509HeaderToBinaryW;
|
||||||
|
break;
|
||||||
|
case CRYPT_STRING_BINARY:
|
||||||
|
decoder = DecodeBinaryToBinaryW;
|
||||||
|
break;
|
||||||
|
case CRYPT_STRING_ANY:
|
||||||
|
decoder = DecodeAnyW;
|
||||||
|
break;
|
||||||
|
case CRYPT_STRING_HEX:
|
||||||
|
case CRYPT_STRING_HEXASCII:
|
||||||
|
case CRYPT_STRING_HEXADDR:
|
||||||
|
case CRYPT_STRING_HEXASCIIADDR:
|
||||||
|
FIXME("Unimplemented type %d\n", dwFlags & 0x7fffffff);
|
||||||
|
/* fall through */
|
||||||
|
default:
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!cchString)
|
||||||
|
cchString = strlenW(pszString);
|
||||||
|
ret = decoder(pszString, cchString, pbBinary, pcbBinary, pdwSkip, pdwFlags);
|
||||||
|
if (ret)
|
||||||
|
SetLastError(ret);
|
||||||
|
return (ret == ERROR_SUCCESS) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
@ -99,7 +99,7 @@
|
|||||||
@ stdcall CryptBinaryToStringA(ptr long long ptr ptr)
|
@ stdcall CryptBinaryToStringA(ptr long long ptr ptr)
|
||||||
@ stub CryptBinaryToStringW # (ptr long long ptr ptr)
|
@ stub CryptBinaryToStringW # (ptr long long ptr ptr)
|
||||||
@ stdcall CryptStringToBinaryA(str long long ptr ptr ptr ptr)
|
@ stdcall CryptStringToBinaryA(str long long ptr ptr ptr ptr)
|
||||||
@ stub CryptStringToBinaryW # (wstr long long ptr ptr ptr ptr)
|
@ stdcall CryptStringToBinaryW (wstr long long ptr ptr ptr ptr)
|
||||||
@ stdcall CryptAcquireContextU(ptr wstr wstr long long) advapi32.CryptAcquireContextW
|
@ stdcall CryptAcquireContextU(ptr wstr wstr long long) advapi32.CryptAcquireContextW
|
||||||
@ stdcall CryptAcquireCertificatePrivateKey(ptr long ptr ptr ptr ptr)
|
@ stdcall CryptAcquireCertificatePrivateKey(ptr long ptr ptr ptr ptr)
|
||||||
@ stub CryptCloseAsyncHandle
|
@ stub CryptCloseAsyncHandle
|
||||||
|
Loading…
x
Reference in New Issue
Block a user