I'd like to validate my ssl server certificates with some extra checks. And sometimes I get a
kSecTrustResultRecoverableTrustFailure
instead of
kSecTrustResultProceed
or kSecTrustResultUnspecified
It seems to happen if
SecTrustSetAnchorCertificatesOnly(trust,YES)
is set and the anchor certificate is only in the built in anchor certificatesIt depends on the AppleX509TP policy used to evaluate the trust.
My problem is I do not want to trust if the chain fails, but I want to trust if MD5 is used.
Is there a way to find out why the evaluation failed?
As an alternative is there a way to extract the CSSM_ALGID_MD5
from a SecCertificateRef
?
It may be a server certificate problem....
Check here, I solved my kSecTrustResultRecoverableTrustFailure problem, adding subjectAltName = DNS:example.com
into openssl config file, specifically in server key generation...
If you are not using openssl to generate it, I'm sorry but I can help you.. Anyway if you want to use openssl, here is a good tutorial to generate those keys and sign then with your own root certificate authority.
From this tutorial, I just changed my openssl server config file to:
[ server ] basicConstraints = critical,CA:FALSE keyUsage = digitalSignature, keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth nsCertType = server subjectAltName = IP:10.0.1.5,DNS:office.totendev.com
Hope it helps !
EDITED:
My Server evaluation code:
#pragma mark - SERVER Auth Helper
//Validate server certificate with challenge
+ (BOOL)validateServerWithChallenge:(NSURLAuthenticationChallenge *)challenge {
//Get server trust management object a set anchor objects to validate it
SecTrustSetAnchorCertificates([challenge.protectionSpace serverTrust], (__bridge CFArrayRef)[self allowedCAcertificates]);
//Set to server trust management object to JUST ALLOW those anchor objects assigned to it (ABOVE), and disable apple CA trusts
SecTrustSetAnchorCertificatesOnly([challenge.protectionSpace serverTrust], YES);
//Try to evalute it
SecTrustResultType evaluateResult = kSecTrustResultInvalid; //evaluate result
OSStatus sanityCheck = SecTrustEvaluate([challenge.protectionSpace serverTrust], &evaluateResult);
//Check for no evaluate error
if (sanityCheck == noErr) {
//Check for result
if ([[self class] validateTrustResult:evaluateResult]) { return YES ; }
}
//deny!
return NO ;
}
//Validate SecTrustResulType
+ (BOOL)validateTrustResult:(SecTrustResultType)result {
switch (result) {
case kSecTrustResultProceed: { TDLog(kLogLevelHandshake,nil,@"kSecTrustResultProceed"); return YES ; }
break;
case kSecTrustResultConfirm: { TDLog(kLogLevelHandshake,nil,@"kSecTrustResultConfirm"); return YES ; }
break;
case kSecTrustResultUnspecified: { TDLog(kLogLevelHandshake,nil,@"kSecTrustResultUnspecified"); return YES ; }
break;
case kSecTrustResultDeny: { TDLog(kLogLevelHandshake,nil,@"kSecTrustResultDeny"); return YES ; }
break;
case kSecTrustResultFatalTrustFailure: { TDLog(kLogLevelHandshake,nil,@"kSecTrustResultFatalTrustFailure"); return NO ; }
break;
case kSecTrustResultInvalid: { TDLog(kLogLevelHandshake,nil,@"kSecTrustResultInvalid"); return NO ; }
break;
case kSecTrustResultOtherError: { TDLog(kLogLevelHandshake,nil,@"kSecTrustResultOtherError"); return NO ; }
break;
case kSecTrustResultRecoverableTrustFailure: { TDLog(kLogLevelHandshake,nil,@"kSecTrustResultRecoverableTrustFailure"); return NO ; }
break;
default: { TDLog(kLogLevelHandshake,nil,@"unkown certificate evaluate result type! denying..."); return NO ; }
break;
}
}
Hope now it helps :) !
Is there a way to find out why the evaluation failed?
Call SecTrustCopyProperties()
after calling SecTrustEvaluate()
:
SecTrustRef trust = ...;
SecTrustResultType trustResult = kSecTrustResultOtherError;
OSStatus status = SecTrustEvaluate(trust, &trustResult);
if (trustResult == kSecTrustResultRecoverableTrustFailure) {
NSArray * trustProperties = (__bridge_transfer id)
SecTrustCopyProperties(certTrust);
}
trustProperties
is an array of dictionaries, one dictionary per cert in the cert chain evaluated. Every dictionary has an entry title
, containing the name of the cert and if the cert didn't evaluate, it also contains an entry error
containing the error. E.g. if the problem was that the cert has expired, the value of error
will be CSSMERR_TP_CERT_EXPIRED
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With