diff options
author | Ben Laurie <ben@openssl.org> | 2012-05-30 10:10:58 +0000 |
---|---|---|
committer | Ben Laurie <ben@openssl.org> | 2012-05-30 10:10:58 +0000 |
commit | a9e1c50bb09a110d4774e6710f9322344684fa2d (patch) | |
tree | e030d9ea1f33d1c7d310e8ceba621e77e59b988b /ssl | |
parent | 03c1d9f99d95e19d4940aae8587808924cab486a (diff) |
RFC 5878 support.
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/s23_clnt.c | 2 | ||||
-rw-r--r-- | ssl/s3_clnt.c | 140 | ||||
-rw-r--r-- | ssl/s3_lib.c | 11 | ||||
-rw-r--r-- | ssl/s3_srvr.c | 116 | ||||
-rw-r--r-- | ssl/ssl.h | 39 | ||||
-rw-r--r-- | ssl/ssl3.h | 22 | ||||
-rw-r--r-- | ssl/ssl_cert.c | 20 | ||||
-rw-r--r-- | ssl/ssl_err.c | 12 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 79 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 15 | ||||
-rw-r--r-- | ssl/ssl_rsa.c | 120 | ||||
-rw-r--r-- | ssl/ssl_sess.c | 11 | ||||
-rw-r--r-- | ssl/t1_lib.c | 205 | ||||
-rw-r--r-- | ssl/tls1.h | 15 |
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 @@ -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) |