bool InteropResolver::checkMatch()

in xsec/tools/checksig/InteropResolver.cpp [300:427]


bool InteropResolver::checkMatch(const DSIGKeyInfoList * lst, X509 * x) const {

    // Check if the parameters in x match the required certificate


    int sz = (int) lst->getSize();
    const DSIGKeyInfo* k;
    
    for (int i = 0; i < sz; ++i) {

        k = lst->item(i);

        if (k->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) {

            const DSIGKeyInfoX509 * kx = static_cast<const DSIGKeyInfoX509 *>(k);
            
            const XMLCh * serial = kx->getX509IssuerSerialNumber();

            if (serial != NULL) {

                char * cserial = XMLString::transcode(serial);
                char * xserial;

                BIGNUM * bnserial = ASN1_INTEGER_to_BN(X509_get_serialNumber(x), NULL);
                xserial = BN_bn2dec(bnserial);
                BN_free(bnserial);

                if (strcmp(xserial, cserial) == 0) {
                    
                    OPENSSL_free(xserial);
                    XSEC_RELEASE_XMLCH(cserial);
                    return true;

                }
                //delete[] xserial;
                XSEC_RELEASE_XMLCH(cserial);
                OPENSSL_free(xserial);

            }

            /* 
             * Either it's not a serial number, or we didn't pass, so lets
             * look at the next option.
             */
            
            const XMLCh * ski = kx->getX509SKI();
            
            if (ski != NULL) {

                char * cski = XMLString::transcode(ski);
                int clen = (int) strlen(cski);
                unsigned char * xski = new unsigned char[clen];
                ArrayJanitor <unsigned char> j_xski(xski);

                // Decode

                OpenSSLCryptoBase64 b64;
                b64.decodeInit();
                int xlen = b64.decode((unsigned char *) cski, clen, xski, clen);
                xlen += b64.decodeFinish(&xski[xlen], clen - xlen);
                XSEC_RELEASE_XMLCH(cski);

                if (xlen != 0) {

                    // Have a buffer with a number in it
                    const STACK_OF(X509_EXTENSION) *exts;
                    exts = X509_get0_extensions(x);

                    if (exts != NULL) {

                        // Find the Subject Key Identifier OID
                        X509_EXTENSION * ext;
                        ASN1_OBJECT * objski = OBJ_nid2obj(NID_subject_key_identifier);
                        int extn = X509v3_get_ext_by_OBJ(exts, objski, -1);
                        if (extn != -1) {
                            // Dummy up an OCTET_STRING from the xski
                            unsigned char * octxski = new unsigned char[xlen + 2];
                            ArrayJanitor<unsigned char> j_octxski(octxski);

                            octxski[0] = 4;
                            octxski[1] = xlen;
                            memcpy(&octxski[2], xski, xlen);
                            
                            ext = sk_X509_EXTENSION_value(exts,extn);
                            ASN1_OCTET_STRING *skid = X509_EXTENSION_get_data(ext);
                            ASN1_OCTET_STRING * xskid = ASN1_OCTET_STRING_new();

                            ASN1_STRING_set(xskid, octxski, xlen+2);
                            
                            if (ASN1_OCTET_STRING_cmp(xskid, skid) == 0) {
                                ASN1_OCTET_STRING_free(xskid);
                                return true;
                            }
                        }

                    }

                }

            }

            /* Not a subject key identifier */
            const XMLCh *sn = kx->getX509SubjectName();

            if (sn != NULL) {

                char * csn = XMLString::transcode(sn);

                X509_NAME * x509name = X509_get_subject_name(x);
                X509_NAME * snname = X509_NAME_create_from_txt(csn);
                XSEC_RELEASE_XMLCH(csn);

                if (snname != NULL) {

                    if (!X509_NAME_cmp(x509name, snname)) {
                        X509_NAME_free(snname);
                        return true;
                    }
                
                    X509_NAME_free(snname);
                }
            }
        }
    }

    return false;

}