diff --git a/crypto/x509/x509type.c b/crypto/x509/x509type.c index 8332d9e9d4..a7695cad77 100644 --- a/crypto/x509/x509type.c +++ b/crypto/x509/x509type.c @@ -94,6 +94,8 @@ int X509_certificate_type(X509 *x, EVP_PKEY *pkey) 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: diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 14b8f6dadc..1fd9bc8e07 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -216,9 +216,10 @@ extern "C" { # 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" @@ -250,12 +251,15 @@ extern "C" { # 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" @@ -2208,6 +2212,7 @@ void ERR_load_SSL_strings(void); # 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 diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h index 5d7b64fbfe..cdc56c634b 100644 --- a/include/openssl/tls1.h +++ b/include/openssl/tls1.h @@ -280,9 +280,12 @@ extern "C" { # 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 @@ -291,10 +294,13 @@ extern "C" { # 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 @@ -920,6 +926,9 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) # 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) 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: + rsign = TLSEXT_signature_gostr34102012_512; + default_nid = NID_id_tc26_signwithdigest_gost3410_2012_512; + break; + default: default_nid = -1; break; @@ -4163,6 +4254,9 @@ void tls1_set_cert_validity(SSL *s) 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 */ diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c index 74d157d016..dc595acead 100644 --- a/ssl/t1_trce.c +++ b/ssl/t1_trce.c @@ -543,14 +543,20 @@ static ssl_trace_tbl ssl_md_tbl[] = { {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[] = {