📄 ossl_tls_funcs.c
字号:
}
/***********************************************************************
*
* Return the password for our user certificate.
*
***********************************************************************/
static int return_password(char *buf, int size, int rwflag, void *userdata)
{
TRACE
if (!xsup_assert((buf != NULL), "buf != NULL", FALSE))
return XEMALLOC;
if (!xsup_assert((userdata != NULL), "userdata != NULL", FALSE))
return XEMALLOC;
if (Strncpy(buf, size, (char *)(userdata), size) != 0)
{
debug_printf(DEBUG_NORMAL, "Attempt to overflow a buffer in %s() at %d!\n",
__FUNCTION__, __LINE__);
return -1;
}
buf[size-1] = '\0';
return(strlen(buf));
}
/**************************************************************************
*
* Load any root certificates that the user would want to use.
*
**************************************************************************/
int tls_funcs_load_root_certs(struct tls_vars *mytls_vars, char *root_cert,
char *root_dir, char *crl_dir)
{
TRACE
if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
return XEMALLOC;
if (!xsup_assert((mytls_vars->ctx != NULL), "mytls_vars->ctx != NULL",
FALSE))
return XEMALLOC;
if ((!root_cert) && (!root_dir))
{
debug_printf(DEBUG_NORMAL, "Error loading cert! Path to cert is NULL!\n");
return XETLSCERTLOAD;
}
if (mytls_vars->ctx == NULL)
{
debug_printf(DEBUG_NORMAL, "Invalid context in tls_funcs_load_root_certs()!\n");
return XEMALLOC;
}
debug_printf(DEBUG_TLS_CORE, "Trying to load root certificate %s or "
"certificate directory %s\n", root_cert, root_dir);
SSL_CTX_set_info_callback(mytls_vars->ctx, (void (*) (const SSL *, int, int)) ssl_info_callback);
if (SSL_CTX_load_verify_locations(mytls_vars->ctx, root_cert, root_dir) == 0)
{
debug_printf(DEBUG_NORMAL, "Failed to initialize path to root certificate!\n");
tls_funcs_process_error();
if(mytls_vars->ctx)
{
SSL_CTX_free(mytls_vars->ctx);
mytls_vars->ctx = NULL;
}
return XETLSCERTLOAD;
}
debug_printf(DEBUG_TLS_CORE, "Loaded root certificate %s and directory %s\n",
root_cert, root_dir);
if (crl_dir) {
if (SSL_CTX_load_verify_locations(mytls_vars->ctx, NULL, crl_dir) == 0)
{
debug_printf(DEBUG_NORMAL, "Failed to initalize path to CRLs!\n");
tls_funcs_process_error();
//debug_printf(DEBUG_NORMAL, "Error : %s\n", ERR_error_string(ERR_get_error(), NULL));
if(mytls_vars->ctx)
{
SSL_CTX_free(mytls_vars->ctx);
mytls_vars->ctx = NULL;
}
return XETLSCERTLOAD;
}
}
/* Do we really want to pick up the default paths? */
if (SSL_CTX_set_default_verify_paths(mytls_vars->ctx) == 0)
{
debug_printf(DEBUG_NORMAL, "Failed to initalize default paths for root certificates!\n");
tls_funcs_process_error();
if(mytls_vars->ctx)
{
SSL_CTX_free(mytls_vars->ctx);
mytls_vars->ctx = NULL;
}
return XETLSCERTLOAD;
}
return XENONE;
}
/*************************************************************************
*
* Use a file to load some random data.
*
*************************************************************************/
int tls_funcs_load_random(struct tls_vars *mytls_vars, char *random_file)
{
char *default_random = "/dev/urandom", *file;
TRACE
if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
return XEMALLOC;
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;
}
/***************************************************************************
*
* Load a user certificate in to OpenSSL so that it can be used for
* authentication.
*
***************************************************************************/
int tls_funcs_load_user_cert(struct tls_vars *mytls_vars,
char *client_cert, char *key_file, char *password)
{
TRACE
if (!xsup_assert((mytls_vars != NULL), "mytls_vars != 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;
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_TLS_CORE, "Loading user Private Key from %s...\n", key_file);
// XXX Add back support for smart card based TLS.
/*
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);
if (mytls_vars->verify_cert == TRUE)
{
SSL_CTX_set_verify(mytls_vars->ctx, SSL_VERIFY_PEER |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
}
else
{
SSL_CTX_set_verify(mytls_vars->ctx, SSL_VERIFY_NONE |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
}
return XENONE;
}
/* TLS PRF from rfc2246 pages 11-12 */
int
ossl_tls_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;
TRACE
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");
ipc_events_malloc_failed(NULL);
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");
ipc_events_malloc_failed(NULL);
FREE(P_seed);
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");
ipc_events_malloc_failed(NULL);
FREE(P_seed);
FREE(P_MD5_buf);
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];
}
FREE(P_seed);
FREE(P_MD5_buf);
FREE(P_SHA1_buf);
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
*/
#ifndef WINDOWS
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;
}
#endif // WINDOWS
/* This function
* - makes the opensc engine available to OpenSSL
*/
#ifndef WINDOWS
int engine_load_dynamic_opensc(struct smartcard *sc)
{
char *pre_cmd[] =
{
"SO_PATH", sc->opensc_so_path,
"ID", OPENSC_ENGINE_ID,
"LIST_ADD", "1",
"LOAD", NULL,
NULL, NULL
};
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;
}
return engine_load_dynamic(pre_cmd);
}
#endif // WINDOWS
/* 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;
}
/**********************************************************************
*
* Generate a key block to be used to derive keys.
*
**********************************************************************/
uint8_t *tls_funcs_gen_keyblock(struct tls_vars *mytls_vars, uint8_t first,
uint8_t *sesskey, uint16_t sesskeylen)
{
uint8_t seed[SSL3_RANDOM_SIZE*2];
uint8_t *p = seed;
uint8_t *retblock;
TRACE
debug_printf(DEBUG_TLS_CORE, "Generating key block!\n");
if (!xsup_assert((mytls_vars != NULL), "mytls_vars != NULL", FALSE))
return NULL;
if (sesskey == NULL)
{
debug_printf(DEBUG_NORMAL, "No keying material is available! It is "
"unlikely that your session will work properly.\n");
return NULL;
}
if (!mytls_vars->ssl)
{
debug_printf(DEBUG_NORMAL, "No valid SSL context found!\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -