📄 tls_funcs.c
字号:
if(mytls_vars->ctx) { SSL_CTX_free(mytls_vars->ctx); mytls_vars->ctx = NULL; } return XETLSCERTLOAD; } return XENONE;}int tls_funcs_load_random(struct generic_eap_data *thisint, char *random_file){ char *default_random = "/dev/urandom", *file; struct tls_vars *mytls_vars; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((thisint->eap_data != NULL), "thisint->eap_data != NULL", FALSE)) return XEMALLOC; mytls_vars = thisint->eap_data; file = random_file == NULL ? default_random : random_file; if (RAND_load_file(file, 1024) < 0) { tls_funcs_process_error(); if(mytls_vars->ctx) { SSL_CTX_free(mytls_vars->ctx); mytls_vars->ctx = NULL; } debug_printf(DEBUG_NORMAL, "Couldn't load random data from %s\n", file); return -1; } return XENONE;}int tls_funcs_load_user_cert(struct generic_eap_data *thisint, char *client_cert, char *key_file, char *password, char *random_file){ struct tls_vars *mytls_vars; struct config_eap_tls *userdata; if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((client_cert != NULL), "client_cert != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((key_file != NULL), "key_file != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((password != NULL), "password != NULL", FALSE)) return XEMALLOC; if (!thisint->eap_data) { debug_printf(DEBUG_NORMAL, "Invalid EAP data in tls_funcs_load_user_cert()!\n"); return XEMALLOC; } mytls_vars = (struct tls_vars *)thisint->eap_data; userdata = (struct config_eap_tls *)thisint->eap_conf_data; SSL_CTX_set_default_passwd_cb_userdata(mytls_vars->ctx, password); SSL_CTX_set_default_passwd_cb(mytls_vars->ctx, return_password); if (SSL_CTX_use_certificate_file(mytls_vars->ctx, client_cert, SSL_FILETYPE_ASN1) != 1 && SSL_CTX_use_certificate_file(mytls_vars->ctx, client_cert, SSL_FILETYPE_PEM) != 1 ) { debug_printf(DEBUG_NORMAL, "Couldn't load client certificate data!\n"); tls_funcs_process_error(); if(mytls_vars->ctx) { SSL_CTX_free(mytls_vars->ctx); mytls_vars->ctx = NULL; } return XETLSCERTLOAD; } debug_printf(DEBUG_CONFIG, "Loading user Private Key from %s...\n", key_file); if (userdata->sc.engine_id) { EVP_PKEY *pkey; debug_printf(DEBUG_CONFIG, "Loading user Private Key with id %s from %s...\n", userdata->sc.key_id, userdata->sc.engine_id); set_smartcard_pin(password); pkey = ENGINE_load_private_key(mytls_vars->engine, userdata->sc.key_id, UI_noninteractive(), NULL); SSL_CTX_use_PrivateKey(mytls_vars->ctx, pkey); //EVP_PKEY_free(pkey); } else if (SSL_CTX_use_PrivateKey_file(mytls_vars->ctx, key_file, SSL_FILETYPE_PEM) != 1 && SSL_CTX_use_PrivateKey_file(mytls_vars->ctx, key_file, SSL_FILETYPE_ASN1) != 1) { tls_funcs_process_error(); if(mytls_vars->ctx) { SSL_CTX_free(mytls_vars->ctx); mytls_vars->ctx = NULL; } debug_printf(DEBUG_NORMAL, "Couldn't load client private key!\n"); return XETLSCERTLOAD; } if (!SSL_CTX_check_private_key(mytls_vars->ctx)) { debug_printf(DEBUG_NORMAL, "Private key isn't valid!\n"); tls_funcs_process_error(); return XETLSCERTLOAD; } SSL_CTX_set_options(mytls_vars->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE); SSL_CTX_set_verify(mytls_vars->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); if (tls_funcs_load_random(thisint, random_file)) { return XETLSCERTLOAD; } debug_printf(DEBUG_CONFIG, "Loaded random data from %s...\n", random_file); // If we made it this far, our user cert is loaded, so indicate it. mytls_vars->cert_loaded = TRUE; return XENONE;}int tls_funcs_failed(struct generic_eap_data *thisint){ struct tls_vars *mytls_vars; int res = 0; debug_printf(DEBUG_EVERYTHING, "(TLS-FUNCS) Cleaning up (possible after a failure)!\n"); if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!thisint->eap_data) { debug_printf(DEBUG_NORMAL, "Invalid EAP data in %s()!\n", __FUNCTION__); return XEMALLOC; } mytls_vars = (struct tls_vars *)thisint->eap_data; if (mytls_vars->ssl) { debug_printf(DEBUG_AUTHTYPES, "(EAP-TLS) Calling SSL_shutdown()\n"); res = SSL_shutdown(mytls_vars->ssl); if (res == 0) { /* Need to call it again to complete the shutdown. */ res = SSL_shutdown(mytls_vars->ssl); if (res == 0) { debug_printf(DEBUG_CONFIG, "Couldn't shut down SSL connection. " "We will leak memory!\n"); } } SSL_free(mytls_vars->ssl); mytls_vars->ssl = NULL; } if (mytls_vars->ctx) { debug_printf(DEBUG_AUTHTYPES, "(EAP-TLS) Freeing mytls_vars->ctx!\n"); SSL_CTX_free(mytls_vars->ctx); mytls_vars->ctx = NULL; } if (mytls_vars->sessionkeyconst != NULL) { debug_printf(DEBUG_AUTHTYPES, "(EAP-TLS) Freeing session key const!\n"); free(mytls_vars->sessionkeyconst); mytls_vars->sessionkeyconst = NULL; } return XENONE;}int tls_funcs_cleanup(struct generic_eap_data *thisint){ int err=XENONE; struct tls_vars *mytls_vars; debug_printf(DEBUG_EVERYTHING, "(TLS-FUNCS) Cleaning up!\n"); if (!xsup_assert((thisint != NULL), "thisint != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((thisint->eap_data != NULL), "thisint->eap_data != NULL", FALSE)) return XEMALLOC; mytls_vars = (struct tls_vars *)thisint->eap_data; err = tls_funcs_failed(thisint); if (mytls_vars->engine) { debug_printf(DEBUG_NORMAL, "Cleaning up OpenSSL Engine\n"); ENGINE_finish(mytls_vars->engine); mytls_vars->engine = NULL; debug_printf(DEBUG_NORMAL, "Cleaning up OpenSSL Engine internal ressources\n"); ENGINE_cleanup(); } return err;}/* TLS PRF from rfc2246 pages 11-12 */inttls_funcs_PRF(uint8_t *secret, int secret_len, uint8_t *label, int label_len, uint8_t *seed, int seed_len, uint8_t *output, int outlen){ int retVal = 0; int L_S1, L_S2; uint8_t *S1, *S2; uint8_t *P_MD5_buf, *P_SHA1_buf; uint8_t *P_seed; int P_seed_len; uint8_t A_MD5[MD5_DIGEST_LENGTH]; uint8_t A_SHA1[SHA_DIGEST_LENGTH]; int MD5_iterations, SHA1_iterations; int i, hashed_len; const EVP_MD *hash; HMAC_CTX ctx; if (!xsup_assert((secret != NULL), "secret != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((label != NULL), "label != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((seed != NULL), "seed != NULL", FALSE)) return XEMALLOC; if (!xsup_assert((output != NULL), "output != NULL", FALSE)) return XEMALLOC; /* determine the length of "half" the secret */ if (secret_len % 2 == 0) { L_S1 = secret_len / 2; } else { L_S1 = secret_len / 2 + 1; } L_S2 = L_S1; S1 = secret; /* first L_S1 bytes of secret */ S2 = secret + secret_len - L_S2; /* last L_S2 bytes of secret */ MD5_iterations = outlen / MD5_DIGEST_LENGTH; /* if there is anything left over, iterate 1 more time */ MD5_iterations = outlen % MD5_DIGEST_LENGTH == 0 ? MD5_iterations : MD5_iterations + 1; SHA1_iterations = outlen / SHA_DIGEST_LENGTH; SHA1_iterations = outlen % SHA_DIGEST_LENGTH == 0 ? SHA1_iterations : SHA1_iterations + 1; P_seed_len = label_len + seed_len; P_seed = (uint8_t *)malloc(sizeof(uint8_t) * P_seed_len); if (P_seed == NULL) { debug_printf(DEBUG_NORMAL, "Error with malloc of P_seed in tls_funcs_PRF().\n"); return XEMALLOC; } memcpy(P_seed, label, label_len); memcpy(P_seed+label_len, seed, seed_len); P_MD5_buf = (uint8_t *)malloc(sizeof(uint8_t) * MD5_iterations * MD5_DIGEST_LENGTH); if (P_MD5_buf == NULL) { debug_printf(DEBUG_NORMAL, "Error with malloc of P_MD5_buf in tls_funcs_PRF().\n"); free(P_seed); P_seed = NULL; return XEMALLOC; } P_SHA1_buf = (uint8_t *)malloc(sizeof(uint8_t) * SHA1_iterations * SHA_DIGEST_LENGTH); if (P_SHA1_buf == NULL) { debug_printf(DEBUG_NORMAL, "Error with malloc of P_SHA1_buf in tls_funcs_PRF().\n"); free(P_seed); P_seed = NULL; free(P_MD5_buf); P_MD5_buf = NULL; return XEMALLOC; } /* P_MD5 */ hash = EVP_md5(); /* Initialize A_MD5 */ HMAC(hash, S1, L_S1, P_seed, P_seed_len, A_MD5, (u_int *) &hashed_len); for (i = 0; i < MD5_iterations; i++) { HMAC_Init(&ctx, S1, L_S1, hash); HMAC_Update(&ctx, A_MD5, MD5_DIGEST_LENGTH); HMAC_Update(&ctx, P_seed, P_seed_len); HMAC_Final(&ctx, P_MD5_buf + i*(MD5_DIGEST_LENGTH), (u_int *) &hashed_len); HMAC_cleanup(&ctx); HMAC(hash, S1, L_S1, A_MD5, MD5_DIGEST_LENGTH, A_MD5, (u_int *) &hashed_len); } /* do P_SHA1 */ hash = EVP_sha1(); /* Initialize A_SHA1 */ HMAC(hash, S2, L_S2, P_seed, P_seed_len, A_SHA1, (u_int *) &hashed_len); for (i = 0; i < SHA1_iterations; i++) { HMAC_Init(&ctx, S2, L_S2, hash); HMAC_Update(&ctx, A_SHA1, SHA_DIGEST_LENGTH); HMAC_Update(&ctx, P_seed, P_seed_len); HMAC_Final(&ctx, P_SHA1_buf + i*(SHA_DIGEST_LENGTH), (u_int *) &hashed_len); HMAC_cleanup(&ctx); HMAC(hash, S2, L_S2, A_SHA1, SHA_DIGEST_LENGTH, A_SHA1, (u_int *) &hashed_len); } /* XOR Them for the answer */ for (i = 0; i < outlen; i++) { *(output + i) = P_MD5_buf[i] ^ P_SHA1_buf[i]; } if (P_seed) {free(P_seed); P_seed = NULL;} if (P_MD5_buf) {free(P_MD5_buf); P_MD5_buf = NULL;} if (P_SHA1_buf) {free(P_SHA1_buf); P_SHA1_buf = NULL;} return retVal;}/* smartcard support */#define OPENSC_ENGINE_SO_PATH "/usr/lib/opensc/engine_opensc.so"#define OPENSC_ENGINE_ID "opensc"/* This function * - loads OpenSSL's "dynamic" engine * - executes all the commands given in the pre array of strings * These commands will usually load the shared object, do some * initialization and add the engine to OpenSSL's internal list of * Engines */int engine_load_dynamic(char *pre[]){ char *engine_id = "dynamic"; int rc; ENGINE *e; ENGINE_load_dynamic(); e = ENGINE_by_id(engine_id); if(!e) { printf("can't find engine %s\n", engine_id); goto err; } while(pre && pre[0]) { /*printf("\"%s\" \"%s\"\n", pre[0], pre[1]);*/ rc = ENGINE_ctrl_cmd_string(e, pre[0], pre[1], 0); if(rc == 0) { printf("ctrl cmd_string failed: %s %s\n", pre[0], pre[1]); goto err_pre; } pre += 2; } /* Free the reference to the "dynamic" engine * The OpenSC engine can still be looked up using * ENGINE_by_id() */ ENGINE_free(e); return 1;err_pre: ENGINE_free(e);err: ENGINE_cleanup(); return 0;}/* This function * - makes the opensc engine available to OpenSSL */int engine_load_dynamic_opensc(struct smartcard *sc){ if (xsup_assert((sc != NULL), "sc != NULL", FALSE)) return XEMALLOC; debug_printf(DEBUG_NORMAL, "Loading opensc engine.\n"); if(!sc->opensc_so_path) { /* use the default value */ sc->opensc_so_path = OPENSC_ENGINE_SO_PATH; } char *pre_cmd[] = { "SO_PATH", sc->opensc_so_path, "ID", OPENSC_ENGINE_ID, "LIST_ADD", "1", "LOAD", NULL, NULL, NULL }; return engine_load_dynamic(pre_cmd);}/* provide a UI_METHOD that makes it possible to use a string as the * smartcard PIN */char *smartcard_pin = NULL;void set_smartcard_pin(char *pin){ smartcard_pin = pin;}void unset_smartcard_pin(){ set_smartcard_pin(NULL);}int read_string(UI *ui, UI_STRING *uis){ if(smartcard_pin) { UI_set_result(ui, uis, smartcard_pin); return 1; } return 0;}UI_METHOD *UI_noninteractive(void){ UI_METHOD *ui_method; ui_method = UI_create_method("ui_noninteractive"); UI_method_set_reader(ui_method, read_string); return ui_method;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -