summary refs log tree commit diff
path: root/crypto/src/tls/SignatureAndHashAlgorithm.cs
blob: 9de2a42e43eb92084dd72c0be7ccbc240222d5c1 (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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
using System;
using System.IO;

namespace Org.BouncyCastle.Tls
{
    /// <summary>RFC 5246 7.4.1.4.1</summary>
    public sealed class SignatureAndHashAlgorithm
    {
        public static readonly SignatureAndHashAlgorithm ecdsa_brainpoolP256r1tls13_sha256 =
            Create(SignatureScheme.ecdsa_brainpoolP256r1tls13_sha256);
        public static readonly SignatureAndHashAlgorithm ecdsa_brainpoolP384r1tls13_sha384 =
            Create(SignatureScheme.ecdsa_brainpoolP384r1tls13_sha384);
        public static readonly SignatureAndHashAlgorithm ecdsa_brainpoolP512r1tls13_sha512 =
            Create(SignatureScheme.ecdsa_brainpoolP512r1tls13_sha512);
        public static readonly SignatureAndHashAlgorithm ed25519 =
            Create(SignatureScheme.ed25519);
        public static readonly SignatureAndHashAlgorithm ed448 =
            Create(SignatureScheme.ed448);
        public static readonly SignatureAndHashAlgorithm gostr34102012_256 =
            Create(HashAlgorithm.Intrinsic, SignatureAlgorithm.gostr34102012_256);
        public static readonly SignatureAndHashAlgorithm gostr34102012_512 =
            Create(HashAlgorithm.Intrinsic, SignatureAlgorithm.gostr34102012_512);
        public static readonly SignatureAndHashAlgorithm rsa_pss_rsae_sha256 =
            Create(SignatureScheme.rsa_pss_rsae_sha256);
        public static readonly SignatureAndHashAlgorithm rsa_pss_rsae_sha384 =
            Create(SignatureScheme.rsa_pss_rsae_sha384);
        public static readonly SignatureAndHashAlgorithm rsa_pss_rsae_sha512 =
            Create(SignatureScheme.rsa_pss_rsae_sha512);
        public static readonly SignatureAndHashAlgorithm rsa_pss_pss_sha256 =
            Create(SignatureScheme.rsa_pss_pss_sha256);
        public static readonly SignatureAndHashAlgorithm rsa_pss_pss_sha384 =
            Create(SignatureScheme.rsa_pss_pss_sha384);
        public static readonly SignatureAndHashAlgorithm rsa_pss_pss_sha512 =
            Create(SignatureScheme.rsa_pss_pss_sha512);

        public static SignatureAndHashAlgorithm GetInstance(short hashAlgorithm, short signatureAlgorithm)
        {
            switch (hashAlgorithm)
            {
            case HashAlgorithm.Intrinsic:
                return GetInstanceIntrinsic(signatureAlgorithm);
            default:
                return Create(hashAlgorithm, signatureAlgorithm);
            }
        }

        private static SignatureAndHashAlgorithm GetInstanceIntrinsic(short signatureAlgorithm)
        {
            switch (signatureAlgorithm)
            {
            case SignatureAlgorithm.ed25519:
                return ed25519;
            case SignatureAlgorithm.ed448:
                return ed448;
            case SignatureAlgorithm.gostr34102012_256:
                return gostr34102012_256;
            case SignatureAlgorithm.gostr34102012_512:
                return gostr34102012_512;
            case SignatureAlgorithm.rsa_pss_rsae_sha256:
                return rsa_pss_rsae_sha256;
            case SignatureAlgorithm.rsa_pss_rsae_sha384:
                return rsa_pss_rsae_sha384;
            case SignatureAlgorithm.rsa_pss_rsae_sha512:
                return rsa_pss_rsae_sha512;
            case SignatureAlgorithm.rsa_pss_pss_sha256:
                return rsa_pss_pss_sha256;
            case SignatureAlgorithm.rsa_pss_pss_sha384:
                return rsa_pss_pss_sha384;
            case SignatureAlgorithm.rsa_pss_pss_sha512:
                return rsa_pss_pss_sha512;
            case SignatureAlgorithm.ecdsa_brainpoolP256r1tls13_sha256:
                return ecdsa_brainpoolP256r1tls13_sha256;
            case SignatureAlgorithm.ecdsa_brainpoolP384r1tls13_sha384:
                return ecdsa_brainpoolP384r1tls13_sha384;
            case SignatureAlgorithm.ecdsa_brainpoolP512r1tls13_sha512:
                return ecdsa_brainpoolP512r1tls13_sha512;
            default:
                return Create(HashAlgorithm.Intrinsic, signatureAlgorithm);
            }
        }

        private static SignatureAndHashAlgorithm Create(int signatureScheme)
        {
            short hashAlgorithm = SignatureScheme.GetHashAlgorithm(signatureScheme);
            short signatureAlgorithm = SignatureScheme.GetSignatureAlgorithm(signatureScheme);
            return Create(hashAlgorithm, signatureAlgorithm);
        }

        private static SignatureAndHashAlgorithm Create(short hashAlgorithm, short signatureAlgorithm)
        {
            return new SignatureAndHashAlgorithm(hashAlgorithm, signatureAlgorithm);
        }

        private readonly short m_hash;
        private readonly short m_signature;

        /// <param name="hash"><see cref="HashAlgorithm"/></param>
        /// <param name="signature"><see cref="SignatureAlgorithm"/></param>
        public SignatureAndHashAlgorithm(short hash, short signature)
        {
            /*
             * TODO]tls] The TlsUtils methods are inlined here to avoid circular static initialization
             * b/w these classes. We should refactor parts of TlsUtils into separate classes. e.g. the
             * TLS low-level encoding methods, and/or the SigAndHash registry and methods.
             */

            //if (!TlsUtilities.IsValidUint8(hash))
            if ((hash & 0xFF) != hash)
                throw new ArgumentException("should be a uint8", "hash");

            //if (!TlsUtilities.IsValidUint8(signature))
            if ((signature & 0xFF) != signature)
                throw new ArgumentException("should be a uint8", "signature");

            this.m_hash = hash;
            this.m_signature = signature;
        }

        /// <returns><see cref="HashAlgorithm"/></returns>
        public short Hash
        {
            get { return m_hash; }
        }

        /// <returns><see cref="SignatureAlgorithm"/></returns>
        public short Signature
        {
            get { return m_signature; }
        }

        /// <summary>Encode this <see cref="SignatureAndHashAlgorithm"/> to a <see cref="Stream"/>.</summary>
        /// <param name="output">the <see cref="Stream"/> to encode to.</param>
        /// <exception cref="IOException"/>
        public void Encode(Stream output)
        {
            TlsUtilities.WriteUint8(Hash, output);
            TlsUtilities.WriteUint8(Signature, output);
        }

        /// <summary>Parse a <see cref="SignatureAndHashAlgorithm"/> from a <see cref="Stream"/>.</summary>
        /// <param name="input">the <see cref="Stream"/> to parse from.</param>
        /// <returns>a <see cref="SignatureAndHashAlgorithm"/> object.</returns>
        /// <exception cref="IOException"/>
        public static SignatureAndHashAlgorithm Parse(Stream input)
        {
            short hash = TlsUtilities.ReadUint8(input);
            short signature = TlsUtilities.ReadUint8(input);

            return GetInstance(hash, signature);
        }

        public override bool Equals(object obj)
        {
            if (!(obj is SignatureAndHashAlgorithm))
                return false;

            SignatureAndHashAlgorithm other = (SignatureAndHashAlgorithm)obj;
            return other.Hash == Hash && other.Signature == Signature;
        }

        public override int GetHashCode()
        {
            return ((int)Hash << 16) | (int)Signature;
        }

        public override string ToString()
        {
            return "{" + HashAlgorithm.GetText(Hash) + "," + SignatureAlgorithm.GetText(Signature) + "}";
        }
    }
}