+#ifndef OPENSSL_NO_PSK
+ /* For PSK parse and retrieve identity, obtain PSK key */
+ if (alg_k & SSL_PSK) {
+ unsigned char psk[PSK_MAX_PSK_LEN];
+ size_t psklen;
+ if (n < 2) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ n2s(p, i);
+ if (i + 2 > n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ if (i > PSK_MAX_IDENTITY_LEN) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+ if (s->psk_server_callback == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ SSL_R_PSK_NO_SERVER_CB);
+ goto f_err;
+ }
+
+ OPENSSL_free(s->session->psk_identity);
+ s->session->psk_identity = BUF_strndup((char *)p, i);
+
+ if (s->session->psk_identity == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+
+ psklen = s->psk_server_callback(s, s->session->psk_identity,
+ psk, sizeof(psk));
+
+ if (psklen > PSK_MAX_PSK_LEN) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ } else if (psklen == 0) {
+ /*
+ * PSK related to the given identity not found
+ */
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ al = SSL_AD_UNKNOWN_PSK_IDENTITY;
+ goto f_err;
+ }
+
+ OPENSSL_free(s->s3->tmp.psk);
+ s->s3->tmp.psk = BUF_memdup(psk, psklen);
+ OPENSSL_cleanse(psk, psklen);
+
+ if (s->s3->tmp.psk == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+
+ s->s3->tmp.psklen = psklen;
+
+ n -= i + 2;
+ p += i;
+ }
+ if (alg_k & SSL_kPSK) {
+ /* Identity extracted earlier: should be nothing left */
+ if (n != 0) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ /* PSK handled by ssl_generate_master_secret */
+ if (!ssl_generate_master_secret(s, NULL, 0, 0)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+ } else
+#endif