ret = EVP_PK_DH | EVP_PKT_EXCH;
break;
case NID_id_GostR3410_2001:
+ case NID_id_GostR3410_2012_256:
+ case NID_id_GostR3410_2012_512:
ret = EVP_PKT_EXCH | EVP_PKT_SIGN;
break;
default:
# define SSL_TXT_aECDH "aECDH"
# define SSL_TXT_aECDSA "aECDSA"
# define SSL_TXT_aPSK "aPSK"
-# define SSL_TXT_aGOST94 "aGOST94"
-# define SSL_TXT_aGOST01 "aGOST01"
-# define SSL_TXT_aGOST "aGOST"
+# define SSL_TXT_aGOST94 "aGOST94"
+# define SSL_TXT_aGOST01 "aGOST01"
+# define SSL_TXT_aGOST12 "aGOST12"
+# define SSL_TXT_aGOST "aGOST"
# define SSL_TXT_aSRP "aSRP"
# define SSL_TXT_DSS "DSS"
# define SSL_TXT_CAMELLIA128 "CAMELLIA128"
# define SSL_TXT_CAMELLIA256 "CAMELLIA256"
# define SSL_TXT_CAMELLIA "CAMELLIA"
+# define SSL_TXT_GOST "GOST89"
# define SSL_TXT_MD5 "MD5"
# define SSL_TXT_SHA1 "SHA1"
# define SSL_TXT_SHA "SHA"/* same as "SHA1" */
# define SSL_TXT_GOST94 "GOST94"
-# define SSL_TXT_GOST89MAC "GOST89MAC"
+# define SSL_TXT_GOST89MAC "GOST89MAC"
+# define SSL_TXT_GOST12 "GOST12"
+# define SSL_TXT_GOST89MAC12 "GOST89MAC12"
# define SSL_TXT_SHA256 "SHA256"
# define SSL_TXT_SHA384 "SHA384"
# define SSL_R_BAD_ECC_CERT 304
# define SSL_R_BAD_ECDSA_SIGNATURE 305
# define SSL_R_BAD_ECPOINT 306
+# define SSL_R_BAD_GOST_SIGNATURE 406
# define SSL_R_BAD_HANDSHAKE_LENGTH 332
# define SSL_R_BAD_HELLO_REQUEST 105
# define SSL_R_BAD_LENGTH 271
# define TLSEXT_signature_rsa 1
# define TLSEXT_signature_dsa 2
# define TLSEXT_signature_ecdsa 3
+# define TLSEXT_signature_gostr34102001 237
+# define TLSEXT_signature_gostr34102012_256 238
+# define TLSEXT_signature_gostr34102012_512 239
/* Total number of different signature algorithms */
-# define TLSEXT_signature_num 4
+# define TLSEXT_signature_num 7
# define TLSEXT_hash_none 0
# define TLSEXT_hash_md5 1
# define TLSEXT_hash_sha256 4
# define TLSEXT_hash_sha384 5
# define TLSEXT_hash_sha512 6
+# define TLSEXT_hash_gostr3411 237
+# define TLSEXT_hash_gostr34112012_256 238
+# define TLSEXT_hash_gostr34112012_512 239
/* Total number of different digest algorithms */
-# define TLSEXT_hash_num 7
+# define TLSEXT_hash_num 10
/* Flag set for unrecognised algorithms */
# define TLSEXT_nid_unknown 0x1000000
# define TLS_CT_RSA_FIXED_ECDH 65
# define TLS_CT_ECDSA_FIXED_ECDH 66
# define TLS_CT_GOST01_SIGN 22
+# define TLS_CT_GOST12_SIGN 238
+# define TLS_CT_GOST12_512_SIGN 239
+
/*
* when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see
* comment there)
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 */
};
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);
}
}
#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 */
{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] = {
#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
{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 */
* 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
{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 */
{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,
{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},
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;
}
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;
enc = "SEED(128)";
break;
case SSL_eGOST2814789CNT:
+ case SSL_eGOST2814789CNT12:
enc = "GOST89(256)";
break;
default:
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;
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;
}
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;
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;
# 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
# 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)
# 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
# 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)
# 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)
/*
# 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) |
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];
* 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 */
}
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,
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);
*/
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,
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;
} 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));
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;
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);
#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
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;
/* 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) {
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);
/* 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;
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);
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);
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);
}
} 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;
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
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
}
}
* 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);
#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)
{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)
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)
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;
}
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;
}
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:
+ rsign = TLSEXT_signature_gostr34102012_512;
+ default_nid = NID_id_tc26_signwithdigest_gost3410_2012_512;
+ break;
+
default:
default_nid = -1;
break;
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DH_RSA);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DH_DSA);
tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST01);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_256);
+ tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_512);
}
/* User level utiity function to check a chain is suitable */
{3, "sha224"},
{4, "sha256"},
{5, "sha384"},
- {6, "sha512"}
+ {6, "sha512"},
+ {237, "md_gost94"},
+ {238, "md_gost2012_256"},
+ {239, "md_gost2012_512"},
};
static ssl_trace_tbl ssl_sig_tbl[] = {
{0, "anonymous"},
{1, "rsa"},
{2, "dsa"},
- {3, "ecdsa"}
+ {3, "ecdsa"},
+ {237, "gost2001"},
+ {238, "gost2012_256"},
+ {239, "gost2012_512"},
};
static ssl_trace_tbl ssl_hb_tbl[] = {