+
+CFDateRef certificateCopyFieldDate(SecCertificateRef cert, const CSSM_OID &policyOid)
+{
+ CFDataRef oidData = NULL;
+ CFDateRef value = NULL;
+ CFDataRef data = NULL;
+ SecAsn1CoderRef coder = NULL;
+ CSSM_DATA str = { 0 };
+ CFAbsoluteTime time = 0.0;
+ OSStatus status = 0;
+ bool isCritical;
+
+ oidData = CFDataCreateWithBytesNoCopy(NULL, policyOid.Data, policyOid.Length,
+ kCFAllocatorNull);
+
+ if (oidData == NULL) {
+ goto out;
+ }
+
+ data = SecCertificateCopyExtensionValue(cert, oidData, &isCritical);
+
+ if (data == NULL) {
+ goto out;
+ }
+
+ status = SecAsn1CoderCreate(&coder);
+ if (status != 0) {
+ goto out;
+ }
+
+ // We currently only support UTF8 strings.
+ status = SecAsn1Decode(coder, CFDataGetBytePtr(data), CFDataGetLength(data),
+ kSecAsn1UTF8StringTemplate, &str);
+ if (status != 0) {
+ goto out;
+ }
+
+ time = SecAbsoluteTimeFromDateContent(ASN1_GENERALIZED_TIME,
+ str.Data, str.Length);
+
+ if (time == 0.0) {
+ goto out;
+ }
+
+ value = CFDateCreate(NULL, time);
+out:
+ if (coder) {
+ SecAsn1CoderRelease(coder);
+ }
+ if (data) {
+ CFRelease(data);
+ }
+ if (oidData) {
+ CFRelease(oidData);
+ }
+
+ return value;
+}
+#endif