2

我有一个SecTrustRef来自系统的对象,我想评估自己。只需打电话SecTrustEvaluateAsync就足以胜任这项工作。问题是,我必须在不同的进程中对其进行评估,因为只有这个其他进程才能访问存储 CA 证书的钥匙串,这可能导致评估成功。

这两个进程有一个 IPC 链接,允许我在它们之间交换任意字节数据,但我看不到任何方法可以轻松地将 a 序列SecTrustRef化为字节数据并将该数据反序列化回另一个进程的对象。似乎没有持久的存储机制SecTrustRef

那么我在这里忽略了一些重要的事情,还是我真的必须获得所有证书(SecTrustGetCertificateAtIndex)和所有策略(SecTrustCopyPolicies)并自己序列化这些?

如果是这样,我将如何序列化策略?

对于证书 ( SecCertificateRef),这很容易,我只是打电话SecCertificateCopyData,然后再打电话SecCertificateCreateWithData

但是对于策略,我只能SecPolicyCopyProperties在一侧调用,然后再调用SecPolicyCreateWithProperties,但是后一个需要第二个参数 apolicyIdentifier并且我认为无法从现有策略中获取该值。我错过了什么?

4

1 回答 1

1

通过阅读安全框架的源代码,我终于弄清楚了如何复制SecPolicyRef

  • SecPolicyCreateWithProperties想要它所谓的“policyIdentifier”。它是一个常数,如kSecPolicyAppleIPsec.
  • 这不会由函数直接存储,它会比较值并调用专用的内部“初始化器”(如SecPolicyCreateIPsec)。
  • 这些依次调用SecPolicyCreate(这是私有的)。它们最终传递了您传递给的相同标识符值SecPolicyCreateWithProperties
  • 然后该值将按原样存储在该_oid字段中!

标识符实际上是 OID。您可以通过SecPolicyCopyProperties(policy)(使用 key 存储在字典中kSecPolicyOid)或通过SecPolicyGetOID(但将其返回为不方便CSSM_OID)来获取它。其中一些专门的初始化程序还使用传递给的属性字典中的值SecPolicyCreateWithProperties,这些值应该已经存在于复制的属性字典中。


所以这给了我们:

序列化:

CFDictionaryRef createSerializedPolicy(SecPolicyRef policy) {
    // Already contains all the information needed.
    return SecPolicyCopyProperties(policy);
}

反序列化:

SecPolicyRef createDeserializedPolicy (CFDictionaryRef serialized) {
    CFStringRef oid = CFDictionaryGetValue(serialized, kSecPolicyOid);
    if (oid == NULL || CFGetTypeID(oid) != CFStringGetTypeID()) {
        return NULL;
    }

   return SecPolicyCreateWithProperties(oid, serialized);
}

为了尽可能地重现原始的 SecTrustRef,还需要复制锚点。一旦您设置了锚点_anchorsOnly,就会设置一个内部变量。true不幸的是,没有办法查询这个值,例如,我已经看到它false在通过的信任NSURLSession中。尚不知道如何以公共方式获得此价值。

另一个有问题的地方是例外:如果_exceptions是 NULL 但你通过 查询它们SecTrustCopyExceptions(trust),你确实得到了数据!如果您通过您将其分配给反序列化信任,SecTrustSetExceptions(trust, exceptions)那么您突然会遇到以前不存在的异常并且可以更改评估结果!(我已经看到那些突然出现的异常导致评估结果为“继续”而不是“可恢复的信任失败”)。

于 2019-10-25T11:16:23.760 回答