+
+#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