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,
|
static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
|
||||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
|
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,
|
static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
|
||||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
|
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,
|
static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
|
||||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
|
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,
|
static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
|
||||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
|
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
|
||||||
|
@ -516,7 +522,7 @@ static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
DWORD bytesNeeded, dataLen, lenBytes, i;
|
DWORD bytesNeeded, dataLen, lenBytes, i;
|
||||||
CERT_EXTENSIONS *exts = (CERT_EXTENSIONS *)pvStructInfo;
|
const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
|
for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
|
||||||
|
@ -881,7 +887,7 @@ static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
|
||||||
|
|
||||||
__TRY
|
__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;
|
DWORD bytesNeeded = 0, lenBytes, size, i;
|
||||||
|
|
||||||
TRACE("encoding name with %ld RDNs\n", info->cRDN);
|
TRACE("encoding name with %ld RDNs\n", info->cRDN);
|
||||||
|
@ -934,6 +940,107 @@ static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
|
||||||
return ret;
|
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)
|
static BOOL CRYPT_EncodeBool(BOOL val, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||||
{
|
{
|
||||||
if (!pbEncoded)
|
if (!pbEncoded)
|
||||||
|
@ -962,8 +1069,8 @@ static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
|
||||||
|
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
CERT_BASIC_CONSTRAINTS2_INFO *info =
|
const CERT_BASIC_CONSTRAINTS2_INFO *info =
|
||||||
(CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
|
(const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
|
||||||
DWORD bytesNeeded = 0, lenBytes, caLen = 0, pathConstraintLen = 0;
|
DWORD bytesNeeded = 0, lenBytes, caLen = 0, pathConstraintLen = 0;
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
@ -1030,7 +1137,7 @@ static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
|
||||||
|
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
|
const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
|
||||||
DWORD bytesNeeded, lenBytes;
|
DWORD bytesNeeded, lenBytes;
|
||||||
|
|
||||||
CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
|
CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
|
||||||
|
@ -1072,12 +1179,17 @@ static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
|
||||||
|
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
|
const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
|
||||||
DWORD bytesNeeded, lenBytes, dataBytes;
|
DWORD bytesNeeded, lenBytes, dataBytes;
|
||||||
BYTE unusedBits;
|
BYTE unusedBits;
|
||||||
|
|
||||||
/* yep, MS allows cUnusedBits to be >= 8 */
|
/* 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;
|
dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
|
||||||
unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
|
unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
|
||||||
|
@ -1150,7 +1262,8 @@ static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
|
||||||
DWORD significantBytes, lenBytes;
|
DWORD significantBytes, lenBytes;
|
||||||
BYTE padByte = 0, bytesNeeded;
|
BYTE padByte = 0, bytesNeeded;
|
||||||
BOOL pad = FALSE;
|
BOOL pad = FALSE;
|
||||||
CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
|
const CRYPT_INTEGER_BLOB *blob =
|
||||||
|
(const CRYPT_INTEGER_BLOB *)pvStructInfo;
|
||||||
|
|
||||||
significantBytes = blob->cbData;
|
significantBytes = blob->cbData;
|
||||||
if (significantBytes)
|
if (significantBytes)
|
||||||
|
@ -1238,7 +1351,8 @@ static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
|
||||||
DWORD significantBytes, lenBytes;
|
DWORD significantBytes, lenBytes;
|
||||||
BYTE bytesNeeded;
|
BYTE bytesNeeded;
|
||||||
BOOL pad = FALSE;
|
BOOL pad = FALSE;
|
||||||
CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
|
const CRYPT_INTEGER_BLOB *blob =
|
||||||
|
(const CRYPT_INTEGER_BLOB *)pvStructInfo;
|
||||||
|
|
||||||
significantBytes = blob->cbData;
|
significantBytes = blob->cbData;
|
||||||
if (significantBytes)
|
if (significantBytes)
|
||||||
|
@ -1464,7 +1578,8 @@ static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
DWORD bytesNeeded, dataLen, lenBytes, i;
|
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++)
|
for (i = 0, dataLen = 0; i < seq->cValue; i++)
|
||||||
dataLen += seq->rgValue[i].cbData;
|
dataLen += seq->rgValue[i].cbData;
|
||||||
|
@ -1544,6 +1659,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
||||||
case (WORD)X509_NAME:
|
case (WORD)X509_NAME:
|
||||||
encodeFunc = CRYPT_AsnEncodeName;
|
encodeFunc = CRYPT_AsnEncodeName;
|
||||||
break;
|
break;
|
||||||
|
case (WORD)X509_PUBLIC_KEY_INFO:
|
||||||
|
encodeFunc = CRYPT_AsnEncodePubKeyInfo;
|
||||||
|
break;
|
||||||
case (WORD)X509_BASIC_CONSTRAINTS2:
|
case (WORD)X509_BASIC_CONSTRAINTS2:
|
||||||
encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
|
encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
|
||||||
break;
|
break;
|
||||||
|
@ -1795,6 +1913,8 @@ static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
|
||||||
(ptr - pbEncoded), &ext->fCritical);
|
(ptr - pbEncoded), &ext->fCritical);
|
||||||
ptr += 3;
|
ptr += 3;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ext->fCritical = FALSE;
|
||||||
ret = CRYPT_AsnDecodeOctets(X509_ASN_ENCODING,
|
ret = CRYPT_AsnDecodeOctets(X509_ASN_ENCODING,
|
||||||
X509_OCTET_STRING, ptr,
|
X509_OCTET_STRING, ptr,
|
||||||
cbEncoded - (ptr - pbEncoded),
|
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
|
else
|
||||||
{
|
{
|
||||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
SetLastError(CRYPT_E_ASN1_EOD);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
__EXCEPT(page_fault)
|
__EXCEPT(page_fault)
|
||||||
{
|
{
|
||||||
|
@ -2705,6 +3025,11 @@ static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
|
||||||
{
|
{
|
||||||
BOOL ret;
|
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
|
__TRY
|
||||||
{
|
{
|
||||||
if (pbEncoded[0] == ASN_BITSTRING)
|
if (pbEncoded[0] == ASN_BITSTRING)
|
||||||
|
@ -3467,6 +3792,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
||||||
case (WORD)X509_NAME:
|
case (WORD)X509_NAME:
|
||||||
decodeFunc = CRYPT_AsnDecodeName;
|
decodeFunc = CRYPT_AsnDecodeName;
|
||||||
break;
|
break;
|
||||||
|
case (WORD)X509_PUBLIC_KEY_INFO:
|
||||||
|
decodeFunc = CRYPT_AsnDecodePubKeyInfo;
|
||||||
|
break;
|
||||||
case (WORD)X509_BASIC_CONSTRAINTS2:
|
case (WORD)X509_BASIC_CONSTRAINTS2:
|
||||||
decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
|
decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -916,7 +916,8 @@ struct encodedBits
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct encodedBits bits[] = {
|
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" },
|
{ 1, "\x03\x03\x01\xff\xfe", 2, "\xff\xfe" },
|
||||||
/* strange test case, showing cUnusedBits >= 8 is allowed */
|
/* strange test case, showing cUnusedBits >= 8 is allowed */
|
||||||
{ 9, "\x03\x02\x01\xfe", 1, "\xfe" },
|
{ 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" },
|
"\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)
|
static void test_encodeExtensions(DWORD dwEncoding)
|
||||||
{
|
{
|
||||||
DWORD i;
|
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 void test_registerOIDFunction(void)
|
||||||
{
|
{
|
||||||
static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 };
|
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_decodeSequenceOfAny(encodings[i]);
|
||||||
test_encodeExtensions(encodings[i]);
|
test_encodeExtensions(encodings[i]);
|
||||||
test_decodeExtensions(encodings[i]);
|
test_decodeExtensions(encodings[i]);
|
||||||
|
test_encodePublicKeyInfo(encodings[i]);
|
||||||
|
test_decodePublicKeyInfo(encodings[i]);
|
||||||
}
|
}
|
||||||
test_registerOIDFunction();
|
test_registerOIDFunction();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue