* MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
*/
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define NONAMELESSUNION
+
+#include "windef.h"
+#include "winbase.h"
+#include "wincrypt.h"
+#include "winnls.h"
+#include "snmp.h"
+#include "wine/debug.h"
+#include "wine/exception.h"
#include "crypt32_private.h"
/* This is a bit arbitrary, but to set some limit: */
static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
/* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
-static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
+static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
DWORD *pcbDecoded);
/* Doesn't check the tag, assumes the caller does so */
{
dataLen = cbEncoded;
indefinite = TRUE;
+ lenBytes += 2;
}
else if (cbEncoded < dataLen)
{
if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, NULL, NULL);
}
CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
};
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, NULL);
return ret;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
NULL, NULL);
if (ret && pvStructInfo)
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
*pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
entry ? entry->SerialNumber.pbData : NULL);
if (ret && entry && !entry->SerialNumber.cbData)
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
- pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
- NULL, NULL);
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
TRACE("Returning %d (%08x)\n", ret, GetLastError());
return ret;
{ ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
sizeof(BOOL), TRUE, FALSE, 0, 0 },
{ ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
+ CRYPT_AsnDecodeOctets, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
offsetof(CERT_EXTENSION, Value.pbData) },
};
BOOL ret = TRUE;
if (ext)
TRACE("ext->pszObjId is %p\n", ext->pszObjId);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
pcbDecoded, ext ? ext->pszObjId : NULL);
if (ext)
if (attr)
TRACE("attr->pszObjId is %p\n", attr->pszObjId);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
attr ? attr->pszObjId : NULL);
if (attr)
if (attr)
TRACE("attr->pszObjId is %p\n", attr->pszObjId);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
attr ? attr->pszObjId : NULL);
if (attr)
{
struct AsnDecodeSequenceItem items[] = {
{ ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
+ CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
{ ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
CRYPT_AsnDecodeCTLEntryAttributes,
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
*pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
return ret;
CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
{ ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
+ CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), TRUE,
TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
{ ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
};
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, NULL, NULL);
}
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, capability ? capability->pszObjId : NULL);
TRACE("returning %d\n", ret);
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
NULL);
if (ret)
*(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
- ret = CRYPT_AsnDecodeSequence(items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- NULL, noticeRef, &bytesNeeded, pcbDecoded,
- noticeRef->pszOrganization);
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags,
+ NULL, noticeRef, &bytesNeeded, pcbDecoded, noticeRef->pszOrganization);
}
}
TRACE("returning %d\n", ret);
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, notice ? notice->pNoticeReference : NULL);
TRACE("returning %d\n", ret);
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, attr ? attr->pszObjId : NULL);
TRACE("returning %d\n", ret);
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo, pcbDecoded);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, algo ? algo->pszObjId : NULL);
if (ret && pvStructInfo)
};
PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
return ret;
{
struct AsnDecodeSequenceItem items[] = {
{ ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB),
+ CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB),
TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
{ ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
+ CRYPT_AsnDecodeOctets, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
{ ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
};
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, NULL, NULL);
}
{
struct AsnDecodeSequenceItem items[] = {
{ ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB),
+ CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB),
TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
{ ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
AuthorityCertSerialNumber.pbData), 0 },
};
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, NULL, NULL);
}
};
CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
- return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ return CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, descr ? descr->pszAccessMethod : NULL);
}
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo, pcbDecoded);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, info ? info->pszObjId : NULL);
return ret;
sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
ContentInfo.pszObjId), 0 },
{ ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
+ CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
};
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
NULL, NULL);
return ret;
offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
};
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, NULL, NULL);
}
sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
};
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, NULL, NULL);
}
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
return ret;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
return ret;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, mapping ? mapping->pszIssuerDomainPolicy : NULL);
return ret;
TRUE, FALSE, 0, 0 },
};
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, NULL, NULL);
}
struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
DWORD size = 0;
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
&size, NULL, NULL);
if (ret)
return ret;
}
-static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
+#define RSA2_MAGIC 0x32415352
+
+struct DECODED_RSA_PRIV_KEY
+{
+ DWORD version;
+ DWORD pubexp;
+ CRYPT_INTEGER_BLOB modulus;
+ CRYPT_INTEGER_BLOB privexp;
+ CRYPT_INTEGER_BLOB prime1;
+ CRYPT_INTEGER_BLOB prime2;
+ CRYPT_INTEGER_BLOB exponent1;
+ CRYPT_INTEGER_BLOB exponent2;
+ CRYPT_INTEGER_BLOB coefficient;
+};
+
+static BOOL WINAPI CRYPT_AsnDecodeRsaPrivKey(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+ DWORD halflen;
+
+ __TRY
+ {
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, version),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, modulus),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, modulus.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, pubexp),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, privexp),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, privexp.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime1),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime1.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime2),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime2.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient.pbData),
+ 0 },
+ };
+ struct DECODED_RSA_PRIV_KEY *decodedKey = NULL;
+ DWORD size = 0;
+
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
+ pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
+ &size, NULL, NULL);
+ if (ret)
+ {
+ halflen = decodedKey->prime1.cbData;
+ if (halflen < decodedKey->prime2.cbData)
+ halflen = decodedKey->prime2.cbData;
+ if (halflen < decodedKey->exponent1.cbData)
+ halflen = decodedKey->exponent1.cbData;
+ if (halflen < decodedKey->exponent2.cbData)
+ halflen = decodedKey->exponent2.cbData;
+ if (halflen < decodedKey->coefficient.cbData)
+ halflen = decodedKey->coefficient.cbData;
+ if (halflen * 2 < decodedKey->modulus.cbData)
+ halflen = decodedKey->modulus.cbData / 2 + decodedKey->modulus.cbData % 2;
+ if (halflen * 2 < decodedKey->privexp.cbData)
+ halflen = decodedKey->privexp.cbData / 2 + decodedKey->privexp.cbData % 2;
+
+ if (ret)
+ {
+ DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
+ (halflen * 9);
+
+ if (!pvStructInfo)
+ {
+ *pcbStructInfo = bytesNeeded;
+ ret = TRUE;
+ }
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ BLOBHEADER *hdr;
+ RSAPUBKEY *rsaPubKey;
+ BYTE *vardata;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+
+ hdr = pvStructInfo;
+ hdr->bType = PRIVATEKEYBLOB;
+ hdr->bVersion = CUR_BLOB_VERSION;
+ hdr->reserved = 0;
+ hdr->aiKeyAlg = CALG_RSA_KEYX;
+
+ rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
+ sizeof(BLOBHEADER));
+ rsaPubKey->magic = RSA2_MAGIC;
+ rsaPubKey->pubexp = decodedKey->pubexp;
+ rsaPubKey->bitlen = halflen * 16;
+
+ vardata = (BYTE*)(rsaPubKey + 1);
+ memset(vardata, 0, halflen * 9);
+ memcpy(vardata,
+ decodedKey->modulus.pbData, decodedKey->modulus.cbData);
+ memcpy(vardata + halflen * 2,
+ decodedKey->prime1.pbData, decodedKey->prime1.cbData);
+ memcpy(vardata + halflen * 3,
+ decodedKey->prime2.pbData, decodedKey->prime2.cbData);
+ memcpy(vardata + halflen * 4,
+ decodedKey->exponent1.pbData, decodedKey->exponent1.cbData);
+ memcpy(vardata + halflen * 5,
+ decodedKey->exponent2.pbData, decodedKey->exponent2.cbData);
+ memcpy(vardata + halflen * 6,
+ decodedKey->coefficient.pbData, decodedKey->coefficient.cbData);
+ memcpy(vardata + halflen * 7,
+ decodedKey->privexp.pbData, decodedKey->privexp.cbData);
+ }
+ }
+
+ LocalFree(decodedKey);
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
DWORD *pcbDecoded)
{
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
+static BOOL CRYPT_AsnDecodeOctetStringInternal(const BYTE *encoded, DWORD encoded_size,
+ DWORD flags, void *buf, DWORD *buf_size, DWORD *ret_decoded)
+{
+ DWORD decoded = 0, indefinite_len_depth = 0, len_size, len, bytes_needed;
+ CRYPT_DATA_BLOB *blob;
+ const BYTE *string;
+
+ while (encoded[0] == (ASN_CONSTRUCTOR | ASN_OCTETSTRING))
+ {
+ if (!CRYPT_GetLengthIndefinite(encoded, encoded_size, &len))
+ return FALSE;
+
+ len_size = GET_LEN_BYTES(encoded[1]);
+ encoded += 1 + len_size;
+ encoded_size -= 1 + len_size;
+ decoded += 1 + len_size;
+
+ if (len == CMSG_INDEFINITE_LENGTH)
+ {
+ indefinite_len_depth++;
+ if (encoded_size < 2)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ return FALSE;
+ }
+ encoded_size -= 2;
+ decoded += 2;
+ }
+ }
+
+ if (encoded[0] != ASN_OCTETSTRING)
+ {
+ WARN("Unexpected tag %02x\n", encoded[0]);
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ return FALSE;
+ }
+
+ if (!CRYPT_GetLen(encoded, encoded_size, &len))
+ return FALSE;
+ len_size = GET_LEN_BYTES(encoded[1]);
+ decoded += 1 + len_size + len;
+ encoded_size -= 1 + len_size;
+
+ if (len > encoded_size)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ return FALSE;
+ }
+ if (ret_decoded)
+ *ret_decoded = decoded;
+
+ encoded += 1 + len_size;
+ string = encoded;
+ encoded += len;
+
+ while (indefinite_len_depth--)
+ {
+ if (encoded[0] || encoded[1])
+ {
+ TRACE("expected 0 TLV, got %02x %02x\n", encoded[0], encoded[1]);
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ return FALSE;
+ }
+ }
+
+ bytes_needed = sizeof(*blob);
+ if (!(flags & CRYPT_DECODE_NOCOPY_FLAG)) bytes_needed += len;
+ if (!buf)
+ {
+ *buf_size = bytes_needed;
+ return TRUE;
+ }
+ if (*buf_size < bytes_needed)
+ {
+ SetLastError(ERROR_MORE_DATA);
+ *buf_size = bytes_needed;
+ return FALSE;
+ }
+
+ *buf_size = bytes_needed;
+ blob = buf;
+ blob->cbData = len;
+ if (flags & CRYPT_DECODE_NOCOPY_FLAG)
+ blob->pbData = (BYTE*)string;
+ else if (blob->cbData)
+ memcpy(blob->pbData, string, blob->cbData);
+
+ if (ret_decoded)
+ *ret_decoded = decoded;
+ return TRUE;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeOctetString(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
+ if (!cbEncoded)
+ {
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ return FALSE;
+ }
+
__TRY
{
DWORD bytesNeeded = 0;
- if (!cbEncoded)
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
- }
- else if (pbEncoded[0] != ASN_OCTETSTRING)
- {
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- }
- else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
+ if ((ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
{
if (!pvStructInfo)
pvStructInfo = *(BYTE **)pvStructInfo;
blob = pvStructInfo;
blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
- ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
+ ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
&bytesNeeded, NULL);
if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
CRL_DIST_POINT *point = pvStructInfo;
BOOL ret;
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
return ret;
fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
};
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, NULL, NULL);
}
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo, pcbDecoded);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
if (pcbDecoded)
offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
};
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, NULL, NULL);
}
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo, pcbDecoded);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
HashEncryptionAlgorithm.pszObjId), 0 },
{ ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
+ CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
{ ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, info ? info->Issuer.pbData : NULL);
return ret;
}
else if (*pbEncoded == (ASN_CONTEXT | 0))
{
- ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
+ ret = CRYPT_AsnDecodeOctets(pbEncoded, cbEncoded, dwFlags,
id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
if (ret)
{
offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
+ /* FIXME: Tests show that CertOpenStore accepts such certificates, but
+ * how exactly should they be interpreted? */
+ { ASN_CONSTRUCTOR | ASN_UNIVERSAL | 0x11, 0, NULL, 0, TRUE, FALSE, 0, 0 },
{ ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
HashEncryptionAlgorithm.pszObjId), 0 },
{ ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
+ CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
{ ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
return ret;
offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
};
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, signedInfo, *pcbSignedInfo);
+ TRACE("%p, %d, %08x, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, signedInfo, pcbSignedInfo);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
NULL, NULL);
TRACE("returning %d\n", ret);
offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
KeyEncryptionAlgorithm.pszObjId), 0 },
{ ASN_OCTETSTRING, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
+ CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey.pbData), 0 },
};
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo, pcbDecoded);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, info ? info->RecipientId.u.IssuerSerialNumber.Issuer.pbData :
NULL);
offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
contentEncryptionAlgorithm.pszObjId), 0 },
{ ASN_CONTEXT | 0, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
- encryptedContent), CRYPT_AsnDecodeOctetsInternal,
+ encryptedContent), CRYPT_AsnDecodeOctets,
sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent.pbData) },
};
TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo, pcbDecoded);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
pcbDecoded, info ? info->contentType : NULL);
TRACE("returning %d\n", ret);
offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo.contentType), 0 },
};
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, envelopedData, *pcbEnvelopedData);
+ TRACE("%p, %d, %08x, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, envelopedData, pcbEnvelopedData);
- ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData,
pcbEnvelopedData, NULL, NULL);
TRACE("returning %d\n", ret);
return ret;
}
+static BOOL WINAPI CRYPT_AsnDecodeObjectIdentifier(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ DWORD bytesNeeded = 0;
+ BOOL ret;
+
+ __TRY
+ {
+ ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
+ NULL, &bytesNeeded, NULL);
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ LPSTR *info;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+
+ info = pvStructInfo;
+ *info = (void *)((BYTE *)info + sizeof(*info));
+ ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
+ pvStructInfo, &bytesNeeded, NULL);
+ if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
+ CRYPT_FreeSpace(pDecodePara, info);
+ }
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeEccSignature(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, r),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
+ TRUE, offsetof(CERT_ECC_SIGNATURE, r.pbData), 0 },
+ { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, s),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
+ TRUE, offsetof(CERT_ECC_SIGNATURE, s.pbData), 0 },
+ };
+
+ __TRY
+ {
+ ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, NULL, NULL);
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
LPCSTR lpszStructType)
{
case LOWORD(RSA_CSP_PUBLICKEYBLOB):
decodeFunc = CRYPT_AsnDecodeRsaPubKey;
break;
+ case LOWORD(PKCS_RSA_PRIVATE_KEY):
+ decodeFunc = CRYPT_AsnDecodeRsaPrivKey;
+ break;
case LOWORD(X509_UNICODE_NAME):
decodeFunc = CRYPT_AsnDecodeUnicodeName;
break;
decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
break;
case LOWORD(X509_OCTET_STRING):
- decodeFunc = CRYPT_AsnDecodeOctets;
+ decodeFunc = CRYPT_AsnDecodeOctetString;
break;
case LOWORD(X509_BITS):
case LOWORD(X509_KEY_USAGE):
case LOWORD(CMS_SIGNER_INFO):
decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
break;
+ case LOWORD(X509_OBJECT_IDENTIFIER):
+ decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
+ break;
+ case LOWORD(X509_ECC_SIGNATURE):
+ decodeFunc = CRYPT_AsnDecodeEccSignature;
+ break;
}
}
else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
decodeFunc = CRYPT_AsnDecodeBits;
else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
- decodeFunc = CRYPT_AsnDecodeOctets;
+ decodeFunc = CRYPT_AsnDecodeOctetString;
else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
decodeFunc = CRYPT_AsnDecodeBasicConstraints;
else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
else if (!strcmp(lpszStructType, szOID_CTL))
decodeFunc = CRYPT_AsnDecodeCTL;
+ else if (!strcmp(lpszStructType, szOID_ECC_PUBLIC_KEY))
+ decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
return decodeFunc;
}