From 7cda088ce02cf8a5924afeaa9622fa548e837e41 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 10 Apr 2024 18:03:12 +0700 Subject: TLS: Some work on GOST support (RFC 9189) --- crypto/src/tls/CipherSuite.cs | 2 +- crypto/src/tls/ClientCertificateType.cs | 2 +- crypto/src/tls/EncryptionAlgorithm.cs | 7 +++ crypto/src/tls/KeyExchangeAlgorithm.cs | 5 ++ crypto/src/tls/NamedGroup.cs | 2 +- crypto/src/tls/PrfAlgorithm.cs | 3 ++ crypto/src/tls/SignatureAlgorithm.cs | 2 +- crypto/src/tls/TlsEccUtilities.cs | 1 + crypto/src/tls/TlsUtilities.cs | 61 ++++++++++++++++++++-- crypto/src/tls/crypto/CryptoHashAlgorithm.cs | 1 + crypto/src/tls/crypto/TlsCryptoUtilities.cs | 7 +++ crypto/src/tls/crypto/impl/bc/BcTlsCrypto.cs | 17 +++++- .../tls/crypto/impl/bc/BcTlsRawKeyCertificate.cs | 8 +++ crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs | 4 +- crypto/test/src/tls/test/TlsTestUtilities.cs | 5 ++ 15 files changed, 116 insertions(+), 11 deletions(-) diff --git a/crypto/src/tls/CipherSuite.cs b/crypto/src/tls/CipherSuite.cs index 5c53268e2..cfa2356ca 100644 --- a/crypto/src/tls/CipherSuite.cs +++ b/crypto/src/tls/CipherSuite.cs @@ -452,7 +452,7 @@ namespace Org.BouncyCastle.Tls public const int TLS_SM4_CCM_SM3 = 0x00C7; /* - * draft-smyshlyaev-tls12-gost-suites-10 + * RFC 9189 */ public const int TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC = 0xC100; public const int TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC = 0xC101; diff --git a/crypto/src/tls/ClientCertificateType.cs b/crypto/src/tls/ClientCertificateType.cs index f3a4a08a6..a37ed0f05 100644 --- a/crypto/src/tls/ClientCertificateType.cs +++ b/crypto/src/tls/ClientCertificateType.cs @@ -23,7 +23,7 @@ namespace Org.BouncyCastle.Tls public const short ecdsa_fixed_ecdh = 66; /* - * draft-smyshlyaev-tls12-gost-suites-10 + * RFC 9189 */ public const short gost_sign256 = 67; public const short gost_sign512 = 68; diff --git a/crypto/src/tls/EncryptionAlgorithm.cs b/crypto/src/tls/EncryptionAlgorithm.cs index 8064451ab..0fc2beeb4 100644 --- a/crypto/src/tls/EncryptionAlgorithm.cs +++ b/crypto/src/tls/EncryptionAlgorithm.cs @@ -78,5 +78,12 @@ namespace Org.BouncyCastle.Tls * GMT 0024-2014 */ public const int SM4_CBC = 28; + + /* + * RFC 9189 + */ + public const int KUZNYECHIK_CTR_OMAC = 29; + public const int MAGMA_CTR_OMAC = 30; + public const int cls_28147_CNT_IMIT = 31; } } diff --git a/crypto/src/tls/KeyExchangeAlgorithm.cs b/crypto/src/tls/KeyExchangeAlgorithm.cs index fdb2773f1..a4432ca49 100644 --- a/crypto/src/tls/KeyExchangeAlgorithm.cs +++ b/crypto/src/tls/KeyExchangeAlgorithm.cs @@ -60,6 +60,11 @@ namespace Org.BouncyCastle.Tls */ public const int SM2 = 25; + /* + * RFC 9189 + */ + public const int GOSTR341112_256 = 26; + public static bool IsAnonymous(int keyExchangeAlgorithm) { switch (keyExchangeAlgorithm) diff --git a/crypto/src/tls/NamedGroup.cs b/crypto/src/tls/NamedGroup.cs index a345b8ce0..85c79d55f 100644 --- a/crypto/src/tls/NamedGroup.cs +++ b/crypto/src/tls/NamedGroup.cs @@ -61,7 +61,7 @@ namespace Org.BouncyCastle.Tls public const int brainpoolP512r1tls13 = 33; /* - * draft-smyshlyaev-tls12-gost-suites-10 + * RFC 9189 */ public const int GC256A = 34; public const int GC256B = 35; diff --git a/crypto/src/tls/PrfAlgorithm.cs b/crypto/src/tls/PrfAlgorithm.cs index ec9c2f249..bba5db94e 100644 --- a/crypto/src/tls/PrfAlgorithm.cs +++ b/crypto/src/tls/PrfAlgorithm.cs @@ -17,6 +17,7 @@ namespace Org.BouncyCastle.Tls public const int tls13_hkdf_sha384 = 5; //public const int tls13_hkdf_sha512 = 6; public const int tls13_hkdf_sm3 = 7; + public const int tls_prf_gostr3411_2012_256 = 8; public static string GetName(int prfAlgorithm) { @@ -36,6 +37,8 @@ namespace Org.BouncyCastle.Tls return "tls13_hkdf_sha384"; case tls13_hkdf_sm3: return "tls13_hkdf_sm3"; + case tls_prf_gostr3411_2012_256: + return "tls_prf_gostr3411_2012_256"; default: return "UNKNOWN"; } diff --git a/crypto/src/tls/SignatureAlgorithm.cs b/crypto/src/tls/SignatureAlgorithm.cs index baf5620e3..ac90d2bda 100644 --- a/crypto/src/tls/SignatureAlgorithm.cs +++ b/crypto/src/tls/SignatureAlgorithm.cs @@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Tls public const short ecdsa_brainpoolP512r1tls13_sha512 = 28; /* - * draft-smyshlyaev-tls12-gost-suites-10 + * RFC 9189 */ public const short gostr34102012_256 = 64; public const short gostr34102012_512 = 65; diff --git a/crypto/src/tls/TlsEccUtilities.cs b/crypto/src/tls/TlsEccUtilities.cs index 59320a717..f21cbd6db 100644 --- a/crypto/src/tls/TlsEccUtilities.cs +++ b/crypto/src/tls/TlsEccUtilities.cs @@ -37,6 +37,7 @@ namespace Org.BouncyCastle.Tls case KeyExchangeAlgorithm.ECDHE_ECDSA: case KeyExchangeAlgorithm.ECDHE_PSK: case KeyExchangeAlgorithm.ECDHE_RSA: + case KeyExchangeAlgorithm.GOSTR341112_256: return true; default: diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs index c6c4a052a..d1160e372 100644 --- a/crypto/src/tls/TlsUtilities.cs +++ b/crypto/src/tls/TlsUtilities.cs @@ -2059,6 +2059,16 @@ namespace Org.BouncyCastle.Tls throw new TlsFatalAlert(AlertDescription.illegal_parameter); } + case CipherSuite.TLS_GOSTR341112_256_WITH_28147_CNT_IMIT: + case CipherSuite.TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC: + case CipherSuite.TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC: + { + if (isTlsV12Exactly) + return PrfAlgorithm.tls_prf_gostr3411_2012_256; + + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: @@ -2543,6 +2553,9 @@ namespace Org.BouncyCastle.Tls { switch (cipherSuite) { + case CipherSuite.TLS_GOSTR341112_256_WITH_28147_CNT_IMIT: + return EncryptionAlgorithm.cls_28147_CNT_IMIT; + case CipherSuite.TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: @@ -2843,6 +2856,12 @@ namespace Org.BouncyCastle.Tls case CipherSuite.TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256: return EncryptionAlgorithm.CHACHA20_POLY1305; + case CipherSuite.TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC: + return EncryptionAlgorithm.KUZNYECHIK_CTR_OMAC; + + case CipherSuite.TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC: + return EncryptionAlgorithm.MAGMA_CTR_OMAC; + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: case CipherSuite.TLS_ECDH_anon_WITH_NULL_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: @@ -2925,6 +2944,9 @@ namespace Org.BouncyCastle.Tls case EncryptionAlgorithm.SM4_CBC: return CipherType.block; + case EncryptionAlgorithm.cls_28147_CNT_IMIT: + case EncryptionAlgorithm.KUZNYECHIK_CTR_OMAC: + case EncryptionAlgorithm.MAGMA_CTR_OMAC: case EncryptionAlgorithm.NULL: case EncryptionAlgorithm.RC4_40: case EncryptionAlgorithm.RC4_128: @@ -3172,6 +3194,11 @@ namespace Org.BouncyCastle.Tls case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: return KeyExchangeAlgorithm.ECDHE_RSA; + case CipherSuite.TLS_GOSTR341112_256_WITH_28147_CNT_IMIT: + case CipherSuite.TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC: + case CipherSuite.TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC: + return KeyExchangeAlgorithm.GOSTR341112_256; + case CipherSuite.TLS_AES_128_CCM_8_SHA256: case CipherSuite.TLS_AES_128_CCM_SHA256: case CipherSuite.TLS_AES_128_GCM_SHA256: @@ -3751,6 +3778,9 @@ namespace Org.BouncyCastle.Tls case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_GOSTR341112_256_WITH_28147_CNT_IMIT: + case CipherSuite.TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC: + case CipherSuite.TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC: case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: case CipherSuite.TLS_PSK_WITH_AES_128_CCM: @@ -3919,8 +3949,6 @@ namespace Org.BouncyCastle.Tls internal static bool IsValidSignatureAlgorithmForServerKeyExchange(short signatureAlgorithm, int keyExchangeAlgorithm) { - // TODO[tls13] - switch (keyExchangeAlgorithm) { case KeyExchangeAlgorithm.DHE_RSA: @@ -3958,6 +3986,7 @@ namespace Org.BouncyCastle.Tls case KeyExchangeAlgorithm.NULL: return SignatureAlgorithm.anonymous != signatureAlgorithm; + case KeyExchangeAlgorithm.GOSTR341112_256: default: return false; } @@ -4220,6 +4249,9 @@ namespace Org.BouncyCastle.Tls return crypto.HasSrpAuthentication() && HasAnyRsaSigAlgs(crypto); + // TODO[RFC 9189] + case KeyExchangeAlgorithm.GOSTR341112_256: + default: return false; } @@ -5275,9 +5307,32 @@ namespace Org.BouncyCastle.Tls { securityParameters.m_verifyDataLength = securityParameters.PrfHashLength; } + else if (negotiatedVersion.IsSsl) + { + securityParameters.m_verifyDataLength = 36; + } else { - securityParameters.m_verifyDataLength = negotiatedVersion.IsSsl ? 36 : 12; + /* + * RFC 9189 4.2.6. The verify_data_length value is equal to 32 for the CTR_OMAC cipher + * suites and is equal to 12 for the CNT_IMIT cipher suite. + */ + switch (cipherSuite) + { + case CipherSuite.TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC: + case CipherSuite.TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC: + { + securityParameters.m_verifyDataLength = 32; + break; + } + + case CipherSuite.TLS_GOSTR341112_256_WITH_28147_CNT_IMIT: + default: + { + securityParameters.m_verifyDataLength = 12; + break; + } + } } } diff --git a/crypto/src/tls/crypto/CryptoHashAlgorithm.cs b/crypto/src/tls/crypto/CryptoHashAlgorithm.cs index dc3c86956..64b8fff77 100644 --- a/crypto/src/tls/crypto/CryptoHashAlgorithm.cs +++ b/crypto/src/tls/crypto/CryptoHashAlgorithm.cs @@ -11,5 +11,6 @@ namespace Org.BouncyCastle.Tls.Crypto public const int sha384 = 5; public const int sha512 = 6; public const int sm3 = 7; + public const int gostr3411_2012_256 = 8; } } diff --git a/crypto/src/tls/crypto/TlsCryptoUtilities.cs b/crypto/src/tls/crypto/TlsCryptoUtilities.cs index 1903065f1..10a3ab61d 100644 --- a/crypto/src/tls/crypto/TlsCryptoUtilities.cs +++ b/crypto/src/tls/crypto/TlsCryptoUtilities.cs @@ -4,6 +4,7 @@ using System.IO; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Nist; using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Rosstandart; using Org.BouncyCastle.Asn1.X509; namespace Org.BouncyCastle.Tls.Crypto @@ -68,6 +69,8 @@ namespace Org.BouncyCastle.Tls.Crypto return CryptoHashAlgorithm.sha384; case PrfAlgorithm.tls13_hkdf_sm3: return CryptoHashAlgorithm.sm3; + case PrfAlgorithm.tls_prf_gostr3411_2012_256: + return CryptoHashAlgorithm.gostr3411_2012_256; default: throw new ArgumentException("unknown PrfAlgorithm: " + PrfAlgorithm.GetText(prfAlgorithm)); } @@ -82,6 +85,7 @@ namespace Org.BouncyCastle.Tls.Crypto case CryptoHashAlgorithm.sha224: case CryptoHashAlgorithm.sha256: case CryptoHashAlgorithm.sm3: + case CryptoHashAlgorithm.gostr3411_2012_256: return 64; case CryptoHashAlgorithm.sha384: case CryptoHashAlgorithm.sha512: @@ -103,6 +107,7 @@ namespace Org.BouncyCastle.Tls.Crypto return 28; case CryptoHashAlgorithm.sha256: case CryptoHashAlgorithm.sm3: + case CryptoHashAlgorithm.gostr3411_2012_256: return 32; case CryptoHashAlgorithm.sha384: return 48; @@ -132,6 +137,8 @@ namespace Org.BouncyCastle.Tls.Crypto // TODO[RFC 8998] //case CryptoHashAlgorithm.sm3: // return GMObjectIdentifiers.sm3; + case CryptoHashAlgorithm.gostr3411_2012_256: + return RosstandartObjectIdentifiers.id_tc26_gost_3411_12_256; default: throw new ArgumentException(); } diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsCrypto.cs b/crypto/src/tls/crypto/impl/bc/BcTlsCrypto.cs index 0686d8ece..defe600eb 100644 --- a/crypto/src/tls/crypto/impl/bc/BcTlsCrypto.cs +++ b/crypto/src/tls/crypto/impl/bc/BcTlsCrypto.cs @@ -125,9 +125,12 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC // NOTE: Ignores macAlgorithm return CreateCipher_SM4_Gcm(cryptoParams); + case EncryptionAlgorithm.cls_28147_CNT_IMIT: case EncryptionAlgorithm.DES40_CBC: case EncryptionAlgorithm.DES_CBC: case EncryptionAlgorithm.IDEA_CBC: + case EncryptionAlgorithm.KUZNYECHIK_CTR_OMAC: + case EncryptionAlgorithm.MAGMA_CTR_OMAC: case EncryptionAlgorithm.RC2_CBC_40: case EncryptionAlgorithm.RC4_128: case EncryptionAlgorithm.RC4_40: @@ -230,6 +233,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC case CryptoHashAlgorithm.sha384: case CryptoHashAlgorithm.sha512: case CryptoHashAlgorithm.sm3: + case CryptoHashAlgorithm.gostr3411_2012_256: return true; default: @@ -254,7 +258,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC case CryptoSignatureAlgorithm.rsa_pss_pss_sha512: return true; - // TODO[draft-smyshlyaev-tls12-gost-suites-10] + // TODO[RFC 9189] case CryptoSignatureAlgorithm.gostr34102012_256: case CryptoSignatureAlgorithm.gostr34102012_512: @@ -305,9 +309,12 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC case EncryptionAlgorithm.SM4_GCM: return true; + case EncryptionAlgorithm.cls_28147_CNT_IMIT: case EncryptionAlgorithm.DES_CBC: case EncryptionAlgorithm.DES40_CBC: case EncryptionAlgorithm.IDEA_CBC: + case EncryptionAlgorithm.KUZNYECHIK_CTR_OMAC: + case EncryptionAlgorithm.MAGMA_CTR_OMAC: case EncryptionAlgorithm.RC2_CBC_40: case EncryptionAlgorithm.RC4_128: case EncryptionAlgorithm.RC4_40: @@ -377,11 +384,13 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC case SignatureAlgorithm.ecdsa_brainpoolP512r1tls13_sha512: return true; - // TODO[draft-smyshlyaev-tls12-gost-suites-10] + // TODO[RFC 9189] case SignatureAlgorithm.gostr34102012_256: case SignatureAlgorithm.gostr34102012_512: + // TODO[RFC 8998] //case SignatureAlgorithm.sm2: + default: return false; } @@ -468,6 +477,8 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC return new Sha512Digest((Sha512Digest)digest); case CryptoHashAlgorithm.sm3: return new SM3Digest((SM3Digest)digest); + case CryptoHashAlgorithm.gostr3411_2012_256: + return new Gost3411_2012_256Digest((Gost3411_2012_256Digest)digest); default: throw new ArgumentException("invalid CryptoHashAlgorithm: " + cryptoHashAlgorithm); } @@ -491,6 +502,8 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC return new Sha512Digest(); case CryptoHashAlgorithm.sm3: return new SM3Digest(); + case CryptoHashAlgorithm.gostr3411_2012_256: + return new Gost3411_2012_256Digest(); default: throw new ArgumentException("invalid CryptoHashAlgorithm: " + cryptoHashAlgorithm); } diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsRawKeyCertificate.cs b/crypto/src/tls/crypto/impl/bc/BcTlsRawKeyCertificate.cs index 0e05b374a..24daf92ae 100644 --- a/crypto/src/tls/crypto/impl/bc/BcTlsRawKeyCertificate.cs +++ b/crypto/src/tls/crypto/impl/bc/BcTlsRawKeyCertificate.cs @@ -112,6 +112,10 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC return new BcTlsRsaPssVerifier(m_crypto, GetPubKeyRsa(), signatureScheme); } + // TODO[RFC 9189] + case SignatureAlgorithm.gostr34102012_256: + case SignatureAlgorithm.gostr34102012_512: + default: throw new TlsFatalAlert(AlertDescription.certificate_unknown); } @@ -471,6 +475,10 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC return SupportsRsa_Pss_Pss(signatureAlgorithm) && publicKey is RsaKeyParameters; + // TODO[RFC 9189] + case SignatureAlgorithm.gostr34102012_256: + case SignatureAlgorithm.gostr34102012_512: + default: return false; } diff --git a/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs b/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs index 16e53b60b..1438c0585 100644 --- a/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs +++ b/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs @@ -119,7 +119,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Tests case SignatureAlgorithm.rsa_pss_rsae_sha512: return LoadCredentialedSigner(cryptoParams, "rsa-sign", signatureAndHashAlgorithm); - // TODO[draft-smyshlyaev-tls12-gost-suites-10] Add test resources for these + // TODO[RFC 9189] Add test resources for these case SignatureAlgorithm.gostr34102012_256: case SignatureAlgorithm.gostr34102012_512: @@ -402,7 +402,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Tests { int[] hashes = new int[] { CryptoHashAlgorithm.md5, CryptoHashAlgorithm.sha1, CryptoHashAlgorithm.sha224, CryptoHashAlgorithm.sha256, CryptoHashAlgorithm.sha384, CryptoHashAlgorithm.sha512, - CryptoHashAlgorithm.sm3 }; + CryptoHashAlgorithm.sm3, CryptoHashAlgorithm.gostr3411_2012_256 }; for (int i = 0; i < hashes.Length; ++i) { diff --git a/crypto/test/src/tls/test/TlsTestUtilities.cs b/crypto/test/src/tls/test/TlsTestUtilities.cs index 789a5b513..72d09c808 100644 --- a/crypto/test/src/tls/test/TlsTestUtilities.cs +++ b/crypto/test/src/tls/test/TlsTestUtilities.cs @@ -159,6 +159,11 @@ namespace Org.BouncyCastle.Tls.Tests return "rsa_pss_384"; case SignatureAlgorithm.rsa_pss_pss_sha512: return "rsa_pss_512"; + + // TODO[RFC 9189] Choose names here and apply reverse mappings in GetCACertResource(String) + case SignatureAlgorithm.gostr34102012_256: + case SignatureAlgorithm.gostr34102012_512: + default: throw new TlsFatalAlert(AlertDescription.internal_error); } -- cgit 1.4.1