How to evaluate trust of x509 certificate on iOS - ios

I am currently developing an iOS app with end to end encryption. In order to let the users authenticate each other, every user generates a x509 Certificate Signing Request (CSR) and sends the CSR to our CA-server for signing.
A user can trust another user by verifying that the other users certificate is signed by the CA.
My question is:
On the iPhone, I currently have the CA-cert and the user-cert that needs to be verified. How do I verify that the user-cert is actually signed by the CA?
My best try is the code that follows, but it does not specify what to evaluate the clientCert against, which confuses me.
-(BOOL) evaluateTrust:(SecCertificateRef) clientCert{
SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
SecCertificateRef certArray[1] = { clientCert };
CFArrayRef myCerts = CFArrayCreate(
NULL, (void *)certArray,
1, NULL);
SecTrustRef myTrust;
OSStatus status = SecTrustCreateWithCertificates(
myCerts,
myPolicy,
&myTrust);
SecTrustResultType trustResult;
if (status == noErr) {
status = SecTrustEvaluate(myTrust, &trustResult);
}
NSLog(#"trustresult %d", trustResult);
return trustResult == kSecTrustResultProceed || trustResult == kSecTrustResultUnspecified;
}

Your code evaluates your clientCert against anchor (trusted root) certificates present in the keychain. If you want to evaluate it against your caCert you need to register your caCert as an anchor certificate with SecTrustSetAnchorCertificates.
Alternatively you can add your caCert to certArray:
SecCertificateRef certArray[2] = { clientCert, caCert };
CFArrayRef myCerts = CFArrayCreate(
NULL, (void *)certArray,
2, NULL);
SecTrustRef myTrust;
OSStatus status = SecTrustCreateWithCertificates(
myCerts,
myPolicy,
&myTrust);
Check out: https://developer.apple.com/library/ios/documentation/security/conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html#//apple_ref/doc/uid/TP40001358-CH208-SW13
It says:
4. ... If you have intermediate certificates or an anchor certificate for the certificate chain, you can include those in the certificate array passed to the SecTrustCreateWithCertificates function. Doing so speeds up the trust evaluation.

Related

iOS checking if root certificate is installed *and* trusted

Our app is installing a root CA profile, and I want to verify it is installed and trusted by the user.
Currently this is roughly what we do (trimmed it for the core)
SecPolicyRef policyObj = SecPolicyCreateBasicX509();
SecTrustRef trustObj;
OSStatus error = SecTrustCreateWithCertificates((__bridge CFTypeRef _Nonnull)(fullChain), policyObj, &trustObj);
SecTrustResultType result;
error = SecTrustEvaluate(trustObj, &result);
CFRelease(trustObj);
CFRelease(policyObj);
return (kSecTrustResultUnspecified == result || kSecTrustResultProceed == result);
The problem is this, once the profile is installed the result is either kSecTrustResultUnspecified (iOS 10~) or kSecTrustResultProceed (iOS 11~)
But I want to check if user trusted it (under General->About->Trust Settings)
I dug around apple's docs and found nothing, moreover in the SecTrustEvaluate doc it says return value 'proceed' means user trusted the cert.
proceed— The user explicitly chose to trust a certificate in the chain (usually by clicking a button in a certificate trust panel).
Anyone has idea how this can be done? what am i missing?
So, after digging around i found out that SecPolicyCreateSSL is working as expect, still not 100% why SecPolicyCreateBasicX509 is not.
So for future ref if someone have this issue, this is what we did instead,
SecPolicyRef policy = SecPolicyCreateSSL(true, NULL);
SecTrustRef testTrust;
OSStatus status = SecTrustCreateWithCertificates((__bridge CFArrayRef)fullChain, policy, &testTrust);
status = SecTrustEvaluate(testTrust, &trustResult);
CFRelease(testTrust);
CFRelease(policy);
return (status == errSecSuccess) && (kSecTrustResultUnspecified == trustResult || kSecTrustResultProceed == trustResult);;
(basically using SecPolicyCreateSSL instead)
Improoved Objective-C code by #Al Ga, it tested and work on iOS 13/14
SecPolicyRef policyObj = SecPolicyCreateBasicX509();
SecTrustRef trustObj;
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"certName" ofType:#"crt"];
NSData *certData = [NSData dataWithContentsOfFile:filePath];
CFDataRef certCFR = (__bridge CFDataRef)certData;
SecCertificateRef certSCR = SecCertificateCreateWithData(NULL, certCFR);
NSArray* certArray = #[ (__bridge id)certSCR ];
OSStatus error = SecTrustCreateWithCertificates((__bridge CFTypeRef _Nonnull)certArray, policyObj, &trustObj);
SecTrustResultType result;
error = SecTrustEvaluate(trustObj, &result);
SecTrustResultType result will be contain uint32_t :
kSecTrustResultInvalid = 0
kSecTrustResultProceed = 1 //root cert Installed
kSecTrustResultConfirm = 2
kSecTrustResultDeny = 3
kSecTrustResultUnspecified = 4
kSecTrustResultRecoverableTrustFailure = 5 //root cert Doesn't installed
kSecTrustResultFatalTrustFailure = 6
kSecTrustResultOtherError = 7

Get public/private key from certificate

I try to get public or private key from certificate saved on device.
I'm using this method:
- (SecKeyRef)publicKeyFromFile:(NSString *)path
{
NSData * certificateData = [[NSData alloc] initWithData:[[NSFileManager defaultManager] contentsAtPath:path]];
if (certificateData != nil && certificateData.bytes != 0) {
CFDataRef cfDataPath = CFDataCreate(NULL, [certificateData bytes], [certificateData length]);
SecCertificateRef certificateFromFile = SecCertificateCreateWithData(NULL, cfDataPath);
if (certificateFromFile) {
SecPolicyRef secPolicy = SecPolicyCreateBasicX509();
SecTrustRef trust;
SecTrustCreateWithCertificates( certificateFromFile, secPolicy, &trust);
SecTrustResultType resultType;
SecTrustEvaluate(trust, &resultType);
SecKeyRef publicKeyObj = SecTrustCopyPublicKey(trust);
return publicKeyObj;
}
}
return nil;
}
There is data in cfDataPath, but certificateFromFile is always nil...
Does anyone know where's the problem?
Apple doc refers:
Obtaining a SecKeyRef Object for Public Key Cryptography
Extracting Keys from the Keychain If you are using existing public and private keys from your keychain, read Certificate, Key, and Trust Services Programming Guide to learn how to retrieve a SecKeychainItemRef object for that key.
Once you have obtained a SecKeychainItemRef, you can cast it to a SecKeyRef for use with this API.
Importing Existing Public and Private Keys Importing and exporting public and private key pairs is somewhat more complicated than generating new keys because of the number of different key formats in common use.
This example describes how to import and export a key pair in PEM (Privacy Enhanced Mail) format.
Read more : https://developer.apple.com/library/mac/documentation/Security/Conceptual/SecTransformPG/SigningandVerifying/SigningandVerifying.html and https://developer.apple.com/library/mac/documentation/Security/Conceptual/CertKeyTrustProgGuide/01introduction/introduction.html#//apple_ref/doc/uid/TP40001358
Try with this:
-(BOOL)trustCertFromChallenge:(NSURLAuthenticationChallenge *)challenge
{
SecTrustResultType trustResult;
SecTrustRef trust = challenge.protectionSpace.serverTrust;
OSStatus status = SecTrustEvaluate(trust, &trustResult);
//DLog(#"Failed: %#",error.localizedDescription);
//DLog(#"Status: %li | Trust: %# - %li",(long)status,trust,(long)trustResult);
if (status == 0 && (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed)) {
SecKeyRef serverKey = SecTrustCopyPublicKey(trust);
NSString *certPath = [[NSBundle mainBundle] pathForResource:#"MYCert" ofType:#"der"];
NSData *certData = [NSData dataWithContentsOfFile:certPath];
SecCertificateRef localCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);
SecKeyRef localKey = NULL;
SecTrustRef localTrust = NULL;
SecCertificateRef certRefs[1] = {localCertificate};
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, (void *)certRefs, 1, NULL);
SecPolicyRef policy = SecPolicyCreateBasicX509();
OSStatus status = SecTrustCreateWithCertificates(certArray, policy, &localTrust);
if (status == errSecSuccess)
localKey = SecTrustCopyPublicKey(localTrust);
CFRelease(localTrust);
CFRelease(policy);
CFRelease(certArray);
if (serverKey != NULL && localKey != NULL && [(__bridge id)serverKey isEqual:(__bridge id)localKey])
return YES;
else
return NO;
}
//DLog(#"Failed: %#",error.localizedDescription);
return NO;
}
Follow the accepted answer for more details: Objective-C / C pulling private key (modulus) from SecKeyRef

How to verify (and require) self-signed certificate in iOS

I'd like to create an SSL connection to my server using self-signed certificates that are shipped with the code in iOS. That way I don't have to worry about more sophisticated man-in-the-middle attacks where someone has access to a high level "trusted" cert authority. I'm having issues doing so using what I believe to be Apple's standard way.
Generating the certificate, via the procedure found here
# Create root CA & private key
openssl req -newkey rsa:4096 -sha512 -days 9999 -x509 -nodes -out root.pem.cer
# Create a certificate signing request
openssl req -newkey rsa:4096 -sha512 -nodes -out ssl.csr -keyout ssl.key
# Create an OpenSSL Configuration file from http://svasey.org/projects/software-usage-notes/ssl_en.html
vim openssl.conf
# Create the indexes
touch certindex
echo 000a > certserial
echo 000a > crlnumber
# Generate SSL certificate
openssl ca -batch -config openssl.conf -notext -in ssl.csr -out ssl.pem.cer
# Create Certificate Revocation List
openssl ca -config openssl.conf -gencrl -keyfile privkey.pem -cert root.pem.cer -out root.crl.pem
openssl crl -inform PEM -in root.crl.pem -outform DER -out root.crl && rm root.crl.pem
And the iOS code:
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
if ([protectionSpace authenticationMethod] == NSURLAuthenticationMethodServerTrust) {
// Load anchor cert.. also tried this with both certs and it doesn't seem to matter
NSString *path = [[NSBundle mainBundle] pathForResource:#"root.der" ofType:#"crt"];
NSData *data = [[NSData alloc] initWithContentsOfFile:path];
SecCertificateRef anchorCert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)data);
CFMutableArrayRef anchorCerts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
CFArrayAppendValue(anchorCerts, anchorCert);
// Set anchor cert
SecTrustRef trust = [protectionSpace serverTrust];
SecTrustSetAnchorCertificates(trust, anchorCerts);
SecTrustSetAnchorCertificatesOnly(trust, YES); // only use that certificate
CFRelease(anchorCert);
CFRelease(anchorCerts);
// Validate cert
SecTrustResultType secresult = kSecTrustResultInvalid;
if (SecTrustEvaluate(trust, &secresult) != errSecSuccess) {
[challenge.sender cancelAuthenticationChallenge:challenge];
return;
}
switch (secresult) {
case kSecTrustResultInvalid:
case kSecTrustResultDeny:
case kSecTrustResultFatalTrustFailure:
case kSecTrustResultOtherError:
case kSecTrustResultRecoverableTrustFailure: {
// !!! It's always kSecTrustResultRecoverableTrustFailure, aka 5
NSLog(#"Failing due to result: %lu", secresult);
[challenge.sender cancelAuthenticationChallenge:challenge];
return;
}
case kSecTrustResultUnspecified: // The OS trusts this certificate implicitly.
case kSecTrustResultProceed: { // The user explicitly told the OS to trust it.
NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
return;
}
default: ;
/* It's somebody else's key. Fall through. */
}
/* The server sent a key other than the trusted key. */
[connection cancel];
// Perform other cleanup here, as needed.
} else {
NSLog(#"In weird space... not handling authentication method: %#", [protectionSpace authenticationMethod]);
[connection cancel];
}
}
I'm always getting kSecTrustResultRecoverableTrustFailure as the result. I don't think this is localhost issue as I've tried using Apple's code to change that too. What to do?
Thanks!
If the trust result is kSecTrustResultRecoverableTrustFailure, you might be able to recover from the failure.
Here is the workaround.
https://developer.apple.com/library/mac/#documentation/security/conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html#//apple_ref/doc/uid/TP40001358-CH208-SW8
Please be sure that your certificate is valid. I think it's name shouldn't be root.der.crt. You can take a look for certificate types from here. The below code is for p12 certificate, I hope it will help.
NSData *PKCS12DataQA = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"CERTIFICATE NAME" ofType:#"CERTIFICATE TYPE"]];
BOOL result = [self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12DataQA];
- (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data
{
OSStatus securityError = errSecSuccess;
//testtest is the passsword for the certificate.
NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:#"testtest" forKey:(id)CFBridgingRelease(kSecImportExportPassphrase)];
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError = SecPKCS12Import((__bridge CFDataRef)(inPKCS12Data),(CFDictionaryRef)CFBridgingRetain(optionsDictionary),&items);
if (securityError == 0) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
*outIdentity = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
*outTrust = (SecTrustRef)tempTrust;
} else {
NSLog(#"Failed with error code %d",(int)securityError);
return NO;
}
return YES;
}

get SecKeyRef from base64 coded string

I'm working on an iOS app and I get a base64 coded public key such as:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3gn+tJ1+PbP0GHa6hmM35WsVyibpypWAwRuBYY4MGfh3VWoXgiyiLo5HJTW1eR9BUFq3z+yOG1rwzSabZ8I4zneWm0kH7xErSjNrMbmjirbL7e6TQNa1ujP/x4x9XVbqf3vIsNVs19kn/qSX/HGzd5Ct3TGAo0AT0T4JwkCfciwIDAQAB
I'd like to encode some text with this public key, but I cannot find a way to convert this string to a useful public key.
What do I need to do?
First, you must base64 decode your NSString to NSData:
See this answer for solutions. If you are developing for iOS 7, you can use initWithBase64EncodedString::options.
Once you have the string decoded as NSData, you can attempt to create a certificate from it. The format of the certificate you received matters - you can use DER (which is common) or PKCS12. You're likely to be getting it as DER, so that's what I'll assume you need guidance on.
Create a certificate and policy:
SecCertificateRef cert = NULL;
SecPolicyRef policy = NULL;
cert = SecCertificateCreateWithData(kCFAllocatorDefault, data);
policy = SecPolicyCreateBasicX509();
If the cerificate data was in an incorrect format when passed to SecCertificateCreateWithData you will get a NULL result.
At this point you have the certificate, but not the public key. To obtain the public key you must create a trust reference and evaluate the trust of the certificate.
OSStatus status = noErr;
SecKeyRef *publicKey = NULL;
SecTrustRef trust = NULL;
SecTrustResultType trustType = kSecTrustResultInvalid;
if (cert != NULL){
SecCertificateRef certArray[1] = {cert};
certs = CFArrayCreate(kCFAllocatorDefault, (void *)certArray, 1, NULL);
status = SecTrustCreateWithCertificates(certs, policy, &trust);
if (status == errSecSuccess){
status = SecTrustEvaluate(trust, &trustType);
// Evaulate the trust.
switch (trustType) {
case kSecTrustResultInvalid:
case kSecTrustResultConfirm:
case kSecTrustResultDeny:
case kSecTrustResultUnspecified:
case kSecTrustResultFatalTrustFailure:
case kSecTrustResultOtherError:
break;
case kSecTrustResultRecoverableTrustFailure:
*publicKey = SecTrustCopyPublicKey(trust);
break;
case kSecTrustResultProceed:
*publicKey = SecTrustCopyPublicKey(trust);
break;
}
}
}
If everything went well, you should now have a populated SecKeyRef with the public key. If it didn't go well, you will have a NULL SecKeyRef and an OSStatus indicating what went wrong. SecBase.h in the Security framework gives more detailed information on those error codes.
Now that you have a SecKeyRef with a public key, using it to encrypt data with a corresponding private key is covered well by the programming guide.
Note that you will have to release the things you allocated above (policy, certs) using ARC or CFRelease.

SecTrustEvaluate always returns kSecTrustResultRecoverableTrustFailure with SecPolicyCreateSSL

My application tries to evaluate a server trust certificate for a self signed certificate. This is working fine with SecPolicyCreateBasicX509 but not working for SecPolicyCreateSSL
Here is my code:
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
// create trust from protection space
SecTrustRef trustRef;
int trustCertificateCount = SecTrustGetCertificateCount(challenge.protectionSpace.serverTrust);
NSMutableArray* trustCertificates = [[NSMutableArray alloc] initWithCapacity:trustCertificateCount];
for (int i = 0; i < trustCertificateCount; i++) {
SecCertificateRef trustCertificate = SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, i);
[trustCertificates addObject:(id) trustCertificate];
}
// set evaluation policy
SecPolicyRef policyRef;
// policyRef = SecPolicyCreateBasicX509(); this is working
policyRef = SecPolicyCreateSSL(NO, (CFStringRef)
SecTrustCreateWithCertificates((CFArrayRef) trustCertificates, policyRef, &trustRef);
[trustCertificates release];
// load known certificates from keychain and set as anchor certificates
NSMutableDictionary* secItemCopyCertificatesParams = [[NSMutableDictionary alloc] init];
[secItemCopyCertificatesParams setObject:(id)kSecClassCertificate forKey:(id)kSecClass];
[secItemCopyCertificatesParams setObject:#"Server_Cert_Label" forKey:(id)kSecAttrLabel];
[secItemCopyCertificatesParams setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef];
[secItemCopyCertificatesParams setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit];
CFArrayRef certificates;
certificates = nil;
SecItemCopyMatching((CFDictionaryRef) secItemCopyCertificatesParams, (CFTypeRef*) &certificates);
if (certificates != nil && CFGetTypeID(certificates) == CFArrayGetTypeID()) {
SecTrustSetAnchorCertificates(trustRef, certificates);
SecTrustSetAnchorCertificatesOnly(trustRef, NO);
}
SecTrustResultType result;
OSStatus trustEvalStatus = SecTrustEvaluate(trustRef, &result);
if (trustEvalStatus == errSecSuccess) {
if (result == kSecTrustResultConfirm || result == kSecTrustResultProceed || result == kSecTrustResultUnspecified) {
// evaluation OK
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
} else {
// evaluation failed
// ask user to add certificate to keychain
} else {
// evaluation failed - cancel authentication
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
After a lot of research i have already made changes to the self-signed certificate by adding extension like mentioned in this post: Unable to trust a self signed certificate on iphone
Does anyone have another hint what might be missing here?
After a lot of testing I have worked out this problem. The following has been changed.
The policy is set to NO for server evaluation. This means the certificate is checked for client authentication. Obviously the server certificate will not have this! Setting this to YES will actually check if extendedKeyUsage is set to serverAuth for the server certificate.
SecTrustSetAnchorCertificates and SecTrustSetAnchorCertificatesOnly should always be called before evaluation and not only if you are providing your own anchor certificates. You need to call this with an empty array, otherwise the system known anchor certificates are not used for evaluation. Even installed trusted root certificates from MDM are working then.
Here is a working sample based on the first code:
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
// create trust from protection space
SecTrustRef trustRef;
int trustCertificateCount = SecTrustGetCertificateCount(challenge.protectionSpace.serverTrust);
NSMutableArray* trustCertificates = [[NSMutableArray alloc] initWithCapacity:trustCertificateCount];
for (int i = 0; i < trustCertificateCount; i++) {
SecCertificateRef trustCertificate = SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, i);
[trustCertificates addObject:(id) trustCertificate];
}
// set evaluation policy
SecPolicyRef policyRef;
// set to YES to verify certificate extendedKeyUsage is set to serverAuth
policyRef = SecPolicyCreateSSL(YES, (CFStringRef) challenge.protectionSpace.host);
SecTrustCreateWithCertificates((CFArrayRef) trustCertificates, policyRef, &trustRef);
[trustCertificates release];
// load known certificates from keychain and set as anchor certificates
NSMutableDictionary* secItemCopyCertificatesParams = [[NSMutableDictionary alloc] init];
[secItemCopyCertificatesParams setObject:(id)kSecClassCertificate forKey:(id)kSecClass];
[secItemCopyCertificatesParams setObject:#"Server_Cert_Label" forKey:(id)kSecAttrLabel];
[secItemCopyCertificatesParams setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef];
[secItemCopyCertificatesParams setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit];
CFArrayRef certificates;
certificates = nil;
SecItemCopyMatching((CFDictionaryRef) secItemCopyCertificatesParams, (CFTypeRef*) &certificates);
if (certificates != nil && CFGetTypeID(certificates) == CFArrayGetTypeID()) {
SecTrustSetAnchorCertificates(trustRef, certificates);
SecTrustSetAnchorCertificatesOnly(trustRef, NO);
} else {
// set empty array as own anchor certificate so system anchos certificates are used too!
SecTrustSetAnchorCertificates(trustRef, (CFArrayRef) [NSArray array]);
SecTrustSetAnchorCertificatesOnly(trustRef, NO);
}
SecTrustResultType result;
OSStatus trustEvalStatus = SecTrustEvaluate(trustRef, &result);
if (trustEvalStatus == errSecSuccess) {
if (result == kSecTrustResultConfirm || result == kSecTrustResultProceed || result == kSecTrustResultUnspecified) {
// evaluation OK
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
else {
// evaluation failed
// ask user to add certificate to keychain
}
}
else {
// evaluation failed - cancel authentication
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
Hope this will help someone.
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 !

Resources