+#ifdef KSSL_DEBUG
+ fprintf(stderr, "tls1_generate_master_secret() complete\n");
+#endif /* KSSL_DEBUG */
+ return (SSL3_MASTER_SECRET_SIZE);
+}
+
+int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
+ const char *label, size_t llen,
+ const unsigned char *context,
+ size_t contextlen, int use_context)
+{
+ unsigned char *buff;
+ unsigned char *val = NULL;
+ size_t vallen, currentvalpos;
+ int rv;
+
+#ifdef KSSL_DEBUG
+ fprintf(stderr, "tls1_export_keying_material(%p,%p,%lu,%s,%lu,%p,%lu)\n",
+ s, out, olen, label, llen, context, contextlen);
+#endif /* KSSL_DEBUG */
+
+ buff = OPENSSL_malloc(olen);
+ if (buff == NULL)
+ goto err2;
+
+ /*
+ * construct PRF arguments we construct the PRF argument ourself rather
+ * than passing separate values into the TLS PRF to ensure that the
+ * concatenation of values does not create a prohibited label.
+ */
+ vallen = llen + SSL3_RANDOM_SIZE * 2;
+ if (use_context) {
+ vallen += 2 + contextlen;
+ }
+
+ val = OPENSSL_malloc(vallen);
+ if (val == NULL)
+ goto err2;
+ currentvalpos = 0;
+ memcpy(val + currentvalpos, (unsigned char *)label, llen);
+ currentvalpos += llen;
+ memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
+ currentvalpos += SSL3_RANDOM_SIZE;
+ memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
+ currentvalpos += SSL3_RANDOM_SIZE;
+
+ if (use_context) {
+ val[currentvalpos] = (contextlen >> 8) & 0xff;
+ currentvalpos++;
+ val[currentvalpos] = contextlen & 0xff;
+ currentvalpos++;
+ if ((contextlen > 0) || (context != NULL)) {
+ memcpy(val + currentvalpos, context, contextlen);
+ }
+ }
+
+ /*
+ * disallow prohibited labels note that SSL3_RANDOM_SIZE > max(prohibited
+ * label len) = 15, so size of val > max(prohibited label len) = 15 and
+ * the comparisons won't have buffer overflow
+ */
+ if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST,
+ TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0)
+ goto err1;
+ if (memcmp(val, TLS_MD_SERVER_FINISH_CONST,
+ TLS_MD_SERVER_FINISH_CONST_SIZE) == 0)
+ goto err1;
+ if (memcmp(val, TLS_MD_MASTER_SECRET_CONST,
+ TLS_MD_MASTER_SECRET_CONST_SIZE) == 0)
+ goto err1;
+ if (memcmp(val, TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+ TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE) == 0)
+ goto err1;
+ if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST,
+ TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0)
+ goto err1;
+
+ rv = tls1_PRF(ssl_get_algorithm2(s),
+ val, vallen,
+ NULL, 0,
+ NULL, 0,
+ NULL, 0,
+ NULL, 0,
+ s->session->master_key, s->session->master_key_length,
+ out, buff, olen);
+ OPENSSL_cleanse(val, vallen);
+ OPENSSL_cleanse(buff, olen);
+
+#ifdef KSSL_DEBUG
+ fprintf(stderr, "tls1_export_keying_material() complete\n");
+#endif /* KSSL_DEBUG */
+ goto ret;
+ err1:
+ SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL,
+ SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
+ rv = 0;
+ goto ret;
+ err2:
+ SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, ERR_R_MALLOC_FAILURE);
+ rv = 0;
+ ret:
+ if (buff != NULL)
+ OPENSSL_free(buff);
+ if (val != NULL)
+ OPENSSL_free(val);
+ return (rv);
+}
+
+int tls1_alert_code(int code)
+{
+ switch (code) {
+ case SSL_AD_CLOSE_NOTIFY:
+ return (SSL3_AD_CLOSE_NOTIFY);
+ case SSL_AD_UNEXPECTED_MESSAGE:
+ return (SSL3_AD_UNEXPECTED_MESSAGE);
+ case SSL_AD_BAD_RECORD_MAC:
+ return (SSL3_AD_BAD_RECORD_MAC);
+ case SSL_AD_DECRYPTION_FAILED:
+ return (TLS1_AD_DECRYPTION_FAILED);
+ case SSL_AD_RECORD_OVERFLOW:
+ return (TLS1_AD_RECORD_OVERFLOW);
+ case SSL_AD_DECOMPRESSION_FAILURE:
+ return (SSL3_AD_DECOMPRESSION_FAILURE);
+ case SSL_AD_HANDSHAKE_FAILURE:
+ return (SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_NO_CERTIFICATE:
+ return (-1);
+ case SSL_AD_BAD_CERTIFICATE:
+ return (SSL3_AD_BAD_CERTIFICATE);
+ case SSL_AD_UNSUPPORTED_CERTIFICATE:
+ return (SSL3_AD_UNSUPPORTED_CERTIFICATE);
+ case SSL_AD_CERTIFICATE_REVOKED:
+ return (SSL3_AD_CERTIFICATE_REVOKED);
+ case SSL_AD_CERTIFICATE_EXPIRED:
+ return (SSL3_AD_CERTIFICATE_EXPIRED);
+ case SSL_AD_CERTIFICATE_UNKNOWN:
+ return (SSL3_AD_CERTIFICATE_UNKNOWN);
+ case SSL_AD_ILLEGAL_PARAMETER:
+ return (SSL3_AD_ILLEGAL_PARAMETER);
+ case SSL_AD_UNKNOWN_CA:
+ return (TLS1_AD_UNKNOWN_CA);
+ case SSL_AD_ACCESS_DENIED:
+ return (TLS1_AD_ACCESS_DENIED);
+ case SSL_AD_DECODE_ERROR:
+ return (TLS1_AD_DECODE_ERROR);
+ case SSL_AD_DECRYPT_ERROR:
+ return (TLS1_AD_DECRYPT_ERROR);
+ case SSL_AD_EXPORT_RESTRICTION:
+ return (TLS1_AD_EXPORT_RESTRICTION);
+ case SSL_AD_PROTOCOL_VERSION:
+ return (TLS1_AD_PROTOCOL_VERSION);
+ case SSL_AD_INSUFFICIENT_SECURITY:
+ return (TLS1_AD_INSUFFICIENT_SECURITY);
+ case SSL_AD_INTERNAL_ERROR:
+ return (TLS1_AD_INTERNAL_ERROR);
+ case SSL_AD_USER_CANCELLED:
+ return (TLS1_AD_USER_CANCELLED);
+ case SSL_AD_NO_RENEGOTIATION:
+ return (TLS1_AD_NO_RENEGOTIATION);
+ case SSL_AD_UNSUPPORTED_EXTENSION:
+ return (TLS1_AD_UNSUPPORTED_EXTENSION);
+ case SSL_AD_CERTIFICATE_UNOBTAINABLE:
+ return (TLS1_AD_CERTIFICATE_UNOBTAINABLE);
+ case SSL_AD_UNRECOGNIZED_NAME:
+ return (TLS1_AD_UNRECOGNIZED_NAME);
+ case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+ return (TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
+ case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
+ return (TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);
+ case SSL_AD_UNKNOWN_PSK_IDENTITY:
+ return (TLS1_AD_UNKNOWN_PSK_IDENTITY);
+ case SSL_AD_INAPPROPRIATE_FALLBACK:
+ return (TLS1_AD_INAPPROPRIATE_FALLBACK);
+ default:
+ return (-1);
+ }
+}