+++ /dev/null
-/*
- * Crypto wrapper for Microsoft CryptoAPI
- * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include <windows.h>
-#include <wincrypt.h>
-
-#include "common.h"
-#include "crypto.h"
-
-#ifndef MS_ENH_RSA_AES_PROV
-#ifdef UNICODE
-#define MS_ENH_RSA_AES_PROV \
-L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
-#else
-#define MS_ENH_RSA_AES_PROV \
-"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
-#endif
-#endif /* MS_ENH_RSA_AES_PROV */
-
-#ifndef CALG_HMAC
-#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC)
-#endif
-
-#ifdef __MINGW32_VERSION
-/*
- * MinGW does not yet include all the needed definitions for CryptoAPI, so
- * define here whatever extra is needed.
- */
-
-static BOOL WINAPI
-(*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType,
- PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
-= NULL; /* to be loaded from crypt32.dll */
-
-
-static int mingw_load_crypto_func(void)
-{
- HINSTANCE dll;
-
- /* MinGW does not yet have full CryptoAPI support, so load the needed
- * function here. */
-
- if (CryptImportPublicKeyInfo)
- return 0;
-
- dll = LoadLibrary("crypt32");
- if (dll == NULL) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 "
- "library");
- return -1;
- }
-
- CryptImportPublicKeyInfo = GetProcAddress(
- dll, "CryptImportPublicKeyInfo");
- if (CryptImportPublicKeyInfo == NULL) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get "
- "CryptImportPublicKeyInfo() address from "
- "crypt32 library");
- return -1;
- }
-
- return 0;
-}
-
-#else /* __MINGW32_VERSION */
-
-static int mingw_load_crypto_func(void)
-{
- return 0;
-}
-
-#endif /* __MINGW32_VERSION */
-
-
-static void cryptoapi_report_error(const char *msg)
-{
- char *s, *pos;
- DWORD err = GetLastError();
-
- if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err);
- }
-
- pos = s;
- while (*pos) {
- if (*pos == '\n' || *pos == '\r') {
- *pos = '\0';
- break;
- }
- pos++;
- }
-
- wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s);
- LocalFree(s);
-}
-
-
-int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem,
- const u8 *addr[], const size_t *len, u8 *mac)
-{
- HCRYPTPROV prov;
- HCRYPTHASH hash;
- size_t i;
- DWORD hlen;
- int ret = 0;
-
- if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) {
- cryptoapi_report_error("CryptAcquireContext");
- return -1;
- }
-
- if (!CryptCreateHash(prov, alg, 0, 0, &hash)) {
- cryptoapi_report_error("CryptCreateHash");
- CryptReleaseContext(prov, 0);
- return -1;
- }
-
- for (i = 0; i < num_elem; i++) {
- if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) {
- cryptoapi_report_error("CryptHashData");
- CryptDestroyHash(hash);
- CryptReleaseContext(prov, 0);
- }
- }
-
- hlen = hash_len;
- if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) {
- cryptoapi_report_error("CryptGetHashParam");
- ret = -1;
- }
-
- CryptDestroyHash(hash);
- CryptReleaseContext(prov, 0);
-
- return ret;
-}
-
-
-int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
-{
- return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac);
-}
-
-
-void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
-{
- u8 next, tmp;
- int i;
- HCRYPTPROV prov;
- HCRYPTKEY ckey;
- DWORD dlen;
- struct {
- BLOBHEADER hdr;
- DWORD len;
- BYTE key[8];
- } key_blob;
- DWORD mode = CRYPT_MODE_ECB;
-
- key_blob.hdr.bType = PLAINTEXTKEYBLOB;
- key_blob.hdr.bVersion = CUR_BLOB_VERSION;
- key_blob.hdr.reserved = 0;
- key_blob.hdr.aiKeyAlg = CALG_DES;
- key_blob.len = 8;
-
- /* Add parity bits to the key */
- next = 0;
- for (i = 0; i < 7; i++) {
- tmp = key[i];
- key_blob.key[i] = (tmp >> i) | next | 1;
- next = tmp << (7 - i);
- }
- key_blob.key[i] = next | 1;
-
- if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT)) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: "
- "%d", (int) GetLastError());
- return;
- }
-
- if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0,
- &ckey)) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d",
- (int) GetLastError());
- CryptReleaseContext(prov, 0);
- return;
- }
-
- if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) "
- "failed: %d", (int) GetLastError());
- CryptDestroyKey(ckey);
- CryptReleaseContext(prov, 0);
- return;
- }
-
- os_memcpy(cypher, clear, 8);
- dlen = 8;
- if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d",
- (int) GetLastError());
- os_memset(cypher, 0, 8);
- }
-
- CryptDestroyKey(ckey);
- CryptReleaseContext(prov, 0);
-}
-
-
-int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
-{
- return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac);
-}
-
-
-int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
-{
- return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac);
-}
-
-
-struct aes_context {
- HCRYPTPROV prov;
- HCRYPTKEY ckey;
-};
-
-
-void * aes_encrypt_init(const u8 *key, size_t len)
-{
- struct aes_context *akey;
- struct {
- BLOBHEADER hdr;
- DWORD len;
- BYTE key[16];
- } key_blob;
- DWORD mode = CRYPT_MODE_ECB;
-
- if (len != 16)
- return NULL;
-
- key_blob.hdr.bType = PLAINTEXTKEYBLOB;
- key_blob.hdr.bVersion = CUR_BLOB_VERSION;
- key_blob.hdr.reserved = 0;
- key_blob.hdr.aiKeyAlg = CALG_AES_128;
- key_blob.len = len;
- os_memcpy(key_blob.key, key, len);
-
- akey = os_zalloc(sizeof(*akey));
- if (akey == NULL)
- return NULL;
-
- if (!CryptAcquireContext(&akey->prov, NULL,
- MS_ENH_RSA_AES_PROV, PROV_RSA_AES,
- CRYPT_VERIFYCONTEXT)) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: "
- "%d", (int) GetLastError());
- os_free(akey);
- return NULL;
- }
-
- if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob),
- 0, 0, &akey->ckey)) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d",
- (int) GetLastError());
- CryptReleaseContext(akey->prov, 0);
- os_free(akey);
- return NULL;
- }
-
- if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) "
- "failed: %d", (int) GetLastError());
- CryptDestroyKey(akey->ckey);
- CryptReleaseContext(akey->prov, 0);
- os_free(akey);
- return NULL;
- }
-
- return akey;
-}
-
-
-void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
-{
- struct aes_context *akey = ctx;
- DWORD dlen;
-
- os_memcpy(crypt, plain, 16);
- dlen = 16;
- if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d",
- (int) GetLastError());
- os_memset(crypt, 0, 16);
- }
-}
-
-
-void aes_encrypt_deinit(void *ctx)
-{
- struct aes_context *akey = ctx;
- if (akey) {
- CryptDestroyKey(akey->ckey);
- CryptReleaseContext(akey->prov, 0);
- os_free(akey);
- }
-}
-
-
-void * aes_decrypt_init(const u8 *key, size_t len)
-{
- return aes_encrypt_init(key, len);
-}
-
-
-void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
-{
- struct aes_context *akey = ctx;
- DWORD dlen;
-
- os_memcpy(plain, crypt, 16);
- dlen = 16;
-
- if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d",
- (int) GetLastError());
- }
-}
-
-
-void aes_decrypt_deinit(void *ctx)
-{
- aes_encrypt_deinit(ctx);
-}
-
-
-struct crypto_hash {
- enum crypto_hash_alg alg;
- int error;
- HCRYPTPROV prov;
- HCRYPTHASH hash;
- HCRYPTKEY key;
-};
-
-struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
- size_t key_len)
-{
- struct crypto_hash *ctx;
- ALG_ID calg;
- struct {
- BLOBHEADER hdr;
- DWORD len;
- BYTE key[32];
- } key_blob;
-
- os_memset(&key_blob, 0, sizeof(key_blob));
- switch (alg) {
- case CRYPTO_HASH_ALG_MD5:
- calg = CALG_MD5;
- break;
- case CRYPTO_HASH_ALG_SHA1:
- calg = CALG_SHA;
- break;
- case CRYPTO_HASH_ALG_HMAC_MD5:
- case CRYPTO_HASH_ALG_HMAC_SHA1:
- calg = CALG_HMAC;
- key_blob.hdr.bType = PLAINTEXTKEYBLOB;
- key_blob.hdr.bVersion = CUR_BLOB_VERSION;
- key_blob.hdr.reserved = 0;
- /*
- * Note: RC2 is not really used, but that can be used to
- * import HMAC keys of up to 16 byte long.
- * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to
- * be able to import longer keys (HMAC-SHA1 uses 20-byte key).
- */
- key_blob.hdr.aiKeyAlg = CALG_RC2;
- key_blob.len = key_len;
- if (key_len > sizeof(key_blob.key))
- return NULL;
- os_memcpy(key_blob.key, key, key_len);
- break;
- default:
- return NULL;
- }
-
- ctx = os_zalloc(sizeof(*ctx));
- if (ctx == NULL)
- return NULL;
-
- ctx->alg = alg;
-
- if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) {
- cryptoapi_report_error("CryptAcquireContext");
- os_free(ctx);
- return NULL;
- }
-
- if (calg == CALG_HMAC) {
-#ifndef CRYPT_IPSEC_HMAC_KEY
-#define CRYPT_IPSEC_HMAC_KEY 0x00000100
-#endif
- if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob,
- sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY,
- &ctx->key)) {
- cryptoapi_report_error("CryptImportKey");
- CryptReleaseContext(ctx->prov, 0);
- os_free(ctx);
- return NULL;
- }
- }
-
- if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) {
- cryptoapi_report_error("CryptCreateHash");
- CryptReleaseContext(ctx->prov, 0);
- os_free(ctx);
- return NULL;
- }
-
- if (calg == CALG_HMAC) {
- HMAC_INFO info;
- os_memset(&info, 0, sizeof(info));
- switch (alg) {
- case CRYPTO_HASH_ALG_HMAC_MD5:
- info.HashAlgid = CALG_MD5;
- break;
- case CRYPTO_HASH_ALG_HMAC_SHA1:
- info.HashAlgid = CALG_SHA;
- break;
- default:
- /* unreachable */
- break;
- }
-
- if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info,
- 0)) {
- cryptoapi_report_error("CryptSetHashParam");
- CryptDestroyHash(ctx->hash);
- CryptReleaseContext(ctx->prov, 0);
- os_free(ctx);
- return NULL;
- }
- }
-
- return ctx;
-}
-
-
-void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
-{
- if (ctx == NULL || ctx->error)
- return;
-
- if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) {
- cryptoapi_report_error("CryptHashData");
- ctx->error = 1;
- }
-}
-
-
-int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
-{
- int ret = 0;
- DWORD hlen;
-
- if (ctx == NULL)
- return -2;
-
- if (mac == NULL || len == NULL)
- goto done;
-
- if (ctx->error) {
- ret = -2;
- goto done;
- }
-
- hlen = *len;
- if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) {
- cryptoapi_report_error("CryptGetHashParam");
- ret = -2;
- }
- *len = hlen;
-
-done:
- if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 ||
- ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5)
- CryptDestroyKey(ctx->key);
-
- os_free(ctx);
-
- return ret;
-}
-
-
-struct crypto_cipher {
- HCRYPTPROV prov;
- HCRYPTKEY key;
-};
-
-
-struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
- const u8 *iv, const u8 *key,
- size_t key_len)
-{
- struct crypto_cipher *ctx;
- struct {
- BLOBHEADER hdr;
- DWORD len;
- BYTE key[32];
- } key_blob;
- DWORD mode = CRYPT_MODE_CBC;
-
- key_blob.hdr.bType = PLAINTEXTKEYBLOB;
- key_blob.hdr.bVersion = CUR_BLOB_VERSION;
- key_blob.hdr.reserved = 0;
- key_blob.len = key_len;
- if (key_len > sizeof(key_blob.key))
- return NULL;
- os_memcpy(key_blob.key, key, key_len);
-
- switch (alg) {
- case CRYPTO_CIPHER_ALG_AES:
- if (key_len == 32)
- key_blob.hdr.aiKeyAlg = CALG_AES_256;
- else if (key_len == 24)
- key_blob.hdr.aiKeyAlg = CALG_AES_192;
- else
- key_blob.hdr.aiKeyAlg = CALG_AES_128;
- break;
- case CRYPTO_CIPHER_ALG_3DES:
- key_blob.hdr.aiKeyAlg = CALG_3DES;
- break;
- case CRYPTO_CIPHER_ALG_DES:
- key_blob.hdr.aiKeyAlg = CALG_DES;
- break;
- case CRYPTO_CIPHER_ALG_RC2:
- key_blob.hdr.aiKeyAlg = CALG_RC2;
- break;
- case CRYPTO_CIPHER_ALG_RC4:
- key_blob.hdr.aiKeyAlg = CALG_RC4;
- break;
- default:
- return NULL;
- }
-
- ctx = os_zalloc(sizeof(*ctx));
- if (ctx == NULL)
- return NULL;
-
- if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV,
- PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
- cryptoapi_report_error("CryptAcquireContext");
- goto fail1;
- }
-
- if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob,
- sizeof(key_blob), 0, 0, &ctx->key)) {
- cryptoapi_report_error("CryptImportKey");
- goto fail2;
- }
-
- if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) {
- cryptoapi_report_error("CryptSetKeyParam(KP_MODE)");
- goto fail3;
- }
-
- if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) {
- cryptoapi_report_error("CryptSetKeyParam(KP_IV)");
- goto fail3;
- }
-
- return ctx;
-
-fail3:
- CryptDestroyKey(ctx->key);
-fail2:
- CryptReleaseContext(ctx->prov, 0);
-fail1:
- os_free(ctx);
- return NULL;
-}
-
-
-int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
- u8 *crypt, size_t len)
-{
- DWORD dlen;
-
- os_memcpy(crypt, plain, len);
- dlen = len;
- if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) {
- cryptoapi_report_error("CryptEncrypt");
- os_memset(crypt, 0, len);
- return -1;
- }
-
- return 0;
-}
-
-
-int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
- u8 *plain, size_t len)
-{
- DWORD dlen;
-
- os_memcpy(plain, crypt, len);
- dlen = len;
- if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) {
- cryptoapi_report_error("CryptDecrypt");
- return -1;
- }
-
- return 0;
-}
-
-
-void crypto_cipher_deinit(struct crypto_cipher *ctx)
-{
- CryptDestroyKey(ctx->key);
- CryptReleaseContext(ctx->prov, 0);
- os_free(ctx);
-}
-
-
-struct crypto_public_key {
- HCRYPTPROV prov;
- HCRYPTKEY rsa;
-};
-
-struct crypto_private_key {
- HCRYPTPROV prov;
- HCRYPTKEY rsa;
-};
-
-
-struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
-{
- /* Use crypto_public_key_from_cert() instead. */
- return NULL;
-}
-
-
-struct crypto_private_key * crypto_private_key_import(const u8 *key,
- size_t len,
- const char *passwd)
-{
- /* TODO */
- return NULL;
-}
-
-
-struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
- size_t len)
-{
- struct crypto_public_key *pk;
- PCCERT_CONTEXT cc;
-
- pk = os_zalloc(sizeof(*pk));
- if (pk == NULL)
- return NULL;
-
- cc = CertCreateCertificateContext(X509_ASN_ENCODING |
- PKCS_7_ASN_ENCODING, buf, len);
- if (!cc) {
- cryptoapi_report_error("CryptCreateCertificateContext");
- os_free(pk);
- return NULL;
- }
-
- if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL,
- 0)) {
- cryptoapi_report_error("CryptAcquireContext");
- os_free(pk);
- CertFreeCertificateContext(cc);
- return NULL;
- }
-
- if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING |
- PKCS_7_ASN_ENCODING,
- &cc->pCertInfo->SubjectPublicKeyInfo,
- &pk->rsa)) {
- cryptoapi_report_error("CryptImportPublicKeyInfo");
- CryptReleaseContext(pk->prov, 0);
- os_free(pk);
- CertFreeCertificateContext(cc);
- return NULL;
- }
-
- CertFreeCertificateContext(cc);
-
- return pk;
-}
-
-
-int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
- const u8 *in, size_t inlen,
- u8 *out, size_t *outlen)
-{
- DWORD clen;
- u8 *tmp;
- size_t i;
-
- if (*outlen < inlen)
- return -1;
- tmp = malloc(*outlen);
- if (tmp == NULL)
- return -1;
-
- os_memcpy(tmp, in, inlen);
- clen = inlen;
- if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) {
- wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using "
- "public key: %d", (int) GetLastError());
- os_free(tmp);
- return -1;
- }
-
- *outlen = clen;
-
- /* Reverse the output */
- for (i = 0; i < *outlen; i++)
- out[i] = tmp[*outlen - 1 - i];
-
- os_free(tmp);
-
- return 0;
-}
-
-
-int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
- const u8 *in, size_t inlen,
- u8 *out, size_t *outlen)
-{
- /* TODO */
- return -1;
-}
-
-
-void crypto_public_key_free(struct crypto_public_key *key)
-{
- if (key) {
- CryptDestroyKey(key->rsa);
- CryptReleaseContext(key->prov, 0);
- os_free(key);
- }
-}
-
-
-void crypto_private_key_free(struct crypto_private_key *key)
-{
- if (key) {
- CryptDestroyKey(key->rsa);
- CryptReleaseContext(key->prov, 0);
- os_free(key);
- }
-}
-
-
-int crypto_global_init(void)
-{
- return mingw_load_crypto_func();
-}
-
-
-void crypto_global_deinit(void)
-{
-}
-
-
-int crypto_mod_exp(const u8 *base, size_t base_len,
- const u8 *power, size_t power_len,
- const u8 *modulus, size_t modulus_len,
- u8 *result, size_t *result_len)
-{
- /* TODO */
- return -1;
-}
+++ /dev/null
-/*
- * SSL/TLS interface functions for Microsoft Schannel
- * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-/*
- * FIX: Go through all SSPI functions and verify what needs to be freed
- * FIX: session resumption
- * TODO: add support for server cert chain validation
- * TODO: add support for CA cert validation
- * TODO: add support for EAP-TLS (client cert/key conf)
- */
-
-#include "includes.h"
-#include <windows.h>
-#include <wincrypt.h>
-#include <schannel.h>
-#define SECURITY_WIN32
-#include <security.h>
-#include <sspi.h>
-
-#include "common.h"
-#include "tls.h"
-
-
-struct tls_global {
- HMODULE hsecurity;
- PSecurityFunctionTable sspi;
- HCERTSTORE my_cert_store;
-};
-
-struct tls_connection {
- int established, start;
- int failed, read_alerts, write_alerts;
-
- SCHANNEL_CRED schannel_cred;
- CredHandle creds;
- CtxtHandle context;
-
- u8 eap_tls_prf[128];
- int eap_tls_prf_set;
-};
-
-
-static int schannel_load_lib(struct tls_global *global)
-{
- INIT_SECURITY_INTERFACE pInitSecurityInterface;
-
- global->hsecurity = LoadLibrary(TEXT("Secur32.dll"));
- if (global->hsecurity == NULL) {
- wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x",
- __func__, (unsigned int) GetLastError());
- return -1;
- }
-
- pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(
- global->hsecurity, "InitSecurityInterfaceA");
- if (pInitSecurityInterface == NULL) {
- wpa_printf(MSG_ERROR, "%s: Could not find "
- "InitSecurityInterfaceA from Secur32.dll",
- __func__);
- FreeLibrary(global->hsecurity);
- global->hsecurity = NULL;
- return -1;
- }
-
- global->sspi = pInitSecurityInterface();
- if (global->sspi == NULL) {
- wpa_printf(MSG_ERROR, "%s: Could not read security "
- "interface - 0x%x",
- __func__, (unsigned int) GetLastError());
- FreeLibrary(global->hsecurity);
- global->hsecurity = NULL;
- return -1;
- }
-
- return 0;
-}
-
-
-void * tls_init(const struct tls_config *conf)
-{
- struct tls_global *global;
-
- global = os_zalloc(sizeof(*global));
- if (global == NULL)
- return NULL;
- if (schannel_load_lib(global)) {
- os_free(global);
- return NULL;
- }
- return global;
-}
-
-
-void tls_deinit(void *ssl_ctx)
-{
- struct tls_global *global = ssl_ctx;
-
- if (global->my_cert_store)
- CertCloseStore(global->my_cert_store, 0);
- FreeLibrary(global->hsecurity);
- os_free(global);
-}
-
-
-int tls_get_errors(void *ssl_ctx)
-{
- return 0;
-}
-
-
-struct tls_connection * tls_connection_init(void *ssl_ctx)
-{
- struct tls_connection *conn;
-
- conn = os_zalloc(sizeof(*conn));
- if (conn == NULL)
- return NULL;
- conn->start = 1;
-
- return conn;
-}
-
-
-void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
-{
- if (conn == NULL)
- return;
-
- os_free(conn);
-}
-
-
-int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
-{
- return conn ? conn->established : 0;
-}
-
-
-int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
-{
- struct tls_global *global = ssl_ctx;
- if (conn == NULL)
- return -1;
-
- conn->eap_tls_prf_set = 0;
- conn->established = conn->failed = 0;
- conn->read_alerts = conn->write_alerts = 0;
- global->sspi->DeleteSecurityContext(&conn->context);
- /* FIX: what else needs to be reseted? */
-
- return 0;
-}
-
-
-int tls_global_set_params(void *tls_ctx,
- const struct tls_connection_params *params)
-{
- return -1;
-}
-
-
-int tls_global_set_verify(void *ssl_ctx, int check_crl)
-{
- return -1;
-}
-
-
-int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
- int verify_peer)
-{
- return -1;
-}
-
-
-int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
- struct tls_keys *keys)
-{
- /* Schannel does not export master secret or client/server random. */
- return -1;
-}
-
-
-int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
- const char *label, int server_random_first,
- u8 *out, size_t out_len)
-{
- /*
- * Cannot get master_key from Schannel, but EapKeyBlock can be used to
- * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and
- * EAP-TTLS cannot use this, though, since they are using different
- * labels. The only option could be to implement TLSv1 completely here
- * and just use Schannel or CryptoAPI for low-level crypto
- * functionality..
- */
-
- if (conn == NULL || !conn->eap_tls_prf_set || server_random_first ||
- os_strcmp(label, "client EAP encryption") != 0 ||
- out_len > sizeof(conn->eap_tls_prf))
- return -1;
-
- os_memcpy(out, conn->eap_tls_prf, out_len);
-
- return 0;
-}
-
-
-static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
- struct tls_connection *conn)
-{
- DWORD sspi_flags, sspi_flags_out;
- SecBufferDesc outbuf;
- SecBuffer outbufs[1];
- SECURITY_STATUS status;
- TimeStamp ts_expiry;
-
- sspi_flags = ISC_REQ_REPLAY_DETECT |
- ISC_REQ_CONFIDENTIALITY |
- ISC_RET_EXTENDED_ERROR |
- ISC_REQ_ALLOCATE_MEMORY |
- ISC_REQ_MANUAL_CRED_VALIDATION;
-
- wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
-
- outbufs[0].pvBuffer = NULL;
- outbufs[0].BufferType = SECBUFFER_TOKEN;
- outbufs[0].cbBuffer = 0;
-
- outbuf.cBuffers = 1;
- outbuf.pBuffers = outbufs;
- outbuf.ulVersion = SECBUFFER_VERSION;
-
-#ifdef UNICODE
- status = global->sspi->InitializeSecurityContextW(
- &conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
- SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
- &outbuf, &sspi_flags_out, &ts_expiry);
-#else /* UNICODE */
- status = global->sspi->InitializeSecurityContextA(
- &conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
- SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
- &outbuf, &sspi_flags_out, &ts_expiry);
-#endif /* UNICODE */
- if (status != SEC_I_CONTINUE_NEEDED) {
- wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA "
- "failed - 0x%x",
- __func__, (unsigned int) status);
- return NULL;
- }
-
- if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
- struct wpabuf *buf;
- wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
- outbufs[0].pvBuffer, outbufs[0].cbBuffer);
- conn->start = 0;
- buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
- outbufs[0].cbBuffer);
- if (buf == NULL)
- return NULL;
- global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
- return buf;
- }
-
- wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
-
- return NULL;
-}
-
-
-#ifndef SECPKG_ATTR_EAP_KEY_BLOCK
-#define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
-
-typedef struct _SecPkgContext_EapKeyBlock {
- BYTE rgbKeys[128];
- BYTE rgbIVs[64];
-} SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
-#endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
-
-static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
-{
- SECURITY_STATUS status;
- SecPkgContext_EapKeyBlock kb;
-
- /* Note: Windows NT and Windows Me/98/95 do not support getting
- * EapKeyBlock */
-
- status = global->sspi->QueryContextAttributes(
- &conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb);
- if (status != SEC_E_OK) {
- wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes("
- "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)",
- __func__, (int) status);
- return -1;
- }
-
- wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys",
- kb.rgbKeys, sizeof(kb.rgbKeys));
- wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs",
- kb.rgbIVs, sizeof(kb.rgbIVs));
-
- os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
- conn->eap_tls_prf_set = 1;
- return 0;
-}
-
-
-struct wpabuf * tls_connection_handshake(void *tls_ctx,
- struct tls_connection *conn,
- const struct wpabuf *in_data,
- struct wpabuf **appl_data)
-{
- struct tls_global *global = tls_ctx;
- DWORD sspi_flags, sspi_flags_out;
- SecBufferDesc inbuf, outbuf;
- SecBuffer inbufs[2], outbufs[1];
- SECURITY_STATUS status;
- TimeStamp ts_expiry;
- struct wpabuf *out_buf = NULL;
-
- if (appl_data)
- *appl_data = NULL;
-
- if (conn->start)
- return tls_conn_hs_clienthello(global, conn);
-
- wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
- (int) wpabuf_len(in_data));
-
- sspi_flags = ISC_REQ_REPLAY_DETECT |
- ISC_REQ_CONFIDENTIALITY |
- ISC_RET_EXTENDED_ERROR |
- ISC_REQ_ALLOCATE_MEMORY |
- ISC_REQ_MANUAL_CRED_VALIDATION;
-
- /* Input buffer for Schannel */
- inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data);
- inbufs[0].cbBuffer = wpabuf_len(in_data);
- inbufs[0].BufferType = SECBUFFER_TOKEN;
-
- /* Place for leftover data from Schannel */
- inbufs[1].pvBuffer = NULL;
- inbufs[1].cbBuffer = 0;
- inbufs[1].BufferType = SECBUFFER_EMPTY;
-
- inbuf.cBuffers = 2;
- inbuf.pBuffers = inbufs;
- inbuf.ulVersion = SECBUFFER_VERSION;
-
- /* Output buffer for Schannel */
- outbufs[0].pvBuffer = NULL;
- outbufs[0].cbBuffer = 0;
- outbufs[0].BufferType = SECBUFFER_TOKEN;
-
- outbuf.cBuffers = 1;
- outbuf.pBuffers = outbufs;
- outbuf.ulVersion = SECBUFFER_VERSION;
-
-#ifdef UNICODE
- status = global->sspi->InitializeSecurityContextW(
- &conn->creds, &conn->context, NULL, sspi_flags, 0,
- SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
- &outbuf, &sspi_flags_out, &ts_expiry);
-#else /* UNICODE */
- status = global->sspi->InitializeSecurityContextA(
- &conn->creds, &conn->context, NULL, sspi_flags, 0,
- SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
- &outbuf, &sspi_flags_out, &ts_expiry);
-#endif /* UNICODE */
-
- wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> "
- "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
- "intype[1]=%d outlen[0]=%d",
- (int) status, (int) inbufs[0].cbBuffer,
- (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer,
- (int) inbufs[1].BufferType,
- (int) outbufs[0].cbBuffer);
- if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED ||
- (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) {
- if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
- wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
- outbufs[0].pvBuffer, outbufs[0].cbBuffer);
- out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
- outbufs[0].cbBuffer);
- global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
- outbufs[0].pvBuffer = NULL;
- if (out_buf == NULL)
- return NULL;
- }
- }
-
- switch (status) {
- case SEC_E_INCOMPLETE_MESSAGE:
- wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
- break;
- case SEC_I_CONTINUE_NEEDED:
- wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED");
- break;
- case SEC_E_OK:
- /* TODO: verify server certificate chain */
- wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake "
- "completed successfully");
- conn->established = 1;
- tls_get_eap(global, conn);
-
- /* Need to return something to get final TLS ACK. */
- if (out_buf == NULL)
- out_buf = wpabuf_alloc(0);
-
- if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
- wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
- "application data",
- inbufs[1].pvBuffer, inbufs[1].cbBuffer);
- if (appl_data) {
- *appl_data = wpabuf_alloc_copy(
- outbufs[1].pvBuffer,
- outbufs[1].cbBuffer);
- }
- global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
- inbufs[1].pvBuffer = NULL;
- }
- break;
- case SEC_I_INCOMPLETE_CREDENTIALS:
- wpa_printf(MSG_DEBUG,
- "Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
- break;
- case SEC_E_WRONG_PRINCIPAL:
- wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL");
- break;
- case SEC_E_INTERNAL_ERROR:
- wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR");
- break;
- }
-
- if (FAILED(status)) {
- wpa_printf(MSG_DEBUG, "Schannel: Handshake failed "
- "(out_buf=%p)", out_buf);
- conn->failed++;
- global->sspi->DeleteSecurityContext(&conn->context);
- return out_buf;
- }
-
- if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
- /* TODO: Can this happen? What to do with this data? */
- wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data",
- inbufs[1].pvBuffer, inbufs[1].cbBuffer);
- global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
- inbufs[1].pvBuffer = NULL;
- }
-
- return out_buf;
-}
-
-
-struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
- struct tls_connection *conn,
- const struct wpabuf *in_data,
- struct wpabuf **appl_data)
-{
- return NULL;
-}
-
-
-struct wpabuf * tls_connection_encrypt(void *tls_ctx,
- struct tls_connection *conn,
- const struct wpabuf *in_data)
-{
- struct tls_global *global = tls_ctx;
- SECURITY_STATUS status;
- SecBufferDesc buf;
- SecBuffer bufs[4];
- SecPkgContext_StreamSizes sizes;
- int i;
- struct wpabuf *out;
-
- status = global->sspi->QueryContextAttributes(&conn->context,
- SECPKG_ATTR_STREAM_SIZES,
- &sizes);
- if (status != SEC_E_OK) {
- wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
- __func__);
- return NULL;
- }
- wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
- __func__,
- (unsigned int) sizes.cbHeader,
- (unsigned int) sizes.cbTrailer);
-
- out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
- sizes.cbTrailer);
-
- os_memset(&bufs, 0, sizeof(bufs));
- bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader);
- bufs[0].cbBuffer = sizes.cbHeader;
- bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
-
- bufs[1].pvBuffer = wpabuf_put(out, 0);
- wpabuf_put_buf(out, in_data);
- bufs[1].cbBuffer = wpabuf_len(in_data);
- bufs[1].BufferType = SECBUFFER_DATA;
-
- bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer);
- bufs[2].cbBuffer = sizes.cbTrailer;
- bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
-
- buf.ulVersion = SECBUFFER_VERSION;
- buf.cBuffers = 3;
- buf.pBuffers = bufs;
-
- status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
-
- wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> "
- "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
- "len[2]=%d type[2]=%d",
- (int) status,
- (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
- (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
- (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
- wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
- "out_data=%p bufs %p %p %p",
- wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer,
- bufs[2].pvBuffer);
-
- for (i = 0; i < 3; i++) {
- if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
- {
- wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
- bufs[i].pvBuffer, bufs[i].cbBuffer);
- }
- }
-
- if (status == SEC_E_OK) {
- wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
- wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data "
- "from EncryptMessage", out);
- return out;
- }
-
- wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
- __func__, (int) status);
- wpabuf_free(out);
- return NULL;
-}
-
-
-struct wpabuf * tls_connection_decrypt(void *tls_ctx,
- struct tls_connection *conn,
- const struct wpabuf *in_data)
-{
- struct tls_global *global = tls_ctx;
- SECURITY_STATUS status;
- SecBufferDesc buf;
- SecBuffer bufs[4];
- int i;
- struct wpabuf *out, *tmp;
-
- wpa_hexdump_buf(MSG_MSGDUMP,
- "Schannel: Encrypted data to DecryptMessage", in_data);
- os_memset(&bufs, 0, sizeof(bufs));
- tmp = wpabuf_dup(in_data);
- if (tmp == NULL)
- return NULL;
- bufs[0].pvBuffer = wpabuf_mhead(tmp);
- bufs[0].cbBuffer = wpabuf_len(in_data);
- bufs[0].BufferType = SECBUFFER_DATA;
-
- bufs[1].BufferType = SECBUFFER_EMPTY;
- bufs[2].BufferType = SECBUFFER_EMPTY;
- bufs[3].BufferType = SECBUFFER_EMPTY;
-
- buf.ulVersion = SECBUFFER_VERSION;
- buf.cBuffers = 4;
- buf.pBuffers = bufs;
-
- status = global->sspi->DecryptMessage(&conn->context, &buf, 0,
- NULL);
- wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> "
- "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
- "len[2]=%d type[2]=%d len[3]=%d type[3]=%d",
- (int) status,
- (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
- (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
- (int) bufs[2].cbBuffer, (int) bufs[2].BufferType,
- (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
- wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
- "out_data=%p bufs %p %p %p %p",
- wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer,
- bufs[2].pvBuffer, bufs[3].pvBuffer);
-
- switch (status) {
- case SEC_E_INCOMPLETE_MESSAGE:
- wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE",
- __func__);
- break;
- case SEC_E_OK:
- wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
- for (i = 0; i < 4; i++) {
- if (bufs[i].BufferType == SECBUFFER_DATA)
- break;
- }
- if (i == 4) {
- wpa_printf(MSG_DEBUG, "%s: No output data from "
- "DecryptMessage", __func__);
- wpabuf_free(tmp);
- return NULL;
- }
- wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
- "DecryptMessage",
- bufs[i].pvBuffer, bufs[i].cbBuffer);
- out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer);
- wpabuf_free(tmp);
- return out;
- }
-
- wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
- __func__, (int) status);
- wpabuf_free(tmp);
- return NULL;
-}
-
-
-int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
-{
- return 0;
-}
-
-
-int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
- u8 *ciphers)
-{
- return -1;
-}
-
-
-int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
- char *buf, size_t buflen)
-{
- return -1;
-}
-
-
-int tls_connection_enable_workaround(void *ssl_ctx,
- struct tls_connection *conn)
-{
- return 0;
-}
-
-
-int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
- int ext_type, const u8 *data,
- size_t data_len)
-{
- return -1;
-}
-
-
-int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
-{
- if (conn == NULL)
- return -1;
- return conn->failed;
-}
-
-
-int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
-{
- if (conn == NULL)
- return -1;
- return conn->read_alerts;
-}
-
-
-int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
-{
- if (conn == NULL)
- return -1;
- return conn->write_alerts;
-}
-
-
-int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
- const struct tls_connection_params *params)
-{
- struct tls_global *global = tls_ctx;
- ALG_ID algs[1];
- SECURITY_STATUS status;
- TimeStamp ts_expiry;
-
- if (conn == NULL)
- return -1;
-
- if (params->subject_match) {
- wpa_printf(MSG_INFO, "TLS: subject_match not supported");
- return -1;
- }
-
- if (params->altsubject_match) {
- wpa_printf(MSG_INFO, "TLS: altsubject_match not supported");
- return -1;
- }
-
- if (params->suffix_match) {
- wpa_printf(MSG_INFO, "TLS: suffix_match not supported");
- return -1;
- }
-
- if (params->domain_match) {
- wpa_printf(MSG_INFO, "TLS: domain_match not supported");
- return -1;
- }
-
- if (params->openssl_ciphers) {
- wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
- return -1;
- }
-
- if (global->my_cert_store == NULL &&
- (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
- NULL) {
- wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
- __func__, (unsigned int) GetLastError());
- return -1;
- }
-
- os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
- conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
- conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
- algs[0] = CALG_RSA_KEYX;
- conn->schannel_cred.cSupportedAlgs = 1;
- conn->schannel_cred.palgSupportedAlgs = algs;
- conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
-#ifdef UNICODE
- status = global->sspi->AcquireCredentialsHandleW(
- NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
- &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
-#else /* UNICODE */
- status = global->sspi->AcquireCredentialsHandleA(
- NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
- &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
-#endif /* UNICODE */
- if (status != SEC_E_OK) {
- wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
- "0x%x", __func__, (unsigned int) status);
- return -1;
- }
-
- return 0;
-}
-
-
-unsigned int tls_capabilities(void *tls_ctx)
-{
- return 0;
-}
-
-
-int tls_get_library_version(char *buf, size_t buf_len)
-{
- return os_snprintf(buf, buf_len, "schannel");
-}