diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 6914837a25a..82374efd55c 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -962,6 +962,33 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextA( return ret; } +static void *get_alg_name(ALG_ID id, BOOL wide) +{ + static const struct { + ALG_ID alg_id; + const char* name; + const WCHAR nameW[8]; + } alg_name_map[] = { + { CALG_ECDSA, "ECDSA", {'E','C','D','S','A',0} }, + { CALG_RSA_SIGN, "RSA", {'R','S','A',0} }, + { CALG_DES, "DES", {'D','E','S',0} }, + { CALG_RC2, "RC2", {'R','C','2',0} }, + { CALG_3DES, "3DES", {'3','D','E','S',0} }, + { CALG_AES_128, "AES", {'A','E','S',0} }, + { CALG_AES_192, "AES", {'A','E','S',0} }, + { CALG_AES_256, "AES", {'A','E','S',0} }, + { CALG_RC4, "RC4", {'R','C','4',0} }, + }; + unsigned i; + + for (i = 0; i < sizeof(alg_name_map)/sizeof(alg_name_map[0]); i++) + if (alg_name_map[i].alg_id == id) + return wide ? (void*)alg_name_map[i].nameW : (void*)alg_name_map[i].name; + + FIXME("Unknown ALG_ID %04x\n", id); + return NULL; +} + static SECURITY_STATUS ensure_remote_cert(struct schan_context *ctx) { HCERTSTORE cert_store; @@ -1016,6 +1043,21 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( return status; } + case SECPKG_ATTR_KEY_INFO: + { + SecPkgContext_ConnectionInfo conn_info; + SECURITY_STATUS status = schan_imp_get_connection_info(ctx->session, &conn_info); + if (status == SEC_E_OK) + { + SecPkgContext_KeyInfoW *info = buffer; + info->KeySize = conn_info.dwCipherStrength; + info->SignatureAlgorithm = schan_imp_get_key_signature_algorithm(ctx->session); + info->EncryptAlgorithm = conn_info.aiCipher; + info->sSignatureAlgorithmName = get_alg_name(info->SignatureAlgorithm, TRUE); + info->sEncryptAlgorithmName = get_alg_name(info->EncryptAlgorithm, TRUE); + } + return status; + } case SECPKG_ATTR_REMOTE_CERT_CONTEXT: { PCCERT_CONTEXT *cert = buffer; @@ -1091,6 +1133,17 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesA( { case SECPKG_ATTR_STREAM_SIZES: return schan_QueryContextAttributesW(context_handle, attribute, buffer); + case SECPKG_ATTR_KEY_INFO: + { + SECURITY_STATUS status = schan_QueryContextAttributesW(context_handle, attribute, buffer); + if (status == SEC_E_OK) + { + SecPkgContext_KeyInfoA *info = buffer; + info->sSignatureAlgorithmName = get_alg_name(info->SignatureAlgorithm, FALSE); + info->sEncryptAlgorithmName = get_alg_name(info->EncryptAlgorithm, FALSE); + } + return status; + } case SECPKG_ATTR_REMOTE_CERT_CONTEXT: return schan_QueryContextAttributesW(context_handle, attribute, buffer); case SECPKG_ATTR_CONNECTION_INFO: diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 33686bc6519..a0281769742 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -383,6 +383,27 @@ SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session, return SEC_E_OK; } +ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session) +{ + gnutls_session_t s = (gnutls_session_t)session; + gnutls_kx_algorithm_t kx = pgnutls_kx_get(s); + + TRACE("(%p)\n", session); + + switch (kx) + { + case GNUTLS_KX_UNKNOWN: return 0; + case GNUTLS_KX_RSA: + case GNUTLS_KX_RSA_EXPORT: + case GNUTLS_KX_DHE_RSA: + case GNUTLS_KX_ECDHE_RSA: return CALG_RSA_SIGN; + case GNUTLS_KX_ECDHE_ECDSA: return CALG_ECDSA; + default: + FIXME("unknown algorithm %d\n", kx); + return 0; + } +} + SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store, PCCERT_CONTEXT *ret) { diff --git a/dlls/secur32/schannel_macosx.c b/dlls/secur32/schannel_macosx.c index 2c5896a67ce..f3972916e58 100644 --- a/dlls/secur32/schannel_macosx.c +++ b/dlls/secur32/schannel_macosx.c @@ -914,6 +914,12 @@ unsigned int schan_imp_get_max_message_size(schan_imp_session session) return 1 << 14; } +ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session) +{ + FIXME("(%p)\n", session); + return 0; +} + SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session, SecPkgContext_ConnectionInfo *info) { diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index 1baa543fe15..9a60d657882 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -252,6 +252,7 @@ extern void schan_imp_set_session_target(schan_imp_session session, const char * extern SECURITY_STATUS schan_imp_handshake(schan_imp_session session) DECLSPEC_HIDDEN; extern unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session) DECLSPEC_HIDDEN; extern unsigned int schan_imp_get_max_message_size(schan_imp_session session) DECLSPEC_HIDDEN; +extern ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session) DECLSPEC_HIDDEN; extern SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session, SecPkgContext_ConnectionInfo *info) DECLSPEC_HIDDEN; extern SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE, diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c index b12a739eae4..b5ed169a978 100644 --- a/dlls/secur32/tests/schannel.c +++ b/dlls/secur32/tests/schannel.c @@ -925,7 +925,7 @@ todo_wine } status = pQueryContextAttributesA(&context, SECPKG_ATTR_KEY_INFO, &key_info); - todo_wine ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_KEY_INFO) failed: %08x\n", status); + ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_KEY_INFO) failed: %08x\n", status); if(status == SEC_E_OK) { ok(broken(key_info.SignatureAlgorithm == 0 /* WinXP,2003 */) || key_info.SignatureAlgorithm == CALG_RSA_SIGN,