Added CCM and CCM_8 cipher suites.
[BoarSSL] / Asn1 / AsnOID.cs
1 /*
2 * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 using System;
26 using System.Collections.Generic;
27 using System.Text;
28
29 namespace Asn1 {
30
31 /*
32 * This class contains some helper methods to convert known OID to
33 * symbolic names and back.
34 */
35
36 public class AsnOID {
37
38 static Dictionary<string, string> OIDToName =
39 new Dictionary<string, string>();
40 static Dictionary<string, string> NameToOID =
41 new Dictionary<string, string>();
42
43 static AsnOID()
44 {
45 /*
46 * From RFC 5280, PKIX1Explicit88 module.
47 */
48 Reg("1.3.6.1.5.5.7", "id-pkix");
49 Reg("1.3.6.1.5.5.7.1", "id-pe");
50 Reg("1.3.6.1.5.5.7.2", "id-qt");
51 Reg("1.3.6.1.5.5.7.3", "id-kp");
52 Reg("1.3.6.1.5.5.7.48", "id-ad");
53 Reg("1.3.6.1.5.5.7.2.1", "id-qt-cps");
54 Reg("1.3.6.1.5.5.7.2.2", "id-qt-unotice");
55 Reg("1.3.6.1.5.5.7.48.1", "id-ad-ocsp");
56 Reg("1.3.6.1.5.5.7.48.2", "id-ad-caIssuers");
57 Reg("1.3.6.1.5.5.7.48.3", "id-ad-timeStamping");
58 Reg("1.3.6.1.5.5.7.48.5", "id-ad-caRepository");
59
60 Reg("2.5.4", "id-at");
61 Reg("2.5.4.41", "id-at-name");
62 Reg("2.5.4.4", "id-at-surname");
63 Reg("2.5.4.42", "id-at-givenName");
64 Reg("2.5.4.43", "id-at-initials");
65 Reg("2.5.4.44", "id-at-generationQualifier");
66 Reg("2.5.4.3", "id-at-commonName");
67 Reg("2.5.4.7", "id-at-localityName");
68 Reg("2.5.4.8", "id-at-stateOrProvinceName");
69 Reg("2.5.4.10", "id-at-organizationName");
70 Reg("2.5.4.11", "id-at-organizationalUnitName");
71 Reg("2.5.4.12", "id-at-title");
72 Reg("2.5.4.46", "id-at-dnQualifier");
73 Reg("2.5.4.6", "id-at-countryName");
74 Reg("2.5.4.5", "id-at-serialNumber");
75 Reg("2.5.4.65", "id-at-pseudonym");
76 Reg("0.9.2342.19200300.100.1.25", "id-domainComponent");
77
78 Reg("1.2.840.113549.1.9", "pkcs-9");
79 Reg("1.2.840.113549.1.9.1", "id-emailAddress");
80
81 /*
82 * From RFC 5280, PKIX1Implicit88 module.
83 */
84 Reg("2.5.29", "id-ce");
85 Reg("2.5.29.35", "id-ce-authorityKeyIdentifier");
86 Reg("2.5.29.14", "id-ce-subjectKeyIdentifier");
87 Reg("2.5.29.15", "id-ce-keyUsage");
88 Reg("2.5.29.16", "id-ce-privateKeyUsagePeriod");
89 Reg("2.5.29.32", "id-ce-certificatePolicies");
90 Reg("2.5.29.33", "id-ce-policyMappings");
91 Reg("2.5.29.17", "id-ce-subjectAltName");
92 Reg("2.5.29.18", "id-ce-issuerAltName");
93 Reg("2.5.29.9", "id-ce-subjectDirectoryAttributes");
94 Reg("2.5.29.19", "id-ce-basicConstraints");
95 Reg("2.5.29.30", "id-ce-nameConstraints");
96 Reg("2.5.29.36", "id-ce-policyConstraints");
97 Reg("2.5.29.31", "id-ce-cRLDistributionPoints");
98 Reg("2.5.29.37", "id-ce-extKeyUsage");
99
100 Reg("2.5.29.37.0", "anyExtendedKeyUsage");
101 Reg("1.3.6.1.5.5.7.3.1", "id-kp-serverAuth");
102 Reg("1.3.6.1.5.5.7.3.2", "id-kp-clientAuth");
103 Reg("1.3.6.1.5.5.7.3.3", "id-kp-codeSigning");
104 Reg("1.3.6.1.5.5.7.3.4", "id-kp-emailProtection");
105 Reg("1.3.6.1.5.5.7.3.8", "id-kp-timeStamping");
106 Reg("1.3.6.1.5.5.7.3.9", "id-kp-OCSPSigning");
107
108 Reg("2.5.29.54", "id-ce-inhibitAnyPolicy");
109 Reg("2.5.29.46", "id-ce-freshestCRL");
110 Reg("1.3.6.1.5.5.7.1.1", "id-pe-authorityInfoAccess");
111 Reg("1.3.6.1.5.5.7.1.11", "id-pe-subjectInfoAccess");
112 Reg("2.5.29.20", "id-ce-cRLNumber");
113 Reg("2.5.29.28", "id-ce-issuingDistributionPoint");
114 Reg("2.5.29.27", "id-ce-deltaCRLIndicator");
115 Reg("2.5.29.21", "id-ce-cRLReasons");
116 Reg("2.5.29.29", "id-ce-certificateIssuer");
117 Reg("2.5.29.23", "id-ce-holdInstructionCode");
118 Reg("2.2.840.10040.2", "WRONG-holdInstruction");
119 Reg("2.2.840.10040.2.1", "WRONG-id-holdinstruction-none");
120 Reg("2.2.840.10040.2.2", "WRONG-id-holdinstruction-callissuer");
121 Reg("2.2.840.10040.2.3", "WRONG-id-holdinstruction-reject");
122 Reg("2.5.29.24", "id-ce-invalidityDate");
123
124 /*
125 * These are the "right" OID. RFC 5280 mistakenly defines
126 * the first OID element as "2".
127 */
128 Reg("1.2.840.10040.2", "holdInstruction");
129 Reg("1.2.840.10040.2.1", "id-holdinstruction-none");
130 Reg("1.2.840.10040.2.2", "id-holdinstruction-callissuer");
131 Reg("1.2.840.10040.2.3", "id-holdinstruction-reject");
132
133 /*
134 * From PKCS#1.
135 */
136 Reg("1.2.840.113549.1.1", "pkcs-1");
137 Reg("1.2.840.113549.1.1.1", "rsaEncryption");
138 Reg("1.2.840.113549.1.1.7", "id-RSAES-OAEP");
139 Reg("1.2.840.113549.1.1.9", "id-pSpecified");
140 Reg("1.2.840.113549.1.1.10", "id-RSASSA-PSS");
141 Reg("1.2.840.113549.1.1.2", "md2WithRSAEncryption");
142 Reg("1.2.840.113549.1.1.4", "md5WithRSAEncryption");
143 Reg("1.2.840.113549.1.1.5", "sha1WithRSAEncryption");
144 Reg("1.2.840.113549.1.1.11", "sha256WithRSAEncryption");
145 Reg("1.2.840.113549.1.1.12", "sha384WithRSAEncryption");
146 Reg("1.2.840.113549.1.1.13", "sha512WithRSAEncryption");
147 Reg("1.3.14.3.2.26", "id-sha1");
148 Reg("1.2.840.113549.2.2", "id-md2");
149 Reg("1.2.840.113549.2.5", "id-md5");
150 Reg("1.2.840.113549.1.1.8", "id-mgf1");
151
152 /*
153 * From NIST: http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
154 */
155 Reg("2.16.840.1.101.3", "csor");
156 Reg("2.16.840.1.101.3.4", "nistAlgorithms");
157 Reg("2.16.840.1.101.3.4.0", "csorModules");
158 Reg("2.16.840.1.101.3.4.0.1", "aesModule1");
159
160 Reg("2.16.840.1.101.3.4.1", "aes");
161 Reg("2.16.840.1.101.3.4.1.1", "id-aes128-ECB");
162 Reg("2.16.840.1.101.3.4.1.2", "id-aes128-CBC");
163 Reg("2.16.840.1.101.3.4.1.3", "id-aes128-OFB");
164 Reg("2.16.840.1.101.3.4.1.4", "id-aes128-CFB");
165 Reg("2.16.840.1.101.3.4.1.5", "id-aes128-wrap");
166 Reg("2.16.840.1.101.3.4.1.6", "id-aes128-GCM");
167 Reg("2.16.840.1.101.3.4.1.7", "id-aes128-CCM");
168 Reg("2.16.840.1.101.3.4.1.8", "id-aes128-wrap-pad");
169 Reg("2.16.840.1.101.3.4.1.21", "id-aes192-ECB");
170 Reg("2.16.840.1.101.3.4.1.22", "id-aes192-CBC");
171 Reg("2.16.840.1.101.3.4.1.23", "id-aes192-OFB");
172 Reg("2.16.840.1.101.3.4.1.24", "id-aes192-CFB");
173 Reg("2.16.840.1.101.3.4.1.25", "id-aes192-wrap");
174 Reg("2.16.840.1.101.3.4.1.26", "id-aes192-GCM");
175 Reg("2.16.840.1.101.3.4.1.27", "id-aes192-CCM");
176 Reg("2.16.840.1.101.3.4.1.28", "id-aes192-wrap-pad");
177 Reg("2.16.840.1.101.3.4.1.41", "id-aes256-ECB");
178 Reg("2.16.840.1.101.3.4.1.42", "id-aes256-CBC");
179 Reg("2.16.840.1.101.3.4.1.43", "id-aes256-OFB");
180 Reg("2.16.840.1.101.3.4.1.44", "id-aes256-CFB");
181 Reg("2.16.840.1.101.3.4.1.45", "id-aes256-wrap");
182 Reg("2.16.840.1.101.3.4.1.46", "id-aes256-GCM");
183 Reg("2.16.840.1.101.3.4.1.47", "id-aes256-CCM");
184 Reg("2.16.840.1.101.3.4.1.48", "id-aes256-wrap-pad");
185
186 Reg("2.16.840.1.101.3.4.2", "hashAlgs");
187 Reg("2.16.840.1.101.3.4.2.1", "id-sha256");
188 Reg("2.16.840.1.101.3.4.2.2", "id-sha384");
189 Reg("2.16.840.1.101.3.4.2.3", "id-sha512");
190 Reg("2.16.840.1.101.3.4.2.4", "id-sha224");
191 Reg("2.16.840.1.101.3.4.2.5", "id-sha512-224");
192 Reg("2.16.840.1.101.3.4.2.6", "id-sha512-256");
193
194 Reg("2.16.840.1.101.3.4.3", "sigAlgs");
195 Reg("2.16.840.1.101.3.4.3.1", "id-dsa-with-sha224");
196 Reg("2.16.840.1.101.3.4.3.2", "id-dsa-with-sha256");
197
198 Reg("1.2.840.113549", "rsadsi");
199 Reg("1.2.840.113549.2", "digestAlgorithm");
200 Reg("1.2.840.113549.2.7", "id-hmacWithSHA1");
201 Reg("1.2.840.113549.2.8", "id-hmacWithSHA224");
202 Reg("1.2.840.113549.2.9", "id-hmacWithSHA256");
203 Reg("1.2.840.113549.2.10", "id-hmacWithSHA384");
204 Reg("1.2.840.113549.2.11", "id-hmacWithSHA512");
205
206 /*
207 * From X9.57: http://oid-info.com/get/1.2.840.10040.4
208 */
209 Reg("1.2.840.10040.4", "x9algorithm");
210 Reg("1.2.840.10040.4", "x9cm");
211 Reg("1.2.840.10040.4.1", "dsa");
212 Reg("1.2.840.10040.4.3", "dsa-with-sha1");
213
214 /*
215 * From SEC: http://oid-info.com/get/1.3.14.3.2
216 */
217 Reg("1.3.14.3.2.2", "md4WithRSA");
218 Reg("1.3.14.3.2.3", "md5WithRSA");
219 Reg("1.3.14.3.2.4", "md4WithRSAEncryption");
220 Reg("1.3.14.3.2.12", "dsaSEC");
221 Reg("1.3.14.3.2.13", "dsaWithSHASEC");
222 Reg("1.3.14.3.2.27", "dsaWithSHA1SEC");
223
224 /*
225 * From Microsoft: http://oid-info.com/get/1.3.6.1.4.1.311.20.2
226 */
227 Reg("1.3.6.1.4.1.311.20.2", "ms-certType");
228 Reg("1.3.6.1.4.1.311.20.2.2", "ms-smartcardLogon");
229 Reg("1.3.6.1.4.1.311.20.2.3", "ms-UserPrincipalName");
230 Reg("1.3.6.1.4.1.311.20.2.3", "ms-UPN");
231 }
232
233 static void Reg(string oid, string name)
234 {
235 if (!OIDToName.ContainsKey(oid)) {
236 OIDToName.Add(oid, name);
237 }
238 string nn = Normalize(name);
239 if (NameToOID.ContainsKey(nn)) {
240 throw new Exception("OID name collision: " + nn);
241 }
242 NameToOID.Add(nn, oid);
243
244 /*
245 * Many names start with 'id-??-' and we want to support
246 * the short names (without that prefix) as aliases. But
247 * we must take care of some collisions on short names.
248 */
249 if (name.StartsWith("id-")
250 && name.Length >= 7 && name[5] == '-')
251 {
252 if (name.StartsWith("id-ad-")) {
253 Reg(oid, name.Substring(6) + "-IA");
254 } else if (name.StartsWith("id-kp-")) {
255 Reg(oid, name.Substring(6) + "-EKU");
256 } else {
257 Reg(oid, name.Substring(6));
258 }
259 }
260 }
261
262 static string Normalize(string name)
263 {
264 StringBuilder sb = new StringBuilder();
265 foreach (char c in name) {
266 int d = (int)c;
267 if (d <= 32 || d == '-') {
268 continue;
269 }
270 if (d >= 'A' && d <= 'Z') {
271 d += 'a' - 'A';
272 }
273 sb.Append((char)c);
274 }
275 return sb.ToString();
276 }
277
278 /*
279 * Convert an OID in numeric form to its symbolic name, if known.
280 * Otherwise, the provided string is returned as is.
281 */
282 public static string ToName(string oid)
283 {
284 return OIDToName.ContainsKey(oid) ? OIDToName[oid] : oid;
285 }
286
287 /*
288 * Convert a symbolic OID name to its numeric representation. If
289 * the source string is already numeric OID, then it is returned
290 * as is. Otherwise, the symbolic name is looked up; this lookup
291 * ignores case as well as spaces and dash characters. If the name
292 * is not recognized, an AsnException is thrown.
293 */
294 public static string ToOID(string name)
295 {
296 if (IsNumericOID(name)) {
297 return name;
298 }
299 string nn = Normalize(name);
300 if (!NameToOID.ContainsKey(nn)) {
301 throw new AsnException(
302 "unrecognized OID name: " + name);
303 }
304 return NameToOID[nn];
305 }
306
307 /*
308 * Test whether a given string "looks like" an OID in numeric
309 * representation. Criteria applied by this function:
310 * - only decimal ASCII digits and dots
311 * - does not start or end with a dot
312 * - at least one dot
313 * - no two consecutive dots
314 */
315 public static bool IsNumericOID(string oid)
316 {
317 foreach (char c in oid) {
318 if (!(c >= '0' && c <= '9') && c != '.') {
319 return false;
320 }
321 }
322 if (oid.StartsWith(".") || oid.EndsWith(".")) {
323 return false;
324 }
325 if (oid.IndexOf("..") >= 0) {
326 return false;
327 }
328 if (oid.IndexOf('.') < 0) {
329 return false;
330 }
331 return true;
332 }
333 }
334
335 }