Posts

Post not yet marked as solved
2 Replies
1.3k 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
.