Commit dd4bd4ad authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

crypt32: Implement X509_NAME_VALUE encoding/decoding.

parent d7043f23
......@@ -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)
{
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)
__TRY
{
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]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment