encode.c
来自「一个类似windows」· C语言 代码 · 共 1,906 行 · 第 1/5 页
C
1,906 行
{
items[cItem].pvStructInfo = &info->NextUpdate;
items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
cItem++;
}
if (info->cCRLEntry)
{
items[cItem].pvStructInfo = &info->cCRLEntry;
items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
cItem++;
}
if (info->cExtension)
{
items[cItem].pvStructInfo = &info->cExtension;
items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
cItem++;
}
ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
BOOL ret;
struct AsnEncodeSequenceItem items[3] = {
{ ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
{ NULL, NULL, 0 },
{ NULL, NULL, 0 },
};
DWORD cItem = 1;
TRACE("%p, %p, %ld\n", ext, pbEncoded, *pcbEncoded);
if (ext->fCritical)
{
items[cItem].pvStructInfo = &ext->fCritical;
items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
cItem++;
}
items[cItem].pvStructInfo = &ext->Value;
items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
cItem++;
ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
pbEncoded, pcbEncoded);
TRACE("returning %d (%08lx)\n", ret, GetLastError());
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret;
__TRY
{
DWORD bytesNeeded, dataLen, lenBytes, i;
const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
ret = TRUE;
for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
{
DWORD size;
ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
if (ret)
dataLen += size;
}
CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + dataLen;
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; i < exts->cExtension; i++)
{
DWORD size = dataLen;
ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
pbEncoded, &size);
pbEncoded += size;
dataLen -= size;
}
}
}
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
LPCSTR pszObjId = (LPCSTR)pvStructInfo;
DWORD bytesNeeded = 0, lenBytes;
BOOL ret = TRUE;
int firstPos = 0;
BYTE firstByte = 0;
TRACE("%s\n", debugstr_a(pszObjId));
if (pszObjId)
{
const char *ptr;
int val1, val2;
if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
{
SetLastError(CRYPT_E_ASN1_ERROR);
return FALSE;
}
bytesNeeded++;
firstByte = val1 * 40 + val2;
ptr = pszObjId + firstPos;
while (ret && *ptr)
{
int pos;
/* note I assume each component is at most 32-bits long in base 2 */
if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
{
if (val1 >= 0x10000000)
bytesNeeded += 5;
else if (val1 >= 0x200000)
bytesNeeded += 4;
else if (val1 >= 0x4000)
bytesNeeded += 3;
else if (val1 >= 0x80)
bytesNeeded += 2;
else
bytesNeeded += 1;
ptr += pos;
if (*ptr == '.')
ptr++;
}
else
{
SetLastError(CRYPT_E_ASN1_ERROR);
return FALSE;
}
}
CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
}
else
lenBytes = 1;
bytesNeeded += 1 + lenBytes;
if (pbEncoded)
{
if (*pcbEncoded < bytesNeeded)
{
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
{
*pbEncoded++ = ASN_OBJECTIDENTIFIER;
CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
if (pszObjId)
{
const char *ptr;
int val, pos;
*pbEncoded++ = firstByte;
ptr = pszObjId + firstPos;
while (ret && *ptr)
{
sscanf(ptr, "%d%n", &val, &pos);
{
unsigned char outBytes[5];
int numBytes, i;
if (val >= 0x10000000)
numBytes = 5;
else if (val >= 0x200000)
numBytes = 4;
else if (val >= 0x4000)
numBytes = 3;
else if (val >= 0x80)
numBytes = 2;
else
numBytes = 1;
for (i = numBytes; i > 0; i--)
{
outBytes[i - 1] = val & 0x7f;
val >>= 7;
}
for (i = 0; i < numBytes - 1; i++)
*pbEncoded++ = outBytes[i] | 0x80;
*pbEncoded++ = outBytes[i];
ptr += pos;
if (*ptr == '.')
ptr++;
}
}
}
}
}
*pcbEncoded = bytesNeeded;
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
CERT_NAME_VALUE *value, 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(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
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)
{
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
{
*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_IA5_STRING:
memcpy(pbEncoded, value->Value.pbData, value->Value.cbData);
}
}
}
*pcbEncoded = bytesNeeded;
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
CERT_RDN_ATTR *attr, BYTE *pbEncoded, DWORD *pcbEncoded)
{
DWORD bytesNeeded = 0, lenBytes, size;
BOOL ret;
ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
0, NULL, NULL, &size);
if (ret)
{
bytesNeeded += size;
/* 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);
if (ret)
{
bytesNeeded += size;
CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
bytesNeeded += 1 + lenBytes;
if (pbEncoded)
{
if (*pcbEncoded < bytesNeeded)
{
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
{
*pbEncoded++ = ASN_SEQUENCE;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
size = bytesNeeded - 1 - lenBytes;
ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
attr->pszObjId, 0, NULL, pbEncoded, &size);
if (ret)
{
pbEncoded += size;
size = bytesNeeded - 1 - lenBytes - size;
ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
(CERT_NAME_VALUE *)&attr->dwValueType, pbEncoded,
&size);
}
}
}
*pcbEncoded = bytesNeeded;
}
}
return ret;
}
static int BLOBComp(const void *l, const void *r)
{
CRYPT_DER_BLOB *a = (CRYPT_DER_BLOB *)l, *b = (CRYPT_DER_BLOB *)r;
int ret;
if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
ret = a->cbData - b->cbData;
return ret;
}
/* This encodes as a SET OF, which in DER must be lexicographically sorted.
*/
static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret;
CRYPT_DER_BLOB *blobs = NULL;
__TRY
{
DWORD bytesNeeded = 0, lenBytes, i;
blobs = NULL;
ret = TRUE;
if (rdn->cRDNAttr)
{
blobs = CryptMemAlloc(rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
if (!blobs)
ret = FALSE;
else
memset(blobs, 0, rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
}
for (i = 0; ret && i < rdn->cRDNAttr; i++)
{
ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
NULL, &blobs[i].cbData);
if (ret)
bytesNeeded += blobs[i].cbData;
}
if (ret)
{
CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
bytesNeeded += 1 + lenBytes;
if (pbEncoded)
{
if (*pcbEncoded < bytesNeeded)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?