Reputation: 31
I am working to upgrade TLS version form 1.0 to 1.2 for existing windows/Win CE application. Right now my application is using Openssl 0.9.8k(supports TLS 1.0). To upgrade TLS version I am using Openssl-1.0.2p(supports TLS 1.2). I was signing data using MD5-SHA1 similar to steps followed in MD5-SHA1 hash using CryptoAPI (my requirement was same as this)
But TLS 1.2 has to sign hash using RSA-SHA256. How can I achieve using Crypto APIs?
I have tried to Created hash using Certificate key handle provider and use CALG_SHA_256 algorithm instead of CALG_SSL3_SHAMD5. But Certificate verification failed at server with error as "Bad Signature".
I have been surfing MSDN pages and I assuming that CNG APIs can do my Job for Windows 7 OS. If it is true, How can I achieve? Also I am not seeing CNG equivalent APIs in Windows CE, How can I achieve in Windows CE?
Thanks.
Upvotes: 1
Views: 155
Reputation: 1
static RSA_METHOD *rsa_meth = NULL;
static int cng_create_rsa_method(void)
{
if (rsa_meth == NULL) {
if ((rsa_meth = RSA_meth_dup(RSA_get_default_method())) == NULL
|| !RSA_meth_set1_name(rsa_meth, "My RSA Provider")
|| !RSA_meth_set_flags(rsa_meth, 0)
|| !RSA_meth_set_priv_enc(rsa_meth, rsa_priv_enc)
|| !RSA_meth_set_sign(rsa_meth, rsa_sign)
|| !RSA_meth_set_init(rsa_meth, rsa_init)) {
CNGerr(CNG_F_CNG_RSA_METHOD, ERR_R_MALLOC_FAILURE);
RSA_meth_free(rsa_meth);
rsa_meth = NULL;
}
}
return rsa_meth != NULL;
}
Then the implementation method of rsa_sign will be:
int rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
unsigned char *sigret, unsigned int *siglen, const RSA *rsa) {
HCRYPTHASH hHash = XXXX; //get the provide from your rsa;
int ret = -1;
std::vector<BYTE> output;
switch (dtype) {
case NID_sha256:
alg = CALG_SHA_256;
break;
case NID_sha384:
alg = CALG_SHA_384;
break;
case NID_sha512:
alg = CALG_SHA_512;
break;
case NID_sha1:
alg = CALG_SHA1;
break;
case NID_md5:
alg = CALG_MD5;
break;
case NID_md5_sha1:
alg = CALG_SSL3_SHAMD5;
break;
}
if (CryptCreateHash(hProv, alg , 0, 0, &hHash)) {
DWORD sigLen = 0;
CryptSetHashParam(hHash, HP_HASHVAL, m, 0);
CryptSignHash(hHash, AT_KEYEXCHANGE, NULL, 0, NULL, &sigLen);
output.resize(sigLen);
success = CryptSignHash(hHash, AT_KEYEXCHANGE, NULL, CRYPT_NOHASHOID, &output[0], &sigLen);
CryptDestroyHash(hHash);
}
if (!output.empty()) {
/*
* Windows Crypto API result is little-endian but OpenSSL is big-endian so we must reverse it.
*/
*siglen = output.size();
unsigned char *sigPtr = sigret;
for (std::vector<BYTE>::reverse_iterator iter = output.rbegin();
iter != output.rend(); iter++) {
*sigPtr = *iter;
sigPtr++;
}
ret = 1;
}
return ret;
}
Upvotes: 0