[CRYPT32] Sync with Wine Staging 3.17. CORE-15127
[reactos.git] / dll / win32 / crypt32 / decode.c
index e5f8baf..f77393e 100644 (file)
@@ -85,7 +85,7 @@ static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
 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 */
@@ -479,6 +479,7 @@ static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
             {
                 dataLen = cbEncoded;
                 indefinite = TRUE;
+                lenBytes += 2;
             }
             else if (cbEncoded < dataLen)
             {
@@ -889,7 +890,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
 
         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);
     }
@@ -934,7 +935,7 @@ static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
        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;
@@ -1019,7 +1020,7 @@ static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
     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)
@@ -1134,7 +1135,7 @@ static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
     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)
@@ -1235,9 +1236,8 @@ static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
     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;
@@ -1421,7 +1421,7 @@ static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
      { 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;
@@ -1432,7 +1432,7 @@ static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
 
     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)
@@ -1870,7 +1870,7 @@ static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
 
     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)
@@ -1967,7 +1967,7 @@ static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
 
     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)
@@ -2183,7 +2183,7 @@ static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
 {
     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,
@@ -2196,7 +2196,7 @@ static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
     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;
@@ -2276,7 +2276,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
            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),
@@ -2299,7 +2299,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
            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);
     }
@@ -2329,7 +2329,7 @@ static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
     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);
@@ -2459,7 +2459,7 @@ static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
     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)
@@ -2495,10 +2495,8 @@ static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
              *(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);
@@ -2652,7 +2650,7 @@ static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
     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);
@@ -2747,7 +2745,7 @@ static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
     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);
@@ -2865,7 +2863,7 @@ static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
     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)
@@ -2892,7 +2890,7 @@ static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
     };
     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;
@@ -3137,11 +3135,11 @@ static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
     {
         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,
@@ -3149,7 +3147,7 @@ static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
            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);
     }
@@ -3172,7 +3170,7 @@ static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
     {
         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),
@@ -3186,7 +3184,7 @@ static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
            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);
     }
@@ -3213,7 +3211,7 @@ static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
     };
     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);
 }
@@ -3322,7 +3320,7 @@ static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
     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;
@@ -3387,11 +3385,11 @@ BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
        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;
@@ -3530,7 +3528,7 @@ static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
            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);
     }
@@ -3559,7 +3557,7 @@ static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
            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);
     }
@@ -3591,7 +3589,7 @@ static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
     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;
@@ -3636,7 +3634,7 @@ static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
     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;
@@ -3693,7 +3691,7 @@ static BOOL CRYPT_AsnDecodeCertPolicyMapping(const BYTE *pbEncoded,
     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;
@@ -3850,7 +3848,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCertPolicyConstraints(
            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);
     }
@@ -3889,7 +3887,7 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
         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)
@@ -3936,7 +3934,150 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
     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)
 {
@@ -3985,7 +4126,99 @@ static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
     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)
 {
@@ -3994,21 +4227,17 @@ static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
     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)
@@ -4022,7 +4251,7 @@ static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
                     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))
@@ -5010,7 +5239,7 @@ static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
     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;
@@ -5112,7 +5341,7 @@ static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
            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);
     }
@@ -5195,7 +5424,7 @@ static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
     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)
@@ -5276,7 +5505,7 @@ static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
            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);
     }
@@ -5306,7 +5535,7 @@ static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
     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)
@@ -5341,7 +5570,7 @@ static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
        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),
@@ -5353,7 +5582,7 @@ static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
     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;
@@ -5466,7 +5695,7 @@ static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
     }
     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)
         {
@@ -5502,12 +5731,15 @@ static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
        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),
@@ -5519,7 +5751,7 @@ static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
     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;
@@ -5616,10 +5848,10 @@ BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
        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);
@@ -5645,14 +5877,14 @@ static BOOL CRYPT_AsnDecodeRecipientInfo(const BYTE *pbEncoded, DWORD cbEncoded,
        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);
@@ -5701,7 +5933,7 @@ static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded,
        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) },
     };
@@ -5709,7 +5941,7 @@ static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded,
     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);
@@ -5734,16 +5966,85 @@ BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded,
        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)
 {
@@ -5798,6 +6099,9 @@ static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
         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;
@@ -5808,7 +6112,7 @@ static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
             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):
@@ -5880,6 +6184,12 @@ static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
         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))
@@ -5899,7 +6209,7 @@ static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
     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))
@@ -5934,6 +6244,8 @@ static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
         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;
 }