summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorDmitry Belyavsky <beldmit@gmail.com>2015-11-17 15:32:30 +0000
committerMatt Caswell <matt@openssl.org>2015-11-23 16:09:42 +0000
commite44380a990a3edf1cd0c190c6459c8c026d53646 (patch)
treecb605454d30bf0eeca8c6369fed11fa5ffd29726 /ssl
parent76eba0d94bb418325be6409b272eac5e2bd4a0a9 (diff)
Patch containing TLS implementation for GOST 2012
This patch contains the necessary changes to provide GOST 2012 ciphersuites in TLS. It requires the use of an external GOST 2012 engine. Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Rich Salz <rsalz@openssl.org>
Diffstat (limited to 'ssl')
-rw-r--r--ssl/s3_lib.c30
-rw-r--r--ssl/ssl_ciph.c65
-rw-r--r--ssl/ssl_lib.c20
-rw-r--r--ssl/ssl_locl.h25
-rw-r--r--ssl/statem/statem_clnt.c69
-rw-r--r--ssl/statem/statem_lib.c4
-rw-r--r--ssl/statem/statem_srvr.c78
-rw-r--r--ssl/t1_lib.c120
-rw-r--r--ssl/t1_trce.c10
9 files changed, 343 insertions, 78 deletions
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index d5e593a640..f40b143793 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3770,6 +3770,34 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
256,
},
+ {
+ 1,
+ "GOST2012-GOST8912-GOST8912",
+ 0x0300ff85,
+ SSL_kGOST,
+ SSL_aGOST12 | SSL_aGOST01,
+ SSL_eGOST2814789CNT12,
+ SSL_GOST89MAC12,
+ SSL_TLSV1,
+ SSL_NOT_EXP | SSL_HIGH,
+ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256 | TLS1_STREAM_MAC,
+ 256,
+ 256},
+ {
+ 1,
+ "GOST2012-NULL-GOST12",
+ 0x0300ff87,
+ SSL_kGOST,
+ SSL_aGOST12 | SSL_aGOST01,
+ SSL_eNULL,
+ SSL_GOST12_256,
+ SSL_TLSV1,
+ SSL_NOT_EXP | SSL_STRONG_NONE,
+ SSL_HANDSHAKE_MAC_GOST12_256 | TLS1_PRF_GOST12_256,
+ 0,
+ 0},
+
+
/* end of list */
};
@@ -4936,6 +4964,8 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
if (s->version >= TLS1_VERSION) {
if (alg_k & SSL_kGOST) {
p[ret++] = TLS_CT_GOST01_SIGN;
+ p[ret++] = TLS_CT_GOST12_SIGN;
+ p[ret++] = TLS_CT_GOST12_512_SIGN;
return (ret);
}
}
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index fe30ab47a1..47f5e0f130 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -168,7 +168,8 @@
#define SSL_ENC_AES256CCM_IDX 15
#define SSL_ENC_AES128CCM8_IDX 16
#define SSL_ENC_AES256CCM8_IDX 17
-#define SSL_ENC_NUM_IDX 18
+#define SSL_ENC_GOST8912_IDX 18
+#define SSL_ENC_NUM_IDX 19
/* NB: make sure indices in these tables match values above */
@@ -196,7 +197,8 @@ static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = {
{SSL_AES128CCM, NID_aes_128_ccm}, /* SSL_ENC_AES128CCM_IDX 14 */
{SSL_AES256CCM, NID_aes_256_ccm}, /* SSL_ENC_AES256CCM_IDX 15 */
{SSL_AES128CCM8, NID_aes_128_ccm}, /* SSL_ENC_AES128CCM8_IDX 16 */
- {SSL_AES256CCM8, NID_aes_256_ccm} /* SSL_ENC_AES256CCM8_IDX 17 */
+ {SSL_AES256CCM8, NID_aes_256_ccm}, /* SSL_ENC_AES256CCM8_IDX 17 */
+ {SSL_eGOST2814789CNT12, NID_gost89_cnt_12}, /* SSL_ENC_GOST8912_IDX */
};
static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX] = {
@@ -216,6 +218,9 @@ static STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
#define SSL_MD_GOST89MAC_IDX 3
#define SSL_MD_SHA256_IDX 4
#define SSL_MD_SHA384_IDX 5
+#define SSL_MD_GOST12_256_IDX 6
+#define SSL_MD_GOST89MAC12_IDX 7
+#define SSL_MD_GOST12_512_IDX 8
/*
* Constant SSL_MAX_DIGEST equal to size of digests array should be defined
* in the ssl_locl.h
@@ -230,11 +235,14 @@ static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = {
{SSL_GOST94, NID_id_GostR3411_94}, /* SSL_MD_GOST94_IDX 2 */
{SSL_GOST89MAC, NID_id_Gost28147_89_MAC}, /* SSL_MD_GOST89MAC_IDX 3 */
{SSL_SHA256, NID_sha256}, /* SSL_MD_SHA256_IDX 4 */
- {SSL_SHA384, NID_sha384} /* SSL_MD_SHA384_IDX 5 */
+ {SSL_SHA384, NID_sha384}, /* SSL_MD_SHA384_IDX 5 */
+ {SSL_GOST12_256, NID_id_GostR3411_2012_256}, /* SSL_MD_GOST12_256_IDX 6 */
+ {SSL_GOST89MAC12, NID_gost_mac_12}, /* SSL_MD_GOST89MAC12_IDX 7 */
+ {SSL_GOST12_512, NID_id_GostR3411_2012_512} /* SSL_MD_GOST12_512_IDX 8 */
};
static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX] = {
- NULL, NULL, NULL, NULL, NULL, NULL
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
/* Utility function for table lookup */
@@ -258,18 +266,23 @@ static int ssl_cipher_info_find(const ssl_cipher_table * table,
* found
*/
static int ssl_mac_pkey_id[SSL_MD_NUM_IDX] = {
+ /* MD5, SHA, GOST94, MAC89 */
EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef,
- EVP_PKEY_HMAC, EVP_PKEY_HMAC
+ /* SHA256, SHA384, GOST2012_256, MAC89-12 */
+ EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, NID_undef,
+ /* GOST2012_512 */
+ EVP_PKEY_HMAC,
};
static int ssl_mac_secret_size[SSL_MD_NUM_IDX] = {
- 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static const int ssl_handshake_digest_flag[SSL_MD_NUM_IDX] = {
SSL_HANDSHAKE_MAC_MD5, SSL_HANDSHAKE_MAC_SHA,
SSL_HANDSHAKE_MAC_GOST94, 0, SSL_HANDSHAKE_MAC_SHA256,
- SSL_HANDSHAKE_MAC_SHA384
+ SSL_HANDSHAKE_MAC_SHA384, SSL_HANDSHAKE_MAC_GOST12_256, 0,
+ SSL_HANDSHAKE_MAC_GOST12_512,
};
#define CIPHER_ADD 1
@@ -339,7 +352,9 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_ECDSA, 0, 0, SSL_aECDSA, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_aPSK, 0, 0, SSL_aPSK, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_aGOST01, 0, 0, SSL_aGOST01, 0, 0, 0, 0, 0, 0, 0},
- {0, SSL_TXT_aGOST, 0, 0, SSL_aGOST01, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_aGOST12, 0, 0, SSL_aGOST12, 0, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_aGOST, 0, 0, SSL_aGOST01 | SSL_aGOST12, 0, 0, 0,
+ 0, 0, 0, 0},
{0, SSL_TXT_aSRP, 0, 0, SSL_aSRP, 0, 0, 0, 0, 0, 0, 0},
/* aliases combining key exchange and server authentication */
@@ -362,6 +377,8 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_IDEA, 0, 0, 0, SSL_IDEA, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_SEED, 0, 0, 0, SSL_SEED, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_eNULL, 0, 0, 0, SSL_eNULL, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_GOST, 0, 0, 0, SSL_eGOST2814789CNT | SSL_eGOST2814789CNT12, 0,
+ 0, 0, 0, 0, 0},
{0, SSL_TXT_AES128, 0, 0, 0, SSL_AES128 | SSL_AES128GCM | SSL_AES128CCM | SSL_AES128CCM8, 0,
0, 0, 0, 0, 0},
{0, SSL_TXT_AES256, 0, 0, 0, SSL_AES256 | SSL_AES256GCM | SSL_AES256CCM | SSL_AES256CCM8, 0,
@@ -383,9 +400,11 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_SHA1, 0, 0, 0, 0, SSL_SHA1, 0, 0, 0, 0, 0},
{0, SSL_TXT_SHA, 0, 0, 0, 0, SSL_SHA1, 0, 0, 0, 0, 0},
{0, SSL_TXT_GOST94, 0, 0, 0, 0, SSL_GOST94, 0, 0, 0, 0, 0},
- {0, SSL_TXT_GOST89MAC, 0, 0, 0, 0, SSL_GOST89MAC, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_GOST89MAC, 0, 0, 0, 0, SSL_GOST89MAC | SSL_GOST89MAC12, 0, 0,
+ 0, 0, 0},
{0, SSL_TXT_SHA256, 0, 0, 0, 0, SSL_SHA256, 0, 0, 0, 0, 0},
{0, SSL_TXT_SHA384, 0, 0, 0, 0, SSL_SHA384, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_GOST12, 0, 0, 0, 0, SSL_GOST12_256, 0, 0, 0, 0, 0},
/* protocol version aliases */
{0, SSL_TXT_SSLV3, 0, 0, 0, 0, 0, SSL_SSLV3, 0, 0, 0, 0},
@@ -542,12 +561,23 @@ void ssl_load_ciphers(void)
disabled_mac_mask |= SSL_GOST89MAC;
}
+ ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX] = get_optional_pkey_id("gost-mac-12");
+ if (ssl_mac_pkey_id[SSL_MD_GOST89MAC12_IDX]) {
+ ssl_mac_secret_size[SSL_MD_GOST89MAC12_IDX] = 32;
+ } else {
+ disabled_mac_mask |= SSL_GOST89MAC12;
+ }
+
if (!get_optional_pkey_id("gost2001"))
- disabled_auth_mask |= SSL_aGOST01;
+ disabled_auth_mask |= SSL_aGOST01 | SSL_aGOST12;
+ if (!get_optional_pkey_id("gost2012_256"))
+ disabled_auth_mask |= SSL_aGOST12;
+ if (!get_optional_pkey_id("gost2012_512"))
+ disabled_auth_mask |= SSL_aGOST12;
/*
* Disable GOST key exchange if no GOST signature algs are available *
*/
- if ((disabled_auth_mask & SSL_aGOST01) == SSL_aGOST01)
+ if ((disabled_auth_mask & (SSL_aGOST01 | SSL_aGOST12)) == (SSL_aGOST01 | SSL_aGOST12))
disabled_mkey_mask |= SSL_kGOST;
}
@@ -1704,6 +1734,10 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
case SSL_aGOST01:
au = "GOST01";
break;
+ /* New GOST ciphersuites have both SSL_aGOST12 and SSL_aGOST01 bits */
+ case (SSL_aGOST12 | SSL_aGOST01):
+ au = "GOST12";
+ break;
default:
au = "unknown";
break;
@@ -1762,6 +1796,7 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
enc = "SEED(128)";
break;
case SSL_eGOST2814789CNT:
+ case SSL_eGOST2814789CNT12:
enc = "GOST89(256)";
break;
default:
@@ -1786,11 +1821,16 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
mac = "AEAD";
break;
case SSL_GOST89MAC:
+ case SSL_GOST89MAC12:
mac = "GOST89";
break;
case SSL_GOST94:
mac = "GOST94";
break;
+ case SSL_GOST12_256:
+ case SSL_GOST12_512:
+ mac = "GOST2012";
+ break;
default:
mac = "unknown";
break;
@@ -1998,8 +2038,11 @@ int ssl_cipher_get_cert_index(const SSL_CIPHER *c)
return SSL_PKEY_DSA_SIGN;
else if (alg_a & SSL_aRSA)
return SSL_PKEY_RSA_ENC;
+ else if (alg_a & SSL_aGOST12)
+ return SSL_PKEY_GOST_EC;
else if (alg_a & SSL_aGOST01)
return SSL_PKEY_GOST01;
+
return -1;
}
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 44374b47e9..5068c15964 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2069,6 +2069,16 @@ void ssl_set_masks(SSL *s, const SSL_CIPHER *cipher)
rsa_enc_export, rsa_sign, dsa_sign, dh_rsa, dh_dsa);
#endif
+ cpk = &(c->pkeys[SSL_PKEY_GOST12_512]);
+ if (cpk->x509 != NULL && cpk->privatekey != NULL) {
+ mask_k |= SSL_kGOST;
+ mask_a |= SSL_aGOST12;
+ }
+ cpk = &(c->pkeys[SSL_PKEY_GOST12_256]);
+ if (cpk->x509 != NULL && cpk->privatekey != NULL) {
+ mask_k |= SSL_kGOST;
+ mask_a |= SSL_aGOST12;
+ }
cpk = &(c->pkeys[SSL_PKEY_GOST01]);
if (cpk->x509 != NULL && cpk->privatekey != NULL) {
mask_k |= SSL_kGOST;
@@ -2255,6 +2265,16 @@ static int ssl_get_server_cert_index(const SSL *s)
idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509)
idx = SSL_PKEY_RSA_SIGN;
+ if (idx == SSL_PKEY_GOST_EC) {
+ if (s->cert->pkeys[SSL_PKEY_GOST12_512].x509)
+ idx = SSL_PKEY_GOST12_512;
+ else if (s->cert->pkeys[SSL_PKEY_GOST12_256].x509)
+ idx = SSL_PKEY_GOST12_256;
+ else if (s->cert->pkeys[SSL_PKEY_GOST01].x509)
+ idx = SSL_PKEY_GOST01;
+ else
+ idx = -1;
+ }
if (idx == -1)
SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX, ERR_R_INTERNAL_ERROR);
return idx;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 0657c20d34..95a9c62776 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -345,6 +345,8 @@
# define SSL_aGOST01 0x00000200U
/* SRP auth */
# define SSL_aSRP 0x00000400U
+/* GOST R 34.10-2012 signature auth */
+# define SSL_aGOST12 0x00000800U
/* Bits for algorithm_enc (symmetric encryption) */
# define SSL_DES 0x00000001U
@@ -365,6 +367,7 @@
# define SSL_AES256CCM 0x00008000U
# define SSL_AES128CCM8 0x00010000U
# define SSL_AES256CCM8 0x00020000U
+# define SSL_eGOST2814789CNT12 0x00040000U
# define SSL_AES (SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM|SSL_AES128CCM|SSL_AES256CCM|SSL_AES128CCM8|SSL_AES256CCM8)
# define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256)
@@ -379,6 +382,9 @@
# define SSL_SHA384 0x00000020U
/* Not a real MAC, just an indication it is part of cipher */
# define SSL_AEAD 0x00000040U
+# define SSL_GOST12_256 0x00000080U
+# define SSL_GOST89MAC12 0x00000100U
+# define SSL_GOST12_512 0x00000200U
/* Bits for algorithm_ssl (protocol version) */
# define SSL_SSLV3 0x00000002U
@@ -392,13 +398,15 @@
# define SSL_HANDSHAKE_MAC_GOST94 0x40
# define SSL_HANDSHAKE_MAC_SHA256 0x80
# define SSL_HANDSHAKE_MAC_SHA384 0x100
+# define SSL_HANDSHAKE_MAC_GOST12_256 0x200
+# define SSL_HANDSHAKE_MAC_GOST12_512 0x400
# define SSL_HANDSHAKE_MAC_DEFAULT (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA)
/*
- * When adding new digest in the ssl_ciph.c and increment SSM_MD_NUM_IDX make
+ * When adding new digest in the ssl_ciph.c and increment SSL_MD_NUM_IDX make
* sure to update this constant too
*/
-# define SSL_MAX_DIGEST 6
+# define SSL_MAX_DIGEST 9
# define TLS1_PRF_DGST_SHIFT 10
# define TLS1_PRF_MD5 (SSL_HANDSHAKE_MAC_MD5 << TLS1_PRF_DGST_SHIFT)
@@ -406,6 +414,8 @@
# define TLS1_PRF_SHA256 (SSL_HANDSHAKE_MAC_SHA256 << TLS1_PRF_DGST_SHIFT)
# define TLS1_PRF_SHA384 (SSL_HANDSHAKE_MAC_SHA384 << TLS1_PRF_DGST_SHIFT)
# define TLS1_PRF_GOST94 (SSL_HANDSHAKE_MAC_GOST94 << TLS1_PRF_DGST_SHIFT)
+# define TLS1_PRF_GOST12_256 (SSL_HANDSHAKE_MAC_GOST12_256 << TLS1_PRF_DGST_SHIFT)
+# define TLS1_PRF_GOST12_512 (SSL_HANDSHAKE_MAC_GOST12_512 << TLS1_PRF_DGST_SHIFT)
# define TLS1_PRF (TLS1_PRF_MD5 | TLS1_PRF_SHA1)
/*
@@ -516,7 +526,14 @@
# define SSL_PKEY_DH_DSA 4
# define SSL_PKEY_ECC 5
# define SSL_PKEY_GOST01 7
-# define SSL_PKEY_NUM 8
+# define SSL_PKEY_GOST12_256 8
+# define SSL_PKEY_GOST12_512 9
+# define SSL_PKEY_NUM 10
+/*
+ * Pseudo-constant. GOST cipher suites can use different certs for 1
+ * SSL_CIPHER. So let's see which one we have in fact.
+ */
+# define SSL_PKEY_GOST_EC SSL_PKEY_NUM+1
/*-
* SSL_kRSA <- RSA_ENC | (RSA_TMP & RSA_SIGN) |
@@ -1249,7 +1266,7 @@ typedef struct ssl3_state_st {
int num_renegotiations;
int in_read_app_data;
struct {
- /* actually only needs to be 16+20 */
+ /* actually needs to be 32+32+64 for GOST */
unsigned char cert_verify_md[EVP_MAX_MD_SIZE * 2];
/* actually only need to be 16+20 for SSLv3 and 12 for TLS */
unsigned char finish_md[EVP_MAX_MD_SIZE * 2];
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 7b7fc229d9..9b1846bd10 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -1365,7 +1365,10 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
* Don't digest cached records if no sigalgs: we may need them for client
* authentication.
*/
- if (!SSL_USE_SIGALGS(s) && !ssl3_digest_cached_records(s, 0))
+ if (!(SSL_USE_SIGALGS(s)
+ || (s->s3->tmp.new_cipher->algorithm_auth
+ & (SSL_aGOST12|SSL_aGOST01)))
+ && !ssl3_digest_cached_records(s, 0))
goto f_err;
/* lets get the compression algorithm */
/* COMPRESSION */
@@ -1556,7 +1559,10 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
}
exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
- if (exp_idx >= 0 && i != exp_idx) {
+ if (exp_idx >= 0 && i != exp_idx
+ && (exp_idx != SSL_PKEY_GOST_EC ||
+ (i != SSL_PKEY_GOST12_512 && i != SSL_PKEY_GOST12_256
+ && i != SSL_PKEY_GOST01))) {
x = NULL;
al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
@@ -2771,6 +2777,10 @@ psk_err:
unsigned char shared_ukm[32], tmp[256];
EVP_MD_CTX *ukm_hash;
EVP_PKEY *pub_key;
+ int dgst_nid = NID_id_GostR3411_94;
+ if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
+ dgst_nid = NID_id_GostR3411_2012_256;
+
pmslen = 32;
pms = OPENSSL_malloc(pmslen);
@@ -2830,7 +2840,7 @@ psk_err:
*/
ukm_hash = EVP_MD_CTX_create();
if (EVP_DigestInit(ukm_hash,
- EVP_get_digestbynid(NID_id_GostR3411_94)) <= 0
+ EVP_get_digestbynid(dgst_nid)) <= 0
|| EVP_DigestUpdate(ukm_hash, s->s3->client_random,
SSL3_RANDOM_SIZE) <= 0
|| EVP_DigestUpdate(ukm_hash, s->s3->server_random,
@@ -3003,7 +3013,7 @@ int tls_client_key_exchange_post_work(SSL *s)
int tls_construct_client_verify(SSL *s)
{
unsigned char *p;
- unsigned char data[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH];
+ unsigned char data[EVP_MAX_MD_SIZE]; /* GOST R 34.11-2012-256*/
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx = NULL;
EVP_MD_CTX mctx;
@@ -3034,20 +3044,33 @@ int tls_construct_client_verify(SSL *s)
} else {
ERR_clear_error();
}
+
/*
* For TLS v1.2 send signature algorithm and signature using agreed
* digest and cached handshake records.
*/
- if (SSL_USE_SIGALGS(s)) {
+ if (SSL_USE_SIGALGS(s) || pkey->type == NID_id_GostR3410_2001
+ || pkey->type == NID_id_GostR3410_2012_256
+ || pkey->type == NID_id_GostR3410_2012_512) {
long hdatalen = 0;
void *hdata;
const EVP_MD *md = s->s3->tmp.md[s->cert->key - s->cert->pkeys];
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ if (!SSL_USE_SIGALGS(s)) {
+ int dgst_nid;
+ if (EVP_PKEY_get_default_digest_nid(pkey, &dgst_nid) <= 0
+ || (md = EVP_get_digestbynid(dgst_nid)) == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md)) {
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
- p += 2;
+ if (SSL_USE_SIGALGS(s) ) {
+ p += 2;
+ }
#ifdef SSL_DEBUG
fprintf(stderr, "Using TLS 1.2 with client alg %s\n",
EVP_MD_name(md));
@@ -3058,8 +3081,20 @@ int tls_construct_client_verify(SSL *s)
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_EVP_LIB);
goto err;
}
+ if (pkey->type == NID_id_GostR3410_2001
+ || pkey->type == NID_id_GostR3410_2012_256
+ || pkey->type == NID_id_GostR3410_2012_512) {
+ unsigned int i, k;
+ for (i = u - 1, k = 0; k < u/2; k++, i--) {
+ char c = p[2 + k];
+ p[2 + k] = p[2 + i];
+ p[2 + i] = c;
+ }
+ }
s2n(u, p);
- n = u + 4;
+ n = u + 2;
+ if (SSL_USE_SIGALGS(s))
+ n += 2;
/* Digest cached records and discard handshake buffer */
if (!ssl3_digest_cached_records(s, 0))
goto err;
@@ -3103,17 +3138,23 @@ int tls_construct_client_verify(SSL *s)
n = j + 2;
} else
#endif
- if (pkey->type == NID_id_GostR3410_2001) {
- unsigned char signbuf[64];
+ if (pkey->type == NID_id_GostR3410_2001
+ || pkey->type == NID_id_GostR3410_2012_256
+ || pkey->type == NID_id_GostR3410_2012_512) {
+ unsigned char signbuf[128];
int i;
- size_t sigsize = 64;
- s->method->ssl3_enc->cert_verify_mac(s,
- NID_id_GostR3411_94, data);
- if (EVP_PKEY_sign(pctx, signbuf, &sigsize, data, 32) <= 0) {
+ size_t sigsize =
+ (pkey->type == NID_id_GostR3410_2012_512) ? 128 : 64;
+ int dgst_nid = NID_undef;
+
+ EVP_PKEY_get_default_digest_nid(pkey, &dgst_nid);
+ s->method->ssl3_enc->cert_verify_mac(s, dgst_nid, data);
+ if (EVP_PKEY_sign(pctx, signbuf, &sigsize, data,
+ EVP_MD_size(EVP_get_digestbynid(dgst_nid))) <= 0) {
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
- for (i = 63, j = 0; i >= 0; j++, i--) {
+ for (i = sigsize - 1, j = 0; i >= 0; j++, i--) {
p[2 + j] = signbuf[i];
}
s2n(j, p);
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index 2f13e92111..24bbded5eb 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -625,6 +625,10 @@ int ssl_cert_type(X509 *x, EVP_PKEY *pkey)
#endif
else if (i == NID_id_GostR3410_2001) {
ret = SSL_PKEY_GOST01;
+ } else if (i == NID_id_GostR3410_2012_256) {
+ ret = SSL_PKEY_GOST12_256;
+ } else if (i == NID_id_GostR3410_2012_512) {
+ ret = SSL_PKEY_GOST12_512;
} else if (x && (i == EVP_PKEY_DH || i == EVP_PKEY_DHX)) {
/*
* For DH two cases: DH certificate signed with RSA and DH
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 61a79f5993..ab9b163671 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -1550,7 +1550,8 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
s->s3->tmp.new_cipher = s->session->cipher;
}
- if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) {
+ if (!(SSL_USE_SIGALGS(s) || (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aGOST12|SSL_aGOST01)) )
+ || !(s->verify_mode & SSL_VERIFY_PEER)) {
if (!ssl3_digest_cached_records(s, 0)) {
al = SSL_AD_INTERNAL_ERROR;
goto f_err;
@@ -2810,8 +2811,20 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
/* Get our certificate private key */
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
- if (alg_a & SSL_aGOST01)
+ if (alg_a & SSL_aGOST12) {
+ /*
+ * New GOST ciphersuites have SSL_aGOST01 bit too
+ */
+ pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey;
+ if (pk == NULL) {
+ pk = s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
+ }
+ if (pk == NULL) {
+ pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
+ }
+ } else if (alg_a & SSL_aGOST01) {
pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
+ }
pkey_ctx = EVP_PKEY_CTX_new(pk, NULL);
if (pkey_ctx == NULL) {
@@ -2955,8 +2968,10 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
if (s->statem.no_cert_verify) {
/* No certificate verify so we no longer need the handshake_buffer */
BIO_free(s->s3->handshake_buffer);
+ s->s3->handshake_buffer = NULL;
return WORK_FINISHED_CONTINUE;
- } else if (SSL_USE_SIGALGS(s)) {
+ } else if (SSL_USE_SIGALGS(s) || (s->s3->tmp.new_cipher->algorithm_auth
+ & (SSL_aGOST12|SSL_aGOST01) )) {
if (!s->session->peer) {
/* No peer certificate so we no longer need the handshake_buffer */
BIO_free(s->s3->handshake_buffer);
@@ -3042,7 +3057,7 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
/* Check for broken implementations of GOST ciphersuites */
/*
* If key is GOST and n is exactly 64, it is bare signature without
- * length field
+ * length field (CryptoPro implementations at least till CSP 4.0)
*/
if (PACKET_remaining(pkt) == 64 && pkey->type == NID_id_GostR3410_2001) {
len = 64;
@@ -3085,7 +3100,10 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
goto f_err;
}
- if (SSL_USE_SIGALGS(s)) {
+ if (SSL_USE_SIGALGS(s)
+ || pkey->type == NID_id_GostR3410_2001
+ || pkey->type == NID_id_GostR3410_2012_256
+ || pkey->type == NID_id_GostR3410_2012_512) {
long hdatalen = 0;
void *hdata;
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
@@ -3098,6 +3116,15 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
fprintf(stderr, "Using TLS 1.2 with client verify alg %s\n",
EVP_MD_name(md));
#endif
+ if (!SSL_USE_SIGALGS(s)) {
+ int dgst_nid;
+ if (EVP_PKEY_get_default_digest_nid(pkey, &dgst_nid) <= 0
+ || (md = EVP_get_digestbynid(dgst_nid)) == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
if (!EVP_VerifyInit_ex(&mctx, md, NULL)
|| !EVP_VerifyUpdate(&mctx, hdata, hdatalen)) {
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
@@ -3105,6 +3132,17 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
goto f_err;
}
+ if (pkey->type == NID_id_GostR3410_2001
+ || pkey->type == NID_id_GostR3410_2012_256
+ || pkey->type == NID_id_GostR3410_2012_512) {
+ unsigned int j1, j2;
+ for (j1 = len - 1, j2 = 0; j2 < len/2; j2++, j1--) {
+ char c = data[j2];
+ data[j2] = data[j1];
+ data[j1] = c;
+ }
+ }
+
if (EVP_VerifyFinal(&mctx, data, len, pkey) <= 0) {
al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
@@ -3154,35 +3192,7 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
}
} else
#endif
- if (pkey->type == NID_id_GostR3410_2001) {
- unsigned char signature[64];
- int idx;
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (pctx == NULL) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
- if (EVP_PKEY_verify_init(pctx) <= 0) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
- goto f_err;
- }
- if (len != 64) {
- fprintf(stderr, "GOST signature length is %d", len);
- }
- for (idx = 0; idx < 64; idx++) {
- signature[63 - idx] = data[idx];
- }
- j = EVP_PKEY_verify(pctx, signature, 64, s->s3->tmp.cert_verify_md,
- 32);
- EVP_PKEY_CTX_free(pctx);
- if (j <= 0) {
- al = SSL_AD_DECRYPT_ERROR;
- SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_ECDSA_SIGNATURE);
- goto f_err;
- }
- } else {
+ {
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
al = SSL_AD_UNSUPPORTED_CERTIFICATE;
goto f_err;
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 1439eaab22..2ba76e3835 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -954,6 +954,11 @@ static const unsigned char tls12_sigalgs[] = {
tlsext_sigalg(TLSEXT_hash_sha256)
tlsext_sigalg(TLSEXT_hash_sha224)
tlsext_sigalg(TLSEXT_hash_sha1)
+#ifndef OPENSSL_NO_GOST
+ TLSEXT_hash_gostr3411, TLSEXT_signature_gostr34102001,
+ TLSEXT_hash_gostr34112012_256, TLSEXT_signature_gostr34102012_256,
+ TLSEXT_hash_gostr34112012_512, TLSEXT_signature_gostr34102012_512
+#endif
};
#ifndef OPENSSL_NO_EC
@@ -992,7 +997,22 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
return s->cert->conf_sigalgslen;
} else {
*psigs = tls12_sigalgs;
+#ifndef OPENSSL_NO_GOST
+ /*
+ * We expect that GOST 2001 signature and GOST 34.11-94 hash are present in all engines
+ * and GOST 2012 algorithms are not always present.
+ * It may change when the old algorithms are deprecated.
+ */
+ if ((EVP_get_digestbynid(NID_id_GostR3411_94) != NULL)
+ && (EVP_get_digestbynid(NID_id_GostR3411_2012_256) == NULL)) {
+ return sizeof(tls12_sigalgs) - 4;
+ } else if (EVP_get_digestbynid(NID_id_GostR3411_94) == NULL) {
+ return sizeof(tls12_sigalgs) - 6;
+ }
return sizeof(tls12_sigalgs);
+#else
+ return sizeof(tls12_sigalgs);
+#endif
}
}
@@ -1714,7 +1734,9 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
* for other cases too.
*/
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_RC4
+ || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
+ || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12)
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
else {
s2n(TLSEXT_TYPE_encrypt_then_mac, ret);
@@ -2696,6 +2718,11 @@ static void ssl_set_default_md(SSL *s)
#ifndef OPENSSL_NO_EC
pmd[SSL_PKEY_ECC] = EVP_sha1();
#endif
+#ifndef OPENSSL_NO_GOST
+ pmd[SSL_PKEY_GOST01] = EVP_get_digestbynid(NID_id_GostR3411_94);
+ pmd[SSL_PKEY_GOST12_256] = EVP_get_digestbynid(NID_id_GostR3411_2012_256);
+ pmd[SSL_PKEY_GOST12_512] = EVP_get_digestbynid(NID_id_GostR3411_2012_512);
+#endif
}
int tls1_set_server_sigalgs(SSL *s)
@@ -3167,13 +3194,19 @@ static const tls12_lookup tls12_md[] = {
{NID_sha224, TLSEXT_hash_sha224},
{NID_sha256, TLSEXT_hash_sha256},
{NID_sha384, TLSEXT_hash_sha384},
- {NID_sha512, TLSEXT_hash_sha512}
+ {NID_sha512, TLSEXT_hash_sha512},
+ {NID_id_GostR3411_94, TLSEXT_hash_gostr3411},
+ {NID_id_GostR3411_2012_256, TLSEXT_hash_gostr34112012_256},
+ {NID_id_GostR3411_2012_512, TLSEXT_hash_gostr34112012_512},
};
static const tls12_lookup tls12_sig[] = {
{EVP_PKEY_RSA, TLSEXT_signature_rsa},
{EVP_PKEY_DSA, TLSEXT_signature_dsa},
- {EVP_PKEY_EC, TLSEXT_signature_ecdsa}
+ {EVP_PKEY_EC, TLSEXT_signature_ecdsa},
+ {NID_id_GostR3410_2001, TLSEXT_signature_gostr34102001},
+ {NID_id_GostR3410_2012_256, TLSEXT_signature_gostr34102012_256},
+ {NID_id_GostR3410_2012_512, TLSEXT_signature_gostr34102012_512}
};
static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen)
@@ -3222,28 +3255,53 @@ typedef struct {
int nid;
int secbits;
const EVP_MD *(*mfunc) (void);
+ unsigned char tlsext_hash;
} tls12_hash_info;
+static const EVP_MD* md_gost94()
+{
+ return EVP_get_digestbynid(NID_id_GostR3411_94);
+}
+
+static const EVP_MD* md_gost2012_256()
+{
+ return EVP_get_digestbynid(NID_id_GostR3411_2012_256);
+}
+
+static const EVP_MD* md_gost2012_512()
+{
+ return EVP_get_digestbynid(NID_id_GostR3411_2012_512);
+}
+
static const tls12_hash_info tls12_md_info[] = {
#ifdef OPENSSL_NO_MD5
- {NID_md5, 64, 0},
+ {NID_md5, 64, 0, TLSEXT_hash_md5},
#else
- {NID_md5, 64, EVP_md5},
+ {NID_md5, 64, EVP_md5, TLSEXT_hash_md5},
#endif
- {NID_sha1, 80, EVP_sha1},
- {NID_sha224, 112, EVP_sha224},
- {NID_sha256, 128, EVP_sha256},
- {NID_sha384, 192, EVP_sha384},
- {NID_sha512, 256, EVP_sha512}
+ {NID_sha1, 80, EVP_sha1, TLSEXT_hash_sha1},
+ {NID_sha224, 112, EVP_sha224, TLSEXT_hash_sha224},
+ {NID_sha256, 128, EVP_sha256, TLSEXT_hash_sha256},
+ {NID_sha384, 192, EVP_sha384, TLSEXT_hash_sha384},
+ {NID_sha512, 256, EVP_sha512, TLSEXT_hash_sha512},
+ {NID_id_GostR3411_94, 128, md_gost94, TLSEXT_hash_gostr3411},
+ {NID_id_GostR3411_2012_256, 128, md_gost2012_256, TLSEXT_hash_gostr34112012_256},
+ {NID_id_GostR3411_2012_512, 256, md_gost2012_512, TLSEXT_hash_gostr34112012_512},
};
static const tls12_hash_info *tls12_get_hash_info(unsigned char hash_alg)
{
+ unsigned int i;
if (hash_alg == 0)
return NULL;
- if (hash_alg > OSSL_NELEM(tls12_md_info))
- return NULL;
- return tls12_md_info + hash_alg - 1;
+
+ for (i=0; i < OSSL_NELEM(tls12_md_info); i++)
+ {
+ if (tls12_md_info[i].tlsext_hash == hash_alg)
+ return tls12_md_info + i;
+ }
+
+ return NULL;
}
const EVP_MD *tls12_get_hash(unsigned char hash_alg)
@@ -3272,6 +3330,16 @@ static int tls12_get_pkey_idx(unsigned char sig_alg)
case TLSEXT_signature_ecdsa:
return SSL_PKEY_ECC;
#endif
+# ifndef OPENSSL_NO_GOST
+ case TLSEXT_signature_gostr34102001:
+ return SSL_PKEY_GOST01;
+
+ case TLSEXT_signature_gostr34102012_256:
+ return SSL_PKEY_GOST12_256;
+
+ case TLSEXT_signature_gostr34102012_512:
+ return SSL_PKEY_GOST12_512;
+# endif
}
return -1;
}
@@ -3546,6 +3614,14 @@ int tls1_process_sigalgs(SSL *s)
if (pmd[SSL_PKEY_ECC] == NULL)
pmd[SSL_PKEY_ECC] = EVP_sha1();
#endif
+# ifndef OPENSSL_NO_GOST
+ if (pmd[SSL_PKEY_GOST01] == NULL)
+ pmd[SSL_PKEY_GOST01] = EVP_get_digestbynid(NID_id_GostR3411_94);
+ if (pmd[SSL_PKEY_GOST12_256] == NULL)
+ pmd[SSL_PKEY_GOST12_256] = EVP_get_digestbynid(NID_id_GostR3411_2012_256);
+ if (pmd[SSL_PKEY_GOST12_512] == NULL)
+ pmd[SSL_PKEY_GOST12_512] = EVP_get_digestbynid(NID_id_GostR3411_2012_512);
+# endif
}
return 1;
}
@@ -3993,6 +4069,21 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
default_nid = NID_ecdsa_with_SHA1;
break;
+ case SSL_PKEY_GOST01:
+ rsign = TLSEXT_signature_gostr34102001;
+ default_nid = NID_id_GostR3411_94_with_GostR3410_2001;
+ break;
+
+ case SSL_PKEY_GOST12_256:
+ rsign = TLSEXT_signature_gostr34102012_256;
+ default_nid = NID_id_tc26_signwithdigest_gost3410_2012_256;
+ break;
+
+ case SSL_PKEY_GOST12_512:
<