Posts

Post not yet marked as solved
2 Replies
762 Views
I am trying to read the private key from certificate in the system keychain on the client to sign random data send by the server.Note that the certificates aren't distributed by me. Users will install the certificate(s) either by downloading them from the different servers or importing pkcs file.I am using below code.std::string osxPrivateKey::signData(const uint8_t* pData, uint32_t nDataSize, vector <uint8_t>& aSignature) { OSStatus nStatus; osxObject<SecTransformRef> signer; CFDataRef rawData = CFDataCreate(NULL, (const uint8_t*)pHash, nHashSize); CFErrorRef error; SecTransformRef signerRef = SecSignTransformCreate(m_privKey.get(), &error); signer.set(signerRef); if (error) { return false; } SecTransformSetAttribute(signer.get(), kSecTransformInputAttributeName, rawData, &error); SecTransformSetAttribute(signer.get(), kSecInputIsAttributeName , kSecInputIsPlainText, &error); //SecTransformSetAttribute(signer.get(), kSecPaddingKey, kSecPaddingPKCS1Key, &error); //SecTransformSetAttribute(signer.get(), kSecDigestTypeAttribute, kSecDigestSHA1, NULL); SecTransformSetAttribute(signer.get(), kSecDigestTypeAttribute, kSecDigestSHA2, NULL); int digestLength = 160; //if (type ==2) digestLength = 256; CFNumberRef dLen = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &digestLength); Boolean set = SecTransformSetAttribute(signer.get(), kSecDigestLengthAttribute, dLen, &error); CFRelease(dLen); if (error) { return false; } DSVERBOSE(Sardeep, "SecTransformExecute begin"); Boolean allowed; SecKeychainGetUserInteractionAllowed(&allowed); DSVERBOSE(Sardeep, "SecKeychainGetUserInteractionAllowed '%d'", allowed); SecKeychainSetUserInteractionAllowed(true); CFDataRef signature = (CFDataRef)SecTransformExecute(signer.get(), &error); if (error) { CFStringRef errorDesc = CFErrorCopyDescription(error); CFIndex length = CFStringGetLength(errorDesc); CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; char *buffer = (char *)malloc(maxSize); CFStringGetCString(errorDesc, buffer, maxSize, kCFStringEncodingUTF8); DSERROR(facility, "SecTransformExecute error : '%s'", buffer); delete buffer; return false; } DSVERBOSE(Sardeep, "SecTransformExecute end"); m_signHashAlgo = HCCertUtils::SIGN_HASH_ALGO_SHA256; char* base64Signature = new char[1024]; unsigned char* rawSignature = new unsigned char[1024]; int size = CFDataGetLength(signature); CFDataGetBytes(signature, CFRangeMake(0,CFDataGetLength(signature)), (UInt8*)(rawSignature)); DSUtilEncodeBase64((const char*)rawSignature, size, base64Signature, 1023); base64Signature[1023] = '\0'; strBase64Signature.assign(base64Signature); DSERROR(facility, "challenge data is successfully signed."); delete []base64Signature; delete []rawSignature; return true; }This code runs as a part of daemon on the client. I have written a test application (not a daemon) using same code and when I execute test application it prompts me for username/password in order to access the keychain. Once I provide username/password everything works fine.But when I execute same code through daemon (client-server communication), it doesn't prompt for username/password. So is there any way or API to skip the password required since daemon runs as system user?Coming from windows background, service (daemon) on windows can access the private key.I have tried following options so far:impersonate to current user from daemon so that user gets the authorisation prompt. But no prompt for username/password. I am expecting prompt when SecTransformExecute is executed ( as in my test application). But it fails with error "Error Domain=Internal CSSM error Code=-2147415839 "Internal error #800108e1 at SignTransform_block_invoke".try to read Access Control List of the certificate and modify access for this certificate so that it doesn't prompt for password everytime my app tries for access.SecAccessRef secaccess; OSStatus ret = SecKeychainItemCopyAccess(pKeychain, &secaccess); SecKeychainItemCopyAccess fails with error -25243 (The specified item has no access control ). 3. manually add my app in the access control from the keychain access.Only 3rd option is working. But I can't expect clients to add it manually as there could be multiple certificates setup for client/server communiation.Any suggestions? Is what I am trying to do possible on MacOS? If yes, how can I achieve it?
Posted
by Sardeep.
Last updated
.
Post not yet marked as solved
3 Replies
595 Views
I am trying to read Access Control List of a KeychainItem. I want to modify access for this KeychainItem so that it doesn't prompt for password everytime my app tries for access it. KeychainItem contains private key.Below the code snippet I am using.SecAccessRef secaccess; OSStatus ret = SecKeychainItemCopyAccess(pKeychain, &secaccess);SecKeychainItemCopyAccess fails with error -25243 (The specified item has no access control ).I believe every item has access control as per the link https://developer.apple.com/documentation/security/keychain_services/access_control_lists?language=objcMy test program ask for password everytime I run it with options "Always Allow" , "Deny" , "Allow". As per documentation, "Always Allow" option will add access control for the KeychainItem. But If I choose Always Allow option, SecKeychainItemCopyAccess fails with same error in subsequent run also.Since I am new to MacOS, I am not sure if I am doing it right.I am trying on MacOS 10.13.4 and 10.12Thanks.
Posted
by Sardeep.
Last updated
.