switch(attribute)
{
@@ -1016,6 +1067,19 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
return status;
}
+ case SECPKG_ATTR_KEY_INFO:
+ {
+ SecPkgContext_KeyInfoW *info = buffer;
+ SECURITY_STATUS status = schan_imp_get_key_info(ctx->session, info);
+ if (status == SEC_E_OK)
+ {
+ info->sSignatureAlgorithmName = ctx->key_signature_name;
+ info->sEncryptAlgorithmName = ctx->key_encrypt_name;
+ fill_alg_name(info->SignatureAlgorithm, info->sSignatureAlgorithmName, TRUE);
+ fill_alg_name(info->EncryptAlgorithm, info->sEncryptAlgorithmName, TRUE);
+ }
+ return status;
+ }
case SECPKG_ATTR_REMOTE_CERT_CONTEXT:
{
PCCERT_CONTEXT *cert = buffer;
@@ -1091,6 +1155,24 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesA(
{
case SECPKG_ATTR_STREAM_SIZES:
return schan_QueryContextAttributesW(context_handle, attribute, buffer);
+ case SECPKG_ATTR_KEY_INFO:
+ {
+ SecPkgContext_KeyInfoA *info = buffer;
+ struct schan_context *ctx;
+ SECURITY_STATUS status;
+ if (!context_handle) return SEC_E_INVALID_HANDLE;
+ ctx = schan_get_object(context_handle->dwLower, SCHAN_HANDLE_CTX);
+ if (!ctx) return SEC_E_INVALID_HANDLE;
+ status = schan_imp_get_key_info(ctx->session, (SecPkgContext_KeyInfoW*)info);
+ if (status == SEC_E_OK)
+ {
+ info->sSignatureAlgorithmName = (SEC_CHAR *)ctx->key_signature_name;
+ info->sEncryptAlgorithmName = (SEC_CHAR *)ctx->key_encrypt_name;
+ fill_alg_name(info->SignatureAlgorithm, info->sSignatureAlgorithmName, FALSE);
+ fill_alg_name(info->EncryptAlgorithm, info->sEncryptAlgorithmName, 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 30640d3..ddf33a8 100644
--- a/dlls/secur32/schannel_gnutls.c
+++ b/dlls/secur32/schannel_gnutls.c
@@ -363,6 +363,22 @@ static ALG_ID schannel_get_kx_algid(int kx)
}
}
+static ALG_ID schannel_get_kx_signature_algid(gnutls_kx_algorithm_t kx)
+{
+ 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;
+ }
+}
+
unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session)
{
gnutls_session_t s = (gnutls_session_t)session;
@@ -394,6 +410,23 @@ SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
return SEC_E_OK;
}
+SECURITY_STATUS schan_imp_get_key_info(schan_imp_session session, SecPkgContext_KeyInfoW *info)
+{
+ gnutls_session_t s = (gnutls_session_t)session;
+ gnutls_cipher_algorithm_t alg = pgnutls_cipher_get(s);
+ gnutls_kx_algorithm_t kx = pgnutls_kx_get(s);
+
+ TRACE("(%p,%p)\n", session, info);
+
+ info->sSignatureAlgorithmName = NULL; /* filled later */
+ info->sEncryptAlgorithmName = NULL; /* filled later */
+ info->KeySize = pgnutls_cipher_get_key_size(alg) * 8;
+ info->SignatureAlgorithm = schannel_get_kx_signature_algid(kx);
+ info->EncryptAlgorithm = schannel_get_cipher_algid(alg);
+
+ return SEC_E_OK;
+}