#include <openssl/trace.h>
#include <internal/cryptlib.h>
+DEFINE_STACK_OF(X509)
+DEFINE_STACK_OF(SSL_COMP)
+DEFINE_STACK_OF_CONST(SSL_CIPHER)
+
static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt);
static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt);
return 0;
}
- /*
- * TODO(3.0) Remove this when EVP_PKEY_get1_tls_encodedpoint()
- * knows how to get a key from an encoded point with the help of
- * a OSSL_SERIALIZER deserializer. We know that EVP_PKEY_get0()
- * downgrades an EVP_PKEY to contain a legacy key.
- *
- * THIS IS TEMPORARY
- */
- EVP_PKEY_get0(s->s3.peer_tmp);
- if (EVP_PKEY_id(s->s3.peer_tmp) == EVP_PKEY_NONE) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3.peer_tmp,
PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt))) {
goto err;
}
- /*
- * TODO(3.0) Remove this when EVP_PKEY_get1_tls_encodedpoint()
- * knows how to get a key from an encoded point with the help of
- * a OSSL_SERIALIZER deserializer. We know that EVP_PKEY_get0()
- * downgrades an EVP_PKEY to contain a legacy key.
- *
- * THIS IS TEMPORARY
- */
- EVP_PKEY_get0(ckey);
- if (EVP_PKEY_id(skey) == EVP_PKEY_NONE) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
if (ssl_derive(s, ckey, skey, 0) == 0) {
/* SSLfatal() already called */
goto err;
#endif
}
+#ifndef OPENSSL_NO_GOST
+int gost18_cke_cipher_nid(const SSL *s)
+{
+ if ((s->s3.tmp.new_cipher->algorithm_enc & SSL_MAGMA) != 0)
+ return NID_magma_ctr;
+ else if ((s->s3.tmp.new_cipher->algorithm_enc & SSL_KUZNYECHIK) != 0)
+ return NID_kuznyechik_ctr;
+
+ return NID_undef;
+}
+
+int gost_ukm(const SSL *s, unsigned char *dgst_buf)
+{
+ EVP_MD_CTX * hash = NULL;
+ unsigned int md_len;
+ const EVP_MD *md = ssl_evp_md_fetch(s->ctx->libctx, NID_id_GostR3411_2012_256, s->ctx->propq);
+
+ if (md == NULL)
+ return 0;
+
+ if ((hash = EVP_MD_CTX_new()) == NULL
+ || EVP_DigestInit(hash, md) <= 0
+ || EVP_DigestUpdate(hash, s->s3.client_random, SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(hash, s->s3.server_random, SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestFinal_ex(hash, dgst_buf, &md_len) <= 0) {
+ EVP_MD_CTX_free(hash);
+ ssl_evp_md_free(md);
+ return 0;
+ }
+
+ EVP_MD_CTX_free(hash);
+ ssl_evp_md_free(md);
+ return 1;
+}
+#endif
+
+static int tls_construct_cke_gost18(SSL *s, WPACKET *pkt)
+{
+#ifndef OPENSSL_NO_GOST
+ /* GOST 2018 key exchange message creation */
+ unsigned char rnd_dgst[32], tmp[255];
+ EVP_PKEY_CTX *pkey_ctx = NULL;
+ X509 *peer_cert;
+ unsigned char *pms = NULL;
+ size_t pmslen = 0;
+ size_t msglen;
+ int cipher_nid = gost18_cke_cipher_nid(s);
+
+ if (cipher_nid == NID_undef) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (gost_ukm(s, rnd_dgst) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Pre-master secret - random bytes */
+ pmslen = 32;
+ pms = OPENSSL_malloc(pmslen);
+ if (pms == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_bytes_ex(s->ctx->libctx, pms, (int)pmslen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Get server certificate PKEY and create ctx from it */
+ peer_cert = s->session->peer;
+ if (peer_cert == NULL) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+ return 0;
+ }
+
+ pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, X509_get0_pubkey(peer_cert), s->ctx->propq);
+ if (pkey_ctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0 ) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ };
+
+ /* Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code */
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
+ EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
+ EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+
+ msglen = 255;
+ if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+
+ if (!WPACKET_memcpy(pkt, tmp, msglen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ EVP_PKEY_CTX_free(pkey_ctx);
+ s->s3.tmp.pms = pms;
+ s->s3.tmp.pmslen = pmslen;
+
+ return 1;
+ err:
+ EVP_PKEY_CTX_free(pkey_ctx);
+ OPENSSL_clear_free(pms, pmslen);
+ return 0;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST18,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
static int tls_construct_cke_srp(SSL *s, WPACKET *pkt)
{
#ifndef OPENSSL_NO_SRP
} else if (alg_k & SSL_kGOST) {
if (!tls_construct_cke_gost(s, pkt))
goto err;
+ } else if (alg_k & SSL_kGOST18) {
+ if (!tls_construct_cke_gost18(s, pkt))
+ goto err;
} else if (alg_k & SSL_kSRP) {
if (!tls_construct_cke_srp(s, pkt))
goto err;