Index: openssl/ssl/ssltest.c |
=================================================================== |
--- openssl/ssl/ssltest.c (revision 105093) |
+++ openssl/ssl/ssltest.c (working copy) |
@@ -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" |
+#ifdef OPENSSL_SYS_VMS |
#define _XOPEN_SOURCE 500 /* Or isascii won't be declared properly on |
VMS (at least with DECompHP C). */ |
+#endif |
+ |
#include <ctype.h> |
#include <openssl/bio.h> |
@@ -207,6 +236,16 @@ |
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; |
@@ -229,9 +268,6 @@ |
{ |
fprintf(stderr,"usage: ssltest [args ...]\n"); |
fprintf(stderr,"\n"); |
-#ifdef OPENSSL_FIPS |
- fprintf(stderr,"-F - run test in FIPS mode\n"); |
-#endif |
fprintf(stderr," -server_auth - check server certificate\n"); |
fprintf(stderr," -client_auth - do client authentication\n"); |
fprintf(stderr," -proxy - allow proxy certificates\n"); |
@@ -250,6 +286,9 @@ |
#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 |
@@ -277,12 +316,14 @@ |
" (default is sect163r2).\n"); |
#endif |
fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n"); |
- fprintf(stderr," -cutthrough - enable 1-RTT full-handshake for strong ciphers\n"); |
+ fprintf(stderr," -c_small_records - enable client side use of small SSL record buffers\n"); |
+ fprintf(stderr," -s_small_records - enable server side use of small SSL record buffers\n"); |
+ fprintf(stderr," -cutthrough - enable 1-RTT full-handshake for strong ciphers\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); |
@@ -387,7 +428,30 @@ |
} |
} |
+#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 ssl_mode = 0; |
+ int c_small_records=0; |
+ int s_small_records=0; |
+ int cutthrough = 0; |
+ |
int main(int argc, char *argv[]) |
{ |
char *CApath=NULL,*CAfile=NULL; |
@@ -408,19 +472,20 @@ |
#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; |
#ifndef OPENSSL_NO_DH |
DH *dh; |
- int dhe1024 = 1, dhe1024dsa = 0; |
+ int dhe1024 = 0, dhe1024dsa = 0; |
#endif |
#ifndef OPENSSL_NO_ECDH |
EC_KEY *ecdh = NULL; |
#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; |
@@ -429,17 +494,12 @@ |
#endif |
STACK_OF(SSL_COMP) *ssl_comp_methods = NULL; |
int test_cipherlist = 0; |
-#ifdef OPENSSL_FIPS |
- int fips_mode=0; |
-#endif |
- int ssl_mode = 0; |
- int cutthrough = 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); |
@@ -458,23 +518,14 @@ |
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++; |
while (argc >= 1) |
{ |
- if(!strcmp(*argv,"-F")) |
- { |
-#ifdef OPENSSL_FIPS |
- fips_mode=1; |
-#else |
- fprintf(stderr,"not compiled with FIPS support, so exitting without running.\n"); |
- EXIT(0); |
-#endif |
- } |
- else if (strcmp(*argv,"-server_auth") == 0) |
+ if (strcmp(*argv,"-server_auth") == 0) |
server_auth=1; |
else if (strcmp(*argv,"-client_auth") == 0) |
client_auth=1; |
@@ -514,6 +565,20 @@ |
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) |
@@ -622,6 +687,14 @@ |
{ |
test_cipherlist = 1; |
} |
+ else if (strcmp(*argv, "-c_small_records") == 0) |
+ { |
+ c_small_records = 1; |
+ } |
+ else if (strcmp(*argv, "-s_small_records") == 0) |
+ { |
+ s_small_records = 1; |
+ } |
else if (strcmp(*argv, "-cutthrough") == 0) |
{ |
cutthrough = 1; |
@@ -660,20 +733,6 @@ |
EXIT(1); |
} |
-#ifdef OPENSSL_FIPS |
- if(fips_mode) |
- { |
- if(!FIPS_mode_set(1)) |
- { |
- ERR_load_crypto_strings(); |
- ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); |
- EXIT(1); |
- } |
- else |
- fprintf(stderr,"*** IN FIPS MODE ***\n"); |
- } |
-#endif |
- |
if (print_time) |
{ |
if (!bio_pair) |
@@ -761,7 +820,22 @@ |
SSL_CTX_set_cipher_list(c_ctx,cipher); |
SSL_CTX_set_cipher_list(s_ctx,cipher); |
} |
+ |
ssl_mode = 0; |
+ if (c_small_records) |
+ { |
+ ssl_mode = SSL_CTX_get_mode(c_ctx); |
+ ssl_mode |= SSL_MODE_SMALL_BUFFERS; |
+ SSL_CTX_set_mode(c_ctx, ssl_mode); |
+ } |
+ ssl_mode = 0; |
+ if (s_small_records) |
+ { |
+ ssl_mode = SSL_CTX_get_mode(s_ctx); |
+ ssl_mode |= SSL_MODE_SMALL_BUFFERS; |
+ SSL_CTX_set_mode(s_ctx, ssl_mode); |
+ } |
+ ssl_mode = 0; |
if (cutthrough) |
{ |
ssl_mode = SSL_CTX_get_mode(c_ctx); |
@@ -825,6 +899,13 @@ |
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); |
@@ -876,6 +957,31 @@ |
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); |
@@ -952,7 +1058,7 @@ |
#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); |
@@ -1365,7 +1471,6 @@ |
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; |
@@ -1400,8 +1505,6 @@ |
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 */ |
@@ -2102,7 +2205,15 @@ |
} |
#ifndef OPENSSL_NO_X509_VERIFY |
+# ifdef OPENSSL_FIPS |
+ if(s->version == TLS1_VERSION) |
+ FIPS_allow_md5(1); |
+# endif |
ok = X509_verify_cert(ctx); |
+# ifdef OPENSSL_FIPS |
+ if(s->version == TLS1_VERSION) |
+ FIPS_allow_md5(0); |
+# endif |
#endif |
if (cb_arg->proxy_auth) |
@@ -2271,11 +2382,74 @@ |
} |
#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; |
- SSL_CIPHER *ci, *tci = NULL; |
+ const SSL_CIPHER *ci, *tci = NULL; |
#ifndef OPENSSL_NO_SSL2 |
fprintf(stderr, "testing SSLv2 cipher list order: "); |