diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index f8365d615a6..8ac04849884 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -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) diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c index d2be5211167..cd0e64467a3 100644 --- a/dlls/crypt32/decode.c +++ b/dlls/crypt32/decode.c @@ -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; diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c index ee1c9cc9332..3fee0c973d3 100644 --- a/dlls/crypt32/encode.c +++ b/dlls/crypt32/encode.c @@ -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; diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c index d5258c16a7a..da5b975ce36 100644 --- a/dlls/crypt32/tests/encode.c +++ b/dlls/crypt32/tests/encode.c @@ -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]);