diff --git a/crypto/src/crypto/tls/BasicTlsPskIdentity.cs b/crypto/src/crypto/tls/BasicTlsPskIdentity.cs
new file mode 100644
index 000000000..db5954422
--- /dev/null
+++ b/crypto/src/crypto/tls/BasicTlsPskIdentity.cs
@@ -0,0 +1,43 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public class BasicTlsPskIdentity
+ : TlsPskIdentity
+ {
+ protected byte[] mIdentity;
+ protected byte[] mPsk;
+
+ public BasicTlsPskIdentity(byte[] identity, byte[] psk)
+ {
+ this.mIdentity = Arrays.Clone(identity);
+ this.mPsk = Arrays.Clone(psk);
+ }
+
+ public BasicTlsPskIdentity(string identity, byte[] psk)
+ {
+ this.mIdentity = Strings.ToUtf8ByteArray(identity);
+ this.mPsk = Arrays.Clone(psk);
+ }
+
+ public virtual void SkipIdentityHint()
+ {
+ }
+
+ public virtual void NotifyIdentityHint(byte[] psk_identity_hint)
+ {
+ }
+
+ public virtual byte[] GetPskIdentity()
+ {
+ return mIdentity;
+ }
+
+ public virtual byte[] GetPsk()
+ {
+ return mPsk;
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/DtlsClientProtocol.cs b/crypto/src/crypto/tls/DtlsClientProtocol.cs
index 67c49f890..2aa4df692 100644
--- a/crypto/src/crypto/tls/DtlsClientProtocol.cs
+++ b/crypto/src/crypto/tls/DtlsClientProtocol.cs
@@ -374,6 +374,7 @@ namespace Org.BouncyCastle.Crypto.Tls
.SetCompressionAlgorithm(securityParameters.compressionAlgorithm)
.SetMasterSecret(securityParameters.masterSecret)
.SetPeerCertificate(serverCertificate)
+ .SetPskIdentity(securityParameters.pskIdentity)
.Build();
state.tlsSession = TlsUtilities.ImportSession(state.tlsSession.SessionID, state.sessionParameters);
diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs
index 6063572a0..1f4b0865c 100644
--- a/crypto/src/crypto/tls/PskTlsClient.cs
+++ b/crypto/src/crypto/tls/PskTlsClient.cs
@@ -3,7 +3,7 @@ using System.Collections;
namespace Org.BouncyCastle.Crypto.Tls
{
- public abstract class PskTlsClient
+ public class PskTlsClient
: AbstractTlsClient
{
protected TlsPskIdentity mPskIdentity;
@@ -25,8 +25,8 @@ namespace Org.BouncyCastle.Crypto.Tls
{
CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
- CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
- CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA
};
}
@@ -124,6 +124,15 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
+ public override TlsAuthentication GetAuthentication()
+ {
+ /*
+ * Note: This method is not called unless a server certificate is sent, which may be the
+ * case e.g. for RSA_PSK key exchange.
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
public override TlsCipher GetCipher()
{
switch (mSelectedCipherSuite)
@@ -254,7 +263,7 @@ namespace Org.BouncyCastle.Crypto.Tls
protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
{
- return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, mNamedCurves,
+ return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, null, mNamedCurves,
mClientECPointFormats, mServerECPointFormats);
}
}
diff --git a/crypto/src/crypto/tls/PskTlsServer.cs b/crypto/src/crypto/tls/PskTlsServer.cs
new file mode 100644
index 000000000..bdb8b74a5
--- /dev/null
+++ b/crypto/src/crypto/tls/PskTlsServer.cs
@@ -0,0 +1,347 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public class PskTlsServer
+ : AbstractTlsServer
+ {
+ protected TlsPskIdentityManager mPskIdentityManager;
+
+ public PskTlsServer(TlsPskIdentityManager pskIdentityManager)
+ : this(new DefaultTlsCipherFactory(), pskIdentityManager)
+ {
+ }
+
+ public PskTlsServer(TlsCipherFactory cipherFactory, TlsPskIdentityManager pskIdentityManager)
+ : base(cipherFactory)
+ {
+ this.mPskIdentityManager = pskIdentityManager;
+ }
+
+ protected virtual TlsEncryptionCredentials GetRsaEncryptionCredentials()
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ protected virtual DHParameters GetDHParameters()
+ {
+ return DHStandardGroups.rfc5114_1024_160;
+ }
+
+ protected override int[] GetCipherSuites()
+ {
+ return new int[]
+ {
+ CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ };
+ }
+
+ public override TlsCredentials GetCredentials()
+ {
+ switch (mSelectedCipherSuite)
+ {
+ case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+
+ case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+
+ case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+ return null;
+
+ case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+ return GetRsaEncryptionCredentials();
+
+ default:
+ /* Note: internal error here; selected a key exchange we don't implement! */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public override TlsKeyExchange GetKeyExchange()
+ {
+ switch (mSelectedCipherSuite)
+ {
+ case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+ return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK);
+
+ case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+ return CreatePskKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK);
+
+ case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+ return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK);
+
+ case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+ return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocol implementation verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher suites, so if
+ * we now can't produce an implementation, we shouldn't have offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public override TlsCipher GetCipher()
+ {
+ switch (mSelectedCipherSuite)
+ {
+ case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null);
+
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null);
+
+ case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+ case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha384);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+ case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+ return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocol implementation verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher suites, so if
+ * we now can't produce an implementation, we shouldn't have offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected TlsKeyExchange CreatePskKeyExchange(int keyExchange)
+ {
+ return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, mPskIdentityManager,
+ GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats);
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/SecurityParameters.cs b/crypto/src/crypto/tls/SecurityParameters.cs
index 12bb59f22..0f48ee23e 100644
--- a/crypto/src/crypto/tls/SecurityParameters.cs
+++ b/crypto/src/crypto/tls/SecurityParameters.cs
@@ -15,6 +15,7 @@ namespace Org.BouncyCastle.Crypto.Tls
internal byte[] clientRandom = null;
internal byte[] serverRandom = null;
internal byte[] sessionHash = null;
+ internal byte[] pskIdentity = null;
// TODO Keep these internal, since it's maybe not the ideal place for them
internal short maxFragmentLength = -1;
@@ -87,5 +88,10 @@ namespace Org.BouncyCastle.Crypto.Tls
{
get { return sessionHash; }
}
+
+ public virtual byte[] PskIdentity
+ {
+ get { return pskIdentity; }
+ }
}
}
diff --git a/crypto/src/crypto/tls/ServerDHParams.cs b/crypto/src/crypto/tls/ServerDHParams.cs
index 381858854..b09262771 100644
--- a/crypto/src/crypto/tls/ServerDHParams.cs
+++ b/crypto/src/crypto/tls/ServerDHParams.cs
@@ -54,7 +54,8 @@ namespace Org.BouncyCastle.Crypto.Tls
BigInteger g = TlsDHUtilities.ReadDHParameter(input);
BigInteger Ys = TlsDHUtilities.ReadDHParameter(input);
- return new ServerDHParams(new DHPublicKeyParameters(Ys, new DHParameters(p, g)));
+ return new ServerDHParams(
+ TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Ys, new DHParameters(p, g))));
}
}
}
diff --git a/crypto/src/crypto/tls/SessionParameters.cs b/crypto/src/crypto/tls/SessionParameters.cs
index c4616ac71..b17e931d7 100644
--- a/crypto/src/crypto/tls/SessionParameters.cs
+++ b/crypto/src/crypto/tls/SessionParameters.cs
@@ -14,6 +14,7 @@ namespace Org.BouncyCastle.Crypto.Tls
private short mCompressionAlgorithm = -1;
private byte[] mMasterSecret = null;
private Certificate mPeerCertificate = null;
+ private byte[] mPskIdentity = null;
private byte[] mEncodedServerExtensions = null;
public Builder()
@@ -26,7 +27,7 @@ namespace Org.BouncyCastle.Crypto.Tls
Validate(this.mCompressionAlgorithm >= 0, "compressionAlgorithm");
Validate(this.mMasterSecret != null, "masterSecret");
return new SessionParameters(mCipherSuite, (byte)mCompressionAlgorithm, mMasterSecret, mPeerCertificate,
- mEncodedServerExtensions);
+ mPskIdentity, mEncodedServerExtensions);
}
public Builder SetCipherSuite(int cipherSuite)
@@ -53,6 +54,12 @@ namespace Org.BouncyCastle.Crypto.Tls
return this;
}
+ public Builder SetPskIdentity(byte[] pskIdentity)
+ {
+ this.mPskIdentity = pskIdentity;
+ return this;
+ }
+
public Builder SetServerExtensions(IDictionary serverExtensions)
{
if (serverExtensions == null)
@@ -79,15 +86,17 @@ namespace Org.BouncyCastle.Crypto.Tls
private byte mCompressionAlgorithm;
private byte[] mMasterSecret;
private Certificate mPeerCertificate;
+ private byte[] mPskIdentity;
private byte[] mEncodedServerExtensions;
private SessionParameters(int cipherSuite, byte compressionAlgorithm, byte[] masterSecret,
- Certificate peerCertificate, byte[] encodedServerExtensions)
+ Certificate peerCertificate, byte[] pskIdentity, byte[] encodedServerExtensions)
{
this.mCipherSuite = cipherSuite;
this.mCompressionAlgorithm = compressionAlgorithm;
this.mMasterSecret = Arrays.Clone(masterSecret);
this.mPeerCertificate = peerCertificate;
+ this.mPskIdentity = Arrays.Clone(pskIdentity);
this.mEncodedServerExtensions = encodedServerExtensions;
}
@@ -102,7 +111,7 @@ namespace Org.BouncyCastle.Crypto.Tls
public SessionParameters Copy()
{
return new SessionParameters(mCipherSuite, mCompressionAlgorithm, mMasterSecret, mPeerCertificate,
- mEncodedServerExtensions);
+ mPskIdentity, mEncodedServerExtensions);
}
public int CipherSuite
@@ -125,6 +134,11 @@ namespace Org.BouncyCastle.Crypto.Tls
get { return mPeerCertificate; }
}
+ public byte[] PskIdentity
+ {
+ get { return mPskIdentity; }
+ }
+
public IDictionary ReadServerExtensions()
{
if (mEncodedServerExtensions == null)
diff --git a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
index 0644bd44d..b99db0c18 100644
--- a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
@@ -34,73 +34,10 @@ namespace Org.BouncyCastle.Crypto.Tls
public override byte[] GenerateServerKeyExchange()
{
- /*
- * First we try to find a supported named curve from the client's list.
- */
- int namedCurve = -1;
- if (mNamedCurves == null)
- {
- // TODO Let the peer choose the default named curve
- namedCurve = NamedCurve.secp256r1;
- }
- else
- {
- for (int i = 0; i < mNamedCurves.Length; ++i)
- {
- int entry = mNamedCurves[i];
- if (NamedCurve.IsValid(entry) && TlsEccUtilities.IsSupportedNamedCurve(entry))
- {
- namedCurve = entry;
- break;
- }
- }
- }
-
- ECDomainParameters curve_params = null;
- if (namedCurve >= 0)
- {
- curve_params = TlsEccUtilities.GetParametersForNamedCurve(namedCurve);
- }
- else
- {
- /*
- * If no named curves are suitable, check if the client supports explicit curves.
- */
- if (Arrays.Contains(mNamedCurves, NamedCurve.arbitrary_explicit_prime_curves))
- {
- curve_params = TlsEccUtilities.GetParametersForNamedCurve(NamedCurve.secp256r1);
- }
- else if (Arrays.Contains(mNamedCurves, NamedCurve.arbitrary_explicit_char2_curves))
- {
- curve_params = TlsEccUtilities.GetParametersForNamedCurve(NamedCurve.sect283r1);
- }
- }
-
- if (curve_params == null)
- {
- /*
- * NOTE: We shouldn't have negotiated ECDHE key exchange since we apparently can't find
- * a suitable curve.
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
-
- AsymmetricCipherKeyPair kp = TlsEccUtilities.GenerateECKeyPair(context.SecureRandom, curve_params);
- this.mECAgreePrivateKey = (ECPrivateKeyParameters)kp.Private;
-
DigestInputBuffer buf = new DigestInputBuffer();
- if (namedCurve < 0)
- {
- TlsEccUtilities.WriteExplicitECParameters(mClientECPointFormats, curve_params, buf);
- }
- else
- {
- TlsEccUtilities.WriteNamedECParameters(namedCurve, buf);
- }
-
- ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters)kp.Public;
- TlsEccUtilities.WriteECPoint(mClientECPointFormats, ecPublicKey.Q, buf);
+ this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, mNamedCurves,
+ mClientECPointFormats, buf);
/*
* RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
diff --git a/crypto/src/crypto/tls/TlsEccUtilities.cs b/crypto/src/crypto/tls/TlsEccUtilities.cs
index 34f0f57ba..e938b1685 100644
--- a/crypto/src/crypto/tls/TlsEccUtilities.cs
+++ b/crypto/src/crypto/tls/TlsEccUtilities.cs
@@ -435,6 +435,69 @@ namespace Org.BouncyCastle.Crypto.Tls
return (ECPrivateKeyParameters)kp.Private;
}
+ // TODO Refactor around ServerECDHParams before making this public
+ internal static ECPrivateKeyParameters GenerateEphemeralServerKeyExchange(SecureRandom random, int[] namedCurves,
+ byte[] ecPointFormats, Stream output)
+ {
+ /* First we try to find a supported named curve from the client's list. */
+ int namedCurve = -1;
+ if (namedCurves == null)
+ {
+ // TODO Let the peer choose the default named curve
+ namedCurve = NamedCurve.secp256r1;
+ }
+ else
+ {
+ for (int i = 0; i < namedCurves.Length; ++i)
+ {
+ int entry = namedCurves[i];
+ if (NamedCurve.IsValid(entry) && IsSupportedNamedCurve(entry))
+ {
+ namedCurve = entry;
+ break;
+ }
+ }
+ }
+
+ ECDomainParameters ecParams = null;
+ if (namedCurve >= 0)
+ {
+ ecParams = GetParametersForNamedCurve(namedCurve);
+ }
+ else
+ {
+ /* If no named curves are suitable, check if the client supports explicit curves. */
+ if (Arrays.Contains(namedCurves, NamedCurve.arbitrary_explicit_prime_curves))
+ {
+ ecParams = GetParametersForNamedCurve(NamedCurve.secp256r1);
+ }
+ else if (Arrays.Contains(namedCurves, NamedCurve.arbitrary_explicit_char2_curves))
+ {
+ ecParams = GetParametersForNamedCurve(NamedCurve.sect283r1);
+ }
+ }
+
+ if (ecParams == null)
+ {
+ /*
+ * NOTE: We shouldn't have negotiated ECDHE key exchange since we apparently can't find
+ * a suitable curve.
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ if (namedCurve < 0)
+ {
+ WriteExplicitECParameters(ecPointFormats, ecParams, output);
+ }
+ else
+ {
+ WriteNamedECParameters(namedCurve, output);
+ }
+
+ return GenerateEphemeralClientKeyExchange(random, ecPointFormats, ecParams, output);
+ }
+
public static ECPublicKeyParameters ValidateECPublicKey(ECPublicKeyParameters key)
{
// TODO Check RFC 4492 for validation
diff --git a/crypto/src/crypto/tls/TlsPskIdentityManager.cs b/crypto/src/crypto/tls/TlsPskIdentityManager.cs
new file mode 100644
index 000000000..a72c2299c
--- /dev/null
+++ b/crypto/src/crypto/tls/TlsPskIdentityManager.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public interface TlsPskIdentityManager
+ {
+ byte[] GetHint();
+
+ byte[] GetPsk(byte[] identity);
+ }
+}
diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
index cd13e3438..a8d0867ef 100644
--- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
@@ -4,7 +4,10 @@ using System.IO;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Crypto.Tls
{
@@ -13,22 +16,29 @@ namespace Org.BouncyCastle.Crypto.Tls
: AbstractTlsKeyExchange
{
protected TlsPskIdentity mPskIdentity;
+ protected TlsPskIdentityManager mPskIdentityManager;
+
protected DHParameters mDHParameters;
protected int[] mNamedCurves;
protected byte[] mClientECPointFormats, mServerECPointFormats;
protected byte[] mPskIdentityHint = null;
+ protected byte[] mPsk = null;
protected DHPrivateKeyParameters mDHAgreePrivateKey = null;
protected DHPublicKeyParameters mDHAgreePublicKey = null;
+ protected ECPrivateKeyParameters mECAgreePrivateKey = null;
+ protected ECPublicKeyParameters mECAgreePublicKey = null;
+
protected AsymmetricKeyParameter mServerPublicKey = null;
protected RsaKeyParameters mRsaServerPublicKey = null;
protected TlsEncryptionCredentials mServerCredentials = null;
protected byte[] mPremasterSecret;
public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity,
- DHParameters dhParameters, int[] namedCurves, byte[] clientECPointFormats, byte[] serverECPointFormats)
+ TlsPskIdentityManager pskIdentityManager, DHParameters dhParameters, int[] namedCurves,
+ byte[] clientECPointFormats, byte[] serverECPointFormats)
: base(keyExchange, supportedSignatureAlgorithms)
{
switch (keyExchange)
@@ -43,6 +53,7 @@ namespace Org.BouncyCastle.Crypto.Tls
}
this.mPskIdentity = pskIdentity;
+ this.mPskIdentityManager = pskIdentityManager;
this.mDHParameters = dhParameters;
this.mNamedCurves = namedCurves;
this.mClientECPointFormats = clientECPointFormats;
@@ -67,8 +78,7 @@ namespace Org.BouncyCastle.Crypto.Tls
public override byte[] GenerateServerKeyExchange()
{
- // TODO[RFC 4279] Need a server-side PSK API to determine hint and resolve identities to keys
- this.mPskIdentityHint = null;
+ this.mPskIdentityHint = mPskIdentityManager.GetHint();
if (this.mPskIdentityHint == null && !RequiresServerKeyExchange)
return null;
@@ -94,7 +104,8 @@ namespace Org.BouncyCastle.Crypto.Tls
}
else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
{
- // TODO[RFC 5489]
+ this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom,
+ mNamedCurves, mClientECPointFormats, buf);
}
return buf.ToArray();
@@ -157,7 +168,12 @@ namespace Org.BouncyCastle.Crypto.Tls
}
else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
{
- // TODO[RFC 5489]
+ ECDomainParameters ecParams = TlsEccUtilities.ReadECParameters(mNamedCurves, mClientECPointFormats, input);
+
+ byte[] point = TlsUtilities.ReadOpaque8(input);
+
+ this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey(
+ mClientECPointFormats, ecParams, point));
}
}
@@ -183,9 +199,17 @@ namespace Org.BouncyCastle.Crypto.Tls
}
byte[] psk_identity = mPskIdentity.GetPskIdentity();
+ if (psk_identity == null)
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+
+ this.mPsk = mPskIdentity.GetPsk();
+ if (mPsk == null)
+ throw new TlsFatalAlert(AlertDescription.internal_error);
TlsUtilities.WriteOpaque16(psk_identity, output);
+ context.SecurityParameters.pskIdentity = psk_identity;
+
if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
{
this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom,
@@ -193,8 +217,8 @@ namespace Org.BouncyCastle.Crypto.Tls
}
else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
{
- // TODO[RFC 5489]
- throw new TlsFatalAlert(AlertDescription.internal_error);
+ this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom,
+ mServerECPointFormats, mECAgreePublicKey.Parameters, output);
}
else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK)
{
@@ -203,14 +227,59 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
+ public override void ProcessClientKeyExchange(Stream input)
+ {
+ byte[] psk_identity = TlsUtilities.ReadOpaque16(input);
+
+ this.mPsk = mPskIdentityManager.GetPsk(psk_identity);
+ if (mPsk == null)
+ throw new TlsFatalAlert(AlertDescription.unknown_psk_identity);
+
+ context.SecurityParameters.pskIdentity = psk_identity;
+
+ if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ BigInteger Yc = TlsDHUtilities.ReadDHParameter(input);
+
+ this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters));
+ }
+ else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+ {
+ byte[] point = TlsUtilities.ReadOpaque8(input);
+
+ ECDomainParameters curve_params = this.mECAgreePrivateKey.Parameters;
+
+ this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey(
+ mServerECPointFormats, curve_params, point));
+ }
+ else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK)
+ {
+ byte[] encryptedPreMasterSecret;
+ if (TlsUtilities.IsSsl(context))
+ {
+ // TODO Do any SSLv3 clients actually include the length?
+ encryptedPreMasterSecret = Streams.ReadAll(input);
+ }
+ else
+ {
+ encryptedPreMasterSecret = TlsUtilities.ReadOpaque16(input);
+ }
+
+ this.mPremasterSecret = mServerCredentials.DecryptPreMasterSecret(encryptedPreMasterSecret);
+ }
+ }
+
public override byte[] GeneratePremasterSecret()
{
- byte[] psk = mPskIdentity.GetPsk();
- byte[] other_secret = GenerateOtherSecret(psk.Length);
+ byte[] other_secret = GenerateOtherSecret(mPsk.Length);
- MemoryStream buf = new MemoryStream(4 + other_secret.Length + psk.Length);
+ MemoryStream buf = new MemoryStream(4 + other_secret.Length + mPsk.Length);
TlsUtilities.WriteOpaque16(other_secret, buf);
- TlsUtilities.WriteOpaque16(psk, buf);
+ TlsUtilities.WriteOpaque16(mPsk, buf);
+
+ Arrays.Fill(mPsk, (byte)0);
+ this.mPsk = null;
+
return buf.ToArray();
}
@@ -228,7 +297,11 @@ namespace Org.BouncyCastle.Crypto.Tls
if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
{
- // TODO[RFC 5489]
+ if (mECAgreePrivateKey != null)
+ {
+ return TlsEccUtilities.CalculateECDHBasicAgreement(mECAgreePublicKey, mECAgreePrivateKey);
+ }
+
throw new TlsFatalAlert(AlertDescription.internal_error);
}
|