Add TLS exporter.

This commit is contained in:
Ben Laurie 2011-11-15 23:50:52 +00:00
parent 333f926d67
commit e0af04056c
12 changed files with 212 additions and 3 deletions

View File

@ -198,6 +198,9 @@
security.
[Emilia Käsper <emilia.kasper@esat.kuleuven.be> (Google)]
*) Add TLS key material exporter from RFC 5705.
[Eric Rescorla]
*) Add DTLS-SRTP negotiation from RFC 5764.
[Eric Rescorla]

View File

@ -206,6 +206,9 @@ static int c_status_req=0;
static int c_msg=0;
static int c_showcerts=0;
static char *keymatexportlabel=NULL;
static int keymatexportlen=20;
static void sc_usage(void);
static void print_stuff(BIO *berr,SSL *con,int full);
#ifndef OPENSSL_NO_TLSEXT
@ -360,6 +363,8 @@ static void sc_usage(void)
#endif
BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n");
BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list");
BIO_printf(bio_err," -keymatexport label - Export keying material using label\n");
BIO_printf(bio_err," -keymatexportlen len - Export len bytes of keying material (default 20)\n");
}
#ifndef OPENSSL_NO_TLSEXT
@ -942,6 +947,17 @@ int MAIN(int argc, char **argv)
if (--argc < 1) goto bad;
srtp_profiles = *(++argv);
}
else if (strcmp(*argv,"-keymatexport") == 0)
{
if (--argc < 1) goto bad;
keymatexportlabel= *(++argv);
}
else if (strcmp(*argv,"-keymatexportlen") == 0)
{
if (--argc < 1) goto bad;
keymatexportlen=atoi(*(++argv));
if (keymatexportlen == 0) goto bad;
}
else
{
BIO_printf(bio_err,"unknown option %s\n",*argv);
@ -1900,6 +1916,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
#ifndef OPENSSL_NO_COMP
const COMP_METHOD *comp, *expansion;
#endif
unsigned char *exportedkeymat;
if (full)
{
@ -2045,6 +2062,30 @@ static void print_stuff(BIO *bio, SSL *s, int full)
}
SSL_SESSION_print(bio,SSL_get_session(s));
if (keymatexportlabel != NULL) {
BIO_printf(bio, "Keying material exporter:\n");
BIO_printf(bio, " Label: '%s'\n", keymatexportlabel);
BIO_printf(bio, " Length: %i bytes\n", keymatexportlen);
exportedkeymat = OPENSSL_malloc(keymatexportlen);
if (exportedkeymat != NULL) {
i = SSL_export_keying_material(s, exportedkeymat,
keymatexportlen,
keymatexportlabel,
strlen(keymatexportlabel),
NULL, 0, 0);
if (i != keymatexportlen) {
BIO_printf(bio,
" Error: return value %i\n", i);
} else {
BIO_printf(bio, " Keying material: ");
for (i=0; i<keymatexportlen; i++)
BIO_printf(bio, "%02X",
exportedkeymat[i]);
BIO_printf(bio, "\n");
}
OPENSSL_free(exportedkeymat);
}
}
BIO_printf(bio,"---\n");
if (peer != NULL)
X509_free(peer);

View File

@ -297,6 +297,9 @@ static int no_resume_ephemeral = 0;
static int s_msg=0;
static int s_quiet=0;
static char *keymatexportlabel=NULL;
static int keymatexportlen=20;
static int hack=0;
#ifndef OPENSSL_NO_ENGINE
static char *engine_id=NULL;
@ -548,6 +551,8 @@ static void sv_usage(void)
# endif
BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list");
#endif
BIO_printf(bio_err," -keymatexport label - Export keying material using label\n");
BIO_printf(bio_err," -keymatexportlen len - Export len bytes of keying material (default 20)\n");
}
static int local_argc=0;
@ -1332,6 +1337,17 @@ int MAIN(int argc, char *argv[])
if (--argc < 1) goto bad;
srtp_profiles = *(++argv);
}
else if (strcmp(*argv,"-keymatexport") == 0)
{
if (--argc < 1) goto bad;
keymatexportlabel= *(++argv);
}
else if (strcmp(*argv,"-keymatexportlen") == 0)
{
if (--argc < 1) goto bad;
keymatexportlen=atoi(*(++argv));
if (keymatexportlen == 0) goto bad;
}
else
{
BIO_printf(bio_err,"unknown option %s\n",*argv);
@ -2354,6 +2370,8 @@ static int init_ssl_connection(SSL *con)
#ifndef OPENSSL_NO_KRB5
char *client_princ;
#endif
unsigned char *exportedkeymat;
if ((i=SSL_accept(con)) <= 0)
{
@ -2425,6 +2443,32 @@ static int init_ssl_connection(SSL *con)
#endif /* OPENSSL_NO_KRB5 */
BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n",
SSL_get_secure_renegotiation_support(con) ? "" : " NOT");
if (keymatexportlabel != NULL) {
BIO_printf(bio_s_out, "Keying material exporter:\n");
BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel);
BIO_printf(bio_s_out, " Length: %i bytes\n",
keymatexportlen);
exportedkeymat = OPENSSL_malloc(keymatexportlen);
if (exportedkeymat != NULL) {
i = SSL_export_keying_material(con, exportedkeymat,
keymatexportlen,
keymatexportlabel,
strlen(keymatexportlabel),
NULL, 0, 0);
if (i != keymatexportlen) {
BIO_printf(bio_s_out,
" Error: return value %i\n", i);
} else {
BIO_printf(bio_s_out, " Keying material: ");
for (i=0; i<keymatexportlen; i++)
BIO_printf(bio_s_out, "%02X",
exportedkeymat[i]);
BIO_printf(bio_s_out, "\n");
}
OPENSSL_free(exportedkeymat);
}
}
return(1);
}

View File

@ -82,6 +82,7 @@ SSL3_ENC_METHOD DTLSv1_enc_data={
TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
};
long dtls1_default_timeout(void)

View File

@ -2904,6 +2904,9 @@ SSL3_ENC_METHOD SSLv3_enc_data={
SSL3_MD_CLIENT_FINISHED_CONST,4,
SSL3_MD_SERVER_FINISHED_CONST,4,
ssl3_alert_code,
(int (*)(SSL *, unsigned char *, unsigned int, const char *,
unsigned int, const unsigned char *, unsigned int,
int use_context))ssl_undefined_function,
};
long ssl3_default_timeout(void)

View File

@ -2259,6 +2259,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_CHANGE_CIPHER_STATE 209
#define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT 274
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 312
#define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT 275
#define SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT 276
#define SSL_F_TLS1_PRF 284
@ -2513,6 +2514,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112
#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110
#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232
#define SSL_R_TLS_ILLEGAL_EXPORTER_LABEL 367
#define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 157
#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 234

View File

@ -277,6 +277,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE), "TLS1_CHANGE_CIPHER_STATE"},
{ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT), "TLS1_CHECK_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
{ERR_FUNC(SSL_F_TLS1_EXPORT_KEYING_MATERIAL), "TLS1_EXPORT_KEYING_MATERIAL"},
{ERR_FUNC(SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT), "TLS1_PREPARE_CLIENTHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT), "TLS1_PREPARE_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_TLS1_PRF), "tls1_prf"},
@ -534,6 +535,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME),"tlsv1 unrecognized name"},
{ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION),"tlsv1 unsupported extension"},
{ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"},
{ERR_REASON(SSL_R_TLS_ILLEGAL_EXPORTER_LABEL),"tls illegal exporter label"},
{ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"},
{ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"},
{ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG),"tls rsa encrypted value length is wrong"},

View File

@ -177,7 +177,10 @@ SSL3_ENC_METHOD ssl3_undef_enc_method={
0, /* client_finished_label_len */
NULL, /* server_finished_label */
0, /* server_finished_label_len */
(int (*)(int))ssl_undefined_function
(int (*)(int))ssl_undefined_function,
(int (*)(SSL *, unsigned char *, unsigned int, const char *,
unsigned int, const unsigned char *, unsigned int,
int use_context))ssl_undefined_function,
};
int SSL_clear(SSL *s)
@ -1627,6 +1630,17 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned
# endif
#endif
int SSL_export_keying_material(SSL *s, unsigned char *out, int olen,
char *label, int llen, unsigned char *p, int plen, int use_context)
{
if (s->version < TLS1_VERSION)
return -1;
return s->method->ssl3_enc->export_keying_material(s, out, olen, label,
llen, p, plen,
use_context);
}
static unsigned long ssl_session_hash(const SSL_SESSION *a)
{
unsigned long l;

View File

@ -569,6 +569,10 @@ typedef struct ssl3_enc_method
const char *server_finished_label;
int server_finished_label_len;
int (*alert_value)(int);
int (*export_keying_material)(SSL *, unsigned char *, unsigned int,
const char *, unsigned int,
const unsigned char *, unsigned int,
int use_context);
} SSL3_ENC_METHOD;
#ifndef OPENSSL_NO_COMP
@ -1055,6 +1059,9 @@ int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
int tls1_mac(SSL *ssl, unsigned char *md, int snd);
int tls1_generate_master_secret(SSL *s, unsigned char *out,
unsigned char *p, int len);
int tls1_export_keying_material(SSL *s, unsigned char *out, unsigned int olen,
const char *label, unsigned int llen, const unsigned char *p,
unsigned int plen, int use_context);
int tls1_alert_code(int code);
int ssl3_alert_code(int code);
int ssl_ok(SSL *s);

View File

@ -1119,6 +1119,95 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
return(SSL3_MASTER_SECRET_SIZE);
}
int tls1_export_keying_material(SSL *s, unsigned char *out, unsigned int olen,
const char *label, unsigned int llen, const unsigned char *context,
unsigned int contextlen, int use_context)
{
unsigned char *buff;
unsigned char *val;
unsigned int vallen, currentvalpos, rv;
#ifdef KSSL_DEBUG
printf ("tls1_export_keying_material(%p, %p,%d, %s,%d, %p,%d)\n", s, out,olen, label,llen, p,plen);
#endif /* KSSL_DEBUG */
buff = OPENSSL_malloc(olen);
if (buff == NULL) goto err2;
/* construct PRF arguments
* we construct the PRF argument ourself rather than passing separate
* values into the TLS PRF to ensure that the concatenation of values
* does not create a prohibited label.
*/
vallen = llen + SSL3_RANDOM_SIZE * 2;
if (use_context)
{
vallen += 2 + contextlen;
}
val = OPENSSL_malloc(vallen);
if (val == NULL) goto err2;
currentvalpos = 0;
memcpy(val + currentvalpos, (unsigned char *) label, llen);
currentvalpos += llen;
memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
currentvalpos += SSL3_RANDOM_SIZE;
memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
currentvalpos += SSL3_RANDOM_SIZE;
if (use_context)
{
val[currentvalpos] = (contextlen << 8) & 0xff;
currentvalpos++;
val[currentvalpos] = contextlen & 0xff;
currentvalpos++;
if ((contextlen > 0) || (context != NULL))
{
memcpy(val + currentvalpos, context, contextlen);
}
}
/* disallow prohibited labels
* note that SSL3_RANDOM_SIZE > max(prohibited label len) =
* 15, so size of val > max(prohibited label len) = 15 and the
* comparisons won't have buffer overflow
*/
if (bcmp(val, TLS_MD_CLIENT_FINISH_CONST,
TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0) goto err1;
if (bcmp(val, TLS_MD_SERVER_FINISH_CONST,
TLS_MD_SERVER_FINISH_CONST_SIZE) == 0) goto err1;
if (bcmp(val, TLS_MD_MASTER_SECRET_CONST,
TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) goto err1;
if (bcmp(val, TLS_MD_KEY_EXPANSION_CONST,
TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) goto err1;
tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
val, vallen,
NULL, 0,
NULL, 0,
NULL, 0,
NULL, 0,
s->session->master_key,s->session->master_key_length,
out,buff,olen);
#ifdef KSSL_DEBUG
printf ("tls1_export_keying_material() complete\n");
#endif /* KSSL_DEBUG */
rv = olen;
goto ret;
err1:
SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
rv = 0;
goto ret;
err2:
SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, ERR_R_MALLOC_FAILURE);
rv = 0;
ret:
if (buff != NULL) OPENSSL_free(buff);
if (val != NULL) OPENSSL_free(val);
return(rv);
}
int tls1_alert_code(int code)
{
switch (code)

View File

@ -136,6 +136,7 @@ SSL3_ENC_METHOD TLSv1_enc_data={
TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
};
long tls1_default_timeout(void)

View File

@ -262,8 +262,10 @@ extern "C" {
#define TLSEXT_MAXLEN_host_name 255
const char *SSL_get_servername(const SSL *s, const int type) ;
int SSL_get_servername_type(const SSL *s) ;
const char *SSL_get_servername(const SSL *s, const int type);
int SSL_get_servername_type(const SSL *s);
int SSL_export_keying_material(SSL *s, unsigned char *out, int olen,
char *label, int llen, unsigned char *p, int plen, int use_context);
#define SSL_set_tlsext_host_name(s,name) \
SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)