summary refs log tree commit diff
path: root/crypto/src/tls/crypto/impl/bc/BcDefaultTlsCredentialedAgreement.cs
blob: 15944cd896f28cf5ef1e279c7b8671e4baf60332 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
using System;

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities;

namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
{
    /// <summay>Credentialed class generating agreed secrets from a peer's public key for our end of the TLS connection
    /// using the BC light-weight API.</summay>
    public class BcDefaultTlsCredentialedAgreement
        : TlsCredentialedAgreement
    {
        protected readonly TlsCredentialedAgreement m_agreementCredentials;

        public BcDefaultTlsCredentialedAgreement(BcTlsCrypto crypto, Certificate certificate,
            AsymmetricKeyParameter privateKey)
        {
            if (crypto == null)
                throw new ArgumentNullException("crypto");
            if (certificate == null)
                throw new ArgumentNullException("certificate");
            if (certificate.IsEmpty)
                throw new ArgumentException("cannot be empty", "certificate");
            if (privateKey == null)
                throw new ArgumentNullException("privateKey");
            if (!privateKey.IsPrivate)
                throw new ArgumentException("must be private", "privateKey");

            if (privateKey is DHPrivateKeyParameters)
            {
                this.m_agreementCredentials = new DHCredentialedAgreement(crypto, certificate,
                    (DHPrivateKeyParameters)privateKey);
            }
            else if (privateKey is ECPrivateKeyParameters)
            {
                this.m_agreementCredentials = new ECCredentialedAgreement(crypto, certificate,
                    (ECPrivateKeyParameters)privateKey);
            }
            else
            {
                throw new ArgumentException("'privateKey' type not supported: " + Platform.GetTypeName(privateKey));
            }
        }

        public virtual Certificate Certificate
        {
            get { return m_agreementCredentials.Certificate; }
        }

        public virtual TlsSecret GenerateAgreement(TlsCertificate peerCertificate)
        {
            return m_agreementCredentials.GenerateAgreement(peerCertificate);
        }

        private sealed class DHCredentialedAgreement
            : TlsCredentialedAgreement
        {
            private readonly BcTlsCrypto m_crypto;
            private readonly Certificate m_certificate;
            private readonly DHPrivateKeyParameters m_privateKey;

            internal DHCredentialedAgreement(BcTlsCrypto crypto, Certificate certificate,
                DHPrivateKeyParameters privateKey)
            {
                this.m_crypto = crypto;
                this.m_certificate = certificate;
                this.m_privateKey = privateKey;
            }

            public TlsSecret GenerateAgreement(TlsCertificate peerCertificate)
            {
                BcTlsCertificate bcCert = BcTlsCertificate.Convert(m_crypto, peerCertificate);
                DHPublicKeyParameters peerPublicKey = bcCert.GetPubKeyDH();
                return BcTlsDHDomain.CalculateDHAgreement(m_crypto, m_privateKey, peerPublicKey, false);
            }

            public Certificate Certificate
            {
                get { return m_certificate; }
            }
        }

        private sealed class ECCredentialedAgreement
            : TlsCredentialedAgreement
        {
            private readonly BcTlsCrypto m_crypto;
            private readonly Certificate m_certificate;
            private readonly ECPrivateKeyParameters m_privateKey;

            internal ECCredentialedAgreement(BcTlsCrypto crypto, Certificate certificate,
                ECPrivateKeyParameters privateKey)
            {
                this.m_crypto = crypto;
                this.m_certificate = certificate;
                this.m_privateKey = privateKey;
            }

            public TlsSecret GenerateAgreement(TlsCertificate peerCertificate)
            {
                BcTlsCertificate bcCert = BcTlsCertificate.Convert(m_crypto, peerCertificate);
                ECPublicKeyParameters peerPublicKey = bcCert.GetPubKeyEC();
                return BcTlsECDomain.CalculateBasicAgreement(m_crypto, m_privateKey, peerPublicKey);
            }

            public Certificate Certificate
            {
                get { return m_certificate; }
            }
        }
    }
}