- value->Value.cbData = 0;
- value->Value.pbData = NULL;
- }
- }
- }
- }
- }
- __EXCEPT(page_fault)
- {
- SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
- }
- __ENDTRY
- return ret;
-}
-
-/* FIXME: this should use CRYPT_AsnDecodeSequence (though that won't accept it
- * at the moment because of the ASN_CONSTRUCTOR tag.)
- */
-static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded,
- DWORD cbEncoded, DWORD dwFlags, CERT_RDN_ATTR *attr, DWORD *pcbAttr)
-{
- BOOL ret;
-
- __TRY
- {
- if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCE))
- {
- DWORD bytesNeeded, dataLen, size;
- BYTE lenBytes;
-
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
- {
- /* The data length must be at least 4, two for the tag and
- * length for the OID, and two for the string (assuming both
- * have short-form lengths.)
- */
- if (dataLen < 4)
- {
- SetLastError(CRYPT_E_ASN1_EOD);
- ret = FALSE;
- }
- else
- {
- bytesNeeded = sizeof(CERT_RDN_ATTR);
- lenBytes = GET_LEN_BYTES(pbEncoded[1]);
- ret = CRYPT_AsnDecodeOid(pbEncoded + 1 + lenBytes,
- cbEncoded - 1 - lenBytes, dwFlags, NULL, &size);
- if (ret)
- {
- /* ugly: need to know the size of the next element of
- * the sequence, so get it directly
- */
- DWORD objIdOfset = 1 + lenBytes, objIdLen,
- nameValueOffset = 0;
-
- ret = CRYPT_GetLen(pbEncoded + objIdOfset,
- cbEncoded - objIdOfset, &objIdLen);
- bytesNeeded += size;
- /* hack: like encoding, this takes advantage of the
- * fact that the rest of the structure is identical to
- * a CERT_NAME_VALUE.
- */
- if (ret)
- {
- nameValueOffset = objIdOfset + objIdLen + 1 +
- GET_LEN_BYTES(pbEncoded[objIdOfset]);
- ret = CRYPT_AsnDecodeNameValue(
- pbEncoded + nameValueOffset,
- cbEncoded - nameValueOffset, dwFlags, NULL, &size);
- }
- if (ret)
- {
- bytesNeeded += size;
- if (!attr)
- *pcbAttr = bytesNeeded;
- else if (*pcbAttr < bytesNeeded)
- {
- *pcbAttr = bytesNeeded;
- SetLastError(ERROR_MORE_DATA);
- ret = FALSE;
- }
- else
- {
- BYTE *originalData = attr->Value.pbData;
-
- *pcbAttr = bytesNeeded;
- /* strange: decode the value first, because it
- * has a counted size, and we can store the OID
- * after it. Keep track of the original data
- * pointer, we'll need to know whether it was
- * changed.
- */
- size = bytesNeeded;
- ret = CRYPT_AsnDecodeNameValue(
- pbEncoded + nameValueOffset,
- cbEncoded - nameValueOffset, dwFlags,
- (CERT_NAME_VALUE *)&attr->dwValueType, &size);
- if (ret)
- {
- if (objIdLen)
- {
- /* if the data were copied to the
- * original location, the OID goes
- * after. Otherwise it goes in the
- * spot originally reserved for the
- * data.
- */
- if (attr->Value.pbData == originalData)
- attr->pszObjId =
- (LPSTR)(attr->Value.pbData +
- attr->Value.cbData);
- else
- attr->pszObjId =
- (LPSTR)originalData;
- size = bytesNeeded - size;
- ret = CRYPT_AsnDecodeOid(
- pbEncoded + objIdOfset,
- cbEncoded - objIdOfset,
- dwFlags, attr->pszObjId, &size);
- }
- else
- attr->pszObjId = NULL;
- }
- }
- }
- }
- }
- }
- }
- else
- {
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- }
- }
- __EXCEPT(page_fault)
- {
- SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
- }
- __ENDTRY
- return ret;
-}
-
-static BOOL WINAPI CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
- DWORD dwFlags, CERT_RDN *rdn, DWORD *pcbRdn)
-{
- BOOL ret = TRUE;
-
- __TRY
- {
- if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SETOF))
- {
- DWORD dataLen;
-
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
- {
- DWORD bytesNeeded, cRDNAttr = 0;
- BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
-
- bytesNeeded = sizeof(CERT_RDN);
- if (dataLen)
- {
- const BYTE *ptr;
- DWORD size;
-
- for (ptr = pbEncoded + 1 + lenBytes; ret &&
- ptr - pbEncoded - 1 - lenBytes < dataLen; )
- {
- ret = CRYPT_AsnDecodeRdnAttr(ptr,
- cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
- if (ret)
- {
- DWORD nextLen;
-
- cRDNAttr++;
- bytesNeeded += size;
- ret = CRYPT_GetLen(ptr,
- cbEncoded - (ptr - pbEncoded), &nextLen);
- if (ret)
- ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
- }
- }
- }
- if (ret)
- {
- if (!rdn)
- *pcbRdn = bytesNeeded;
- else if (*pcbRdn < bytesNeeded)
- {
- *pcbRdn = bytesNeeded;
- SetLastError(ERROR_MORE_DATA);
- ret = FALSE;
- }
- else
- {
- DWORD size, i;
- BYTE *nextData;
- const BYTE *ptr;
-
- *pcbRdn = bytesNeeded;
- rdn->cRDNAttr = cRDNAttr;
- rdn->rgRDNAttr = (CERT_RDN_ATTR *)((BYTE *)rdn +
- sizeof(CERT_RDN));
- nextData = (BYTE *)rdn->rgRDNAttr +
- rdn->cRDNAttr * sizeof(CERT_RDN_ATTR);
- for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
- i < cRDNAttr && ptr - pbEncoded - 1 - lenBytes <
- dataLen; i++)
- {
- rdn->rgRDNAttr[i].Value.pbData = nextData;
- size = bytesNeeded;
- ret = CRYPT_AsnDecodeRdnAttr(ptr,
- cbEncoded - (ptr - pbEncoded), dwFlags,
- &rdn->rgRDNAttr[i], &size);
- if (ret)
- {
- DWORD nextLen;
-
- bytesNeeded -= size;
- /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
- * data may not have been copied.
- */
- if (rdn->rgRDNAttr[i].Value.pbData == nextData)
- nextData +=
- rdn->rgRDNAttr[i].Value.cbData;
- /* Ugly: the OID, if copied, is stored in
- * memory after the value, so increment by its
- * string length if it's set and points here.
- */
- if ((const BYTE *)rdn->rgRDNAttr[i].pszObjId
- == nextData)
- nextData += strlen(
- rdn->rgRDNAttr[i].pszObjId) + 1;
- ret = CRYPT_GetLen(ptr,
- cbEncoded - (ptr - pbEncoded), &nextLen);
- if (ret)
- ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
- }
- }