iOS:使用SecTrustEvaluate检查用户钥匙串中是否存在中间CA.

时间:2014-08-25 16:23:25

标签: certificate keychain

我们的任务是在我们的应用程序内部确定iOS设备上是否安装了特定的配置文件。没有公共API来检查设备上安装了哪些配置文件,但本文http://blog.markhorgan.com/?p=701描述了一种解决方法。

基本上,一个在配置文件中包含一个根CA,并在此根CA上签名第二个证书。第二个证书捆绑在应用程序中,然后对应用程序中第二个证书的信任评估将显示根CA是否存在(这意味着已安装配置文件)。

现在,我们无法篡改我们的配置文件(因为它已安装在许多设备上),但它已包含2个我们可以访问的证书:

  • OurRootCA(发布者:OurRootCA)
  • OurIntermediateCA(发布者:OurRootCA)

遗憾的是,OurRootCA不仅包含在相关配置文件中,还包含在其他配置文件中(因此使用此方法检查可能会产生误报),但幸运的是OurIntermediateCA仅用于我们要检查的configurationProfile中

不幸的是,由于某些原因,如果使用由OurIntermediateCA颁发的测试SSL证书执行测试失败(它总是返回kSecTrustResultRecoverableTrustFailure)(它可以使用OurRootCA颁发的测试SSL证书)。

这是验证码:

//NSString* certPath = [[NSBundle mainBundle] pathForResource:@"TestCertificateSignedByRoot" ofType:@"cer"]; //with this cert, the validation works
NSString* certPath = [[NSBundle mainBundle] pathForResource:@"TestCertificateSignedByIntermediate" ofType:@"cer"];

    NSData* certData = [NSData dataWithContentsOfFile:certPath];
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) certData);

    SecPolicyRef policy = SecPolicyCreateBasicX509();        
    SecTrustRef trust;
    OSStatus err = SecTrustCreateWithCertificates((__bridge CFArrayRef) [NSArray arrayWithObject:(__bridge id)cert], policy, &trust);

    // set trust anchor certificates to empty array as advised in http://stackoverflow.com/questions/7900896/sectrustevaluate-always-returns-ksectrustresultrecoverabletrustfailure-with-secp
    SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef) [NSArray array]);
    SecTrustSetAnchorCertificatesOnly(trust, NO);

    SecTrustResultType trustResult = -1;
    err = SecTrustEvaluate(trust, &trustResult);
    CFRelease(trust);
    CFRelease(policy);
    CFRelease(cert);
    switch(trustResult) {
        case kSecTrustResultUnspecified:
        case kSecTrustResultProceed: {
            return YES;
            // this is the result if TestCertificateSignedByRoot is used 
            break;
        }
        case kSecTrustResultRecoverableTrustFailure: {
            return NO;
            // this is the result if TestCertificateSignedByIntermediate is used 
            break;
        }
        default: {
            return NO;
            break;
        }
    }

因此,该技术似乎有效 - 用户钥匙串中的(自签名)rootCA用于验证我们的测试证书。但是,如果检查中间CA,则测试始终返回kSecTrustResultRecoverableTrustFailure。这可能是什么问题以及如何调试?

0 个答案:

没有答案