crypt32: Implement more string types for X509_NAME_VALUE.
This commit is contained in:
parent
9bce49543b
commit
1eefa005da
|
@ -1272,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)
|
||||
|
@ -1310,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);
|
||||
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
|
||||
|
|
|
@ -384,19 +384,19 @@ 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 ((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;
|
||||
}
|
||||
|
||||
|
@ -913,47 +913,15 @@ static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
|
||||
BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
|
||||
__TRY
|
||||
{
|
||||
BYTE tag;
|
||||
LPCSTR str = (LPCSTR)value->Value.pbData;
|
||||
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);
|
||||
ret = FALSE;
|
||||
break;
|
||||
default:
|
||||
FIXME("String type %ld unimplemented\n", value->dwValueType);
|
||||
ret = FALSE;
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
|
||||
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + encodedLen;
|
||||
if (!pbEncoded)
|
||||
|
@ -968,17 +936,154 @@ static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
|
|||
*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)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
|
||||
__TRY
|
||||
{
|
||||
const CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
|
||||
|
||||
switch (value->dwValueType)
|
||||
{
|
||||
case CERT_RDN_ANY_TYPE:
|
||||
/* explicitly disallowed */
|
||||
SetLastError(E_INVALIDARG);
|
||||
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:
|
||||
case CERT_RDN_T61_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:
|
||||
memcpy(pbEncoded, value->Value.pbData,
|
||||
value->Value.cbData);
|
||||
}
|
||||
}
|
||||
}
|
||||
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:
|
||||
SetLastError(CRYPT_E_ASN1_CHOICE);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
|
@ -1156,39 +1261,6 @@ static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
|
|||
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 CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
|
||||
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded)
|
||||
|
@ -1228,42 +1300,6 @@ static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
|
|||
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 WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
|
|
|
@ -605,6 +605,12 @@ static const BYTE twoRDNs[] = {
|
|||
0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
|
||||
0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
|
||||
0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
|
||||
static const BYTE encodedTwoRDNs[] = {
|
||||
0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
|
||||
0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
|
||||
0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
|
||||
0x6e,0x67,0x00,
|
||||
};
|
||||
|
||||
static const BYTE us[] = { 0x55, 0x53 };
|
||||
static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
|
||||
|
@ -742,6 +748,21 @@ static void test_encodeName(DWORD dwEncoding)
|
|||
"Got unexpected encoding for two RDN array\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
/* A name can be "encoded" with previously encoded RDN attrs. */
|
||||
attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
|
||||
attrs[0].Value.pbData = (LPBYTE)twoRDNs;
|
||||
attrs[0].Value.cbData = sizeof(twoRDNs);
|
||||
rdn.cRDNAttr = 1;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(encodedTwoRDNs), "Unexpected size %ld\n", size);
|
||||
ok(!memcmp(buf, encodedTwoRDNs, size),
|
||||
"Unexpected value for re-endoded two RDN array\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
/* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
|
||||
rdn.cRDNAttr = 1;
|
||||
attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
|
||||
|
@ -774,11 +795,12 @@ static void compareNameValues(const CERT_NAME_VALUE *expected,
|
|||
"Expected string type %ld, got %ld\n", expected->dwValueType,
|
||||
got->dwValueType);
|
||||
ok(got->Value.cbData == expected->Value.cbData,
|
||||
"Unexpected data size, got %ld, expected %ld\n", got->Value.cbData,
|
||||
expected->Value.cbData);
|
||||
"String type %ld: unexpected data size, got %ld, expected %ld\n",
|
||||
expected->dwValueType, got->Value.cbData, expected->Value.cbData);
|
||||
if (got->Value.cbData && got->Value.pbData)
|
||||
ok(!memcmp(got->Value.pbData, expected->Value.pbData,
|
||||
min(got->Value.cbData, expected->Value.cbData)), "Unexpected value\n");
|
||||
min(got->Value.cbData, expected->Value.cbData)),
|
||||
"String type %ld: unexpected value\n", expected->dwValueType);
|
||||
}
|
||||
|
||||
static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
|
||||
|
@ -908,56 +930,112 @@ struct EncodedNameValue
|
|||
{
|
||||
CERT_NAME_VALUE value;
|
||||
const BYTE *encoded;
|
||||
DWORD encodedSize;
|
||||
};
|
||||
|
||||
static const char bogusIA5[] = "\x80";
|
||||
static const char bogusPrintable[] = "~";
|
||||
static const char bogusNumeric[] = "A";
|
||||
static const char bogusT61[] = "\xff";
|
||||
static const BYTE bin39[] = { 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
|
||||
0x67,0x00 };
|
||||
static const BYTE bin40[] = { 0x16,0x05,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
static const BYTE bin41[] = { 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
|
||||
0x67,0x00 };
|
||||
static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
|
||||
static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
|
||||
static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
|
||||
static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
|
||||
static const BYTE bin45[] = { 0x14,0x02,0xff,0x00 };
|
||||
static BYTE octetCommonNameValue[] = {
|
||||
0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
static BYTE numericCommonNameValue[] = {
|
||||
0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
static BYTE printableCommonNameValue[] = {
|
||||
0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
static BYTE t61CommonNameValue[] = {
|
||||
0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
static BYTE videotexCommonNameValue[] = {
|
||||
0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
static BYTE ia5CommonNameValue[] = {
|
||||
0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
static BYTE graphicCommonNameValue[] = {
|
||||
0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
static BYTE visibleCommonNameValue[] = {
|
||||
0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
static BYTE generalCommonNameValue[] = {
|
||||
0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
static BYTE bmpCommonNameValue[] = {
|
||||
0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
|
||||
0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
|
||||
static BYTE utf8CommonNameValue[] = {
|
||||
0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||
|
||||
struct EncodedNameValue nameValues[] = {
|
||||
static struct EncodedNameValue nameValues[] = {
|
||||
{ { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
||||
octetCommonNameValue, sizeof(octetCommonNameValue) },
|
||||
{ { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
||||
numericCommonNameValue, sizeof(numericCommonNameValue) },
|
||||
{ { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
||||
bin39 },
|
||||
{ { CERT_RDN_IA5_STRING, { sizeof(surName), (BYTE *)surName } }, bin40 },
|
||||
{ { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } }, bin41 },
|
||||
printableCommonNameValue, sizeof(printableCommonNameValue) },
|
||||
{ { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
||||
t61CommonNameValue, sizeof(t61CommonNameValue) },
|
||||
{ { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
||||
videotexCommonNameValue, sizeof(videotexCommonNameValue) },
|
||||
{ { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
||||
ia5CommonNameValue, sizeof(ia5CommonNameValue) },
|
||||
{ { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
||||
graphicCommonNameValue, sizeof(graphicCommonNameValue) },
|
||||
{ { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
||||
visibleCommonNameValue, sizeof(visibleCommonNameValue) },
|
||||
{ { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
||||
generalCommonNameValue, sizeof(generalCommonNameValue) },
|
||||
{ { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
|
||||
bmpCommonNameValue, sizeof(bmpCommonNameValue) },
|
||||
{ { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
|
||||
utf8CommonNameValue, sizeof(utf8CommonNameValue) },
|
||||
/* The following tests succeed under Windows, but really should fail,
|
||||
* they contain characters that are illegal for the encoding. I'm
|
||||
* including them to justify my lazy encoding.
|
||||
*/
|
||||
{ { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42 },
|
||||
{ { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
|
||||
sizeof(bin42) },
|
||||
{ { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
|
||||
(BYTE *)bogusPrintable } }, bin43 },
|
||||
(BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
|
||||
{ { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
|
||||
bin44 },
|
||||
{ { CERT_RDN_T61_STRING, { sizeof(bogusT61), (BYTE *)bogusT61 } }, bin45 },
|
||||
bin44, sizeof(bin44) },
|
||||
};
|
||||
|
||||
|
||||
static void test_encodeNameValue(DWORD dwEncoding)
|
||||
{
|
||||
BYTE *buf = NULL;
|
||||
DWORD size = 0, i;
|
||||
BOOL ret;
|
||||
CERT_NAME_VALUE value = { 0, { 0, NULL } };
|
||||
|
||||
value.dwValueType = 14;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(!ret && GetLastError() == CRYPT_E_ASN1_CHOICE,
|
||||
"Expected CRYPT_E_ASN1_CHOICE, got %08lx\n", GetLastError());
|
||||
value.dwValueType = CERT_RDN_ENCODED_BLOB;
|
||||
value.Value.pbData = printableCommonNameValue;
|
||||
value.Value.cbData = sizeof(printableCommonNameValue);
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(printableCommonNameValue), "Unexpected size %ld\n",
|
||||
size);
|
||||
ok(!memcmp(buf, printableCommonNameValue, size),
|
||||
"Unexpected encoding\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
|
||||
{
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
|
||||
&nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
|
||||
&size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
|
||||
ok(ret, "Type %ld: CryptEncodeObjectEx failed: %08lx\n",
|
||||
nameValues[i].value.dwValueType, GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == nameValues[i].encoded[1] + 2,
|
||||
"Expected size %d, got %ld\n", nameValues[i].encoded[1] + 2, size);
|
||||
ok(size == nameValues[i].encodedSize,
|
||||
"Expected size %ld, got %ld\n", nameValues[i].encodedSize, size);
|
||||
ok(!memcmp(buf, nameValues[i].encoded, size),
|
||||
"Got unexpected encoding\n");
|
||||
LocalFree(buf);
|
||||
|
@ -978,7 +1056,8 @@ static void test_decodeNameValue(DWORD dwEncoding)
|
|||
nameValues[i].encoded, nameValues[i].encoded[1] + 2,
|
||||
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
|
||||
(BYTE *)&buf, &bufSize);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
|
||||
ok(ret, "Value type %ld: CryptDecodeObjectEx failed: %08lx\n",
|
||||
nameValues[i].value.dwValueType, GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
compareNameValues(&nameValues[i].value,
|
||||
|
|
Loading…
Reference in New Issue