RFC 5878 support.

This commit is contained in:
Ben Laurie 2012-05-30 10:10:58 +00:00
parent 03c1d9f99d
commit a9e1c50bb0
19 changed files with 864 additions and 57 deletions

View File

@ -4,6 +4,9 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
*) RFC 5878 support.
[Emilia Kasper, Adam Langley, Ben Laurie (Google)]
*) Support for automatic EC temporary key parameter selection. If enabled
the most preferred EC parameters are automatically used instead of
hardcoded fixed parameters. Now a server just has to call:

View File

@ -156,6 +156,10 @@ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file);
int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
STACK_OF(X509) *chain);
# ifndef OPENSSL_NO_TLSEXT
int set_cert_key_and_authz(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
unsigned char *authz, size_t authz_length);
# endif
int ssl_print_sigalgs(BIO *out, SSL *s);
int ssl_print_curves(BIO *out, SSL *s);
#endif

View File

@ -237,8 +237,8 @@ int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file)
/* If we are using DSA, we can copy the parameters from
* the private key */
/* Now we know that a key and cert have been set against
* the SSL context */
if (!SSL_CTX_check_private_key(ctx))
@ -251,9 +251,9 @@ int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file)
}
int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
STACK_OF(X509) *chain)
STACK_OF(X509) *chain)
{
if (cert == NULL)
if (cert == NULL)
return 1;
if (SSL_CTX_use_certificate(ctx,cert) <= 0)
{
@ -261,16 +261,16 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
ERR_print_errors(bio_err);
return 0;
}
if (SSL_CTX_use_PrivateKey(ctx,key) <= 0)
{
BIO_printf(bio_err,"error setting private key\n");
ERR_print_errors(bio_err);
return 0;
}
/* Now we know that a key and cert have been set against
* the SSL context */
if (SSL_CTX_use_PrivateKey(ctx,key) <= 0)
{
BIO_printf(bio_err,"error setting private key\n");
ERR_print_errors(bio_err);
return 0;
}
/* Now we know that a key and cert have been set against
* the SSL context */
if (!SSL_CTX_check_private_key(ctx))
{
BIO_printf(bio_err,"Private key does not match the certificate public key\n");

View File

@ -202,6 +202,7 @@ static int c_debug=0;
#ifndef OPENSSL_NO_TLSEXT
static int c_tlsextdebug=0;
static int c_status_req=0;
static int c_proof_debug=0;
#endif
static int c_msg=0;
static int c_showcerts=0;
@ -213,6 +214,7 @@ static void sc_usage(void);
static void print_stuff(BIO *berr,SSL *con,int full);
#ifndef OPENSSL_NO_TLSEXT
static int ocsp_resp_cb(SSL *s, void *arg);
static int audit_proof_cb(SSL *s, void *arg);
#endif
static BIO *bio_c_out=NULL;
static int c_quiet=0;
@ -357,6 +359,7 @@ static void sc_usage(void)
BIO_printf(bio_err," -tlsextdebug - hex dump of all TLS extensions received\n");
BIO_printf(bio_err," -status - request certificate status from server\n");
BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n");
BIO_printf(bio_err," -proof_debug - request an audit proof and print its hex dump\n");
# ifndef OPENSSL_NO_NEXTPROTONEG
BIO_printf(bio_err," -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n");
# endif
@ -731,6 +734,8 @@ int MAIN(int argc, char **argv)
c_tlsextdebug=1;
else if (strcmp(*argv,"-status") == 0)
c_status_req=1;
else if (strcmp(*argv,"-proof_debug") == 0)
c_proof_debug=1;
#endif
#ifdef WATT32
else if (strcmp(*argv,"-wdebug") == 0)
@ -1212,6 +1217,9 @@ bad:
}
#endif
if (c_proof_debug)
SSL_CTX_set_tlsext_authz_server_audit_proof_cb(ctx,
audit_proof_cb);
#endif
con=SSL_new(ctx);
@ -2147,4 +2155,26 @@ static int ocsp_resp_cb(SSL *s, void *arg)
return 1;
}
static int audit_proof_cb(SSL *s, void *arg)
{
const unsigned char *proof;
size_t proof_len;
size_t i;
SSL_SESSION *sess = SSL_get_session(s);
proof = SSL_SESSION_get_tlsext_authz_server_audit_proof(sess,
&proof_len);
if (proof != NULL)
{
BIO_printf(bio_c_out, "Audit proof: ");
for (i = 0; i < proof_len; ++i)
BIO_printf(bio_c_out, "%02X", proof[i]);
BIO_printf(bio_c_out, "\n");
}
else
{
BIO_printf(bio_c_out, "No audit proof found.\n");
}
return 1;
}
#endif

View File

@ -313,6 +313,12 @@ static long socket_mtu;
static int cert_chain = 0;
#endif
#ifndef OPENSSL_NO_TLSEXT
static BIO *authz_in = NULL;
static const char *s_authz_file = NULL;
static unsigned char *authz = NULL;
static size_t authz_length;
#endif
#ifndef OPENSSL_NO_PSK
static char *psk_identity="Client_identity";
@ -473,6 +479,7 @@ static void sv_usage(void)
BIO_printf(bio_err," -Verify arg - turn on peer certificate verification, must have a cert.\n");
BIO_printf(bio_err," -cert arg - certificate file to use\n");
BIO_printf(bio_err," (default is %s)\n",TEST_CERT);
BIO_printf(bio_err," -authz arg - binary authz file for certificate\n");
BIO_printf(bio_err," -crl_check - check the peer certificate has not been revoked by its CA.\n" \
" The CRL(s) are appended to the certificate file\n");
BIO_printf(bio_err," -crl_check_all - check the peer certificate has not been revoked by its CA\n" \
@ -1044,6 +1051,13 @@ int MAIN(int argc, char *argv[])
if (--argc < 1) goto bad;
s_cert_file= *(++argv);
}
#ifndef OPENSSL_NO_TLSEXT
else if (strcmp(*argv,"-authz") == 0)
{
if (--argc < 1) goto bad;
s_authz_file = *(++argv);
}
#endif
else if (strcmp(*argv,"-certform") == 0)
{
if (--argc < 1) goto bad;
@ -1490,7 +1504,34 @@ bad:
next_proto.data = NULL;
}
# endif
#endif
if (s_authz_file != NULL)
{
/* Allow authzs up to 64KB bytes. */
static const size_t authz_limit = 65536;
authz_in = BIO_new(BIO_s_file_internal());
if (authz_in == NULL)
{
ERR_print_errors(bio_err);
goto end;
}
if (BIO_read_filename(authz_in, s_authz_file) <= 0)
{
ERR_print_errors(bio_err);
goto end;
}
authz = OPENSSL_malloc(authz_limit);
authz_length = BIO_read(authz_in, authz, authz_limit);
if (authz_length == authz_limit || authz_length <= 0)
{
BIO_printf(bio_err, "authz too large\n");
goto end;
}
BIO_free(authz_in);
authz_in = NULL;
}
#endif /* OPENSSL_NO_TLSEXT */
}
@ -1789,6 +1830,10 @@ bad:
if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain))
goto end;
#ifndef OPENSSL_NO_TLSEXT
if (authz != NULL && !SSL_CTX_use_authz(ctx, authz, authz_length))
goto end;
#endif
#ifndef OPENSSL_NO_TLSEXT
if (ctx2 && !set_cert_key_stuff(ctx2,s_cert2,s_key2, NULL))
goto end;
@ -1983,6 +2028,10 @@ end:
X509_free(s_cert2);
if (s_key2)
EVP_PKEY_free(s_key2);
if (authz != NULL)
OPENSSL_free(authz);
if (authz_in != NULL)
BIO_free(authz_in);
#endif
if (bio_s_out != NULL)
{

View File

@ -340,6 +340,8 @@ static int ssl23_client_hello(SSL *s)
if (s->ctx->tlsext_opaque_prf_input_callback != 0 || s->tlsext_opaque_prf_input != NULL)
ssl2_compat = 0;
#endif
if (s->ctx->tlsext_authz_server_audit_proof_cb != NULL)
ssl2_compat = 0;
}
#endif

View File

@ -307,10 +307,27 @@ int ssl3_connect(SSL *s)
#endif
}
else
s->state=SSL3_ST_CR_CERT_A;
{
#ifndef OPENSSL_NO_TLSEXT
/* The server hello indicated that
* an audit proof would follow. */
if (s->s3->tlsext_authz_server_promised)
s->state=SSL3_ST_CR_SUPPLEMENTAL_DATA_A;
else
#endif
s->state=SSL3_ST_CR_CERT_A;
}
s->init_num=0;
break;
#ifndef OPENSSL_NO_TLSEXT
case SSL3_ST_CR_SUPPLEMENTAL_DATA_A:
case SSL3_ST_CR_SUPPLEMENTAL_DATA_B:
ret = tls1_get_server_supplemental_data(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_CR_CERT_A;
s->init_num = 0;
break;
#endif
case SSL3_ST_CR_CERT_A:
case SSL3_ST_CR_CERT_B:
#ifndef OPENSSL_NO_TLSEXT
@ -1231,8 +1248,22 @@ int ssl3_get_server_certificate(SSL *s)
s->session->verify_result = s->verify_result;
x=NULL;
ret=1;
#ifndef OPENSSL_NO_TLSEXT
/* Check the audit proof. */
if (s->ctx->tlsext_authz_server_audit_proof_cb)
{
ret = s->ctx->tlsext_authz_server_audit_proof_cb(s,
s->ctx->tlsext_authz_server_audit_proof_cb_arg);
if (ret <= 0)
{
al = SSL_AD_BAD_CERTIFICATE;
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_INVALID_AUDIT_PROOF);
goto f_err;
}
}
#endif
ret=1;
if (0)
{
f_err:
@ -3432,3 +3463,106 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
i = s->ctx->client_cert_cb(s,px509,ppkey);
return i;
}
#ifndef OPENSSL_NO_TLSEXT
int tls1_get_server_supplemental_data(SSL *s)
{
int al;
int ok;
unsigned long supp_data_len, authz_data_len;
long n;
unsigned short supp_data_type, authz_data_type, proof_len;
const unsigned char *p;
unsigned char *new_proof;
n=s->method->ssl_get_message(s,
SSL3_ST_CR_SUPPLEMENTAL_DATA_A,
SSL3_ST_CR_SUPPLEMENTAL_DATA_B,
SSL3_MT_SUPPLEMENTAL_DATA,
/* use default limit */
TLSEXT_MAXLEN_supplemental_data,
&ok);
if (!ok) return((int)n);
p = (unsigned char *)s->init_msg;
/* The message cannot be empty */
if (n < 3)
{
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
/* Length of supplemental data */
n2l3(p,supp_data_len);
n -= 3;
/* We must have at least one supplemental data entry
* with type (1 byte) and length (2 bytes). */
if (supp_data_len != (unsigned long) n || n < 4)
{
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
/* Supplemental data type: must be authz_data */
n2s(p,supp_data_type);
n -= 2;
if (supp_data_type != TLSEXT_SUPPLEMENTALDATATYPE_authz_data)
{
al = SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_UNKNOWN_SUPPLEMENTAL_DATA_TYPE);
goto f_err;
}
/* Authz data length */
n2s(p, authz_data_len);
n -= 2;
if (authz_data_len != (unsigned long) n || n < 1)
{
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
/* Authz data type: must be audit_proof */
authz_data_type = *(p++);
n -= 1;
if (authz_data_type != TLSEXT_AUTHZDATAFORMAT_audit_proof)
{
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_UNKNOWN_AUTHZ_DATA_TYPE);
goto f_err;
}
/* We have a proof: read its length */
if (n < 2)
{
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
n2s(p, proof_len);
n -= 2;
if (proof_len != (unsigned long) n)
{
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
/* Store the proof */
new_proof = OPENSSL_realloc(s->session->audit_proof,
proof_len);
if (new_proof == NULL)
{
SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,ERR_R_MALLOC_FAILURE);
return 0;
}
s->session->audit_proof_length = proof_len;
s->session->audit_proof = new_proof;
memcpy(s->session->audit_proof, p, proof_len);
/* Got the proof, but can't verify it yet. */
return 1;
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
return -1;
}
#endif

View File

@ -3684,6 +3684,11 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
case SSL_CTRL_SET_ECDH_AUTO:
ctx->cert->ecdh_tmp_auto = larg;
break;
case SSL_CTRL_SET_TLSEXT_AUTHZ_SERVER_AUDIT_PROOF_CB_ARG:
ctx->tlsext_authz_server_audit_proof_cb_arg = parg;
break;
#endif /* !OPENSSL_NO_TLSEXT */
/* A Thawte special :-) */
@ -3793,6 +3798,12 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
ctx->srp_ctx.SRP_give_srp_client_pwd_callback=(char *(*)(SSL *,void *))fp;
break;
#endif
case SSL_CTRL_SET_TLSEXT_AUTHZ_SERVER_AUDIT_PROOF_CB:
ctx->tlsext_authz_server_audit_proof_cb =
(int (*)(SSL *, void *))fp;
break;
#endif
case SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB:
{

View File

@ -403,10 +403,31 @@ int ssl3_accept(SSL *s)
s->state=SSL3_ST_SW_CHANGE_A;
#endif
else
s->state=SSL3_ST_SW_CERT_A;
s->init_num=0;
#ifndef OPENSSL_NO_TLSEXT
s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_A;
#else
s->state = SSL3_ST_SW_CERT_A;
#endif
s->init_num = 0;
break;
#ifndef OPENSSL_NO_TLSEXT
case SSL3_ST_SW_SUPPLEMENTAL_DATA_A:
case SSL3_ST_SW_SUPPLEMENTAL_DATA_B:
/* We promised to send an audit proof in the hello. */
if (s->s3->tlsext_authz_promised_to_client)
{
ret = tls1_send_server_supplemental_data(s);
if (ret <= 0) goto end;
}
else
skip = 1;
s->state = SSL3_ST_SW_CERT_A;
s->init_num = 0;
break;
#endif
case SSL3_ST_SW_CERT_A:
case SSL3_ST_SW_CERT_B:
/* Check if it is anon DH or anon ECDH, */
@ -3629,4 +3650,95 @@ int ssl3_get_next_proto(SSL *s)
return 1;
}
# endif
int tls1_send_server_supplemental_data(SSL *s)
{
size_t length = 0;
const unsigned char *authz, *orig_authz;
unsigned char *p;
size_t authz_length, i;
if (s->state != SSL3_ST_SW_SUPPLEMENTAL_DATA_A)
return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
orig_authz = authz = ssl_get_authz_data(s, &authz_length);
if (authz == NULL)
{
/* This should never occur. */
return 0;
}
/* First we walk over the authz data to see how long the handshake
* message will be. */
for (i = 0; i < authz_length; i++)
{
unsigned short len;
unsigned char type;
type = *(authz++);
n2s(authz, len);
if (memchr(s->s3->tlsext_authz_client_types,
type,
s->s3->tlsext_authz_client_types_len) != NULL)
length += 1 /* authz type */ + 2 /* length */ + len;
authz += len;
i += len;
}
length += 1 /* handshake type */ +
3 /* handshake length */ +
3 /* supplemental data length */ +
2 /* supplemental entry type */ +
2 /* supplemental entry length */;
if (!BUF_MEM_grow_clean(s->init_buf, length))
{
SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
return 0;
}
p = (unsigned char *)s->init_buf->data;
*(p++) = SSL3_MT_SUPPLEMENTAL_DATA;
/* Handshake length */
l2n3(length - 4, p);
/* Length of supplemental data */
l2n3(length - 7, p);
/* Supplemental data type */
s2n(TLSEXT_SUPPLEMENTALDATATYPE_authz_data, p);
/* Its length */
s2n(length - 11, p);
authz = orig_authz;
/* Walk over the authz again and append the selected elements. */
for (i = 0; i < authz_length; i++)
{
unsigned short len;
unsigned char type;
type = *(authz++);
n2s(authz, len);
if (memchr(s->s3->tlsext_authz_client_types,
type,
s->s3->tlsext_authz_client_types_len) != NULL)
{
*(p++) = type;
s2n(len, p);
memcpy(p, authz, len);
p += len;
}
authz += len;
i += len;
}
s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_B;
s->init_num = length;
s->init_off = 0;
return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
}
#endif

View File

@ -539,11 +539,18 @@ struct ssl_session_st
#endif /* OPENSSL_NO_EC */
/* RFC4507 info */
unsigned char *tlsext_tick; /* Session ticket */
size_t tlsext_ticklen; /* Session ticket length */
size_t tlsext_ticklen; /* Session ticket length */
long tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */
#endif
#ifndef OPENSSL_NO_SRP
char *srp_username;
#endif
#ifndef OPENSSL_NO_TLSEXT
/* Used by client: the proof for this session.
* We store it outside the sess_cert structure, since the proof
* is received before the certificate. */
unsigned char *audit_proof;
size_t audit_proof_length;
#endif
};
@ -977,7 +984,7 @@ struct ssl_ctx_st
void *next_proto_select_cb_arg;
# endif
/* SRTP profiles we are willing to do from RFC 5764 */
STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
#endif
/* Callback for disabling session caching and ticket support
* on a session basis, depending on the chosen cipher. */
@ -989,6 +996,8 @@ struct ssl_ctx_st
size_t tlsext_ellipticcurvelist_length;
unsigned char *tlsext_ellipticcurvelist;
#endif /* OPENSSL_NO_EC */
int (*tlsext_authz_server_audit_proof_cb)(SSL *s, void *arg);
void *tlsext_authz_server_audit_proof_cb_arg;
};
#endif
@ -1608,7 +1617,10 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_GET_TLS_EXT_HEARTBEAT_PENDING 86
#define SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS 87
#endif
#endif
/* Callback for verifying audit proofs (client only) */
#define SSL_CTRL_SET_TLSEXT_AUTHZ_SERVER_AUDIT_PROOF_CB 95
#define SSL_CTRL_SET_TLSEXT_AUTHZ_SERVER_AUDIT_PROOF_CB_ARG 96
#endif /* OPENSSL_NO_TLSEXT */
#define DTLS_CTRL_GET_TIMEOUT 73
#define DTLS_CTRL_HANDLE_TIMEOUT 74
@ -1768,6 +1780,11 @@ int SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
int SSL_use_certificate(SSL *ssl, X509 *x);
int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
#ifndef OPENSSL_NO_TLSEXT
int SSL_CTX_use_authz(SSL_CTX *ctx, unsigned char *authz, size_t authz_length);
int SSL_use_authz(SSL *ssl, unsigned char *authz, size_t authz_length);
#endif
#ifndef OPENSSL_NO_STDIO
int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
@ -1812,6 +1829,10 @@ int SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses);
#ifndef OPENSSL_NO_BIO
int SSL_SESSION_print(BIO *fp,const SSL_SESSION *ses);
#endif
#ifndef OPENSSL_NO_TLSEXT
unsigned char *SSL_SESSION_get_tlsext_authz_server_audit_proof(SSL_SESSION *s,
size_t *proof_length);
#endif
void SSL_SESSION_free(SSL_SESSION *ses);
int i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
int SSL_set_session(SSL *to, SSL_SESSION *session);
@ -2115,6 +2136,7 @@ void ERR_load_SSL_strings(void);
/* Error codes for the SSL functions. */
/* Function codes. */
#define SSL_F_AUTHZ_VALIDATE 323
#define SSL_F_CLIENT_CERTIFICATE 100
#define SSL_F_CLIENT_FINISHED 167
#define SSL_F_CLIENT_HELLO 101
@ -2260,6 +2282,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219
#define SSL_F_SSL_CTX_SET_SSL_VERSION 170
#define SSL_F_SSL_CTX_SET_TRUST 229
#define SSL_F_SSL_CTX_USE_AUTHZ 324
#define SSL_F_SSL_CTX_USE_CERTIFICATE 171
#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172
#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE 220
@ -2274,6 +2297,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL_DO_HANDSHAKE 180
#define SSL_F_SSL_GET_NEW_SESSION 181
#define SSL_F_SSL_GET_PREV_SESSION 217
#define SSL_F_SSL_GET_SERVER_CERT_INDEX 329
#define SSL_F_SSL_GET_SERVER_SEND_PKEY 182
#define SSL_F_SSL_GET_SIGN_PKEY 183
#define SSL_F_SSL_INIT_WBIO_BUFFER 184
@ -2297,6 +2321,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL_SESSION_PRINT_FP 190
#define SSL_F_SSL_SESSION_SET1_ID_CONTEXT 312
#define SSL_F_SSL_SESS_CERT_NEW 225
#define SSL_F_SSL_SET_AUTHZ 325
#define SSL_F_SSL_SET_CERT 191
#define SSL_F_SSL_SET_CIPHER_LIST 271
#define SSL_F_SSL_SET_FD 192
@ -2313,6 +2338,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL_UNDEFINED_CONST_FUNCTION 243
#define SSL_F_SSL_UNDEFINED_FUNCTION 197
#define SSL_F_SSL_UNDEFINED_VOID_FUNCTION 244
#define SSL_F_SSL_USE_AUTHZ 328
#define SSL_F_SSL_USE_CERTIFICATE 198
#define SSL_F_SSL_USE_CERTIFICATE_ASN1 199
#define SSL_F_SSL_USE_CERTIFICATE_FILE 200
@ -2330,16 +2356,19 @@ void ERR_load_SSL_strings(void);
#define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT 274
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 314
#define SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA 326
#define SSL_F_TLS1_HEARTBEAT 315
#define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT 275
#define SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT 276
#define SSL_F_TLS1_PRF 284
#define SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA 327
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
#define SSL_R_AUTHZ_DATA_TOO_LARGE 375
#define SSL_R_BAD_ALERT_RECORD 101
#define SSL_R_BAD_AUTHENTICATION_TYPE 102
#define SSL_R_BAD_CHANGE_CIPHER_SPEC 103
@ -2428,6 +2457,8 @@ void ERR_load_SSL_strings(void);
#define SSL_R_HTTP_REQUEST 156
#define SSL_R_ILLEGAL_PADDING 283
#define SSL_R_INCONSISTENT_COMPRESSION 340
#define SSL_R_INVALID_AUDIT_PROOF 371
#define SSL_R_INVALID_AUTHZ_DATA 374
#define SSL_R_INVALID_CHALLENGE_LENGTH 158
#define SSL_R_INVALID_COMMAND 280
#define SSL_R_INVALID_COMPRESSION_ALGORITHM 341
@ -2607,6 +2638,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_UNEXPECTED_RECORD 245
#define SSL_R_UNINITIALIZED 276
#define SSL_R_UNKNOWN_ALERT_TYPE 246
#define SSL_R_UNKNOWN_AUTHZ_DATA_TYPE 372
#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 247
#define SSL_R_UNKNOWN_CIPHER_RETURNED 248
#define SSL_R_UNKNOWN_CIPHER_TYPE 249
@ -2617,6 +2649,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 253
#define SSL_R_UNKNOWN_SSL_VERSION 254
#define SSL_R_UNKNOWN_STATE 255
#define SSL_R_UNKNOWN_SUPPLEMENTAL_DATA_TYPE 373
#define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 338
#define SSL_R_UNSUPPORTED_CIPHER 256
#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 257

View File

@ -540,6 +540,22 @@ typedef struct ssl3_state_st
our peer. */
int next_proto_neg_seen;
#endif
#ifndef OPENSSL_NO_TLSEXT
/* tlsext_authz_client_types contains an array of supported authz
* types, as advertised by the client. The array is sorted and
* does not contain any duplicates. */
unsigned char *tlsext_authz_client_types;
size_t tlsext_authz_client_types_len;
/* tlsext_authz_promised_to_client is true iff we're a server and we
* echoed the client's supplemental data extension and therefore must
* send a supplemental data handshake message. */
char tlsext_authz_promised_to_client;
/* tlsext_authz_server_promised is true iff we're a client and the
* server echoed our server_authz extension and therefore must send us
* a supplemental data handshake message. */
char tlsext_authz_server_promised;
#endif
} SSL3_STATE;
#endif
@ -568,6 +584,8 @@ typedef struct ssl3_state_st
#define SSL3_ST_CR_CERT_REQ_B (0x151|SSL_ST_CONNECT)
#define SSL3_ST_CR_SRVR_DONE_A (0x160|SSL_ST_CONNECT)
#define SSL3_ST_CR_SRVR_DONE_B (0x161|SSL_ST_CONNECT)
#define SSL3_ST_CR_SUPPLEMENTAL_DATA_A (0x210|SSL_ST_CONNECT)
#define SSL3_ST_CR_SUPPLEMENTAL_DATA_B (0x211|SSL_ST_CONNECT)
/* write to server */
#define SSL3_ST_CW_CERT_A (0x170|SSL_ST_CONNECT)
#define SSL3_ST_CW_CERT_B (0x171|SSL_ST_CONNECT)
@ -647,6 +665,8 @@ typedef struct ssl3_state_st
#define SSL3_ST_SW_SESSION_TICKET_B (0x1F1|SSL_ST_ACCEPT)
#define SSL3_ST_SW_CERT_STATUS_A (0x200|SSL_ST_ACCEPT)
#define SSL3_ST_SW_CERT_STATUS_B (0x201|SSL_ST_ACCEPT)
#define SSL3_ST_SW_SUPPLEMENTAL_DATA_A (0x220|SSL_ST_ACCEPT)
#define SSL3_ST_SW_SUPPLEMENTAL_DATA_B (0x221|SSL_ST_ACCEPT)
#define SSL3_MT_HELLO_REQUEST 0
#define SSL3_MT_CLIENT_HELLO 1
@ -660,6 +680,7 @@ typedef struct ssl3_state_st
#define SSL3_MT_CLIENT_KEY_EXCHANGE 16
#define SSL3_MT_FINISHED 20
#define SSL3_MT_CERTIFICATE_STATUS 22
#define SSL3_MT_SUPPLEMENTAL_DATA 23
#ifndef OPENSSL_NO_NEXTPROTONEG
#define SSL3_MT_NEXT_PROTO 67
#endif
@ -682,4 +703,3 @@ typedef struct ssl3_state_st
}
#endif
#endif

View File

@ -334,6 +334,22 @@ CERT *ssl_cert_dup(CERT *cert)
CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
}
}
if (cert->pkeys[i].authz != NULL)
{
/* Just copy everything. */
ret->pkeys[i].authz_length =
cert->pkeys[i].authz_length;
ret->pkeys[i].authz =
OPENSSL_malloc(ret->pkeys[i].authz_length);
if (ret->pkeys[i].authz == NULL)
{
SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
return(NULL);
}
memcpy(ret->pkeys[i].authz,
cert->pkeys[i].authz,
cert->pkeys[i].authz_length);
}
}
ret->references=1;
@ -421,6 +437,10 @@ void ssl_cert_free(CERT *c)
#if 0
if (c->pkeys[i].publickey != NULL)
EVP_PKEY_free(c->pkeys[i].publickey);
#endif
#ifndef OPENSSL_NO_TLSEXT
if (c->pkeys[i].authz != NULL)
OPENSSL_free(c->pkeys[i].authz);
#endif
}
if (c->sigalgs)

View File

@ -70,6 +70,7 @@
static ERR_STRING_DATA SSL_str_functs[]=
{
{ERR_FUNC(SSL_F_AUTHZ_VALIDATE), "AUTHZ_VALIDATE"},
{ERR_FUNC(SSL_F_CLIENT_CERTIFICATE), "CLIENT_CERTIFICATE"},
{ERR_FUNC(SSL_F_CLIENT_FINISHED), "CLIENT_FINISHED"},
{ERR_FUNC(SSL_F_CLIENT_HELLO), "CLIENT_HELLO"},
@ -215,6 +216,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT), "SSL_CTX_set_session_id_context"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_SSL_VERSION), "SSL_CTX_set_ssl_version"},
{ERR_FUNC(SSL_F_SSL_CTX_SET_TRUST), "SSL_CTX_set_trust"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_AUTHZ), "SSL_CTX_use_authz"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE), "SSL_CTX_use_certificate"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1), "SSL_CTX_use_certificate_ASN1"},
{ERR_FUNC(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE), "SSL_CTX_use_certificate_chain_file"},
@ -229,6 +231,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE), "SSL_do_handshake"},
{ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION), "SSL_GET_NEW_SESSION"},
{ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION), "SSL_GET_PREV_SESSION"},
{ERR_FUNC(SSL_F_SSL_GET_SERVER_CERT_INDEX), "SSL_GET_SERVER_CERT_INDEX"},
{ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_PKEY), "SSL_GET_SERVER_SEND_PKEY"},
{ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY), "SSL_GET_SIGN_PKEY"},
{ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER), "SSL_INIT_WBIO_BUFFER"},
@ -252,6 +255,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP), "SSL_SESSION_print_fp"},
{ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID_CONTEXT), "SSL_SESSION_set1_id_context"},
{ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW), "SSL_SESS_CERT_NEW"},
{ERR_FUNC(SSL_F_SSL_SET_AUTHZ), "SSL_SET_AUTHZ"},
{ERR_FUNC(SSL_F_SSL_SET_CERT), "SSL_SET_CERT"},
{ERR_FUNC(SSL_F_SSL_SET_CIPHER_LIST), "SSL_set_cipher_list"},
{ERR_FUNC(SSL_F_SSL_SET_FD), "SSL_set_fd"},
@ -268,6 +272,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_SSL_UNDEFINED_CONST_FUNCTION), "SSL_UNDEFINED_CONST_FUNCTION"},
{ERR_FUNC(SSL_F_SSL_UNDEFINED_FUNCTION), "SSL_UNDEFINED_FUNCTION"},
{ERR_FUNC(SSL_F_SSL_UNDEFINED_VOID_FUNCTION), "SSL_UNDEFINED_VOID_FUNCTION"},
{ERR_FUNC(SSL_F_SSL_USE_AUTHZ), "SSL_use_authz"},
{ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE), "SSL_use_certificate"},
{ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_ASN1), "SSL_use_certificate_ASN1"},
{ERR_FUNC(SSL_F_SSL_USE_CERTIFICATE_FILE), "SSL_use_certificate_file"},
@ -285,10 +290,12 @@ static ERR_STRING_DATA SSL_str_functs[]=
{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_GET_SERVER_SUPPLEMENTAL_DATA), "TLS1_GET_SERVER_SUPPLEMENTAL_DATA"},
{ERR_FUNC(SSL_F_TLS1_HEARTBEAT), "SSL_F_TLS1_HEARTBEAT"},
{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"},
{ERR_FUNC(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA), "TLS1_SEND_SERVER_SUPPLEMENTAL_DATA"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
{0,NULL}
@ -298,6 +305,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{
{ERR_REASON(SSL_R_APP_DATA_IN_HANDSHAKE) ,"app data in handshake"},
{ERR_REASON(SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT),"attempt to reuse session in different context"},
{ERR_REASON(SSL_R_AUTHZ_DATA_TOO_LARGE) ,"authz data too large"},
{ERR_REASON(SSL_R_BAD_ALERT_RECORD) ,"bad alert record"},
{ERR_REASON(SSL_R_BAD_AUTHENTICATION_TYPE),"bad authentication type"},
{ERR_REASON(SSL_R_BAD_CHANGE_CIPHER_SPEC),"bad change cipher spec"},
@ -386,6 +394,8 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_HTTP_REQUEST) ,"http request"},
{ERR_REASON(SSL_R_ILLEGAL_PADDING) ,"illegal padding"},
{ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION),"inconsistent compression"},
{ERR_REASON(SSL_R_INVALID_AUDIT_PROOF) ,"invalid audit proof"},
{ERR_REASON(SSL_R_INVALID_AUTHZ_DATA) ,"invalid authz data"},
{ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH),"invalid challenge length"},
{ERR_REASON(SSL_R_INVALID_COMMAND) ,"invalid command"},
{ERR_REASON(SSL_R_INVALID_COMPRESSION_ALGORITHM),"invalid compression algorithm"},
@ -565,6 +575,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_UNEXPECTED_RECORD) ,"unexpected record"},
{ERR_REASON(SSL_R_UNINITIALIZED) ,"uninitialized"},
{ERR_REASON(SSL_R_UNKNOWN_ALERT_TYPE) ,"unknown alert type"},
{ERR_REASON(SSL_R_UNKNOWN_AUTHZ_DATA_TYPE),"unknown authz data type"},
{ERR_REASON(SSL_R_UNKNOWN_CERTIFICATE_TYPE),"unknown certificate type"},
{ERR_REASON(SSL_R_UNKNOWN_CIPHER_RETURNED),"unknown cipher returned"},
{ERR_REASON(SSL_R_UNKNOWN_CIPHER_TYPE) ,"unknown cipher type"},
@ -575,6 +586,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
{ERR_REASON(SSL_R_UNKNOWN_REMOTE_ERROR_TYPE),"unknown remote error type"},
{ERR_REASON(SSL_R_UNKNOWN_SSL_VERSION) ,"unknown ssl version"},
{ERR_REASON(SSL_R_UNKNOWN_STATE) ,"unknown state"},
{ERR_REASON(SSL_R_UNKNOWN_SUPPLEMENTAL_DATA_TYPE),"unknown supplemental data type"},
{ERR_REASON(SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED),"unsafe legacy renegotiation disabled"},
{ERR_REASON(SSL_R_UNSUPPORTED_CIPHER) ,"unsupported cipher"},
{ERR_REASON(SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"},

View File

@ -2323,15 +2323,10 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
#endif
/* THIS NEEDS CLEANING UP */
CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
static int ssl_get_server_cert_index(SSL *s)
{
unsigned long alg_k,alg_a;
CERT *c;
int i;
unsigned long alg_k, alg_a;
c=s->cert;
ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
@ -2348,42 +2343,53 @@ CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
* checks for SSL_kECDH before RSA
* checks ensures the correct cert is chosen.
*/
i=SSL_PKEY_ECC;
return SSL_PKEY_ECC;
}
else if (alg_a & SSL_aECDSA)
{
i=SSL_PKEY_ECC;
}
return SSL_PKEY_ECC;
else if (alg_k & SSL_kDHr)
i=SSL_PKEY_DH_RSA;
return SSL_PKEY_DH_RSA;
else if (alg_k & SSL_kDHd)
i=SSL_PKEY_DH_DSA;
return SSL_PKEY_DH_DSA;
else if (alg_a & SSL_aDSS)
i=SSL_PKEY_DSA_SIGN;
return SSL_PKEY_DSA_SIGN;
else if (alg_a & SSL_aRSA)
{
if (c->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
i=SSL_PKEY_RSA_SIGN;
if (s->cert->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
return SSL_PKEY_RSA_SIGN;
else
i=SSL_PKEY_RSA_ENC;
return SSL_PKEY_RSA_ENC;
}
else if (alg_a & SSL_aKRB5)
{
/* VRS something else here? */
return(NULL);
}
return -1;
else if (alg_a & SSL_aGOST94)
i=SSL_PKEY_GOST94;
return SSL_PKEY_GOST94;
else if (alg_a & SSL_aGOST01)
i=SSL_PKEY_GOST01;
return SSL_PKEY_GOST01;
else /* if (alg_a & SSL_aNULL) */
{
SSLerr(SSL_F_SSL_GET_SERVER_SEND_PKEY,ERR_R_INTERNAL_ERROR);
return(NULL);
SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX,ERR_R_INTERNAL_ERROR);
return -1;
}
if (c->pkeys[i].x509 == NULL) return(NULL);
}
return(&c->pkeys[i]);
CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
{
CERT *c;
int i;
c = s->cert;
ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
i = ssl_get_server_cert_index(s);
/* This may or may not be an error. */
if (i < 0)
return NULL;
/* May be NULL. */
return &c->pkeys[i];
}
EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
@ -2418,6 +2424,27 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
return c->pkeys[idx].privatekey;
}
#ifndef OPENSSL_NO_TLSEXT
unsigned char *ssl_get_authz_data(SSL *s, size_t *authz_length)
{
CERT *c;
int i;
c = s->cert;
i = ssl_get_server_cert_index(s);
if (i == -1)
return NULL;
*authz_length = 0;
if (c->pkeys[i].authz == NULL)
return(NULL);
*authz_length = c->pkeys[i].authz_length;
return c->pkeys[i].authz;
}
#endif
void ssl_update_cache(SSL *s,int mode)
{
int i;

View File

@ -474,6 +474,15 @@ typedef struct cert_pkey_st
const EVP_MD *digest;
/* Chain for this certificate */
STACK_OF(X509) *chain;
#ifndef OPENSSL_NO_TLSEXT
/* authz/authz_length contain authz data for this certificate. The data
* is in wire format, specifically it's a series of records like:
* uint8_t authz_type; // (RFC 5878, AuthzDataFormat)
* uint16_t length;
* uint8_t data[length]; */
unsigned char *authz;
size_t authz_length;
#endif
} CERT_PKEY;
typedef struct cert_st
@ -856,6 +865,7 @@ int ssl_undefined_function(SSL *s);
int ssl_undefined_void_function(void);
int ssl_undefined_const_function(const SSL *s);
CERT_PKEY *ssl_get_server_send_pkey(SSL *);
unsigned char *ssl_get_authz_data(SSL *s, size_t *authz_length);
EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c, const EVP_MD **pmd);
int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
@ -1125,6 +1135,11 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d,
int ssl_prepare_clienthello_tlsext(SSL *s);
int ssl_prepare_serverhello_tlsext(SSL *s);
/* server only */
int tls1_send_server_supplemental_data(SSL *s);
/* client only */
int tls1_get_server_supplemental_data(SSL *s);
#ifndef OPENSSL_NO_HEARTBEATS
int tls1_heartbeat(SSL *s);
int dtls1_heartbeat(SSL *s);

View File

@ -66,6 +66,10 @@
static int ssl_set_cert(CERT *c, X509 *x509);
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
#ifndef OPENSSL_NO_TLSEXT
static int ssl_set_authz(CERT *c, unsigned char *authz,
size_t authz_length);
#endif
int SSL_use_certificate(SSL *ssl, X509 *x)
{
if (x == NULL)
@ -459,6 +463,15 @@ static int ssl_set_cert(CERT *c, X509 *x)
X509_free(c->pkeys[i].x509);
CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
c->pkeys[i].x509=x;
#ifndef OPENSSL_NO_TLSEXT
/* Free the old authz data, if it exists. */
if (c->pkeys[i].authz != NULL)
{
OPENSSL_free(c->pkeys[i].authz);
c->pkeys[i].authz = NULL;
c->pkeys[i].authz_length = 0;
}
#endif
c->key= &(c->pkeys[i]);
c->valid=0;
@ -725,7 +738,7 @@ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */
in=BIO_new(BIO_s_file_internal());
in = BIO_new(BIO_s_file_internal());
if (in == NULL)
{
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_BUF_LIB);
@ -738,14 +751,16 @@ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
goto end;
}
x=PEM_read_bio_X509_AUX(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata);
x=PEM_read_bio_X509_AUX(in,NULL,ctx->default_passwd_callback,
ctx->default_passwd_callback_userdata);
if (x == NULL)
{
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_PEM_LIB);
goto end;
}
ret=SSL_CTX_use_certificate(ctx,x);
ret = SSL_CTX_use_certificate(ctx, x);
if (ERR_peek_error() != 0)
ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */
if (ret)
@ -757,13 +772,15 @@ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file)
int r;
unsigned long err;
if (ctx->extra_certs != NULL)
if (ctx->extra_certs != NULL)
{
sk_X509_pop_free(ctx->extra_certs, X509_free);
ctx->extra_certs = NULL;
}
while ((ca = PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata))
while ((ca = PEM_read_bio_X509(in, NULL,
ctx->default_passwd_callback,
ctx->default_passwd_callback_userdata))
!= NULL)
{
r = SSL_CTX_add_extra_chain_cert(ctx, ca);
@ -792,3 +809,96 @@ end:
return(ret);
}
#endif
#ifndef OPENSSL_NO_TLSEXT
/* authz_validate returns true iff authz is well formed, i.e. that it meets the
* wire format as documented in the CERT_PKEY structure and that there are no
* duplicate entries. */
static char authz_validate(const unsigned char *authz, size_t length)
{
unsigned char types_seen_bitmap[32];
if (!authz)
return 1;
memset(types_seen_bitmap, 0, sizeof(types_seen_bitmap));
for (;;)
{
unsigned char type, byte, bit;
unsigned short len;
if (!length)
return 1;
type = *(authz++);
length--;
byte = type / 8;
bit = type & 7;
if (types_seen_bitmap[byte] & (1 << bit))
return 0;
types_seen_bitmap[byte] |= (1 << bit);
if (length < 2)
return 0;
len = ((unsigned short) authz[0]) << 8 |
((unsigned short) authz[1]);
authz += 2;
length -= 2;
if (length < len)
return 0;
authz += len;
length -= len;
}
}
static int ssl_set_authz(CERT *c, unsigned char *authz, size_t authz_length)
{
CERT_PKEY *current_key = c->key;
if (current_key == NULL)
return 0;
if (!authz_validate(authz, authz_length))
{
SSLerr(SSL_F_SSL_SET_AUTHZ,SSL_R_INVALID_AUTHZ_DATA);
return(0);
}
current_key->authz = OPENSSL_realloc(current_key->authz, authz_length);
current_key->authz_length = authz_length;
memcpy(current_key->authz, authz, authz_length);
return 1;
}
int SSL_CTX_use_authz(SSL_CTX *ctx, unsigned char *authz,
size_t authz_length)
{
if (authz == NULL)
{
SSLerr(SSL_F_SSL_CTX_USE_AUTHZ,ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!ssl_cert_inst(&ctx->cert))
{
SSLerr(SSL_F_SSL_CTX_USE_AUTHZ,ERR_R_MALLOC_FAILURE);
return 0;
}
return ssl_set_authz(ctx->cert, authz, authz_length);
}
int SSL_use_authz(SSL *ssl, unsigned char *authz, size_t authz_length)
{
if (authz == NULL)
{
SSLerr(SSL_F_SSL_USE_AUTHZ,ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!ssl_cert_inst(&ssl->cert))
{
SSLerr(SSL_F_SSL_USE_AUTHZ,ERR_R_MALLOC_FAILURE);
return 0;
}
return ssl_set_authz(ssl->cert, authz, authz_length);
}
#endif /* OPENSSL_NO_TLSEXT */

View File

@ -739,6 +739,8 @@ void SSL_SESSION_free(SSL_SESSION *ss)
ss->tlsext_ellipticcurvelist_length = 0;
if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
#endif /* OPENSSL_NO_EC */
if (ss->audit_proof != NULL) OPENSSL_free(ss->audit_proof);
ss->audit_proof_length = 0;
#endif
#ifndef OPENSSL_NO_PSK
if (ss->psk_identity_hint != NULL)
@ -860,6 +862,15 @@ int SSL_SESSION_set1_id_context(SSL_SESSION *s,const unsigned char *sid_ctx,
return 1;
}
#ifndef OPENSSL_NO_TLSEXT
unsigned char *SSL_SESSION_get_tlsext_authz_server_audit_proof(SSL_SESSION *s, size_t *proof_length)
{
if (s->audit_proof != NULL)
*proof_length = s->audit_proof_length;
return s->audit_proof;
}
#endif
long SSL_CTX_set_timeout(SSL_CTX *s, long t)
{
long l;

View File

@ -642,6 +642,19 @@ int tls12_get_req_sig_algs(SSL *s, unsigned char *p)
return (int)slen;
}
/* byte_compare is a compare function for qsort(3) that compares bytes. */
static int byte_compare(const void *in_a, const void *in_b)
{
unsigned char a = *((const unsigned char*) in_a);
unsigned char b = *((const unsigned char*) in_b);
if (a > b)
return 1;
else if (a < b)
return -1;
return 0;
}
unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
{
int extdatalen=0;
@ -983,7 +996,27 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
ret += el;
}
if ((extdatalen = ret-p-2)== 0)
/* Add TLS extension Server_Authz_DataFormats to the ClientHello */
/* 2 bytes for extension type */
/* 2 bytes for extension length */
/* 1 byte for the list length */
/* 1 byte for the list (we only support audit proofs) */
if (s->ctx->tlsext_authz_server_audit_proof_cb != NULL)
{
size_t lenmax;
const unsigned short ext_len = 2;
const unsigned char list_len = 1;
if ((lenmax = limit - ret - 6) < 0) return NULL;
s2n(TLSEXT_TYPE_server_authz, ret);
/* Extension length: 2 bytes */
s2n(ext_len, ret);
*(ret++) = list_len;
*(ret++) = TLSEXT_AUTHZDATAFORMAT_audit_proof;
}
if ((extdatalen = ret-p-2) == 0)
return p;
s2n(extdatalen,p);
@ -1170,6 +1203,75 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
}
#endif
/* If the client supports authz then see whether we have any to offer
* to it. */
if (s->s3->tlsext_authz_client_types_len)
{
size_t authz_length;
/* By now we already know the new cipher, so we can look ahead
* to see whether the cert we are going to send
* has any authz data attached to it. */
const unsigned char* authz = ssl_get_authz_data(s, &authz_length);
const unsigned char* const orig_authz = authz;
size_t i;
unsigned authz_count = 0;
/* The authz data contains a number of the following structures:
* uint8_t authz_type
* uint16_t length
* uint8_t data[length]
*
* First we walk over it to find the number of authz elements. */
for (i = 0; i < authz_length; i++)
{
unsigned short length;
unsigned char type;
type = *(authz++);
if (memchr(s->s3->tlsext_authz_client_types,
type,
s->s3->tlsext_authz_client_types_len) != NULL)
authz_count++;
n2s(authz, length);
authz += length;
i += length;
}
if (authz_count)
{
/* Add TLS extension server_authz to the ServerHello message
* 2 bytes for extension type
* 2 bytes for extension length
* 1 byte for the list length
* n bytes for the list */
const unsigned short ext_len = 1 + authz_count;
if ((long)(limit - ret - 4 - ext_len) < 0) return NULL;
s2n(TLSEXT_TYPE_server_authz, ret);
s2n(ext_len, ret);
*(ret++) = authz_count;
s->s3->tlsext_authz_promised_to_client = 1;
}
authz = orig_authz;
for (i = 0; i < authz_length; i++)
{
unsigned short length;
unsigned char type;
authz_count++;
type = *(authz++);
if (memchr(s->s3->tlsext_authz_client_types,
type,
s->s3->tlsext_authz_client_types_len) != NULL)
*(ret++) = type;
n2s(authz, length);
authz += length;
i += length;
}
}
if ((extdatalen = ret-p-2)== 0)
return p;
@ -1650,9 +1752,67 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
return 0;
}
else if (type == TLSEXT_TYPE_server_authz)
{
unsigned char *sdata = data;
unsigned char server_authz_dataformatlist_length;
if (size == 0)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
server_authz_dataformatlist_length = *(sdata++);
if (server_authz_dataformatlist_length != size - 1)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
/* Successful session resumption uses the same authz
* information as the original session so we ignore this
* in the case of a session resumption. */
if (!s->hit)
{
size_t i;
s->s3->tlsext_authz_client_types =
OPENSSL_malloc(server_authz_dataformatlist_length);
if (!s->s3->tlsext_authz_client_types)
{
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
s->s3->tlsext_authz_client_types_len =
server_authz_dataformatlist_length;
memcpy(s->s3->tlsext_authz_client_types,
sdata,
server_authz_dataformatlist_length);
/* Sort the types in order to check for duplicates. */
qsort(s->s3->tlsext_authz_client_types,
server_authz_dataformatlist_length,
1 /* element size */,
byte_compare);
for (i = 0; i < server_authz_dataformatlist_length; i++)
{
if (i > 0 &&
s->s3->tlsext_authz_client_types[i] ==
s->s3->tlsext_authz_client_types[i-1])
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
}
}
}
data+=size;
}
*p = data;
ri_check:
@ -1916,7 +2076,46 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
return 0;
}
data+=size;
else if (type == TLSEXT_TYPE_server_authz)
{
/* We only support audit proofs. It's an error to send
* an authz hello extension if the client
* didn't request a proof. */
unsigned char *sdata = data;
unsigned char server_authz_dataformatlist_length;
if (!s->ctx->tlsext_authz_server_audit_proof_cb)
{
*al = TLS1_AD_UNSUPPORTED_EXTENSION;
return 0;
}
if (!size)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
server_authz_dataformatlist_length = *(sdata++);
if (server_authz_dataformatlist_length != size - 1)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
/* We only support audit proofs, so a legal ServerHello
* authz list contains exactly one entry. */
if (server_authz_dataformatlist_length != 1 ||
sdata[0] != TLSEXT_AUTHZDATAFORMAT_audit_proof)
{
*al = TLS1_AD_UNSUPPORTED_EXTENSION;
return 0;
}
s->s3->tlsext_authz_server_promised = 1;
}
data += size;
}
if (data != d+n)

View File

@ -281,6 +281,14 @@ extern "C" {
#define TLSEXT_MAXLEN_host_name 255
/* From RFC 5878 */
#define TLSEXT_SUPPLEMENTALDATATYPE_authz_data 16386
/* This is not IANA assigned. See
* https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#authorization-data-rules */
#define TLSEXT_AUTHZDATAFORMAT_audit_proof 182
#define TLSEXT_MAXLEN_supplemental_data 1024*16 /* Let's limit to 16k */
const char *SSL_get_servername(const SSL *s, const int type);
int SSL_get_servername_type(const SSL *s);
/* SSL_export_keying_material exports a value derived from the master secret,
@ -360,6 +368,13 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG, 0, arg)
#define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \
SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
/* Used by clients to process audit proofs. */
#define SSL_CTX_set_tlsext_authz_server_audit_proof_cb(ctx, cb) \
SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TLSEXT_AUTHZ_SERVER_AUDIT_PROOF_CB,(void (*)(void))cb)
#define SSL_CTX_set_tlsext_authz_server_audit_proof_cb_arg(ctx, arg) \
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_AUTHZ_SERVER_AUDIT_PROOF_CB_ARG, 0, arg);
#ifndef OPENSSL_NO_HEARTBEATS
#define SSL_TLSEXT_HB_ENABLED 0x01
#define SSL_TLSEXT_HB_DONT_SEND_REQUESTS 0x02