PORT_SetError(SEC_ERROR_BAD_DER); return SECFailure;
*match = PR_FALSE; return SECSuccess;
static SECStatus MatchComponentType(const SEC_ASN1Template* templateEntry,                                    SECItem* item, PRBool* match, void* dest){    unsigned long kind = 0;    unsigned char tag = 0;    if ( (!item) || (!templateEntry) || (!match) )    {        PORT_SetError(SEC_ERROR_INVALID_ARGS);        return SECFailure;    }    if (!item->len || !item->data)    {        *match = PR_FALSE;        return SECSuccess;    }    kind = templateEntry->kind;    tag = *(unsigned char*) item->data;    if ( ( (kind & SEC_ASN1_INLINE) ||           (kind & SEC_ASN1_POINTER) ) &&           (0 == (kind & SEC_ASN1_TAG_MASK) ) )    {        /* These cases are special because the template's "kind" does not           give us the information for the ASN.1 tag of the next item. It can           only be figured out from the subtemplate. */        if (!(kind & SEC_ASN1_OPTIONAL))        {            /* This is a required component. If there is a type mismatch,               the decoding of the subtemplate will fail, so assume this               is a match at the parent level and let it fail later. This               avoids a redundant check in matching cases */            *match = PR_TRUE;            return SECSuccess;        }        else        {            /* optional component. This is the hard case. Now we need to               look at the subtemplate to get the expected kind */            const SEC_ASN1Template* subTemplate =                 SEC_ASN1GetSubtemplate (templateEntry, dest, PR_FALSE);            if (!subTemplate)            {                PORT_SetError(SEC_ERROR_BAD_TEMPLATE);                return SECFailure;            }            if ( (subTemplate->kind & SEC_ASN1_INLINE) ||                 (subTemplate->kind & SEC_ASN1_POINTER) )            {                /* disallow nesting SEC_ASN1_POINTER and SEC_ASN1_INLINE,                   otherwise you may get a false positive due to the recursion                   optimization above that always matches the type if the                   component is required . Nesting these should never be                   required, so that no one should miss this ability */                PORT_SetError(SEC_ERROR_BAD_TEMPLATE);                return SECFailure;            }            return MatchComponentType(subTemplate, item, match,                                      (void*)((char*)dest + templateEntry->offset));        }    }    if (kind & SEC_ASN1_CHOICE)    {        /* we need to check the component's tag against each choice's tag */        /* XXX it would be nice to save the index of the choice here so that           DecodeChoice wouldn't have to do this again. However, due to the           recursivity of MatchComponentType, we don't know if we are in a           required or optional component, so we can't write anywhere in           the destination within this function */        unsigned choiceIndex = 1;        const SEC_ASN1Template* choiceEntry;        while ( (choiceEntry = &templateEntry[choiceIndex++]) && (choiceEntry->kind))        {            if ( (SECSuccess == MatchComponentType(choiceEntry, item, match,                                (void*)((char*)dest + choiceEntry->offset))) &&                 (PR_TRUE == *match) )            {                return SECSuccess;            }        }        PORT_SetError(SEC_ERROR_BAD_DER);        return SECFailure;    }    if (kind & SEC_ASN1_ANY)    {        /* SEC_ASN1_ANY always matches */        *match = PR_TRUE;        return SECSuccess;    }    if ( (0 == ((unsigned char)kind & SEC_ASN1_TAGNUM_MASK)) &&         (!(kind & SEC_ASN1_EXPLICIT)) &&         ( ( (kind & SEC_ASN1_SAVE) ||             (kind & SEC_ASN1_SKIP) ) &&           (!(kind & SEC_ASN1_OPTIONAL))          )       )    {        /* when saving or skipping a required component,  a type is not           required in the template. This is for legacy support of           SEC_ASN1_SAVE and SEC_ASN1_SKIP only. XXX I would like to           deprecate these usages and always require a type, as this           disables type checking, and effectively forbids us from           transparently ignoring optional components we aren't aware of */        *match = PR_TRUE;        return SECSuccess;    }    /* first, do a class check */    if ( (tag & SEC_ASN1_CLASS_MASK) !=         (((unsigned char)kind) & SEC_ASN1_CLASS_MASK) )    {#ifdef DEBUG        /* this is only to help debugging of the decoder in case of problems */        unsigned char tagclass = tag & SEC_ASN1_CLASS_MASK;        unsigned char expectedclass = (unsigned char)kind & SEC_ASN1_CLASS_MASK;#endif        *match = PR_FALSE;        return SECSuccess;    }    /* now do a tag check */    if ( ((unsigned char)kind & SEC_ASN1_TAGNUM_MASK) !=         (tag & SEC_ASN1_TAGNUM_MASK))    {        *match = PR_FALSE;        return SECSuccess;    }    /* now, do a method check. This depends on the class */    switch (tag & SEC_ASN1_CLASS_MASK)    {    case SEC_ASN1_UNIVERSAL:        /* For types of the SEC_ASN1_UNIVERSAL class, we know which must be           primitive or constructed based on the tag */        switch (tag & SEC_ASN1_TAGNUM_MASK)        {        case SEC_ASN1_SEQUENCE:        case SEC_ASN1_SET:        case SEC_ASN1_EMBEDDED_PDV:            /* this component must be a constructed type */            /* XXX add any new universal constructed type here */            if (tag & SEC_ASN1_CONSTRUCTED)            {                *match = PR_TRUE;                return SECSuccess;            }            break;        default:            /* this component must be a primitive type */            if (! (tag & SEC_ASN1_CONSTRUCTED))            {                *match = PR_TRUE;                return SECSuccess;            }            break;        }        break;    default:        /* for all other classes, we check the method based on the template */        if ( (unsigned char)(kind & SEC_ASN1_METHOD_MASK) ==             (tag & SEC_ASN1_METHOD_MASK) )        {            *match = PR_TRUE;            return SECSuccess;        }        /* method does not match between template and component */        break;    }    *match = PR_FALSE;    return SECSuccess;}