Autosyncing with Wine HEAD

svn path=/trunk/; revision=23201
This commit is contained in:
The Wine Synchronizer 2006-07-21 11:13:18 +00:00
parent 74739f95d9
commit fb9067d427
8 changed files with 950 additions and 145 deletions

View file

@ -244,12 +244,7 @@ static BOOL WINAPI CertContext_GetProperty(void *context, DWORD dwPropId,
return ret;
}
/* info is assumed to be a CRYPT_KEY_PROV_INFO, followed by its container name,
* provider name, and any provider parameters, in a contiguous buffer, but
* where info's pointers are assumed to be invalid. Upon return, info's
* pointers point to the appropriate memory locations.
*/
static void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info)
void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info)
{
DWORD i, containerLen, provNameLen;
LPBYTE data = (LPBYTE)info + sizeof(CRYPT_KEY_PROV_INFO);
@ -1826,6 +1821,7 @@ static PCCERT_CONTEXT CRYPT_CreateSignedCert(PCRYPT_DER_BLOB blob,
}
/* Copies data from the parameters into info, where:
* pSerialNumber: The serial number. Must not be NULL.
* pSubjectIssuerBlob: Specifies both the subject and issuer for info.
* Must not be NULL
* pSignatureAlgorithm: Optional.
@ -1836,23 +1832,22 @@ static PCCERT_CONTEXT CRYPT_CreateSignedCert(PCRYPT_DER_BLOB blob,
* pubKey: The public key of the certificate. Must not be NULL.
* pExtensions: Extensions to be included with the certificate. Optional.
*/
static void CRYPT_MakeCertInfo(PCERT_INFO info,
static void CRYPT_MakeCertInfo(PCERT_INFO info, PCRYPT_DATA_BLOB pSerialNumber,
PCERT_NAME_BLOB pSubjectIssuerBlob,
PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, PSYSTEMTIME pStartTime,
PSYSTEMTIME pEndTime, PCERT_PUBLIC_KEY_INFO pubKey,
PCERT_EXTENSIONS pExtensions)
{
/* FIXME: what serial number to use? */
static const BYTE serialNum[] = { 1 };
static CHAR oid[] = szOID_RSA_SHA1RSA;
assert(info);
assert(pSerialNumber);
assert(pSubjectIssuerBlob);
assert(pubKey);
info->dwVersion = CERT_V3;
info->SerialNumber.cbData = sizeof(serialNum);
info->SerialNumber.pbData = (LPBYTE)serialNum;
info->SerialNumber.cbData = pSerialNumber->cbData;
info->SerialNumber.pbData = pSerialNumber->pbData;
if (pSignatureAlgorithm)
memcpy(&info->SignatureAlgorithm, pSignatureAlgorithm,
sizeof(info->SignatureAlgorithm));
@ -1910,9 +1905,9 @@ static HCRYPTPROV CRYPT_CreateKeyProv(void)
UuidCreateFunc uuidCreate = (UuidCreateFunc)GetProcAddress(rpcrt,
"UuidCreate");
UuidToStringFunc uuidToString = (UuidToStringFunc)GetProcAddress(rpcrt,
"UuidToString");
"UuidToStringA");
RpcStringFreeFunc rpcStringFree = (RpcStringFreeFunc)GetProcAddress(
rpcrt, "RpcStringFree");
rpcrt, "RpcStringFreeA");
if (uuidCreate && uuidToString && rpcStringFree)
{
@ -1978,10 +1973,12 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV hProv,
{
CERT_INFO info = { 0 };
CRYPT_DER_BLOB blob = { 0, NULL };
BOOL ret;
BYTE serial[16];
CRYPT_DATA_BLOB serialBlob = { sizeof(serial), serial };
CRYPT_MakeCertInfo(&info, pSubjectIssuerBlob, pSignatureAlgorithm,
pStartTime, pEndTime, pubKey, pExtensions);
CryptGenRandom(hProv, sizeof(serial), serial);
CRYPT_MakeCertInfo(&info, &serialBlob, pSubjectIssuerBlob,
pSignatureAlgorithm, pStartTime, pEndTime, pubKey, pExtensions);
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED,
&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&blob.pbData,
&blob.cbData);

View file

@ -89,7 +89,7 @@
@ stdcall CertVerifySubjectCertificateContext(ptr ptr ptr)
@ stdcall CertVerifyTimeValidity(ptr ptr)
@ stub CertVerifyValidityNesting
@ stub CreateFileU
@ stdcall CreateFileU(wstr long long ptr long long ptr) kernel32.CreateFileW
@ stdcall CryptBinaryToStringA(ptr long long ptr ptr)
@ stub CryptBinaryToStringW # (ptr long long ptr ptr)
@ stdcall CryptStringToBinaryA(str long long ptr ptr ptr ptr)

View file

@ -23,13 +23,20 @@
#define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
#define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
#define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
#define ASN_UTF8STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0c)
#define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
#define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
#define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
#define ASN_T61STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x14)
#define ASN_VIDEOTEXSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x15)
#define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
#define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
#define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
#define ASN_GRAPHICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x19)
#define ASN_VISIBLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1a)
#define ASN_GENERALSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1b)
#define ASN_UNIVERSALSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1c)
#define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
/* The following aren't defined in wincrypt.h, as they're "reserved" */
#define CERT_CERT_PROP_ID 32
@ -97,6 +104,14 @@ extern PCWINE_CONTEXT_INTERFACE pCTLInterface;
const void *CRYPT_ReadSerializedElement(const BYTE *pbElement,
DWORD cbElement, DWORD dwContextTypeFlags, DWORD *pdwContentType);
/* Fixes up the the pointers in info, where info is assumed to be a
* CRYPT_KEY_PROV_INFO, followed by its container name, provider name, and any
* provider parameters, in a contiguous buffer, but where info's pointers are
* assumed to be invalid. Upon return, info's pointers point to the
* appropriate memory locations.
*/
void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info);
DWORD CertStore_GetAccessState(HCERTSTORE hCertStore);
/**

View file

@ -42,6 +42,7 @@
#include "winbase.h"
#include "excpt.h"
#include "wincrypt.h"
#include "winnls.h"
#include "winreg.h"
#include "snmp.h"
#include "wine/debug.h"
@ -1271,33 +1272,75 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
switch (pbEncoded[0])
{
case ASN_OCTETSTRING:
valueType = CERT_RDN_OCTET_STRING;
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += dataLen;
break;
case ASN_NUMERICSTRING:
valueType = CERT_RDN_NUMERIC_STRING;
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += dataLen;
break;
case ASN_PRINTABLESTRING:
valueType = CERT_RDN_PRINTABLE_STRING;
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += dataLen;
break;
case ASN_IA5STRING:
valueType = CERT_RDN_IA5_STRING;
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += dataLen;
break;
case ASN_T61STRING:
valueType = CERT_RDN_T61_STRING;
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += dataLen;
break;
case ASN_VIDEOTEXSTRING:
valueType = CERT_RDN_VIDEOTEX_STRING;
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += dataLen;
break;
case ASN_GRAPHICSTRING:
valueType = CERT_RDN_GRAPHIC_STRING;
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += dataLen;
break;
case ASN_VISIBLESTRING:
valueType = CERT_RDN_VISIBLE_STRING;
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += dataLen;
break;
case ASN_GENERALSTRING:
valueType = CERT_RDN_GENERAL_STRING;
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += dataLen;
break;
case ASN_UNIVERSALSTRING:
FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
break;
case ASN_BMPSTRING:
valueType = CERT_RDN_BMP_STRING;
bytesNeeded += dataLen;
break;
case ASN_UTF8STRING:
valueType = CERT_RDN_UTF8_STRING;
bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
(LPSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
break;
default:
FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
SetLastError(OSS_UNIMPLEMENTED);
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
if (ret)
{
DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
switch (pbEncoded[0])
{
case ASN_NUMERICSTRING:
case ASN_PRINTABLESTRING:
case ASN_IA5STRING:
case ASN_T61STRING:
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += dataLen;
break;
}
if (!value)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
@ -1309,40 +1352,53 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
else
{
*pcbStructInfo = bytesNeeded;
switch (pbEncoded[0])
{
case ASN_NUMERICSTRING:
value->dwValueType = CERT_RDN_NUMERIC_STRING;
break;
case ASN_PRINTABLESTRING:
value->dwValueType = CERT_RDN_PRINTABLE_STRING;
break;
case ASN_IA5STRING:
value->dwValueType = CERT_RDN_IA5_STRING;
break;
case ASN_T61STRING:
value->dwValueType = CERT_RDN_T61_STRING;
break;
}
value->dwValueType = valueType;
if (dataLen)
{
DWORD i;
assert(value->Value.pbData);
switch (pbEncoded[0])
{
case ASN_OCTETSTRING:
case ASN_NUMERICSTRING:
case ASN_PRINTABLESTRING:
case ASN_IA5STRING:
case ASN_T61STRING:
case ASN_VIDEOTEXSTRING:
case ASN_GRAPHICSTRING:
case ASN_VISIBLESTRING:
case ASN_GENERALSTRING:
value->Value.cbData = dataLen;
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
value->Value.pbData = (BYTE *)pbEncoded + 1 +
lenBytes;
else
if (dataLen)
{
assert(value->Value.pbData);
memcpy(value->Value.pbData,
pbEncoded + 1 + lenBytes, dataLen);
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
memcpy(value->Value.pbData,
pbEncoded + 1 + lenBytes, dataLen);
else
value->Value.pbData = (LPBYTE)pbEncoded + 1 +
lenBytes;
}
break;
case ASN_BMPSTRING:
{
LPWSTR str = (LPWSTR)value->Value.pbData;
value->Value.cbData = dataLen;
for (i = 0; i < dataLen / 2; i++)
str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
pbEncoded[1 + lenBytes + 2 * i + 1];
break;
}
case ASN_UTF8STRING:
{
LPWSTR str = (LPWSTR)value->Value.pbData;
value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
(LPSTR)pbEncoded + 1 + lenBytes, dataLen,
str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
break;
}
}
}
else
@ -1395,6 +1451,179 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret = TRUE;
DWORD dataLen;
CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
switch (pbEncoded[0])
{
case ASN_NUMERICSTRING:
valueType = CERT_RDN_NUMERIC_STRING;
bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_PRINTABLESTRING:
valueType = CERT_RDN_PRINTABLE_STRING;
bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_IA5STRING:
valueType = CERT_RDN_IA5_STRING;
bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_T61STRING:
valueType = CERT_RDN_T61_STRING;
bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_VIDEOTEXSTRING:
valueType = CERT_RDN_VIDEOTEX_STRING;
bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_GRAPHICSTRING:
valueType = CERT_RDN_GRAPHIC_STRING;
bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_VISIBLESTRING:
valueType = CERT_RDN_VISIBLE_STRING;
bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_GENERALSTRING:
valueType = CERT_RDN_GENERAL_STRING;
bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_UNIVERSALSTRING:
valueType = CERT_RDN_UNIVERSAL_STRING;
bytesNeeded += dataLen / 2 + 2;
break;
case ASN_BMPSTRING:
valueType = CERT_RDN_BMP_STRING;
bytesNeeded += dataLen + 2;
break;
case ASN_UTF8STRING:
valueType = CERT_RDN_UTF8_STRING;
bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
(LPSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2 + 2;
break;
default:
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
if (ret)
{
if (!value)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
{
*pcbStructInfo = bytesNeeded;
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
{
*pcbStructInfo = bytesNeeded;
value->dwValueType = valueType;
if (dataLen)
{
DWORD i;
LPWSTR str = (LPWSTR)value->Value.pbData;
assert(value->Value.pbData);
switch (pbEncoded[0])
{
case ASN_NUMERICSTRING:
case ASN_PRINTABLESTRING:
case ASN_IA5STRING:
case ASN_T61STRING:
case ASN_VIDEOTEXSTRING:
case ASN_GRAPHICSTRING:
case ASN_VISIBLESTRING:
case ASN_GENERALSTRING:
value->Value.cbData = dataLen * 2 + 2;
for (i = 0; i < dataLen; i++)
str[i] = pbEncoded[1 + lenBytes + i];
str[i] = 0;
break;
case ASN_UNIVERSALSTRING:
value->Value.cbData = dataLen / 2 + 2;
for (i = 0; i < dataLen / 4; i++)
str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
| pbEncoded[1 + lenBytes + 2 * i + 3];
str[i] = 0;
break;
case ASN_BMPSTRING:
value->Value.cbData = dataLen + 2;
for (i = 0; i < dataLen / 2; i++)
str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
pbEncoded[1 + lenBytes + 2 * i + 1];
str[i] = 0;
break;
case ASN_UTF8STRING:
value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
(LPSTR)pbEncoded + 1 + lenBytes, dataLen,
str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
str[value->Value.cbData / 2] = 0;
value->Value.cbData += 2;
break;
}
}
else
{
value->Value.cbData = 0;
value->Value.pbData = NULL;
}
}
}
}
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret = TRUE;
__TRY
{
ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
lpszStructType, pbEncoded, cbEncoded,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
if (ret && pvStructInfo)
{
ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, *pcbStructInfo);
if (ret)
{
CERT_NAME_VALUE *value;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
value = (CERT_NAME_VALUE *)pvStructInfo;
value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
pcbStructInfo);
}
}
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
@ -3190,6 +3419,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
case (WORD)RSA_CSP_PUBLICKEYBLOB:
decodeFunc = CRYPT_AsnDecodeRsaPubKey;
break;
case (WORD)X509_UNICODE_NAME_VALUE:
decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
break;
case (WORD)X509_OCTET_STRING:
decodeFunc = CRYPT_AsnDecodeOctets;
break;

View file

@ -46,6 +46,7 @@
#include "snmp.h"
#include "wine/debug.h"
#include "wine/exception.h"
#include "wine/unicode.h"
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
@ -163,6 +164,8 @@ static BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags,
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
*pcbEncoded = bytesNeeded;
return ret;
}
@ -381,18 +384,18 @@ static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
*pcbEncoded = blob->cbData;
ret = TRUE;
}
else if (*pcbEncoded < blob->cbData)
{
*pcbEncoded = blob->cbData;
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
{
if (blob->cbData)
memcpy(pbEncoded, blob->pbData, blob->cbData);
*pcbEncoded = blob->cbData;
ret = TRUE;
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, blob->cbData)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
if (blob->cbData)
memcpy(pbEncoded, blob->pbData, blob->cbData);
*pcbEncoded = blob->cbData;
ret = TRUE;
}
}
return ret;
}
@ -910,6 +913,104 @@ static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
return ret;
}
static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
BOOL ret = TRUE;
LPCSTR str = (LPCSTR)value->Value.pbData;
DWORD bytesNeeded, lenBytes, encodedLen;
encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + encodedLen;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = tag;
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
memcpy(pbEncoded, str, encodedLen);
}
}
return ret;
}
static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
BOOL ret = TRUE;
LPCWSTR str = (LPCWSTR)value->Value.pbData;
DWORD bytesNeeded, lenBytes, strLen;
strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
lstrlenW(str);
CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + strLen * 2;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
DWORD i;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_BMPSTRING;
CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; i < strLen; i++)
{
*pbEncoded++ = (str[i] & 0xff00) >> 8;
*pbEncoded++ = str[i] & 0x00ff;
}
}
}
return ret;
}
static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
BOOL ret = TRUE;
LPCWSTR str = (LPCWSTR)value->Value.pbData;
DWORD bytesNeeded, lenBytes, encodedLen, strLen;
strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
lstrlenW(str);
encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
NULL);
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + encodedLen;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_UTF8STRING;
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
bytesNeeded - lenBytes - 1, NULL, NULL);
}
}
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
@ -918,59 +1019,71 @@ static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
__TRY
{
BYTE tag;
DWORD bytesNeeded, lenBytes, encodedLen;
const CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
switch (value->dwValueType)
{
case CERT_RDN_NUMERIC_STRING:
tag = ASN_NUMERICSTRING;
encodedLen = value->Value.cbData;
break;
case CERT_RDN_PRINTABLE_STRING:
tag = ASN_PRINTABLESTRING;
encodedLen = value->Value.cbData;
break;
case CERT_RDN_T61_STRING:
tag = ASN_T61STRING;
encodedLen = value->Value.cbData;
break;
case CERT_RDN_IA5_STRING:
tag = ASN_IA5STRING;
encodedLen = value->Value.cbData;
break;
case CERT_RDN_ANY_TYPE:
/* explicitly disallowed */
SetLastError(E_INVALIDARG);
return FALSE;
ret = FALSE;
break;
case CERT_RDN_ENCODED_BLOB:
ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
&value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_OCTET_STRING:
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_NUMERIC_STRING:
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_PRINTABLE_STRING:
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_TELETEX_STRING:
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_VIDEOTEX_STRING:
ret = CRYPT_AsnEncodeStringCoerce(value,
ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_IA5_STRING:
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_GRAPHIC_STRING:
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_VISIBLE_STRING:
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_GENERAL_STRING:
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_UNIVERSAL_STRING:
FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
SetLastError(CRYPT_E_ASN1_CHOICE);
ret = FALSE;
break;
case CERT_RDN_BMP_STRING:
ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
pbEncoded, pcbEncoded);
break;
case CERT_RDN_UTF8_STRING:
ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
pbEncoded, pcbEncoded);
break;
default:
FIXME("String type %ld unimplemented\n", value->dwValueType);
return FALSE;
}
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + encodedLen;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = tag;
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
switch (value->dwValueType)
{
case CERT_RDN_NUMERIC_STRING:
case CERT_RDN_PRINTABLE_STRING:
case CERT_RDN_T61_STRING:
case CERT_RDN_IA5_STRING:
memcpy(pbEncoded, value->Value.pbData, value->Value.cbData);
}
}
SetLastError(CRYPT_E_ASN1_CHOICE);
ret = FALSE;
}
}
__EXCEPT_PAGE_FAULT
@ -982,6 +1095,284 @@ static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
return ret;
}
static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
BOOL ret = TRUE;
LPCWSTR str = (LPCWSTR)value->Value.pbData;
DWORD bytesNeeded, lenBytes, encodedLen;
encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
lstrlenW(str);
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + encodedLen;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
DWORD i;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = tag;
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; i < encodedLen; i++)
*pbEncoded++ = (BYTE)str[i];
}
}
return ret;
}
static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
BOOL ret = TRUE;
LPCWSTR str = (LPCWSTR)value->Value.pbData;
DWORD bytesNeeded, lenBytes, encodedLen;
encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
lstrlenW(str);
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + encodedLen;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
DWORD i;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_NUMERICSTRING;
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; ret && i < encodedLen; i++)
{
if (isdigitW(str[i]))
*pbEncoded++ = (BYTE)str[i];
else
{
*pcbEncoded = i;
SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
ret = FALSE;
}
}
}
}
return ret;
}
static inline int isprintableW(WCHAR wc)
{
return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
wc == '/' || wc == ':' || wc == '=' || wc == '?';
}
static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
BOOL ret = TRUE;
LPCWSTR str = (LPCWSTR)value->Value.pbData;
DWORD bytesNeeded, lenBytes, encodedLen;
encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
lstrlenW(str);
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + encodedLen;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
DWORD i;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_PRINTABLESTRING;
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; ret && i < encodedLen; i++)
{
if (isprintableW(str[i]))
*pbEncoded++ = (BYTE)str[i];
else
{
*pcbEncoded = i;
SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
ret = FALSE;
}
}
}
}
return ret;
}
static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
BOOL ret = TRUE;
LPCWSTR str = (LPCWSTR)value->Value.pbData;
DWORD bytesNeeded, lenBytes, encodedLen;
encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
lstrlenW(str);
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + encodedLen;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
DWORD i;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_IA5STRING;
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; ret && i < encodedLen; i++)
{
if (str[i] <= 0x7f)
*pbEncoded++ = (BYTE)str[i];
else
{
*pcbEncoded = i;
SetLastError(CRYPT_E_INVALID_IA5_STRING);
ret = FALSE;
}
}
}
}
return ret;
}
static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
BOOL ret = TRUE;
LPCWSTR str = (LPCWSTR)value->Value.pbData;
DWORD bytesNeeded, lenBytes, strLen;
/* FIXME: doesn't handle composite characters */
strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
lstrlenW(str);
CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + strLen * 4;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
DWORD i;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_UNIVERSALSTRING;
CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; i < strLen; i++)
{
*pbEncoded++ = 0;
*pbEncoded++ = 0;
*pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
*pbEncoded++ = (BYTE)(str[i] & 0x00ff);
}
}
}
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret = FALSE;
__TRY
{
const CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
switch (value->dwValueType)
{
case CERT_RDN_ANY_TYPE:
case CERT_RDN_ENCODED_BLOB:
case CERT_RDN_OCTET_STRING:
SetLastError(CRYPT_E_NOT_CHAR_STRING);
break;
case CERT_RDN_NUMERIC_STRING:
ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
pbEncoded, pcbEncoded);
break;
case CERT_RDN_PRINTABLE_STRING:
ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
pbEncoded, pcbEncoded);
break;
case CERT_RDN_TELETEX_STRING:
ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_VIDEOTEX_STRING:
ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_IA5_STRING:
ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
pbEncoded, pcbEncoded);
break;
case CERT_RDN_GRAPHIC_STRING:
ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_VISIBLE_STRING:
ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_GENERAL_STRING:
ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
break;
case CERT_RDN_UNIVERSAL_STRING:
ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
pbEncoded, pcbEncoded);
break;
case CERT_RDN_BMP_STRING:
ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
pbEncoded, pcbEncoded);
break;
case CERT_RDN_UTF8_STRING:
ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
pbEncoded, pcbEncoded);
break;
default:
SetLastError(CRYPT_E_ASN1_CHOICE);
}
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
}
__ENDTRY
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
CERT_RDN_ATTR *attr, BYTE *pbEncoded, DWORD *pcbEncoded)
{
@ -2396,6 +2787,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
case (WORD)RSA_CSP_PUBLICKEYBLOB:
encodeFunc = CRYPT_AsnEncodeRsaPubKey;
break;
case (WORD)X509_UNICODE_NAME_VALUE:
encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
break;
case (WORD)X509_OCTET_STRING:
encodeFunc = CRYPT_AsnEncodeOctets;
break;

View file

@ -363,6 +363,16 @@ const void *CRYPT_ReadSerializedElement(const BYTE *pbElement, DWORD cbElement,
ret = contextInterface->setProp(context,
hdr->propID, 0, pbElement);
break;
case CERT_KEY_PROV_INFO_PROP_ID:
{
PCRYPT_KEY_PROV_INFO info =
(PCRYPT_KEY_PROV_INFO)pbElement;
CRYPT_FixKeyProvInfoPointers(info);
ret = contextInterface->setProp(context,
hdr->propID, 0, pbElement);
break;
}
default:
FIXME("prop ID %ld: stub\n", hdr->propID);
}

View file

@ -1723,6 +1723,54 @@ static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
return ret;
}
static PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara)
{
FIXME("(%ld, %08lx, %s): stub\n", hCryptProv, dwFlags,
debugstr_w((LPCWSTR)pvPara));
return NULL;
}
static PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara)
{
int len;
PWINECRYPT_CERTSTORE ret = NULL;
TRACE("(%ld, %08lx, %s)\n", hCryptProv, dwFlags,
debugstr_a((LPCSTR)pvPara));
if (!pvPara)
{
SetLastError(ERROR_FILE_NOT_FOUND);
return NULL;
}
len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
if (len)
{
LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
if (storeName)
{
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
ret = CRYPT_FileNameOpenStoreW(hCryptProv, dwFlags, storeName);
CryptMemFree(storeName);
}
}
return ret;
}
static PWINECRYPT_CERTSTORE CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara)
{
if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
FIXME("(%ld, %08lx, %p): stub\n", hCryptProv, dwFlags, pvPara);
else
FIXME("(%ld, %08lx, %s): stub\n", hCryptProv, dwFlags,
debugstr_w((LPCWSTR)pvPara));
return NULL;
}
HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
DWORD dwMsgAndCertEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags,
const void* pvPara)
@ -1743,6 +1791,12 @@ HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
case (int)CERT_STORE_PROV_REG:
openFunc = CRYPT_RegOpenStore;
break;
case (int)CERT_STORE_PROV_FILENAME_A:
openFunc = CRYPT_FileNameOpenStoreA;
break;
case (int)CERT_STORE_PROV_FILENAME_W:
openFunc = CRYPT_FileNameOpenStoreW;
break;
case (int)CERT_STORE_PROV_COLLECTION:
openFunc = CRYPT_CollectionOpenStore;
break;
@ -1758,6 +1812,9 @@ HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_W:
openFunc = CRYPT_SysRegOpenStoreW;
break;
case (int)CERT_STORE_PROV_PHYSICAL_W:
openFunc = CRYPT_PhysOpenStoreW;
break;
default:
if (LOWORD(lpszStoreProvider))
FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));

View file

@ -62,6 +62,7 @@ DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
}
else
ret++;
TRACE("returning %ld (%s)\n", ret, debugstr_a(psz));
return ret;
}
@ -106,9 +107,35 @@ DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
}
else
ret++;
TRACE("returning %ld (%s)\n", ret, debugstr_w(psz));
return ret;
}
/* Adds the prefix prefix to the string pointed to by psz, followed by the
* character '='. Copies no more than csz characters. Returns the number of
* characters copied. If psz is NULL, returns the number of characters that
* would be copied.
*/
static DWORD CRYPT_AddPrefixA(LPCSTR prefix, LPSTR psz, DWORD csz)
{
DWORD chars;
TRACE("(%s, %p, %ld)\n", debugstr_a(prefix), psz, csz);
if (psz)
{
chars = min(lstrlenA(prefix), csz);
memcpy(psz, prefix, chars);
csz -= chars;
*(psz + chars) = '=';
chars++;
csz--;
}
else
chars = lstrlenA(prefix) + 1;
return chars;
}
DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
DWORD dwStrType, LPSTR psz, DWORD csz)
{
@ -147,36 +174,45 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
else
rdnSep = plusSep;
rdnSepLen = strlen(rdnSep);
for (i = 0; ret < csz && i < info->cRDN; i++)
for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
{
for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
for (j = 0; (!psz || ret < csz) && j < info->rgRDN[i].cRDNAttr; j++)
{
DWORD chars;
char prefixBuf[10]; /* big enough for GivenName */
LPCSTR prefix = NULL;
if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
prefix = info->rgRDN[i].rgRDNAttr[j].pszObjId;
else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
{
PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
CRYPT_OID_INFO_OID_KEY,
info->rgRDN[i].rgRDNAttr[j].pszObjId,
CRYPT_RDN_ATTR_OID_GROUP_ID);
if (oidInfo)
{
WideCharToMultiByte(CP_ACP, 0, oidInfo->pwszName, -1,
prefixBuf, sizeof(prefixBuf), NULL, NULL);
prefix = prefixBuf;
}
else
prefix = info->rgRDN[i].rgRDNAttr[j].pszObjId;
}
if (prefix)
{
/* - 1 is needed to account for the NULL terminator. */
chars = min(
lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
csz - ret - 1);
if (psz && chars)
memcpy(psz + ret, info->rgRDN[i].rgRDNAttr[j].pszObjId,
chars);
chars = CRYPT_AddPrefixA(prefix,
psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
ret += chars;
csz -= chars;
if (csz > 1)
{
if (psz)
*(psz + ret) = '=';
ret++;
csz--;
}
}
/* FIXME: handle quoting */
chars = CertRDNValueToStrA(
info->rgRDN[i].rgRDNAttr[j].dwValueType,
&info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
csz - ret - 1);
psz ? csz - ret : 0);
if (chars)
ret += chars - 1;
if (j < info->rgRDN[i].cRDNAttr - 1)
@ -203,9 +239,64 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
}
else
ret++;
TRACE("Returning %s\n", debugstr_a(psz));
return ret;
}
/* Adds the prefix prefix to the wide-character string pointed to by psz,
* followed by the character '='. Copies no more than csz characters. Returns
* the number of characters copied. If psz is NULL, returns the number of
* characters that would be copied.
* Assumes the characters in prefix are ASCII (not multibyte characters.)
*/
static DWORD CRYPT_AddPrefixAToW(LPCSTR prefix, LPWSTR psz, DWORD csz)
{
DWORD chars;
TRACE("(%s, %p, %ld)\n", debugstr_a(prefix), psz, csz);
if (psz)
{
DWORD i;
chars = min(lstrlenA(prefix), csz);
for (i = 0; i < chars; i++)
*(psz + i) = prefix[i];
csz -= chars;
*(psz + chars) = '=';
chars++;
csz--;
}
else
chars = lstrlenA(prefix) + 1;
return chars;
}
/* Adds the prefix prefix to the string pointed to by psz, followed by the
* character '='. Copies no more than csz characters. Returns the number of
* characters copied. If psz is NULL, returns the number of characters that
* would be copied.
*/
static DWORD CRYPT_AddPrefixW(LPCWSTR prefix, LPWSTR psz, DWORD csz)
{
DWORD chars;
TRACE("(%s, %p, %ld)\n", debugstr_w(prefix), psz, csz);
if (psz)
{
chars = min(lstrlenW(prefix), csz);
memcpy(psz, prefix, chars * sizeof(WCHAR));
csz -= chars;
*(psz + chars) = '=';
chars++;
csz--;
}
else
chars = lstrlenW(prefix) + 1;
return chars;
}
DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
DWORD dwStrType, LPWSTR psz, DWORD csz)
{
@ -244,41 +335,49 @@ DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
else
rdnSep = plusSep;
rdnSepLen = lstrlenW(rdnSep);
for (i = 0; ret < csz && i < info->cRDN; i++)
for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
{
for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
for (j = 0; (!psz || ret < csz) && j < info->rgRDN[i].cRDNAttr; j++)
{
DWORD chars;
LPCSTR prefixA = NULL;
LPCWSTR prefixW = NULL;
if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
prefixA = info->rgRDN[i].rgRDNAttr[j].pszObjId;
else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
{
PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
CRYPT_OID_INFO_OID_KEY,
info->rgRDN[i].rgRDNAttr[j].pszObjId,
CRYPT_RDN_ATTR_OID_GROUP_ID);
if (oidInfo)
prefixW = oidInfo->pwszName;
else
prefixA = info->rgRDN[i].rgRDNAttr[j].pszObjId;
}
if (prefixW)
{
/* - 1 is needed to account for the NULL terminator. */
chars = min(
lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
csz - ret - 1);
if (psz && chars)
{
DWORD k;
for (k = 0; k < chars; k++)
*(psz + ret + k) =
info->rgRDN[i].rgRDNAttr[j].pszObjId[k];
}
chars = CRYPT_AddPrefixW(prefixW,
psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
ret += chars;
csz -= chars;
}
else if (prefixA)
{
/* - 1 is needed to account for the NULL terminator. */
chars = CRYPT_AddPrefixAToW(prefixA,
psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
ret += chars;
csz -= chars;
if (csz > 1)
{
if (psz)
*(psz + ret) = '=';
ret++;
csz--;
}
}
/* FIXME: handle quoting */
chars = CertRDNValueToStrW(
info->rgRDN[i].rgRDNAttr[j].dwValueType,
&info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
csz - ret - 1);
psz ? csz - ret : 0);
if (chars)
ret += chars - 1;
if (j < info->rgRDN[i].cRDNAttr - 1)
@ -305,6 +404,7 @@ DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
}
else
ret++;
TRACE("Returning %s\n", debugstr_w(psz));
return ret;
}