Commit 5a5530a2 authored by Dmitry Belyavskiy's avatar Dmitry Belyavskiy

New Russian TLS 1.2 implementation

Reviewed-by: default avatarMatt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11442)
parent 0e139a02
......@@ -977,6 +977,8 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
unsigned char padval;
int imac_size;
const EVP_CIPHER *enc;
int tlstree_enc = sending ? (s->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE)
: (s->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE);
if (n_recs == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
......@@ -1156,6 +1158,27 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
}
}
if (!SSL_IS_DTLS(s) && tlstree_enc) {
unsigned char *seq;
int decrement_seq = 0;
/*
* When sending, seq is incremented after MAC calculation.
* So if we are in ETM mode, we use seq 'as is' in the ctrl-function.
* Otherwise we have to decrease it in the implementation
*/
if (sending && !SSL_WRITE_ETM(s))
decrement_seq = 1;
seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer)
: RECORD_LAYER_get_read_sequence(&s->rlayer);
if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_TLSTREE, decrement_seq, seq) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
ERR_R_INTERNAL_ERROR);
return -1;
}
}
/* TODO(size_t): Convert this call */
tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input,
(unsigned int)reclen[0]);
......@@ -1319,8 +1342,10 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
int i;
EVP_MD_CTX *hmac = NULL, *mac_ctx;
unsigned char header[13];
int stream_mac = (sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
: (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM));
int stream_mac = sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
: (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM);
int tlstree_mac = sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE)
: (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE);
int t;
if (sending) {
......@@ -1348,6 +1373,11 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
mac_ctx = hmac;
}
if (!SSL_IS_DTLS(ssl) && tlstree_mac && EVP_MD_CTX_ctrl(mac_ctx, EVP_MD_CTRL_TLSTREE, 0, seq) <= 0) {
EVP_MD_CTX_free(hmac);
return 0;
}
if (SSL_IS_DTLS(ssl)) {
unsigned char dtlsseq[8], *p = dtlsseq;
......
......@@ -2687,6 +2687,38 @@ static SSL_CIPHER ssl3_ciphers[] = {
0,
0,
},
{
1,
"GOST2012-KUZNYECHIK-KUZNYECHIKOMAC",
NULL,
0x0300C100,
SSL_kGOST18,
SSL_aGOST12,
SSL_KUZNYECHIK,
SSL_KUZNYECHIKOMAC,
TLS1_2_VERSION, TLS1_2_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_TLSTREE,
256,
256,
},
{
1,
"GOST2012-MAGMA-MAGMAOMAC",
NULL,
0x0300C101,
SSL_kGOST18,
SSL_aGOST12,
SSL_MAGMA,
SSL_MAGMAOMAC,
TLS1_2_VERSION, TLS1_2_VERSION,
0, 0,
SSL_HIGH,
SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_TLSTREE,
256,
256,
},
#endif /* OPENSSL_NO_GOST */
#ifndef OPENSSL_NO_IDEA
......@@ -4374,11 +4406,17 @@ int ssl3_get_req_cert_type(SSL *s, WPACKET *pkt)
#ifndef OPENSSL_NO_GOST
if (s->version >= TLS1_VERSION && (alg_k & SSL_kGOST))
return WPACKET_put_bytes_u8(pkt, TLS_CT_GOST01_SIGN)
&& WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_SIGN)
&& WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_512_SIGN)
&& WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_LEGACY_SIGN)
&& WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_LEGACY_512_SIGN);
if (!WPACKET_put_bytes_u8(pkt, TLS_CT_GOST01_SIGN)
|| !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_SIGN)
|| !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_512_SIGN)
|| !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_LEGACY_SIGN)
|| !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_LEGACY_512_SIGN))
return 0;
if (s->version >= TLS1_2_VERSION && (alg_k & SSL_kGOST18))
if (!WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_SIGN)
|| !WPACKET_put_bytes_u8(pkt, TLS_CT_GOST12_IANA_512_SIGN))
return 0;
#endif
if ((s->version == SSL3_VERSION) && (alg_k & SSL_kDHE)) {
......
......@@ -56,6 +56,8 @@ static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = {
{SSL_CHACHA20POLY1305, NID_chacha20_poly1305}, /* SSL_ENC_CHACHA_IDX 19 */
{SSL_ARIA128GCM, NID_aria_128_gcm}, /* SSL_ENC_ARIA128GCM_IDX 20 */
{SSL_ARIA256GCM, NID_aria_256_gcm}, /* SSL_ENC_ARIA256GCM_IDX 21 */
{SSL_MAGMA, NID_magma_ctr_acpkm}, /* SSL_ENC_MAGMA_IDX */
{SSL_KUZNYECHIK, NID_kuznyechik_ctr_acpkm}, /* SSL_ENC_KUZNYECHIK_IDX */
};
#define SSL_COMP_NULL_IDX 0
......@@ -81,7 +83,9 @@ static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = {
{SSL_GOST12_512, NID_id_GostR3411_2012_512}, /* SSL_MD_GOST12_512_IDX 8 */
{0, NID_md5_sha1}, /* SSL_MD_MD5_SHA1_IDX 9 */
{0, NID_sha224}, /* SSL_MD_SHA224_IDX 10 */
{0, NID_sha512} /* SSL_MD_SHA512_IDX 11 */
{0, NID_sha512}, /* SSL_MD_SHA512_IDX 11 */
{SSL_MAGMAOMAC, NID_magma_mac}, /* sSL_MD_MAGMAOMAC_IDX */
{SSL_KUZNYECHIKOMAC, NID_kuznyechik_mac} /* SSL_MD_KUZNYECHIKOMAC_IDX */
};
/* *INDENT-OFF* */
......@@ -95,6 +99,7 @@ static const ssl_cipher_table ssl_cipher_table_kx[] = {
{SSL_kPSK, NID_kx_psk},
{SSL_kSRP, NID_kx_srp},
{SSL_kGOST, NID_kx_gost},
{SSL_kGOST18, NID_kx_gost18},
{SSL_kANY, NID_kx_any}
};
......@@ -138,8 +143,8 @@ static int ssl_mac_pkey_id[SSL_MD_NUM_IDX] = {
EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef,
/* GOST2012_512 */
EVP_PKEY_HMAC,
/* MD5/SHA1, SHA224, SHA512 */
NID_undef, NID_undef, NID_undef
/* MD5/SHA1, SHA224, SHA512, MAGMAOMAC, KUZNYECHIKOMAC */
NID_undef, NID_undef, NID_undef, NID_undef, NID_undef
};
#define CIPHER_ADD 1
......@@ -193,6 +198,7 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_kDHEPSK, NULL, 0, SSL_kDHEPSK},
{0, SSL_TXT_kSRP, NULL, 0, SSL_kSRP},
{0, SSL_TXT_kGOST, NULL, 0, SSL_kGOST},
{0, SSL_TXT_kGOST18, NULL, 0, SSL_kGOST18},
/* server authentication aliases */
{0, SSL_TXT_aRSA, NULL, 0, 0, SSL_aRSA},
......@@ -226,7 +232,8 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_IDEA, NULL, 0, 0, 0, SSL_IDEA},
{0, SSL_TXT_SEED, NULL, 0, 0, 0, SSL_SEED},
{0, SSL_TXT_eNULL, NULL, 0, 0, 0, SSL_eNULL},
{0, SSL_TXT_GOST, NULL, 0, 0, 0, SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12},
{0, SSL_TXT_GOST, NULL, 0, 0, 0,
SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12 | SSL_MAGMA | SSL_KUZNYECHIK},
{0, SSL_TXT_AES128, NULL, 0, 0, 0,
SSL_AES128 | SSL_AES128GCM | SSL_AES128CCM | SSL_AES128CCM8},
{0, SSL_TXT_AES256, NULL, 0, 0, 0,
......@@ -381,24 +388,38 @@ int ssl_load_ciphers(SSL_CTX *ctx)
* Check for presence of GOST 34.10 algorithms, and if they are not
* present, disable appropriate auth and key exchange
*/
ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id("gost-mac");
ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX] = get_optional_pkey_id(SN_id_Gost28147_89_MAC);
if (ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX])
ctx->ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX] = 32;
else
disabled_mac_mask |= SSL_GOST89MAC;
ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX] =
get_optional_pkey_id("gost-mac-12");
get_optional_pkey_id(SN_gost_mac_12);
if (ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX])
ctx->ssl_mac_secret_size[SSL_MD_GOST89MAC12_IDX] = 32;
else
disabled_mac_mask |= SSL_GOST89MAC12;
if (!get_optional_pkey_id("gost2001"))
ssl_mac_pkey_id[SSL_MD_MAGMAOMAC_IDX] =
get_optional_pkey_id(SN_magma_mac);
if (ssl_mac_pkey_id[SSL_MD_MAGMAOMAC_IDX])
ctx->ssl_mac_secret_size[SSL_MD_MAGMAOMAC_IDX] = 32;
else
disabled_mac_mask |= SSL_MAGMAOMAC;
ssl_mac_pkey_id[SSL_MD_KUZNYECHIKOMAC_IDX] =
get_optional_pkey_id(SN_kuznyechik_mac);
if (ssl_mac_pkey_id[SSL_MD_KUZNYECHIKOMAC_IDX])
ctx->ssl_mac_secret_size[SSL_MD_KUZNYECHIKOMAC_IDX] = 32;
else
disabled_mac_mask |= SSL_KUZNYECHIKOMAC;
if (!get_optional_pkey_id(SN_id_GostR3410_2001))
disabled_auth_mask |= SSL_aGOST01 | SSL_aGOST12;
if (!get_optional_pkey_id("gost2012_256"))
if (!get_optional_pkey_id(SN_id_GostR3410_2012_256))
disabled_auth_mask |= SSL_aGOST12;
if (!get_optional_pkey_id("gost2012_512"))
if (!get_optional_pkey_id(SN_id_GostR3410_2012_512))
disabled_auth_mask |= SSL_aGOST12;
/*
* Disable GOST key exchange if no GOST signature algs are available *
......@@ -407,6 +428,9 @@ int ssl_load_ciphers(SSL_CTX *ctx)
(SSL_aGOST01 | SSL_aGOST12))
disabled_mkey_mask |= SSL_kGOST;
if ((disabled_auth_mask & SSL_aGOST12) == SSL_aGOST12)
disabled_mkey_mask |= SSL_kGOST18;
return 1;
}
......@@ -1695,6 +1719,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
case SSL_kGOST:
kx = "GOST";
break;
case SSL_kGOST18:
kx = "GOST18";
break;
case SSL_kANY:
kx = "any";
break;
......@@ -1798,6 +1825,12 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
case SSL_eGOST2814789CNT12:
enc = "GOST89(256)";
break;
case SSL_MAGMA:
enc = "MAGMA";
break;
case SSL_KUZNYECHIK:
enc = "KUZNYECHIK";
break;
case SSL_CHACHA20POLY1305:
enc = "CHACHA20/POLY1305(256)";
break;
......
......@@ -14,6 +14,8 @@
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ALGORITHM_FETCH_FAILED),
"algorithm fetch failed"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY),
"application data after close notify"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APP_DATA_IN_HANDSHAKE),
......@@ -171,8 +173,6 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"ext length mismatch"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FAILED_TO_INIT_ASYNC),
"failed to init async"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_ALGORITHM_FETCH_FAILED),
"algorithm fetch failed"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_FRAGMENTED_CLIENT_HELLO),
"fragmented client hello"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_GOT_A_FIN_BEFORE_A_CCS),
......
......@@ -3495,11 +3495,11 @@ void ssl_set_masks(SSL *s)
#ifndef OPENSSL_NO_GOST
if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) {
mask_k |= SSL_kGOST;
mask_k |= SSL_kGOST | SSL_kGOST18;
mask_a |= SSL_aGOST12;
}
if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) {
mask_k |= SSL_kGOST;
mask_k |= SSL_kGOST | SSL_kGOST18;
mask_a |= SSL_aGOST12;
}
if (ssl_has_cert(s, SSL_PKEY_GOST01)) {
......
......@@ -180,6 +180,8 @@
# define SSL_kRSAPSK 0x00000040U
# define SSL_kECDHEPSK 0x00000080U
# define SSL_kDHEPSK 0x00000100U
/* GOST KDF key exchange, draft-smyshlyaev-tls12-gost-suites */
# define SSL_kGOST18 0x00000200U
/* all PSK */
......@@ -234,6 +236,8 @@
# define SSL_CHACHA20POLY1305 0x00080000U
# define SSL_ARIA128GCM 0x00100000U
# define SSL_ARIA256GCM 0x00200000U
# define SSL_MAGMA 0x00400000U
# define SSL_KUZNYECHIK 0x00800000U
# define SSL_AESGCM (SSL_AES128GCM | SSL_AES256GCM)
# define SSL_AESCCM (SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8)
......@@ -256,6 +260,8 @@
# define SSL_GOST12_256 0x00000080U
# define SSL_GOST89MAC12 0x00000100U
# define SSL_GOST12_512 0x00000200U
# define SSL_MAGMAOMAC 0x00000400U
# define SSL_KUZNYECHIKOMAC 0x00000800U
/*
* When adding new digest in the ssl_ciph.c and increment SSL_MD_NUM_IDX make
......@@ -274,7 +280,9 @@
# define SSL_MD_MD5_SHA1_IDX 9
# define SSL_MD_SHA224_IDX 10
# define SSL_MD_SHA512_IDX 11
# define SSL_MAX_DIGEST 12
# define SSL_MD_MAGMAOMAC_IDX 12
# define SSL_MD_KUZNYECHIKOMAC_IDX 13
# define SSL_MAX_DIGEST 14
#define SSL_MD_NUM_IDX SSL_MAX_DIGEST
......@@ -305,6 +313,11 @@
* goes into algorithm2)
*/
# define TLS1_STREAM_MAC 0x10000
/*
* TLSTREE cipher/mac key derivation from draft-smyshlyaev-tls12-gost-suites
* (currently this also goes into algorithm2)
*/
# define TLS1_TLSTREE 0x20000
# define SSL_STRONG_MASK 0x0000001FU
# define SSL_DEFAULT_MASK 0X00000020U
......@@ -413,7 +426,9 @@
# define SSL_ENC_CHACHA_IDX 19
# define SSL_ENC_ARIA128GCM_IDX 20
# define SSL_ENC_ARIA256GCM_IDX 21
# define SSL_ENC_NUM_IDX 22
# define SSL_ENC_MAGMA_IDX 22
# define SSL_ENC_KUZNYECHIK_IDX 23
# define SSL_ENC_NUM_IDX 24
/*-
* SSL_kRSA <- RSA_ENC
......
......@@ -1648,7 +1648,9 @@ EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
if (s->s3.tmp.new_cipher->algorithm_mac == SSL_AEAD
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_RC4
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_MAGMA
|| s->s3.tmp.new_cipher->algorithm_enc == SSL_KUZNYECHIK) {
s->ext.use_etm = 0;
return EXT_RETURN_NOT_SENT;
}
......
......@@ -3314,6 +3314,146 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
#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
......@@ -3370,6 +3510,9 @@ int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
} 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;
......
......@@ -153,6 +153,11 @@ __owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
__owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt);
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt);
#ifndef OPENSSL_NO_GOST
/* These functions are used in GOST18 CKE, both for client and server */
int gost18_cke_cipher_nid(const SSL *s);
int gost_ukm(const SSL *s, unsigned char *dgst_buf);
#endif
/* Extension processing */
......
......@@ -3430,6 +3430,93 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt)
#endif
}
static int tls_process_cke_gost18(SSL *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_GOST
unsigned char rnd_dgst[32];
EVP_PKEY_CTX *pkey_ctx = NULL;
EVP_PKEY *pk = NULL;
unsigned char premaster_secret[32];
const unsigned char *start = NULL;
size_t outlen = 32, inlen = 0;
int ret = 0;
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;
}
/* Get our certificate private key */
pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey != NULL ?
s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey :
s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
if (pk == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
SSL_R_BAD_HANDSHAKE_STATE);
goto err;
}
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pk, s->ctx->propq);
if (pkey_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code depending on size */
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
SSL_R_LIBRARY_BUG);
goto err;
}
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
SSL_R_LIBRARY_BUG);
goto err;
}
inlen = PACKET_remaining(pkt);
start = PACKET_data(pkt);
if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
SSL_R_DECRYPTION_FAILED);
goto err;
}
/* Generate master secret */
if (!ssl_generate_master_secret(s, premaster_secret,
sizeof(premaster_secret), 0)) {
/* SSLfatal() already called */
goto err;
}
ret = 1;
err:
EVP_PKEY_CTX_free(pkey_ctx);
return ret;
#else
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST18,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
{
unsigned long alg_k;
......@@ -3480,6 +3567,11 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
/* SSLfatal() already called */
goto err;
}
} else if (alg_k & SSL_kGOST18) {
if (!tls_process_cke_gost18(s, pkt)) {
/* SSLfatal() already called */
goto err;
}
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
......
......@@ -180,6 +180,11 @@ int tls1_change_cipher_state(SSL *s, int which)
else
s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;
if (s->s3.tmp.new_cipher->algorithm2 & TLS1_TLSTREE)
s->mac_flags |= SSL_MAC_FLAG_READ_MAC_TLSTREE;
else
s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_TLSTREE;
if (s->enc_read_ctx != NULL) {
reuse_dd = 1;
} else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
......@@ -230,6 +235,11 @@ int tls1_change_cipher_state(SSL *s, int which)
s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
else
s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
if (s->s3.tmp.new_cipher->algorithm2 & TLS1_TLSTREE)
s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_TLSTREE;
else
s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_TLSTREE;
if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) {
reuse_dd = 1;
} else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
......@@ -617,6 +627,10 @@ size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen,
{
size_t hashlen;
unsigned char hash[EVP_MAX_MD_SIZE];
size_t finished_size = TLS1_FINISH_MAC_LENGTH;
if (s->s3.tmp.new_cipher->algorithm_mkey & SSL_kGOST18)
finished_size = 32;
if (!ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
......@@ -630,12 +644,12 @@ size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen,
if (!tls1_PRF(s, str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0,
s->session->master_key, s->session->master_key_length,
out, TLS1_FINISH_MAC_LENGTH, 1)) {
out, finished_size, 1)) {
/* SSLfatal() already called */
return 0;
}
OPENSSL_cleanse(hash, hashlen);
return TLS1_FINISH_MAC_LENGTH;
return finished_size;
}
int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
......
......@@ -1001,6 +1001,21 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
}
}
}
/*
* As both SSL_PKEY_GOST12_512 and SSL_PKEY_GOST12_256 indices can be used
* with new (aGOST12-only) ciphersuites, we should find out which one is available really.
*/
else if (idx == SSL_PKEY_GOST12_256) {
int real_idx;
for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST12_256;
real_idx--) {
if (s->cert->pkeys[real_idx].privatekey != NULL) {
idx = real_idx;
break;
}
}
}
} else {
idx = s->cert->key - s->cert->pkeys;
}
......@@ -1794,7 +1809,7 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
continue;
if ((c->algorithm_mkey & SSL_kGOST) != 0)
if ((c->algorithm_mkey & (SSL_kGOST | SSL_kGOST18)) != 0)
break;
}
if (i == num)
......
......@@ -444,6 +444,9 @@ static const ssl_trace_tbl ssl_ciphers_tbl[] = {
{0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},
{0xFF85, "LEGACY-GOST2012-GOST8912-GOST8912"},
{0xFF87, "GOST2012-NULL-GOST12"},
{0xC100, "GOST2012-KUZNYECHIK-KUZNYECHIKOMAC"},
{0xC101, "GOST2012-MAGMA-MAGMAOMAC"},
{0xC102, "GOST2012-GOST8912-IANA"},