crypt32: Implement X509_NAME_VALUE encoding/decoding.
This commit is contained in:
parent
d7043f23ca
commit
dd4bd4ad28
|
@ -26,6 +26,7 @@
|
|||
#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_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
|
||||
#define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
|
||||
#define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
|
||||
|
|
|
@ -1182,7 +1182,7 @@ static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
|
|||
* order to avoid overwriting memory. (In some cases, it may change it, if it
|
||||
* doesn't copy anything to memory.) Be sure to set it correctly!
|
||||
*/
|
||||
static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
|
||||
static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
|
@ -1199,6 +1199,7 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
|
|||
case ASN_NUMERICSTRING:
|
||||
case ASN_PRINTABLESTRING:
|
||||
case ASN_IA5STRING:
|
||||
case ASN_T61STRING:
|
||||
break;
|
||||
default:
|
||||
FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
|
||||
|
@ -1214,6 +1215,7 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
|
|||
case ASN_NUMERICSTRING:
|
||||
case ASN_PRINTABLESTRING:
|
||||
case ASN_IA5STRING:
|
||||
case ASN_T61STRING:
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
|
@ -1240,6 +1242,9 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
|
|||
case ASN_IA5STRING:
|
||||
value->dwValueType = CERT_RDN_IA5_STRING;
|
||||
break;
|
||||
case ASN_T61STRING:
|
||||
value->dwValueType = CERT_RDN_T61_STRING;
|
||||
break;
|
||||
}
|
||||
if (dataLen)
|
||||
{
|
||||
|
@ -1248,6 +1253,7 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
|
|||
case ASN_NUMERICSTRING:
|
||||
case ASN_PRINTABLESTRING:
|
||||
case ASN_IA5STRING:
|
||||
case ASN_T61STRING:
|
||||
value->Value.cbData = dataLen;
|
||||
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
|
||||
value->Value.pbData = (BYTE *)pbEncoded + 1 +
|
||||
|
@ -1272,6 +1278,45 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeNameValue(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_AsnDecodeNameValueInternal(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_AsnDecodeNameValueInternal(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)
|
||||
|
@ -1282,7 +1327,7 @@ static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
|
|||
CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
|
||||
offsetof(CERT_RDN_ATTR, pszObjId), 0 },
|
||||
{ 0, offsetof(CERT_RDN_ATTR, dwValueType),
|
||||
CRYPT_AsnDecodeNameValue, sizeof(CERT_NAME_VALUE),
|
||||
CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
|
||||
FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
|
||||
};
|
||||
CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
|
||||
|
@ -2940,6 +2985,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)X509_EXTENSIONS:
|
||||
decodeFunc = CRYPT_AsnDecodeExtensions;
|
||||
break;
|
||||
case (WORD)X509_NAME_VALUE:
|
||||
decodeFunc = CRYPT_AsnDecodeNameValue;
|
||||
break;
|
||||
case (WORD)X509_NAME:
|
||||
decodeFunc = CRYPT_AsnDecodeName;
|
||||
break;
|
||||
|
|
|
@ -906,58 +906,74 @@ static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
|
|||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
|
||||
CERT_NAME_VALUE *value, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
{
|
||||
BYTE tag;
|
||||
DWORD bytesNeeded, lenBytes, encodedLen;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
switch (value->dwValueType)
|
||||
__TRY
|
||||
{
|
||||
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_IA5_STRING:
|
||||
tag = ASN_IA5STRING;
|
||||
encodedLen = value->Value.cbData;
|
||||
break;
|
||||
case CERT_RDN_ANY_TYPE:
|
||||
/* explicitly disallowed */
|
||||
SetLastError(E_INVALIDARG);
|
||||
return FALSE;
|
||||
default:
|
||||
FIXME("String type %ld unimplemented\n", value->dwValueType);
|
||||
return FALSE;
|
||||
}
|
||||
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + encodedLen;
|
||||
if (pbEncoded)
|
||||
{
|
||||
if (*pcbEncoded < bytesNeeded)
|
||||
BYTE tag;
|
||||
DWORD bytesNeeded, lenBytes, encodedLen;
|
||||
const CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
|
||||
|
||||
switch (value->dwValueType)
|
||||
{
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
ret = FALSE;
|
||||
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;
|
||||
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
|
||||
{
|
||||
*pbEncoded++ = tag;
|
||||
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
switch (value->dwValueType)
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
|
||||
pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
case CERT_RDN_NUMERIC_STRING:
|
||||
case CERT_RDN_PRINTABLE_STRING:
|
||||
case CERT_RDN_IA5_STRING:
|
||||
memcpy(pbEncoded, value->Value.pbData, value->Value.cbData);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*pcbEncoded = bytesNeeded;
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
ret = FALSE;
|
||||
}
|
||||
__ENDTRY
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -975,8 +991,8 @@ static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
|
|||
/* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
|
||||
* with dwValueType, so "cast" it to get its encoded size
|
||||
*/
|
||||
ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
|
||||
(CERT_NAME_VALUE *)&attr->dwValueType, NULL, &size);
|
||||
ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType, X509_NAME_VALUE,
|
||||
(CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
|
||||
if (ret)
|
||||
{
|
||||
bytesNeeded += size;
|
||||
|
@ -1003,8 +1019,8 @@ static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
|
|||
pbEncoded += size;
|
||||
size = bytesNeeded - 1 - lenBytes - size;
|
||||
ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
|
||||
(CERT_NAME_VALUE *)&attr->dwValueType, pbEncoded,
|
||||
&size);
|
||||
X509_NAME_VALUE, (CERT_NAME_VALUE *)&attr->dwValueType,
|
||||
0, NULL, pbEncoded, &size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2264,6 +2280,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)X509_EXTENSIONS:
|
||||
encodeFunc = CRYPT_AsnEncodeExtensions;
|
||||
break;
|
||||
case (WORD)X509_NAME_VALUE:
|
||||
encodeFunc = CRYPT_AsnEncodeNameValue;
|
||||
break;
|
||||
case (WORD)X509_NAME:
|
||||
encodeFunc = CRYPT_AsnEncodeName;
|
||||
break;
|
||||
|
|
|
@ -3204,10 +3204,8 @@ START_TEST(encode)
|
|||
test_decodeFiletime(encodings[i]);
|
||||
test_encodeName(encodings[i]);
|
||||
test_decodeName(encodings[i]);
|
||||
todo_wine {
|
||||
test_encodeNameValue(encodings[i]);
|
||||
test_decodeNameValue(encodings[i]);
|
||||
}
|
||||
test_encodeAltName(encodings[i]);
|
||||
test_decodeAltName(encodings[i]);
|
||||
test_encodeOctets(encodings[i]);
|
||||
|
|
Loading…
Reference in New Issue