Encode/decode CERT_PUBLIC_KEY_INFO, with tests.
This commit is contained in:
parent
6d9150dd38
commit
417edaadcf
|
@ -68,6 +68,9 @@ static BOOL CRYPT_EncodeBool(BOOL val, BYTE *pbEncoded, DWORD *pcbEncoded);
|
|||
static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
|
||||
static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
|
||||
static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
|
||||
|
@ -81,6 +84,9 @@ static BOOL WINAPI CRYPT_DecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
|
|||
static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
|
||||
static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
|
||||
static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
|
||||
|
@ -516,7 +522,7 @@ static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
|
|||
__TRY
|
||||
{
|
||||
DWORD bytesNeeded, dataLen, lenBytes, i;
|
||||
CERT_EXTENSIONS *exts = (CERT_EXTENSIONS *)pvStructInfo;
|
||||
const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
|
||||
|
||||
ret = TRUE;
|
||||
for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
|
||||
|
@ -881,7 +887,7 @@ static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
|
|||
|
||||
__TRY
|
||||
{
|
||||
CERT_NAME_INFO *info = (CERT_NAME_INFO *)pvStructInfo;
|
||||
const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
|
||||
DWORD bytesNeeded = 0, lenBytes, size, i;
|
||||
|
||||
TRACE("encoding name with %ld RDNs\n", info->cRDN);
|
||||
|
@ -934,6 +940,107 @@ static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_AsnEncodeAlgorithmIdentifier(
|
||||
const CRYPT_ALGORITHM_IDENTIFIER *algo, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD bytesNeeded, dataBytes, lenBytes;
|
||||
|
||||
ret = CRYPT_AsnEncodeOid(algo->pszObjId, NULL, &dataBytes);
|
||||
if (ret)
|
||||
{
|
||||
if (algo->Parameters.cbData)
|
||||
dataBytes += algo->Parameters.cbData;
|
||||
else
|
||||
dataBytes += 2; /* enough space for ASN_NULL */
|
||||
CRYPT_EncodeLen(dataBytes, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + dataBytes;
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else if (*pcbEncoded < bytesNeeded)
|
||||
{
|
||||
*pcbEncoded = bytesNeeded;
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pcbEncoded = bytesNeeded;
|
||||
*pbEncoded++ = ASN_SEQUENCE;
|
||||
CRYPT_EncodeLen(dataBytes, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
ret = CRYPT_AsnEncodeOid(algo->pszObjId, pbEncoded, &dataBytes);
|
||||
if (ret)
|
||||
{
|
||||
pbEncoded += dataBytes;
|
||||
if (algo->Parameters.cbData)
|
||||
memcpy(pbEncoded, algo->Parameters.pbData,
|
||||
algo->Parameters.cbData);
|
||||
else
|
||||
{
|
||||
*pbEncoded++ = ASN_NULL;
|
||||
*pbEncoded++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
__TRY
|
||||
{
|
||||
const CERT_PUBLIC_KEY_INFO *info =
|
||||
(const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
|
||||
DWORD bitBlobLen, lenBytes, dataBytes, bytesNeeded;
|
||||
|
||||
TRACE("Encoding public key with OID %s\n",
|
||||
debugstr_a(info->Algorithm.pszObjId));
|
||||
ret = CRYPT_AsnEncodeAlgorithmIdentifier(&info->Algorithm, NULL,
|
||||
&dataBytes);
|
||||
if (ret)
|
||||
{
|
||||
ret = CRYPT_AsnEncodeBits(dwCertEncodingType, X509_BITS,
|
||||
&info->PublicKey, 0, NULL, NULL, &bitBlobLen);
|
||||
if (ret)
|
||||
{
|
||||
dataBytes += bitBlobLen;
|
||||
CRYPT_EncodeLen(dataBytes, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + dataBytes;
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
*pbEncoded++ = ASN_SEQUENCE;
|
||||
CRYPT_EncodeLen(dataBytes, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
ret = CRYPT_AsnEncodeAlgorithmIdentifier(&info->Algorithm,
|
||||
pbEncoded, &dataBytes);
|
||||
if (ret)
|
||||
{
|
||||
pbEncoded += dataBytes;
|
||||
ret = CRYPT_AsnEncodeBits(dwCertEncodingType, X509_BITS,
|
||||
&info->PublicKey, 0, NULL, pbEncoded, &bitBlobLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__EXCEPT(page_fault)
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
ret = FALSE;
|
||||
}
|
||||
__ENDTRY
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_EncodeBool(BOOL val, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
{
|
||||
if (!pbEncoded)
|
||||
|
@ -962,8 +1069,8 @@ static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
|
|||
|
||||
__TRY
|
||||
{
|
||||
CERT_BASIC_CONSTRAINTS2_INFO *info =
|
||||
(CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
|
||||
const CERT_BASIC_CONSTRAINTS2_INFO *info =
|
||||
(const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
|
||||
DWORD bytesNeeded = 0, lenBytes, caLen = 0, pathConstraintLen = 0;
|
||||
|
||||
ret = TRUE;
|
||||
|
@ -1030,7 +1137,7 @@ static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
|
|||
|
||||
__TRY
|
||||
{
|
||||
CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
|
||||
const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
|
||||
DWORD bytesNeeded, lenBytes;
|
||||
|
||||
CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
|
||||
|
@ -1072,12 +1179,17 @@ static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
|
|||
|
||||
__TRY
|
||||
{
|
||||
CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
|
||||
const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
|
||||
DWORD bytesNeeded, lenBytes, dataBytes;
|
||||
BYTE unusedBits;
|
||||
|
||||
/* yep, MS allows cUnusedBits to be >= 8 */
|
||||
if (blob->cbData * 8 > blob->cUnusedBits)
|
||||
if (!blob->cUnusedBits)
|
||||
{
|
||||
dataBytes = blob->cbData;
|
||||
unusedBits = 0;
|
||||
}
|
||||
else if (blob->cbData * 8 > blob->cUnusedBits)
|
||||
{
|
||||
dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
|
||||
unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
|
||||
|
@ -1150,7 +1262,8 @@ static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
|
|||
DWORD significantBytes, lenBytes;
|
||||
BYTE padByte = 0, bytesNeeded;
|
||||
BOOL pad = FALSE;
|
||||
CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
|
||||
const CRYPT_INTEGER_BLOB *blob =
|
||||
(const CRYPT_INTEGER_BLOB *)pvStructInfo;
|
||||
|
||||
significantBytes = blob->cbData;
|
||||
if (significantBytes)
|
||||
|
@ -1238,7 +1351,8 @@ static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
|
|||
DWORD significantBytes, lenBytes;
|
||||
BYTE bytesNeeded;
|
||||
BOOL pad = FALSE;
|
||||
CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
|
||||
const CRYPT_INTEGER_BLOB *blob =
|
||||
(const CRYPT_INTEGER_BLOB *)pvStructInfo;
|
||||
|
||||
significantBytes = blob->cbData;
|
||||
if (significantBytes)
|
||||
|
@ -1464,7 +1578,8 @@ static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
|
|||
__TRY
|
||||
{
|
||||
DWORD bytesNeeded, dataLen, lenBytes, i;
|
||||
CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
|
||||
const CRYPT_SEQUENCE_OF_ANY *seq =
|
||||
(const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
|
||||
|
||||
for (i = 0, dataLen = 0; i < seq->cValue; i++)
|
||||
dataLen += seq->rgValue[i].cbData;
|
||||
|
@ -1544,6 +1659,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)X509_NAME:
|
||||
encodeFunc = CRYPT_AsnEncodeName;
|
||||
break;
|
||||
case (WORD)X509_PUBLIC_KEY_INFO:
|
||||
encodeFunc = CRYPT_AsnEncodePubKeyInfo;
|
||||
break;
|
||||
case (WORD)X509_BASIC_CONSTRAINTS2:
|
||||
encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
|
||||
break;
|
||||
|
@ -1795,6 +1913,8 @@ static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
|
|||
(ptr - pbEncoded), &ext->fCritical);
|
||||
ptr += 3;
|
||||
}
|
||||
else
|
||||
ext->fCritical = FALSE;
|
||||
ret = CRYPT_AsnDecodeOctets(X509_ASN_ENCODING,
|
||||
X509_OCTET_STRING, ptr,
|
||||
cbEncoded - (ptr - pbEncoded),
|
||||
|
@ -2496,13 +2616,213 @@ static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
__EXCEPT(page_fault)
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
ret = FALSE;
|
||||
}
|
||||
__ENDTRY
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Warning: assumes algo->Parameters.pbData is set ahead of time! */
|
||||
static BOOL CRYPT_AsnDecodeAlgorithmIdentifier(const BYTE *pbEncoded,
|
||||
DWORD cbEncoded, DWORD dwFlags, CRYPT_ALGORITHM_IDENTIFIER *algo,
|
||||
DWORD *pcbAlgo)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
|
||||
if (pbEncoded[0] == ASN_SEQUENCE)
|
||||
{
|
||||
DWORD dataLen, bytesNeeded;
|
||||
|
||||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||
{
|
||||
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]), oidLenBytes = 0;
|
||||
|
||||
bytesNeeded = sizeof(CRYPT_ALGORITHM_IDENTIFIER);
|
||||
if (dataLen)
|
||||
{
|
||||
const BYTE *ptr = pbEncoded + 1 + lenBytes;
|
||||
DWORD encodedOidLen, oidLen;
|
||||
|
||||
CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
|
||||
&encodedOidLen);
|
||||
oidLenBytes = GET_LEN_BYTES(ptr[1]);
|
||||
ret = CRYPT_AsnDecodeOid(ptr, cbEncoded - (ptr - pbEncoded),
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &oidLen);
|
||||
if (ret)
|
||||
{
|
||||
bytesNeeded += oidLen;
|
||||
ptr += 1 + encodedOidLen + oidLenBytes;
|
||||
/* The remaining bytes are just copied as-is, no decoding
|
||||
* is done.
|
||||
* FIXME: is the CRYPT_DECODE_NOCOPY_FLAG used?
|
||||
*/
|
||||
bytesNeeded += cbEncoded - (ptr - pbEncoded);
|
||||
if (!algo)
|
||||
*pcbAlgo = bytesNeeded;
|
||||
else if (*pcbAlgo < bytesNeeded)
|
||||
{
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD paramsLen;
|
||||
|
||||
/* Get and sanity-check parameters first */
|
||||
if ((ret = CRYPT_GetLen(ptr, cbEncoded -
|
||||
(ptr - pbEncoded), ¶msLen)))
|
||||
{
|
||||
BYTE paramsLenBytes = GET_LEN_BYTES(ptr[1]);
|
||||
|
||||
if (paramsLen != dataLen - encodedOidLen - 1 -
|
||||
oidLenBytes - 1 - paramsLenBytes)
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_CORRUPT);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pcbAlgo = bytesNeeded;
|
||||
algo->Parameters.cbData = dataLen -
|
||||
encodedOidLen - 1 - oidLenBytes;
|
||||
if (algo->Parameters.cbData)
|
||||
{
|
||||
memcpy(algo->Parameters.pbData, ptr,
|
||||
algo->Parameters.cbData);
|
||||
algo->pszObjId = algo->Parameters.pbData +
|
||||
algo->Parameters.cbData;
|
||||
}
|
||||
else
|
||||
algo->pszObjId = algo->Parameters.pbData;
|
||||
ptr = pbEncoded + 1 + lenBytes;
|
||||
ret = CRYPT_AsnDecodeOid(ptr,
|
||||
cbEncoded - (ptr - pbEncoded),
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
|
||||
algo->pszObjId, &oidLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_EOD);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
|
||||
__TRY
|
||||
{
|
||||
if (pbEncoded[0] == ASN_SEQUENCE)
|
||||
{
|
||||
DWORD dataLen;
|
||||
|
||||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||
{
|
||||
DWORD algoLen, bitLen, bytesNeeded = 0;
|
||||
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
|
||||
|
||||
/* at least enough for the outer sequence and the inner
|
||||
* sequence/OID combo
|
||||
*/
|
||||
if (dataLen >= 6)
|
||||
{
|
||||
DWORD encodedAlgoLen;
|
||||
BYTE algoLenBytes;
|
||||
|
||||
CRYPT_GetLen(pbEncoded + 1 + lenBytes,
|
||||
cbEncoded - 1 - lenBytes, &encodedAlgoLen);
|
||||
algoLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]);
|
||||
ret = CRYPT_AsnDecodeAlgorithmIdentifier(
|
||||
pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
|
||||
dwFlags, NULL, &algoLen);
|
||||
if (ret)
|
||||
{
|
||||
bytesNeeded += algoLen;
|
||||
ret = CRYPT_AsnDecodeBits(dwCertEncodingType,
|
||||
X509_BITS, pbEncoded + 2 + lenBytes + algoLenBytes +
|
||||
encodedAlgoLen, cbEncoded - (2 + lenBytes +
|
||||
algoLenBytes + encodedAlgoLen), dwFlags, pDecodePara,
|
||||
NULL, &bitLen);
|
||||
if (ret)
|
||||
{
|
||||
bytesNeeded += bitLen;
|
||||
if (!pvStructInfo)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
|
||||
pDecodePara, pvStructInfo, pcbStructInfo,
|
||||
bytesNeeded)))
|
||||
{
|
||||
CERT_PUBLIC_KEY_INFO *info;
|
||||
|
||||
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
||||
pvStructInfo = *(BYTE **)pvStructInfo;
|
||||
info = (CERT_PUBLIC_KEY_INFO *)pvStructInfo;
|
||||
memset(info, 0, sizeof(*info));
|
||||
ret = CRYPT_AsnDecodeBits(
|
||||
dwCertEncodingType, X509_BITS,
|
||||
pbEncoded + 2 + lenBytes + algoLenBytes +
|
||||
encodedAlgoLen,
|
||||
cbEncoded - (2 + lenBytes + algoLenBytes +
|
||||
encodedAlgoLen),
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
|
||||
pDecodePara, &info->PublicKey, &bitLen);
|
||||
if (ret)
|
||||
{
|
||||
if (info->PublicKey.cbData)
|
||||
info->Algorithm.Parameters.pbData =
|
||||
info->PublicKey.pbData +
|
||||
info->PublicKey.cbData;
|
||||
else
|
||||
info->Algorithm.Parameters.pbData =
|
||||
(BYTE *)pvStructInfo +
|
||||
sizeof(CERT_PUBLIC_KEY_INFO);
|
||||
ret = CRYPT_AsnDecodeAlgorithmIdentifier(
|
||||
pbEncoded + 1 + lenBytes, cbEncoded - 1 -
|
||||
lenBytes, dwFlags, &info->Algorithm,
|
||||
&algoLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
SetLastError(CRYPT_E_ASN1_EOD);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
__EXCEPT(page_fault)
|
||||
{
|
||||
|
@ -2705,6 +3025,11 @@ static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
|
|||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
|
||||
dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
|
||||
"(integer value)", pbEncoded, cbEncoded, dwFlags, pDecodePara,
|
||||
pvStructInfo, pcbStructInfo);
|
||||
|
||||
__TRY
|
||||
{
|
||||
if (pbEncoded[0] == ASN_BITSTRING)
|
||||
|
@ -3467,6 +3792,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)X509_NAME:
|
||||
decodeFunc = CRYPT_AsnDecodeName;
|
||||
break;
|
||||
case (WORD)X509_PUBLIC_KEY_INFO:
|
||||
decodeFunc = CRYPT_AsnDecodePubKeyInfo;
|
||||
break;
|
||||
case (WORD)X509_BASIC_CONSTRAINTS2:
|
||||
decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
|
||||
break;
|
||||
|
|
|
@ -916,7 +916,8 @@ struct encodedBits
|
|||
};
|
||||
|
||||
static const struct encodedBits bits[] = {
|
||||
/* normal test case */
|
||||
/* normal test cases */
|
||||
{ 0, "\x03\x03\x00\xff\xff", 2, "\xff\xff" },
|
||||
{ 1, "\x03\x03\x01\xff\xfe", 2, "\xff\xfe" },
|
||||
/* strange test case, showing cUnusedBits >= 8 is allowed */
|
||||
{ 9, "\x03\x02\x01\xfe", 1, "\xfe" },
|
||||
|
@ -1233,17 +1234,6 @@ static const struct encodedExtensions exts[] = {
|
|||
"\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01" },
|
||||
};
|
||||
|
||||
#if 0
|
||||
static void printBytes(const BYTE *pbData, size_t cb)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < cb; i++)
|
||||
printf("%02x ", pbData[i]);
|
||||
putchar('\n');
|
||||
}
|
||||
#endif
|
||||
|
||||
static void test_encodeExtensions(DWORD dwEncoding)
|
||||
{
|
||||
DWORD i;
|
||||
|
@ -1307,6 +1297,109 @@ static void test_decodeExtensions(DWORD dwEncoding)
|
|||
}
|
||||
}
|
||||
|
||||
struct encodedPublicKey
|
||||
{
|
||||
CERT_PUBLIC_KEY_INFO info;
|
||||
const BYTE *encoded;
|
||||
CERT_PUBLIC_KEY_INFO decoded;
|
||||
};
|
||||
|
||||
static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
|
||||
0xe, 0xf };
|
||||
static const BYTE params[] = { 0x02, 0x01, 0x01 };
|
||||
|
||||
static const struct encodedPublicKey pubKeys[] = {
|
||||
/* with a bogus OID */
|
||||
{ { { "1.2.3", { 0, NULL } }, { 0, NULL, 0 } },
|
||||
"\x30\x0b\x30\x06\x06\x02\x2a\x03\x05\x00\x03\x01\x00",
|
||||
{ { "1.2.3", { 2, "\x05\x00" } }, { 0, NULL, 0 } } },
|
||||
/* some normal keys */
|
||||
{ { { szOID_RSA, { 0, NULL } }, { 0, NULL, 0} },
|
||||
"\x30\x0f\x30\x0a\x06\x06\x2a\x86\x48\x86\xf7\x0d\x05\x00\x03\x01\x00",
|
||||
{ { szOID_RSA, { 2, "\x05\x00" } }, { 0, NULL, 0 } } },
|
||||
{ { { szOID_RSA, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
|
||||
"\x30\x1f\x30\x0a\x06\x06\x2a\x86\x48\x86\xf7\x0d\x05\x00\x03\x11\x00\x00\x01"
|
||||
"\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
|
||||
{ { szOID_RSA, { 2, "\x05\x00" } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
|
||||
/* with add'l parameters--note they must be DER-encoded */
|
||||
{ { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
|
||||
(BYTE *)aKey, 0 } },
|
||||
"\x30\x20\x30\x0b\x06\x06\x2a\x86\x48\x86\xf7\x0d\x02\x01\x01"
|
||||
"\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
|
||||
"\x0f",
|
||||
{ { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
|
||||
(BYTE *)aKey, 0 } } },
|
||||
};
|
||||
|
||||
static void test_encodePublicKeyInfo(DWORD dwEncoding)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
|
||||
{
|
||||
BOOL ret;
|
||||
BYTE *buf = NULL;
|
||||
DWORD bufSize = 0;
|
||||
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
|
||||
&pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
|
||||
&bufSize);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(bufSize == pubKeys[i].encoded[1] + 2,
|
||||
"Expected %d bytes, got %ld\n", pubKeys[i].encoded[1] + 2,
|
||||
bufSize);
|
||||
ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
|
||||
"Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_decodePublicKeyInfo(DWORD dwEncoding)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
|
||||
{
|
||||
BOOL ret;
|
||||
BYTE *buf = NULL;
|
||||
DWORD bufSize = 0;
|
||||
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
|
||||
pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
|
||||
NULL, (BYTE *)&buf, &bufSize);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
CERT_PUBLIC_KEY_INFO *info = (CERT_PUBLIC_KEY_INFO *)buf;
|
||||
|
||||
ok(!strcmp(pubKeys[i].decoded.Algorithm.pszObjId,
|
||||
info->Algorithm.pszObjId), "Expected OID %s, got %s\n",
|
||||
pubKeys[i].decoded.Algorithm.pszObjId, info->Algorithm.pszObjId);
|
||||
ok(pubKeys[i].decoded.Algorithm.Parameters.cbData ==
|
||||
info->Algorithm.Parameters.cbData,
|
||||
"Expected parameters of %ld bytes, got %ld\n",
|
||||
pubKeys[i].decoded.Algorithm.Parameters.cbData,
|
||||
info->Algorithm.Parameters.cbData);
|
||||
if (pubKeys[i].decoded.Algorithm.Parameters.cbData)
|
||||
ok(!memcmp(pubKeys[i].decoded.Algorithm.Parameters.pbData,
|
||||
info->Algorithm.Parameters.pbData,
|
||||
info->Algorithm.Parameters.cbData),
|
||||
"Unexpected algorithm parameters\n");
|
||||
ok(pubKeys[i].decoded.PublicKey.cbData == info->PublicKey.cbData,
|
||||
"Expected public key of %ld bytes, got %ld\n",
|
||||
pubKeys[i].decoded.PublicKey.cbData, info->PublicKey.cbData);
|
||||
if (pubKeys[i].decoded.PublicKey.cbData)
|
||||
ok(!memcmp(pubKeys[i].decoded.PublicKey.pbData,
|
||||
info->PublicKey.pbData, info->PublicKey.cbData),
|
||||
"Unexpected public key value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_registerOIDFunction(void)
|
||||
{
|
||||
static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 };
|
||||
|
@ -1387,6 +1480,8 @@ START_TEST(encode)
|
|||
test_decodeSequenceOfAny(encodings[i]);
|
||||
test_encodeExtensions(encodings[i]);
|
||||
test_decodeExtensions(encodings[i]);
|
||||
test_encodePublicKeyInfo(encodings[i]);
|
||||
test_decodePublicKeyInfo(encodings[i]);
|
||||
}
|
||||
test_registerOIDFunction();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue