X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssltest.c;h=175635881daf50702cc490df19cea99c39d38078;hp=bbfbfc9b38b9711ef3a8cab4ef23ffc290f1f6f8;hb=d135da51922dc756ab42643099de96728891f1d4;hpb=35e8510e60ef0b033b304289db28a3cb19c6cbdd diff --git a/ssl/ssltest.c b/ssl/ssltest.c index bbfbfc9b38..175635881d 100644 --- a/ssl/ssltest.c +++ b/ssl/ssltest.c @@ -113,6 +113,32 @@ * ECC cipher suite support in OpenSSL originally developed by * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ #define _BSD_SOURCE 1 /* Or gethostname won't be declared properly on Linux and GNU platforms. */ @@ -128,8 +154,11 @@ #define USE_SOCKETS #include "e_os.h" -#define _XOPEN_SOURCE 1 /* Or isascii won't be declared properly on +#ifdef OPENSSL_SYS_VMS +#define _XOPEN_SOURCE 500 /* Or isascii won't be declared properly on VMS (at least with DECompHP C). */ +#endif + #include #include @@ -143,9 +172,15 @@ #endif #include #include +#ifndef OPENSSL_NO_RSA #include +#endif +#ifndef OPENSSL_NO_DSA #include +#endif +#ifndef OPENSSL_NO_DH #include +#endif #include #define _XOPEN_SOURCE_EXTENDED 1 /* Or gethostname won't be declared properly @@ -201,6 +236,16 @@ static DH *get_dh1024(void); static DH *get_dh1024dsa(void); #endif + +static char *psk_key=NULL; /* by default PSK is not used */ +#ifndef OPENSSL_NO_PSK +static unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identity, + unsigned int max_identity_len, unsigned char *psk, + unsigned int max_psk_len); +static unsigned int psk_server_callback(SSL *ssl, const char *identity, unsigned char *psk, + unsigned int max_psk_len); +#endif + static BIO *bio_err=NULL; static BIO *bio_stdout=NULL; @@ -218,6 +263,7 @@ static const char rnd_seed[] = "string to make the random number generator think int doit_biopair(SSL *s_ssl,SSL *c_ssl,long bytes,clock_t *s_time,clock_t *c_time); int doit(SSL *s_ssl,SSL *c_ssl,long bytes); +static int do_test_cipherlist(void); static void sv_usage(void) { fprintf(stderr,"usage: ssltest [args ...]\n"); @@ -240,6 +286,9 @@ static void sv_usage(void) #ifndef OPENSSL_NO_ECDH fprintf(stderr," -no_ecdhe - disable ECDHE\n"); #endif +#ifndef OPENSSL_NO_PSK + fprintf(stderr," -psk arg - PSK in hex (without 0x)\n"); +#endif #ifndef OPENSSL_NO_SSL2 fprintf(stderr," -ssl2 - use SSLv2\n"); #endif @@ -266,11 +315,12 @@ static void sv_usage(void) " Use \"openssl ecparam -list_curves\" for all names\n" \ " (default is sect163r2).\n"); #endif + fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n"); } static void print_details(SSL *c_ssl, const char *prefix) { - SSL_CIPHER *ciph; + const SSL_CIPHER *ciph; X509 *cert; ciph=SSL_get_current_cipher(c_ssl); @@ -375,6 +425,26 @@ static void lock_dbg_cb(int mode, int type, const char *file, int line) } } +#ifdef TLSEXT_TYPE_opaque_prf_input +struct cb_info_st { void *input; size_t len; int ret; }; +struct cb_info_st co1 = { "C", 1, 1 }; /* try to negotiate oqaque PRF input */ +struct cb_info_st co2 = { "C", 1, 2 }; /* insist on oqaque PRF input */ +struct cb_info_st so1 = { "S", 1, 1 }; /* try to negotiate oqaque PRF input */ +struct cb_info_st so2 = { "S", 1, 2 }; /* insist on oqaque PRF input */ + +int opaque_prf_input_cb(SSL *ssl, void *peerinput, size_t len, void *arg_) + { + struct cb_info_st *arg = arg_; + + if (arg == NULL) + return 1; + + if (!SSL_set_tlsext_opaque_prf_input(ssl, arg->input, arg->len)) + return 0; + return arg->ret; + } +#endif + int main(int argc, char *argv[]) { char *CApath=NULL,*CAfile=NULL; @@ -390,10 +460,12 @@ int main(int argc, char *argv[]) char *server_key=NULL; char *client_cert=TEST_CLIENT_CERT; char *client_key=NULL; +#ifndef OPENSSL_NO_ECDH char *named_curve = NULL; +#endif SSL_CTX *s_ctx=NULL; SSL_CTX *c_ctx=NULL; - SSL_METHOD *meth=NULL; + const SSL_METHOD *meth=NULL; SSL *c_ssl,*s_ssl; int number=1,reuse=0; long bytes=256L; @@ -406,17 +478,21 @@ int main(int argc, char *argv[]) #endif int no_dhe = 0; int no_ecdhe = 0; + int no_psk = 0; int print_time = 0; clock_t s_time = 0, c_time = 0; int comp = 0; +#ifndef OPENSSL_NO_COMP COMP_METHOD *cm = NULL; STACK_OF(SSL_COMP) *ssl_comp_methods = NULL; +#endif + int test_cipherlist = 0; verbose = 0; debug = 0; cipher = 0; - bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); + bio_err=BIO_new_fp(stderr,BIO_NOCLOSE|BIO_FP_TEXT); CRYPTO_set_locking_callback(lock_dbg_cb); @@ -435,7 +511,7 @@ int main(int argc, char *argv[]) RAND_seed(rnd_seed, sizeof rnd_seed); - bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE); + bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE|BIO_FP_TEXT); argc--; argv++; @@ -482,6 +558,20 @@ int main(int argc, char *argv[]) no_dhe=1; else if (strcmp(*argv,"-no_ecdhe") == 0) no_ecdhe=1; + else if (strcmp(*argv,"-psk") == 0) + { + if (--argc < 1) goto bad; + psk_key=*(++argv); +#ifndef OPENSSL_NO_PSK + if (strspn(psk_key, "abcdefABCDEF1234567890") != strlen(psk_key)) + { + BIO_printf(bio_err,"Not a hex number '%s'\n",*argv); + goto bad; + } +#else + no_psk=1; +#endif + } else if (strcmp(*argv,"-ssl2") == 0) ssl2=1; else if (strcmp(*argv,"-tls1") == 0) @@ -586,6 +676,10 @@ int main(int argc, char *argv[]) { app_verify_arg.allow_proxy_certs = 1; } + else if (strcmp(*argv,"-test_cipherlist") == 0) + { + test_cipherlist = 1; + } else { fprintf(stderr,"unknown option %s\n",*argv); @@ -602,6 +696,15 @@ bad: goto end; } + if (test_cipherlist == 1) + { + /* ensure that the cipher list are correctly sorted and exit */ + if (do_test_cipherlist() == 0) + EXIT(1); + ret = 0; + goto end; + } + if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force) { fprintf(stderr, "This case cannot work. Use -f to perform " @@ -627,6 +730,7 @@ bad: SSL_library_init(); SSL_load_error_strings(); +#ifndef OPENSSL_NO_COMP if (comp == COMP_ZLIB) cm = COMP_zlib(); if (comp == COMP_RLE) cm = COMP_rle(); if (cm != NULL) @@ -663,6 +767,7 @@ bad: fprintf(stderr, " %d: %s\n", c->id, c->name); } } +#endif #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) if (ssl2) @@ -720,36 +825,30 @@ bad: #ifndef OPENSSL_NO_ECDH if (!no_ecdhe) { - ecdh = EC_KEY_new(); - if (ecdh != NULL) - { - if (named_curve) - { - int nid = OBJ_sn2nid(named_curve); + int nid; - if (nid == 0) - { - BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve); - EC_KEY_free(ecdh); - goto end; - } - - ecdh->group = EC_GROUP_new_by_curve_name(nid); - if (ecdh->group == NULL) - { - BIO_printf(bio_err, "unable to create curve (%s)\n", named_curve); - EC_KEY_free(ecdh); - goto end; - } + if (named_curve != NULL) + { + nid = OBJ_sn2nid(named_curve); + if (nid == 0) + { + BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve); + goto end; } - - if (ecdh->group == NULL) - ecdh->group=EC_GROUP_new_by_curve_name(NID_sect163r2); + } + else + nid = NID_sect163r2; - SSL_CTX_set_tmp_ecdh(s_ctx, ecdh); - SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE); - EC_KEY_free(ecdh); + ecdh = EC_KEY_new_by_curve_name(nid); + if (ecdh == NULL) + { + BIO_printf(bio_err, "unable to create curve\n"); + goto end; } + + SSL_CTX_set_tmp_ecdh(s_ctx, ecdh); + SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE); + EC_KEY_free(ecdh); } #else (void)no_ecdhe; @@ -759,6 +858,13 @@ bad: SSL_CTX_set_tmp_rsa_callback(s_ctx,tmp_rsa_cb); #endif +#ifdef TLSEXT_TYPE_opaque_prf_input + SSL_CTX_set_tlsext_opaque_prf_input_callback(c_ctx, opaque_prf_input_cb); + SSL_CTX_set_tlsext_opaque_prf_input_callback(s_ctx, opaque_prf_input_cb); + SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(c_ctx, &co1); /* or &co2 or NULL */ + SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(s_ctx, &so1); /* or &so2 or NULL */ +#endif + if (!SSL_CTX_use_certificate_file(s_ctx,server_cert,SSL_FILETYPE_PEM)) { ERR_print_errors(bio_err); @@ -810,6 +916,31 @@ bad: SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, sizeof session_id_context); } + /* Use PSK only if PSK key is given */ + if (psk_key != NULL) + { + /* no_psk is used to avoid putting psk command to openssl tool */ + if (no_psk) + { + /* if PSK is not compiled in and psk key is + * given, do nothing and exit successfully */ + ret=0; + goto end; + } +#ifndef OPENSSL_NO_PSK + SSL_CTX_set_psk_client_callback(c_ctx, psk_client_callback); + SSL_CTX_set_psk_server_callback(s_ctx, psk_server_callback); + if (debug) + BIO_printf(bio_err,"setting PSK identity hint to s_ctx\n"); + if (!SSL_CTX_use_psk_identity_hint(s_ctx, "ctx server identity_hint")) + { + BIO_printf(bio_err,"error setting PSK identity hint to s_ctx\n"); + ERR_print_errors(bio_err); + goto end; + } +#endif + } + c_ssl=SSL_new(c_ctx); s_ssl=SSL_new(s_ctx); @@ -886,11 +1017,12 @@ end: #endif CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); - ERR_remove_state(0); + ERR_remove_thread_state(NULL); EVP_cleanup(); CRYPTO_mem_leaks(bio_err); if (bio_err != NULL) BIO_free(bio_err); EXIT(ret); + return ret; } int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, @@ -1298,7 +1430,6 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) BIO *c_bio=NULL; BIO *s_bio=NULL; int c_r,c_w,s_r,s_w; - int c_want,s_want; int i,j; int done=0; int c_write,s_write; @@ -1333,8 +1464,6 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) c_r=0; s_r=1; c_w=1; s_w=0; - c_want=W_WRITE; - s_want=0; c_write=1,s_write=0; /* We can always do writes */ @@ -1700,7 +1829,7 @@ static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) fprintf(stderr, " Certificate proxy rights = %*.*s", i, i, s); while(i-- > 0) { - char c = *s++; + int c = *s++; if (isascii(c) && isalpha(c)) { if (islower(c)) @@ -1761,11 +1890,11 @@ static int process_proxy_cond_adders(unsigned int letters[26], static int process_proxy_cond_val(unsigned int letters[26], const char *cond, const char **cond_end, int *pos, int indent) { - char c; + int c; int ok = 1; int negate = 0; - while(isspace(*cond)) + while(isspace((int)*cond)) { cond++; (*pos)++; } @@ -1780,7 +1909,7 @@ static int process_proxy_cond_val(unsigned int letters[26], { negate = !negate; cond++; (*pos)++; - while(isspace(*cond)) + while(isspace((int)*cond)) { cond++; (*pos)++; } @@ -1795,7 +1924,7 @@ static int process_proxy_cond_val(unsigned int letters[26], cond = *cond_end; if (ok < 0) goto end; - while(isspace(*cond)) + while(isspace((int)*cond)) { cond++; (*pos)++; } @@ -1855,7 +1984,7 @@ static int process_proxy_cond_multipliers(unsigned int letters[26], while(ok >= 0) { - while(isspace(*cond)) + while(isspace((int)*cond)) { cond++; (*pos)++; } @@ -1922,7 +2051,7 @@ static int process_proxy_cond_adders(unsigned int letters[26], while(ok >= 0) { - while(isspace(*cond)) + while(isspace((int)*cond)) { cond++; (*pos)++; } @@ -1987,7 +2116,7 @@ static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg) fprintf(stderr, "In app_verify_callback, allowing cert. "); fprintf(stderr, "Arg is: %s\n", cb_arg->string); fprintf(stderr, "Finished printing do we have a context? 0x%p a cert? 0x%p\n", - ctx, ctx->cert); + (void *)ctx, (void *)ctx->cert); if (ctx->cert) s=X509_NAME_oneline(X509_get_subject_name(ctx->cert),buf,256); if (s != NULL) @@ -2005,7 +2134,7 @@ static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg) letters[i] = 0; for(sp = cb_arg->proxy_auth; *sp; sp++) { - char c = *sp; + int c = *sp; if (isascii(c) && isalpha(c)) { if (islower(c)) @@ -2048,7 +2177,7 @@ static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg) if (cb_arg->proxy_auth) { - if (ok) + if (ok > 0) { const char *cond_end = NULL; @@ -2211,3 +2340,123 @@ static DH *get_dh1024dsa() return(dh); } #endif + +#ifndef OPENSSL_NO_PSK +/* convert the PSK key (psk_key) in ascii to binary (psk) */ +static int psk_key2bn(const char *pskkey, unsigned char *psk, + unsigned int max_psk_len) + { + int ret; + BIGNUM *bn = NULL; + + ret = BN_hex2bn(&bn, pskkey); + if (!ret) + { + BIO_printf(bio_err,"Could not convert PSK key '%s' to BIGNUM\n", pskkey); + if (bn) + BN_free(bn); + return 0; + } + if (BN_num_bytes(bn) > (int)max_psk_len) + { + BIO_printf(bio_err,"psk buffer of callback is too small (%d) for key (%d)\n", + max_psk_len, BN_num_bytes(bn)); + BN_free(bn); + return 0; + } + ret = BN_bn2bin(bn, psk); + BN_free(bn); + return ret; + } + +static unsigned int psk_client_callback(SSL *ssl, const char *hint, char *identity, + unsigned int max_identity_len, unsigned char *psk, + unsigned int max_psk_len) + { + int ret; + unsigned int psk_len = 0; + + ret = BIO_snprintf(identity, max_identity_len, "Client_identity"); + if (ret < 0) + goto out_err; + if (debug) + fprintf(stderr, "client: created identity '%s' len=%d\n", identity, ret); + ret = psk_key2bn(psk_key, psk, max_psk_len); + if (ret < 0) + goto out_err; + psk_len = ret; +out_err: + return psk_len; + } + +static unsigned int psk_server_callback(SSL *ssl, const char *identity, + unsigned char *psk, unsigned int max_psk_len) + { + unsigned int psk_len=0; + + if (strcmp(identity, "Client_identity") != 0) + { + BIO_printf(bio_err, "server: PSK error: client identity not found\n"); + return 0; + } + psk_len=psk_key2bn(psk_key, psk, max_psk_len); + return psk_len; + } +#endif + +static int do_test_cipherlist(void) + { + int i = 0; + const SSL_METHOD *meth; + const SSL_CIPHER *ci, *tci = NULL; + +#ifndef OPENSSL_NO_SSL2 + fprintf(stderr, "testing SSLv2 cipher list order: "); + meth = SSLv2_method(); + while ((ci = meth->get_cipher(i++)) != NULL) + { + if (tci != NULL) + if (ci->id >= tci->id) + { + fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id); + return 0; + } + tci = ci; + } + fprintf(stderr, "ok\n"); +#endif +#ifndef OPENSSL_NO_SSL3 + fprintf(stderr, "testing SSLv3 cipher list order: "); + meth = SSLv3_method(); + tci = NULL; + while ((ci = meth->get_cipher(i++)) != NULL) + { + if (tci != NULL) + if (ci->id >= tci->id) + { + fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id); + return 0; + } + tci = ci; + } + fprintf(stderr, "ok\n"); +#endif +#ifndef OPENSSL_NO_TLS1 + fprintf(stderr, "testing TLSv1 cipher list order: "); + meth = TLSv1_method(); + tci = NULL; + while ((ci = meth->get_cipher(i++)) != NULL) + { + if (tci != NULL) + if (ci->id >= tci->id) + { + fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id); + return 0; + } + tci = ci; + } + fprintf(stderr, "ok\n"); +#endif + + return 1; + }