I'm trying to implement c++ external PKI sign method for openvpn client. I need to sign data with RSA_PKCS1_PSS_PADDING algorithm, but Security framework has no such method.
There is my function:
void MacStore::sign(const std::string &data, std::string &sig, const std::string &algorithm,
const std::string &hashalg, const std::string &saltlen) {
SecKeyAlgorithm alg;
if (!hashalg.empty()) {
alg = kSecKeyAlgorithmRSASignatureDigestPSSSHA256;
} else {
alg = kSecKeyAlgorithmRSASignatureMessagePSSSHA1;
}
openvpn::BufferAllocated signdata(256, openvpn::BufferAllocated::GROW);
openvpn::base64->decode(signdata, data);
SecKeyRef pkey;
OSStatus status = SecIdentityCopyPrivateKey((SecIdentityRef)identity, &pkey);
if (status) {
// error
return;
}
auto isSupported = SecKeyIsAlgorithmSupported(pkey, kSecKeyOperationTypeSign, alg);
std::cout << (isSupported ? "supported" : "not supported") << std::endl;
auto dataToSign = CFStringCreateWithCString(nullptr, buf_c_str(signdata), kCFStringEncodingASCII);
auto dataToSignPtr = CFStringCreateExternalRepresentation(nullptr, dataToSign, kCFStringEncodingASCII, 0);
CFErrorRef err = nullptr;
auto signature = SecKeyCreateSignature(pkey, alg, dataToSignPtr, &err);
if (err) {
return;
}
SecCertificateRef cert;
SecIdentityCopyCertificate((SecIdentityRef)identity, &cert);
SecKeyRef pub;
SecCertificateCopyPublicKey(cert, &pub);
int signatureLength = CFDataGetLength(signature);
openvpn::BufferAllocated signer(signatureLength, openvpn::BufferAllocated::ARRAY);
auto range = CFRangeMake(0, signatureLength);
CFDataGetBytes(signature, range, signer.data());
signer.set_size(signatureLength);
CFRelease(signature);
CFRelease(dataToSign);
sig = openvpn::base64->encode(signer);
std::cout << "SIGNATURE[" << signatureLength << "]: " << signer.c_str() << std::endl;
}
On connect server log prints:
// Verifies certificate - OK
OpenSSL: error:02000087:rsa routines::salt length recovery failed
Dec 09 12:51:38 server openvpn[29669]: 10.31.154.84:50843 OpenSSL: error:1C880004:Provider routines::RSA lib
Dec 09 12:51:38 server openvpn[29669]: 10.31.154.84:50843 OpenSSL: error:0A00007B:SSL routines::bad signature
Dec 09 12:51:38 server openvpn[29669]: 10.31.154.84:50843 TLS_ERROR: BIO read tls_read_plaintext error
Dec 09 12:51:38 server openvpn[29669]: 10.31.154.84:50843 TLS Error: TLS object -> incoming plaintext read error
Dec 09 12:51:38 server openvpn[29669]: 10.31.154.84:50843 TLS Error: TLS handshake failed
Dec 09 12:51:38 server openvpn[29669]: 10.31.154.84:50843 Fatal TLS error (check_tls_errors_co), restarting
Dec 09 12:51:38 server openvpn[29669]: 10.31.154.84:50843 SIGUSR1[soft,tls-error] received, client-instance restarting
My question is: which SecAlgorithm should I choose to produce valid rsa signature?
UPD: Verify method with same data to sign returns false(invalid signature) as well...