summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorBen Laurie <ben@openssl.org>2012-05-30 10:10:58 +0000
committerBen Laurie <ben@openssl.org>2012-05-30 10:10:58 +0000
commita9e1c50bb09a110d4774e6710f9322344684fa2d (patch)
treee030d9ea1f33d1c7d310e8ceba621e77e59b988b /ssl
parent03c1d9f99d95e19d4940aae8587808924cab486a (diff)
RFC 5878 support.
Diffstat (limited to 'ssl')
-rw-r--r--ssl/s23_clnt.c2
-rw-r--r--ssl/s3_clnt.c140
-rw-r--r--ssl/s3_lib.c11
-rw-r--r--ssl/s3_srvr.c116
-rw-r--r--ssl/ssl.h39
-rw-r--r--ssl/ssl3.h22
-rw-r--r--ssl/ssl_cert.c20
-rw-r--r--ssl/ssl_err.c12
-rw-r--r--ssl/ssl_lib.c79
-rw-r--r--ssl/ssl_locl.h15
-rw-r--r--ssl/ssl_rsa.c120
-rw-r--r--ssl/ssl_sess.c11
-rw-r--r--ssl/t1_lib.c205
-rw-r--r--ssl/tls1.h15
14 files changed, 764 insertions, 43 deletions
diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c
index 47673e740a..807dd0ba26 100644
--- a/ssl/s23_clnt.c
+++ b/ssl/s23_clnt.c
@@ -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
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index cd4f0ad468..e8fe968e59 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -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
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 0456230fd3..9653de6eea 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -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:
{
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 632b924ef2..ba324848c1 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -403,9 +403,30 @@ 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:
@@ -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
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 352e91b32a..31eccf904d 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -539,12 +539,19 @@ 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
};
#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
diff --git a/ssl/ssl3.h b/ssl/ssl3.h
index 4e72c1749b..84198ff501 100644
--- a/ssl/ssl3.h
+++ b/ssl/ssl3.h
@@ -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
-
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 222f703284..fcf462d41a 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -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;
@@ -422,6 +438,10 @@ void ssl_cert_free(CERT *c)
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)
OPENSSL_free(c->sigalgs);
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 0a43d249e8..ce004558a2 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -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"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 679894cb3d..cb098b3002 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -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);
+ }
+
+CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
+ {
+ CERT *c;
+ int i;
- return(&c->pkeys[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;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index b83b174da9..d0167e8283 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -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);
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index b7c19051e9..855952d54c 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -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)