tls_schannel.c

Go to the documentation of this file.
00001 
00016 /*
00017  * FIX: Go through all SSPI functions and verify what needs to be freed
00018  * FIX: session resumption
00019  * TODO: add support for server cert chain validation
00020  * TODO: add support for CA cert validation
00021  * TODO: add support for EAP-TLS (client cert/key conf)
00022  */
00023 
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 #include <string.h>
00027 #include <windows.h>
00028 #include <wincrypt.h>
00029 #include <schannel.h>
00030 #define SECURITY_WIN32
00031 #include <security.h>
00032 #include <sspi.h>
00033 
00034 #include "common.h"
00035 #include "tls.h"
00036 
00037 
00038 struct tls_global {
00039         HMODULE hsecurity;
00040         PSecurityFunctionTable sspi;
00041         HCERTSTORE my_cert_store;
00042 };
00043 
00044 struct tls_connection {
00045         int established, start;
00046         int failed, read_alerts, write_alerts;
00047 
00048         SCHANNEL_CRED schannel_cred;
00049         CredHandle creds;
00050         CtxtHandle context;
00051 
00052         u8 eap_tls_prf[128];
00053         int eap_tls_prf_set;
00054 };
00055 
00056 
00057 static int schannel_load_lib(struct tls_global *global)
00058 {
00059         INIT_SECURITY_INTERFACE pInitSecurityInterface;
00060 
00061         global->hsecurity = LoadLibrary("Secur32.dll");
00062         if (global->hsecurity == NULL) {
00063                 wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x",
00064                            __func__, (unsigned int) GetLastError());
00065                 return -1;
00066         }
00067 
00068         pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(
00069                 global->hsecurity, "InitSecurityInterfaceA");
00070         if (pInitSecurityInterface == NULL) {
00071                 wpa_printf(MSG_ERROR, "%s: Could not find "
00072                            "InitSecurityInterfaceA from Secur32.dll",
00073                            __func__);
00074                 FreeLibrary(global->hsecurity);
00075                 global->hsecurity = NULL;
00076                 return -1;
00077         }
00078 
00079         global->sspi = pInitSecurityInterface();
00080         if (global->sspi == NULL) {
00081                 wpa_printf(MSG_ERROR, "%s: Could not read security "
00082                            "interface - 0x%x",
00083                            __func__, (unsigned int) GetLastError());
00084                 FreeLibrary(global->hsecurity);
00085                 global->hsecurity = NULL;
00086                 return -1;
00087         }
00088 
00089         return 0;
00090 }
00091 
00092 
00093 void * tls_init(const struct tls_config *conf)
00094 {
00095         struct tls_global *global;
00096 
00097         global = malloc(sizeof(*global));
00098         if (global == NULL)
00099                 return NULL;
00100         memset(global, 0, sizeof(*global));
00101         if (schannel_load_lib(global)) {
00102                 free(global);
00103                 return NULL;
00104         }
00105         return global;
00106 }
00107 
00108 
00109 void tls_deinit(void *ssl_ctx)
00110 {
00111         struct tls_global *global = ssl_ctx;
00112 
00113         if (global->my_cert_store)
00114                 CertCloseStore(global->my_cert_store, 0);
00115         FreeLibrary(global->hsecurity);
00116         free(global);
00117 }
00118 
00119 
00120 int tls_get_errors(void *ssl_ctx)
00121 {
00122         return 0;
00123 }
00124 
00125 
00126 struct tls_connection * tls_connection_init(void *ssl_ctx)
00127 {
00128         struct tls_connection *conn;
00129 
00130         conn = malloc(sizeof(*conn));
00131         if (conn == NULL)
00132                 return NULL;
00133         memset(conn, 0, sizeof(*conn));
00134         conn->start = 1;
00135 
00136         return conn;
00137 }
00138 
00139 
00140 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
00141 {
00142         if (conn == NULL)
00143                 return;
00144 
00145         free(conn);
00146 }
00147 
00148 
00149 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
00150 {
00151         return conn ? conn->established : 0;
00152 }
00153 
00154 
00155 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
00156 {
00157         struct tls_global *global = ssl_ctx;
00158         if (conn == NULL)
00159                 return -1;
00160 
00161         conn->eap_tls_prf_set = 0;
00162         conn->established = conn->failed = 0;
00163         conn->read_alerts = conn->write_alerts = 0;
00164         global->sspi->DeleteSecurityContext(&conn->context);
00165         /* FIX: what else needs to be reseted? */
00166 
00167         return 0;
00168 }
00169 
00170 
00171 int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert)
00172 {
00173         return -1;
00174 }
00175 
00176 
00177 int tls_global_set_verify(void *ssl_ctx, int check_crl)
00178 {
00179         return -1;
00180 }
00181 
00182 
00183 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
00184                               int verify_peer)
00185 {
00186         return -1;
00187 }
00188 
00189 
00190 int tls_global_client_cert(void *_ssl_ctx, const char *client_cert)
00191 {
00192         return -1;
00193 }
00194 
00195 
00196 int tls_global_private_key(void *_ssl_ctx, const char *private_key,
00197                            const char *private_key_passwd)
00198 {
00199         return -1;
00200 }
00201 
00202 
00203 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
00204                             struct tls_keys *keys)
00205 {
00206         if (conn == NULL || keys == NULL || !conn->eap_tls_prf_set)
00207                 return -1;
00208 
00209         memset(keys, 0, sizeof(*keys));
00210 
00211         /*
00212          * Cannot get master_key from Schannel, but EapKeyBlock can be used to
00213          * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and
00214          * EAP-TTLS cannot use this, though, since they are using different
00215          * labels. The only option could be to implement TLSv1 completely here
00216          * and just use Schannel or CryptoAPI for low-level crypto
00217          * functionality..
00218          */
00219         keys->eap_tls_prf = conn->eap_tls_prf;
00220         keys->eap_tls_prf_len = sizeof(conn->eap_tls_prf);
00221 
00222         return 0;
00223 }
00224 
00225 
00226 static u8 * tls_conn_hs_clienthello(struct tls_global *global,
00227                                     struct tls_connection *conn,
00228                                     size_t *out_len)
00229 {
00230         DWORD sspi_flags, sspi_flags_out;
00231         SecBufferDesc outbuf;
00232         SecBuffer outbufs[1];
00233         SECURITY_STATUS status;
00234         TimeStamp ts_expiry;
00235 
00236         sspi_flags = ISC_REQ_REPLAY_DETECT |
00237                 ISC_REQ_CONFIDENTIALITY |
00238                 ISC_RET_EXTENDED_ERROR |
00239                 ISC_REQ_ALLOCATE_MEMORY |
00240                 ISC_REQ_MANUAL_CRED_VALIDATION;
00241 
00242         wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__);
00243 
00244         outbufs[0].pvBuffer = NULL;
00245         outbufs[0].BufferType = SECBUFFER_TOKEN;
00246         outbufs[0].cbBuffer = 0;
00247 
00248         outbuf.cBuffers = 1;
00249         outbuf.pBuffers = outbufs;
00250         outbuf.ulVersion = SECBUFFER_VERSION;
00251 
00252         status = global->sspi->InitializeSecurityContextA(
00253                 &conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
00254                 SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
00255                 &outbuf, &sspi_flags_out, &ts_expiry);
00256         if (status != SEC_I_CONTINUE_NEEDED) {
00257                 wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA "
00258                            "failed - 0x%x",
00259                            __func__, (unsigned int) status);
00260                 return NULL;
00261         }
00262 
00263         if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
00264                 u8 *buf;
00265                 wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
00266                             outbufs[0].pvBuffer, outbufs[0].cbBuffer);
00267                 conn->start = 0;
00268                 *out_len = outbufs[0].cbBuffer;
00269                 buf = malloc(*out_len);
00270                 if (buf == NULL)
00271                         return NULL;
00272                 memcpy(buf, outbufs[0].pvBuffer, *out_len);
00273                 global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
00274                 return buf;
00275         }
00276 
00277         wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello");
00278 
00279         return NULL;
00280 }
00281 
00282 
00283 #ifndef SECPKG_ATTR_EAP_KEY_BLOCK
00284 #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b
00285 
00286 typedef struct _SecPkgContext_EapKeyBlock {
00287         BYTE rgbKeys[128];
00288         BYTE rgbIVs[64];
00289 } SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock;
00290 #endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */
00291 
00292 static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
00293 {
00294         SECURITY_STATUS status;
00295         SecPkgContext_EapKeyBlock kb;
00296 
00297         /* Note: Windows NT and Windows Me/98/95 do not support getting
00298          * EapKeyBlock */
00299 
00300         status = global->sspi->QueryContextAttributes(
00301                 &conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb);
00302         if (status != SEC_E_OK) {
00303                 wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes("
00304                            "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)",
00305                            __func__, (int) status);
00306                 return -1;
00307         }
00308 
00309         wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys",
00310                         kb.rgbKeys, sizeof(kb.rgbKeys));
00311         wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs",
00312                         kb.rgbIVs, sizeof(kb.rgbIVs));
00313 
00314         memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
00315         conn->eap_tls_prf_set = 1;
00316 }
00317 
00318 
00319 u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
00320                               const u8 *in_data, size_t in_len,
00321                               size_t *out_len)
00322 {
00323         struct tls_global *global = ssl_ctx;
00324         DWORD sspi_flags, sspi_flags_out;
00325         SecBufferDesc inbuf, outbuf;
00326         SecBuffer inbufs[2], outbufs[1];
00327         SECURITY_STATUS status;
00328         TimeStamp ts_expiry;
00329         u8 *out_buf = NULL;
00330 
00331         if (conn->start) {
00332                 return tls_conn_hs_clienthello(global, conn, out_len);
00333         }
00334 
00335         wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
00336                    in_len);
00337 
00338         sspi_flags = ISC_REQ_REPLAY_DETECT |
00339                 ISC_REQ_CONFIDENTIALITY |
00340                 ISC_RET_EXTENDED_ERROR |
00341                 ISC_REQ_ALLOCATE_MEMORY |
00342                 ISC_REQ_MANUAL_CRED_VALIDATION;
00343 
00344         /* Input buffer for Schannel */
00345         inbufs[0].pvBuffer = (u8 *) in_data;
00346         inbufs[0].cbBuffer = in_len;
00347         inbufs[0].BufferType = SECBUFFER_TOKEN;
00348 
00349         /* Place for leftover data from Schannel */
00350         inbufs[1].pvBuffer = NULL;
00351         inbufs[1].cbBuffer = 0;
00352         inbufs[1].BufferType = SECBUFFER_EMPTY;
00353 
00354         inbuf.cBuffers = 2;
00355         inbuf.pBuffers = inbufs;
00356         inbuf.ulVersion = SECBUFFER_VERSION;
00357 
00358         /* Output buffer for Schannel */
00359         outbufs[0].pvBuffer = NULL;
00360         outbufs[0].cbBuffer = 0;
00361         outbufs[0].BufferType = SECBUFFER_TOKEN;
00362 
00363         outbuf.cBuffers = 1;
00364         outbuf.pBuffers = outbufs;
00365         outbuf.ulVersion = SECBUFFER_VERSION;
00366 
00367         status = global->sspi->InitializeSecurityContextA(
00368                 &conn->creds, &conn->context, NULL, sspi_flags, 0,
00369                 SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
00370                 &outbuf, &sspi_flags_out, &ts_expiry);
00371 
00372         wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContextA -> "
00373                    "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
00374                    "intype[1]=%d outlen[0]=%d",
00375                    (int) status, (int) inbufs[0].cbBuffer,
00376                    (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer,
00377                    (int) inbufs[1].BufferType,
00378                    (int) outbufs[0].cbBuffer);
00379         if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED ||
00380             (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) {
00381                 if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
00382                         wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
00383                                     outbufs[0].pvBuffer, outbufs[0].cbBuffer);
00384                         *out_len = outbufs[0].cbBuffer;
00385                         out_buf = malloc(*out_len);
00386                         if (out_buf == NULL)
00387                                 return NULL;
00388                         memcpy(out_buf, outbufs[0].pvBuffer, *out_len);
00389                         global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
00390                         outbufs[0].pvBuffer = NULL;
00391                 }
00392         }
00393 
00394         switch (status) {
00395         case SEC_E_INCOMPLETE_MESSAGE:
00396                 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE");
00397                 break;
00398         case SEC_I_CONTINUE_NEEDED:
00399                 wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED");
00400                 break;
00401         case SEC_E_OK:
00402                 /* TODO: verify server certificate chain */
00403                 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake "
00404                            "completed successfully");
00405                 conn->established = 1;
00406                 tls_get_eap(global, conn);
00407 
00408                 /* Need to return something to get final TLS ACK. */
00409                 if (out_buf == NULL)
00410                         out_buf = malloc(1);
00411 
00412                 if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
00413                         wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
00414                                     "application data",
00415                                     inbufs[1].pvBuffer, inbufs[1].cbBuffer);
00416                         /* FIX: need to fix TLS API to allow this data to be
00417                          * passed to the caller */
00418                         global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
00419                         inbufs[1].pvBuffer = NULL;
00420                 }
00421                 break;
00422         case SEC_I_INCOMPLETE_CREDENTIALS:
00423                 wpa_printf(MSG_DEBUG,
00424                            "Schannel: SEC_I_INCOMPLETE_CREDENTIALS");
00425                 break;
00426         case SEC_E_WRONG_PRINCIPAL:
00427                 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL");
00428                 break;
00429         case SEC_E_INTERNAL_ERROR:
00430                 wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR");
00431                 break;
00432         }
00433 
00434         if (FAILED(status)) {
00435                 wpa_printf(MSG_DEBUG, "Schannel: Handshake failed "
00436                            "(out_buf=%p)", out_buf);
00437                 conn->failed++;
00438                 global->sspi->DeleteSecurityContext(&conn->context);
00439                 return out_buf;
00440         }
00441 
00442         if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
00443                 /* TODO: Can this happen? What to do with this data? */
00444                 wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data",
00445                             inbufs[1].pvBuffer, inbufs[1].cbBuffer);
00446                 global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
00447                 inbufs[1].pvBuffer = NULL;
00448         }
00449 
00450         return out_buf;
00451 }
00452 
00453 
00454 u8 * tls_connection_server_handshake(void *ssl_ctx,
00455                                      struct tls_connection *conn,
00456                                      const u8 *in_data, size_t in_len,
00457                                      size_t *out_len)
00458 {
00459         return NULL;
00460 }
00461 
00462 
00463 int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
00464                            const u8 *in_data, size_t in_len,
00465                            u8 *out_data, size_t out_len)
00466 {
00467         struct tls_global *global = ssl_ctx;
00468         SECURITY_STATUS status;
00469         SecBufferDesc buf;
00470         SecBuffer bufs[4];
00471         SecPkgContext_StreamSizes sizes;
00472         int i;
00473         size_t total_len;
00474 
00475         status = global->sspi->QueryContextAttributes(&conn->context,
00476                                                       SECPKG_ATTR_STREAM_SIZES,
00477                                                       &sizes);
00478         if (status != SEC_E_OK) {
00479                 wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
00480                            __func__);
00481                 return -1;
00482         }
00483         wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
00484                    __func__,
00485                    (unsigned int) sizes.cbHeader,
00486                    (unsigned int) sizes.cbTrailer);
00487 
00488         total_len = sizes.cbHeader + in_len + sizes.cbTrailer;
00489 
00490         if (out_len < total_len) {
00491                 wpa_printf(MSG_DEBUG, "%s: too short out_data (out_len=%lu "
00492                            "in_len=%lu total_len=%lu)", __func__,
00493                            (unsigned long) out_len, (unsigned long) in_len,
00494                            (unsigned long) total_len);
00495                 return -1;
00496         }
00497 
00498         memset(&bufs, 0, sizeof(bufs));
00499         bufs[0].pvBuffer = out_data;
00500         bufs[0].cbBuffer = sizes.cbHeader;
00501         bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
00502 
00503         memcpy(out_data + sizes.cbHeader, in_data, in_len);
00504         bufs[1].pvBuffer = out_data + sizes.cbHeader;
00505         bufs[1].cbBuffer = in_len;
00506         bufs[1].BufferType = SECBUFFER_DATA;
00507 
00508         bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len;
00509         bufs[2].cbBuffer = sizes.cbTrailer;
00510         bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
00511 
00512         buf.ulVersion = SECBUFFER_VERSION;
00513         buf.cBuffers = 3;
00514         buf.pBuffers = bufs;
00515 
00516         status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0);
00517 
00518         wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> "
00519                    "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
00520                    "len[2]=%d type[2]=%d",
00521                    (int) status,
00522                    (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
00523                    (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
00524                    (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
00525         wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
00526                    "out_data=%p bufs %p %p %p",
00527                    out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
00528                    bufs[2].pvBuffer);
00529 
00530         for (i = 0; i < 3; i++) {
00531                 if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY)
00532                 {
00533                         wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs",
00534                                     bufs[i].pvBuffer, bufs[i].cbBuffer);
00535                 }
00536         }
00537 
00538         if (status == SEC_E_OK) {
00539                 wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
00540                 wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Encrypted data from "
00541                                 "EncryptMessage", out_data, total_len);
00542                 return total_len;
00543         }
00544 
00545         wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
00546                    __func__, (int) status);
00547         return -1;
00548 }
00549 
00550 
00551 int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
00552                            const u8 *in_data, size_t in_len,
00553                            u8 *out_data, size_t out_len)
00554 {
00555         struct tls_global *global = ssl_ctx;
00556         SECURITY_STATUS status;
00557         SecBufferDesc buf;
00558         SecBuffer bufs[4];
00559         int i;
00560 
00561         if (out_len < in_len) {
00562                 wpa_printf(MSG_DEBUG, "%s: out_len=%lu < in_len=%lu", __func__,
00563                            (unsigned long) out_len, (unsigned long) in_len);
00564                 return -1;
00565         }
00566 
00567         wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage",
00568                     in_data, in_len);
00569         memset(&bufs, 0, sizeof(bufs));
00570         memcpy(out_data, in_data, in_len);
00571         bufs[0].pvBuffer = out_data;
00572         bufs[0].cbBuffer = in_len;
00573         bufs[0].BufferType = SECBUFFER_DATA;
00574 
00575         bufs[1].BufferType = SECBUFFER_EMPTY;
00576         bufs[2].BufferType = SECBUFFER_EMPTY;
00577         bufs[3].BufferType = SECBUFFER_EMPTY;
00578 
00579         buf.ulVersion = SECBUFFER_VERSION;
00580         buf.cBuffers = 4;
00581         buf.pBuffers = bufs;
00582 
00583         status = global->sspi->DecryptMessage(&conn->context, &buf, 0,
00584                                                     NULL);
00585         wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> "
00586                    "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d "
00587                    "len[2]=%d type[2]=%d len[3]=%d type[3]=%d",
00588                    (int) status,
00589                    (int) bufs[0].cbBuffer, (int) bufs[0].BufferType,
00590                    (int) bufs[1].cbBuffer, (int) bufs[1].BufferType,
00591                    (int) bufs[2].cbBuffer, (int) bufs[2].BufferType,
00592                    (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
00593         wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
00594                    "out_data=%p bufs %p %p %p %p",
00595                    out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
00596                    bufs[2].pvBuffer, bufs[3].pvBuffer);
00597 
00598         switch (status) {
00599         case SEC_E_INCOMPLETE_MESSAGE:
00600                 wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE",
00601                            __func__);
00602                 break;
00603         case SEC_E_OK:
00604                 wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
00605                 for (i = 0; i < 4; i++) {
00606                         if (bufs[i].BufferType == SECBUFFER_DATA)
00607                                 break;
00608                 }
00609                 if (i == 4) {
00610                         wpa_printf(MSG_DEBUG, "%s: No output data from "
00611                                    "DecryptMessage", __func__);
00612                         return -1;
00613                 }
00614                 wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
00615                                 "DecryptMessage",
00616                                 bufs[i].pvBuffer, bufs[i].cbBuffer);
00617                 if (bufs[i].cbBuffer > out_len) {
00618                         wpa_printf(MSG_DEBUG, "%s: Too long output data",
00619                                    __func__);
00620                         return -1;
00621                 }
00622                 memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
00623                 return bufs[i].cbBuffer;
00624         }
00625 
00626         wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
00627                    __func__, (int) status);
00628         return -1;
00629 }
00630 
00631 
00632 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
00633 {
00634         return 0;
00635 }
00636 
00637 
00638 #ifdef EAP_FAST
00639 int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
00640                                   const u8 *key, size_t key_len)
00641 {
00642         return -1;
00643 }
00644 #endif /* EAP_FAST */
00645 
00646 
00647 int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn)
00648 {
00649         return -1;
00650 }
00651 
00652 
00653 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
00654                    char *buf, size_t buflen)
00655 {
00656         return -1;
00657 }
00658 
00659 
00660 int tls_connection_enable_workaround(void *ssl_ctx,
00661                                      struct tls_connection *conn)
00662 {
00663         return 0;
00664 }
00665 
00666 
00667 #ifdef EAP_FAST
00668 /* ClientHello TLS extensions require a patch to openssl, so this function is
00669  * commented out unless explicitly needed for EAP-FAST in order to be able to
00670  * build this file with unmodified openssl. */
00671 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
00672                                     int ext_type, const u8 *data,
00673                                     size_t data_len)
00674 {
00675         return -1;
00676 }
00677 #endif /* EAP_FAST */
00678 
00679 
00680 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
00681 {
00682         if (conn == NULL)
00683                 return -1;
00684         return conn->failed;
00685 }
00686 
00687 
00688 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
00689 {
00690         if (conn == NULL)
00691                 return -1;
00692         return conn->read_alerts;
00693 }
00694 
00695 
00696 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
00697 {
00698         if (conn == NULL)
00699                 return -1;
00700         return conn->write_alerts;
00701 }
00702 
00703 
00704 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
00705                               const struct tls_connection_params *params)
00706 {
00707         struct tls_global *global = tls_ctx;
00708         ALG_ID algs[1];
00709         SECURITY_STATUS status;
00710         TimeStamp ts_expiry;
00711 
00712         if (conn == NULL)
00713                 return -1;
00714 
00715         if (global->my_cert_store == NULL &&
00716             (global->my_cert_store = CertOpenSystemStore(0, "MY")) == NULL) {
00717                 wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
00718                            __func__, (unsigned int) GetLastError());
00719                 return -1;
00720         }
00721 
00722         memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
00723         conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
00724         conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
00725         algs[0] = CALG_RSA_KEYX;
00726         conn->schannel_cred.cSupportedAlgs = 1;
00727         conn->schannel_cred.palgSupportedAlgs = algs;
00728         conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
00729         status = global->sspi->AcquireCredentialsHandleA(
00730                 NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
00731                 &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
00732         if (status != SEC_E_OK) {
00733                 wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
00734                            "0x%x", __func__, (unsigned int) status);
00735                 return -1;
00736         }
00737 
00738         return 0;
00739 }
00740 

Generated on Sat May 6 21:13:39 2006 for wpa_supplicant by  doxygen 1.4.2