github.com/zmap/zcrypto@v0.0.0-20240512203510-0fef58d9a9db/x509/extensions.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package x509 6 7 import ( 8 "encoding/hex" 9 "encoding/json" 10 "net" 11 "strconv" 12 "strings" 13 14 "github.com/zmap/zcrypto/encoding/asn1" 15 "github.com/zmap/zcrypto/x509/ct" 16 "github.com/zmap/zcrypto/x509/pkix" 17 ) 18 19 var ( 20 oidExtKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 15} 21 oidExtBasicConstraints = asn1.ObjectIdentifier{2, 5, 29, 19} 22 oidExtSubjectAltName = asn1.ObjectIdentifier{2, 5, 29, 17} 23 oidExtIssuerAltName = asn1.ObjectIdentifier{2, 5, 29, 18} 24 oidExtNameConstraints = asn1.ObjectIdentifier{2, 5, 29, 30} 25 oidCRLDistributionPoints = asn1.ObjectIdentifier{2, 5, 29, 31} 26 oidExtAuthKeyId = asn1.ObjectIdentifier{2, 5, 29, 35} 27 oidExtSubjectKeyId = asn1.ObjectIdentifier{2, 5, 29, 14} 28 oidExtExtendedKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 37} 29 oidExtCertificatePolicy = asn1.ObjectIdentifier{2, 5, 29, 32} 30 oidExtensionCRLNumber = asn1.ObjectIdentifier{2, 5, 29, 20} 31 oidExtensionReasonCode = asn1.ObjectIdentifier{2, 5, 29, 21} 32 33 oidExtAuthorityInfoAccess = oidExtensionAuthorityInfoAccess 34 oidExtensionCTPrecertificatePoison = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 3} 35 oidExtSignedCertificateTimestampList = oidExtensionSignedCertificateTimestampList 36 37 oidExtCABFOrganizationID = asn1.ObjectIdentifier{2, 23, 140, 3, 1} 38 oidExtQCStatements = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 3} 39 ) 40 41 type CertificateExtensions struct { 42 KeyUsage KeyUsage `json:"key_usage,omitempty"` 43 BasicConstraints *BasicConstraints `json:"basic_constraints,omitempty"` 44 SubjectAltName *GeneralNames `json:"subject_alt_name,omitempty"` 45 IssuerAltName *GeneralNames `json:"issuer_alt_name,omitempty"` 46 NameConstraints *NameConstraints `json:"name_constraints,omitempty"` 47 CRLDistributionPoints CRLDistributionPoints `json:"crl_distribution_points,omitempty"` 48 AuthKeyID SubjAuthKeyId `json:"authority_key_id,omitempty"` 49 SubjectKeyID SubjAuthKeyId `json:"subject_key_id,omitempty"` 50 ExtendedKeyUsage *ExtendedKeyUsageExtension `json:"extended_key_usage,omitempty"` 51 CertificatePolicies *CertificatePoliciesData `json:"certificate_policies,omitempty"` 52 AuthorityInfoAccess *AuthorityInfoAccess `json:"authority_info_access,omitempty"` 53 IsPrecert IsPrecert `json:"ct_poison,omitempty"` 54 SignedCertificateTimestampList []*ct.SignedCertificateTimestamp `json:"signed_certificate_timestamps,omitempty"` 55 TorServiceDescriptors []*TorServiceDescriptorHash `json:"tor_service_descriptors,omitempty"` 56 CABFOrganizationIdentifier *CABFOrganizationIdentifier `json:"cabf_organization_id,omitempty"` 57 QCStatements *QCStatements `json:"qc_statements,omitempty"` 58 } 59 60 type UnknownCertificateExtensions []pkix.Extension 61 62 type IsPrecert bool 63 64 type BasicConstraints struct { 65 IsCA bool `json:"is_ca"` 66 MaxPathLen *int `json:"max_path_len,omitempty"` 67 } 68 69 type NoticeReference struct { 70 Organization string `json:"organization,omitempty"` 71 NoticeNumbers NoticeNumber `json:"notice_numbers,omitempty"` 72 } 73 74 type UserNoticeData struct { 75 ExplicitText string `json:"explicit_text,omitempty"` 76 NoticeReference []NoticeReference `json:"notice_reference,omitempty"` 77 } 78 79 type CertificatePoliciesJSON struct { 80 PolicyIdentifier string `json:"id,omitempty"` 81 CPSUri []string `json:"cps,omitempty"` 82 UserNotice []UserNoticeData `json:"user_notice,omitempty"` 83 } 84 85 type CertificatePolicies []CertificatePoliciesJSON 86 87 type CertificatePoliciesData struct { 88 PolicyIdentifiers []asn1.ObjectIdentifier 89 QualifierId [][]asn1.ObjectIdentifier 90 CPSUri [][]string 91 ExplicitTexts [][]string 92 NoticeRefOrganization [][]string 93 NoticeRefNumbers [][]NoticeNumber 94 } 95 96 func (cp *CertificatePoliciesData) MarshalJSON() ([]byte, error) { 97 policies := CertificatePolicies{} 98 for idx, oid := range cp.PolicyIdentifiers { 99 cpsJSON := CertificatePoliciesJSON{} 100 cpsJSON.PolicyIdentifier = oid.String() 101 for _, uri := range cp.CPSUri[idx] { 102 cpsJSON.CPSUri = append(cpsJSON.CPSUri, uri) 103 } 104 105 for idx2, explicit_text := range cp.ExplicitTexts[idx] { 106 uNoticeData := UserNoticeData{} 107 uNoticeData.ExplicitText = explicit_text 108 noticeRef := NoticeReference{} 109 if len(cp.NoticeRefOrganization[idx]) > 0 { 110 organization := cp.NoticeRefOrganization[idx][idx2] 111 noticeRef.Organization = organization 112 noticeRef.NoticeNumbers = cp.NoticeRefNumbers[idx][idx2] 113 uNoticeData.NoticeReference = append(uNoticeData.NoticeReference, noticeRef) 114 } 115 cpsJSON.UserNotice = append(cpsJSON.UserNotice, uNoticeData) 116 } 117 118 policies = append(policies, cpsJSON) 119 } 120 return json.Marshal(policies) 121 } 122 123 // GeneralNames corresponds an X.509 GeneralName defined in 124 // Section 4.2.1.6 of RFC 5280. 125 // 126 // GeneralName ::= CHOICE { 127 // otherName [0] AnotherName, 128 // rfc822Name [1] IA5String, 129 // dNSName [2] IA5String, 130 // x400Address [3] ORAddress, 131 // directoryName [4] Name, 132 // ediPartyName [5] EDIPartyName, 133 // uniformResourceIdentifier [6] IA5String, 134 // iPAddress [7] OCTET STRING, 135 // registeredID [8] OBJECT IDENTIFIER } 136 type GeneralNames struct { 137 DirectoryNames []pkix.Name 138 DNSNames []string 139 EDIPartyNames []pkix.EDIPartyName 140 EmailAddresses []string 141 IPAddresses []net.IP 142 OtherNames []pkix.OtherName 143 RegisteredIDs []asn1.ObjectIdentifier 144 URIs []string 145 } 146 147 type jsonGeneralNames struct { 148 DirectoryNames []pkix.Name `json:"directory_names,omitempty"` 149 DNSNames []string `json:"dns_names,omitempty"` 150 EDIPartyNames []pkix.EDIPartyName `json:"edi_party_names,omitempty"` 151 EmailAddresses []string `json:"email_addresses,omitempty"` 152 IPAddresses []net.IP `json:"ip_addresses,omitempty"` 153 OtherNames []pkix.OtherName `json:"other_names,omitempty"` 154 RegisteredIDs []string `json:"registered_ids,omitempty"` 155 URIs []string `json:"uniform_resource_identifiers,omitempty"` 156 } 157 158 func (gn *GeneralNames) MarshalJSON() ([]byte, error) { 159 jsan := jsonGeneralNames{ 160 DirectoryNames: gn.DirectoryNames, 161 DNSNames: gn.DNSNames, 162 EDIPartyNames: gn.EDIPartyNames, 163 EmailAddresses: gn.EmailAddresses, 164 IPAddresses: gn.IPAddresses, 165 OtherNames: gn.OtherNames, 166 RegisteredIDs: make([]string, 0, len(gn.RegisteredIDs)), 167 URIs: gn.URIs, 168 } 169 for _, id := range gn.RegisteredIDs { 170 jsan.RegisteredIDs = append(jsan.RegisteredIDs, id.String()) 171 } 172 return json.Marshal(jsan) 173 } 174 175 func (gn *GeneralNames) UnmarshalJSON(b []byte) error { 176 var jsan jsonGeneralNames 177 err := json.Unmarshal(b, &jsan) 178 if err != nil { 179 return err 180 } 181 182 gn.DirectoryNames = jsan.DirectoryNames 183 gn.DNSNames = jsan.DNSNames 184 gn.EDIPartyNames = jsan.EDIPartyNames 185 gn.EmailAddresses = jsan.EmailAddresses 186 gn.IPAddresses = jsan.IPAddresses 187 gn.OtherNames = jsan.OtherNames 188 gn.RegisteredIDs = make([]asn1.ObjectIdentifier, len(jsan.RegisteredIDs)) 189 gn.URIs = jsan.URIs 190 191 for i, rID := range jsan.RegisteredIDs { 192 arcs := strings.Split(rID, ".") 193 oid := make(asn1.ObjectIdentifier, len(arcs)) 194 195 for j, s := range arcs { 196 tmp, err := strconv.ParseInt(s, 10, 32) 197 if err != nil { 198 return err 199 } 200 oid[j] = int(tmp) 201 } 202 gn.RegisteredIDs[i] = oid 203 } 204 return nil 205 } 206 207 // TODO: Handle excluded names 208 209 type NameConstraints struct { 210 Critical bool `json:"critical"` 211 212 PermittedDNSNames []GeneralSubtreeString 213 PermittedEmailAddresses []GeneralSubtreeString 214 PermittedURIs []GeneralSubtreeString 215 PermittedIPAddresses []GeneralSubtreeIP 216 PermittedDirectoryNames []GeneralSubtreeName 217 PermittedEdiPartyNames []GeneralSubtreeEdi 218 PermittedRegisteredIDs []GeneralSubtreeOid 219 220 ExcludedEmailAddresses []GeneralSubtreeString 221 ExcludedDNSNames []GeneralSubtreeString 222 ExcludedURIs []GeneralSubtreeString 223 ExcludedIPAddresses []GeneralSubtreeIP 224 ExcludedDirectoryNames []GeneralSubtreeName 225 ExcludedEdiPartyNames []GeneralSubtreeEdi 226 ExcludedRegisteredIDs []GeneralSubtreeOid 227 } 228 229 type NameConstraintsJSON struct { 230 Critical bool `json:"critical"` 231 232 PermittedDNSNames []string `json:"permitted_names,omitempty"` 233 PermittedEmailAddresses []string `json:"permitted_email_addresses,omitempty"` 234 PermittedURIs []string `json:"permitted_uris,omitempty"` 235 PermittedIPAddresses []GeneralSubtreeIP `json:"permitted_ip_addresses,omitempty"` 236 PermittedDirectoryNames []pkix.Name `json:"permitted_directory_names,omitempty"` 237 PermittedEdiPartyNames []pkix.EDIPartyName `json:"permitted_edi_party_names,omitempty"` 238 PermittedRegisteredIDs []string `json:"permitted_registred_id,omitempty"` 239 240 ExcludedDNSNames []string `json:"excluded_names,omitempty"` 241 ExcludedEmailAddresses []string `json:"excluded_email_addresses,omitempty"` 242 ExcludedURIs []string `json:"excluded_uris,omitempty"` 243 ExcludedIPAddresses []GeneralSubtreeIP `json:"excluded_ip_addresses,omitempty"` 244 ExcludedDirectoryNames []pkix.Name `json:"excluded_directory_names,omitempty"` 245 ExcludedEdiPartyNames []pkix.EDIPartyName `json:"excluded_edi_party_names,omitempty"` 246 ExcludedRegisteredIDs []string `json:"excluded_registred_id,omitempty"` 247 } 248 249 func (nc *NameConstraints) UnmarshalJSON(b []byte) error { 250 var ncJson NameConstraintsJSON 251 err := json.Unmarshal(b, &ncJson) 252 if err != nil { 253 return err 254 } 255 for _, dns := range ncJson.PermittedDNSNames { 256 nc.PermittedDNSNames = append(nc.PermittedDNSNames, GeneralSubtreeString{Data: dns}) 257 } 258 for _, email := range ncJson.PermittedEmailAddresses { 259 nc.PermittedEmailAddresses = append(nc.PermittedEmailAddresses, GeneralSubtreeString{Data: email}) 260 } 261 for _, uri := range ncJson.PermittedURIs { 262 nc.PermittedURIs = append(nc.PermittedURIs, GeneralSubtreeString{Data: uri}) 263 } 264 for _, constraint := range ncJson.PermittedIPAddresses { 265 nc.PermittedIPAddresses = append(nc.PermittedIPAddresses, constraint) 266 } 267 for _, directory := range ncJson.PermittedDirectoryNames { 268 nc.PermittedDirectoryNames = append(nc.PermittedDirectoryNames, GeneralSubtreeName{Data: directory}) 269 } 270 for _, edi := range ncJson.PermittedEdiPartyNames { 271 nc.PermittedEdiPartyNames = append(nc.PermittedEdiPartyNames, GeneralSubtreeEdi{Data: edi}) 272 } 273 for _, id := range ncJson.PermittedRegisteredIDs { 274 arcs := strings.Split(id, ".") 275 oid := make(asn1.ObjectIdentifier, len(arcs)) 276 277 for j, s := range arcs { 278 tmp, err := strconv.ParseInt(s, 10, 32) 279 if err != nil { 280 return err 281 } 282 oid[j] = int(tmp) 283 } 284 nc.PermittedRegisteredIDs = append(nc.PermittedRegisteredIDs, GeneralSubtreeOid{Data: oid}) 285 } 286 287 for _, dns := range ncJson.ExcludedDNSNames { 288 nc.ExcludedDNSNames = append(nc.ExcludedDNSNames, GeneralSubtreeString{Data: dns}) 289 } 290 for _, email := range ncJson.ExcludedEmailAddresses { 291 nc.ExcludedEmailAddresses = append(nc.ExcludedEmailAddresses, GeneralSubtreeString{Data: email}) 292 } 293 for _, uri := range ncJson.ExcludedURIs { 294 nc.ExcludedURIs = append(nc.ExcludedURIs, GeneralSubtreeString{Data: uri}) 295 } 296 for _, constraint := range ncJson.ExcludedIPAddresses { 297 nc.ExcludedIPAddresses = append(nc.ExcludedIPAddresses, constraint) 298 } 299 for _, directory := range ncJson.ExcludedDirectoryNames { 300 nc.ExcludedDirectoryNames = append(nc.ExcludedDirectoryNames, GeneralSubtreeName{Data: directory}) 301 } 302 for _, edi := range ncJson.ExcludedEdiPartyNames { 303 nc.ExcludedEdiPartyNames = append(nc.ExcludedEdiPartyNames, GeneralSubtreeEdi{Data: edi}) 304 } 305 for _, id := range ncJson.ExcludedRegisteredIDs { 306 arcs := strings.Split(id, ".") 307 oid := make(asn1.ObjectIdentifier, len(arcs)) 308 309 for j, s := range arcs { 310 tmp, err := strconv.ParseInt(s, 10, 32) 311 if err != nil { 312 return err 313 } 314 oid[j] = int(tmp) 315 } 316 nc.ExcludedRegisteredIDs = append(nc.ExcludedRegisteredIDs, GeneralSubtreeOid{Data: oid}) 317 } 318 return nil 319 } 320 321 func (nc NameConstraints) MarshalJSON() ([]byte, error) { 322 var out NameConstraintsJSON 323 for _, dns := range nc.PermittedDNSNames { 324 out.PermittedDNSNames = append(out.PermittedDNSNames, dns.Data) 325 } 326 for _, email := range nc.PermittedEmailAddresses { 327 out.PermittedEmailAddresses = append(out.PermittedEmailAddresses, email.Data) 328 } 329 for _, uri := range nc.PermittedURIs { 330 out.PermittedURIs = append(out.PermittedURIs, uri.Data) 331 } 332 out.PermittedIPAddresses = nc.PermittedIPAddresses 333 for _, directory := range nc.PermittedDirectoryNames { 334 out.PermittedDirectoryNames = append(out.PermittedDirectoryNames, directory.Data) 335 } 336 for _, edi := range nc.PermittedEdiPartyNames { 337 out.PermittedEdiPartyNames = append(out.PermittedEdiPartyNames, edi.Data) 338 } 339 for _, id := range nc.PermittedRegisteredIDs { 340 out.PermittedRegisteredIDs = append(out.PermittedRegisteredIDs, id.Data.String()) 341 } 342 343 for _, dns := range nc.ExcludedDNSNames { 344 out.ExcludedDNSNames = append(out.ExcludedDNSNames, dns.Data) 345 } 346 for _, email := range nc.ExcludedEmailAddresses { 347 out.ExcludedEmailAddresses = append(out.ExcludedEmailAddresses, email.Data) 348 } 349 for _, uri := range nc.ExcludedURIs { 350 out.ExcludedURIs = append(out.ExcludedURIs, uri.Data) 351 } 352 for _, ip := range nc.ExcludedIPAddresses { 353 out.ExcludedIPAddresses = append(out.ExcludedIPAddresses, ip) 354 } 355 for _, directory := range nc.ExcludedDirectoryNames { 356 out.ExcludedDirectoryNames = append(out.ExcludedDirectoryNames, directory.Data) 357 } 358 for _, edi := range nc.ExcludedEdiPartyNames { 359 out.ExcludedEdiPartyNames = append(out.ExcludedEdiPartyNames, edi.Data) 360 } 361 for _, id := range nc.ExcludedRegisteredIDs { 362 out.ExcludedRegisteredIDs = append(out.ExcludedRegisteredIDs, id.Data.String()) 363 } 364 return json.Marshal(out) 365 } 366 367 type CRLDistributionPoints []string 368 369 type SubjAuthKeyId []byte 370 371 func (kid SubjAuthKeyId) MarshalJSON() ([]byte, error) { 372 enc := hex.EncodeToString(kid) 373 return json.Marshal(enc) 374 } 375 376 type ExtendedKeyUsage []ExtKeyUsage 377 378 type ExtendedKeyUsageExtension struct { 379 Known ExtendedKeyUsage 380 Unknown []asn1.ObjectIdentifier 381 } 382 383 // MarshalJSON implements the json.Marshal interface. The output is a struct of 384 // bools, with an additional `Value` field containing the actual OIDs. 385 func (e *ExtendedKeyUsageExtension) MarshalJSON() ([]byte, error) { 386 aux := new(auxExtendedKeyUsage) 387 for _, e := range e.Known { 388 aux.populateFromExtKeyUsage(e) 389 } 390 for _, oid := range e.Unknown { 391 aux.Unknown = append(aux.Unknown, oid.String()) 392 } 393 return json.Marshal(aux) 394 } 395 396 func (e *ExtendedKeyUsageExtension) UnmarshalJSON(b []byte) error { 397 aux := new(auxExtendedKeyUsage) 398 if err := json.Unmarshal(b, aux); err != nil { 399 return err 400 } 401 // TODO: Generate the reverse functions. 402 return nil 403 } 404 405 //go:generate go run extended_key_usage_gen.go 406 407 // The string functions for CertValidationLevel are auto-generated via 408 // `go generate <full_path_to_x509_package>` or running `go generate` in the package directory 409 // 410 //go:generate stringer -type=CertValidationLevel -output=generated_certvalidationlevel_string.go 411 type CertValidationLevel int 412 413 const ( 414 UnknownValidationLevel CertValidationLevel = 0 415 DV CertValidationLevel = 1 416 OV CertValidationLevel = 2 417 EV CertValidationLevel = 3 418 ) 419 420 func (c *CertValidationLevel) MarshalJSON() ([]byte, error) { 421 if *c == UnknownValidationLevel || *c < 0 || *c > EV { 422 return json.Marshal("unknown") 423 } 424 return json.Marshal(c.String()) 425 } 426 427 // TODO: All of validation-level maps should be auto-generated from 428 // https://github.com/zmap/constants. 429 430 // ExtendedValidationOIDs contains the UNION of Chromium 431 // (https://chromium.googlesource.com/chromium/src/net/+/master/cert/ev_root_ca_metadata.cc) 432 // and Firefox 433 // (http://hg.mozilla.org/mozilla-central/file/tip/security/certverifier/ExtendedValidation.cpp) 434 // EV OID lists 435 var ExtendedValidationOIDs = map[string]interface{}{ 436 // CA/Browser Forum EV OID standard 437 // https://cabforum.org/object-registry/ 438 "2.23.140.1.1": nil, 439 // CA/Browser Forum EV Code Signing 440 "2.23.140.1.3": nil, 441 // CA/Browser Forum .onion EV Certs 442 "2.23.140.1.31": nil, 443 // AC Camerfirma S.A. Chambers of Commerce Root - 2008 444 // https://www.camerfirma.com 445 // AC Camerfirma uses the last two arcs to track how the private key 446 // is managed - the effective verification policy is the same. 447 "1.3.6.1.4.1.17326.10.14.2.1.2": nil, 448 "1.3.6.1.4.1.17326.10.14.2.2.2": nil, 449 // AC Camerfirma S.A. Global Chambersign Root - 2008 450 // https://server2.camerfirma.com:8082 451 // AC Camerfirma uses the last two arcs to track how the private key 452 // is managed - the effective verification policy is the same. 453 "1.3.6.1.4.1.17326.10.8.12.1.2": nil, 454 "1.3.6.1.4.1.17326.10.8.12.2.2": nil, 455 // Actalis Authentication Root CA 456 // https://ssltest-a.actalis.it:8443 457 "1.3.159.1.17.1": nil, 458 // AffirmTrust Commercial 459 // https://commercial.affirmtrust.com/ 460 "1.3.6.1.4.1.34697.2.1": nil, 461 // AffirmTrust Networking 462 // https://networking.affirmtrust.com:4431 463 "1.3.6.1.4.1.34697.2.2": nil, 464 // AffirmTrust Premium 465 // https://premium.affirmtrust.com:4432/ 466 "1.3.6.1.4.1.34697.2.3": nil, 467 // AffirmTrust Premium ECC 468 // https://premiumecc.affirmtrust.com:4433/ 469 "1.3.6.1.4.1.34697.2.4": nil, 470 // Autoridad de Certificacion Firmaprofesional CIF A62634068 471 // https://publifirma.firmaprofesional.com/ 472 "1.3.6.1.4.1.13177.10.1.3.10": nil, 473 // Buypass Class 3 CA 1 474 // https://valid.evident.ca13.ssl.buypass.no/ 475 "2.16.578.1.26.1.3.3": nil, 476 // Certification Authority of WoSign 477 // CA 沃通根证书 478 // https://root2evtest.wosign.com/ 479 "1.3.6.1.4.1.36305.2": nil, 480 // CertPlus Class 2 Primary CA (KEYNECTIS) 481 // https://www.keynectis.com/ 482 "1.3.6.1.4.1.22234.2.5.2.3.1": nil, 483 // Certum Trusted Network CA 484 // https://juice.certum.pl/ 485 "1.2.616.1.113527.2.5.1.1": nil, 486 // China Internet Network Information Center EV Certificates Root 487 // https://evdemo.cnnic.cn/ 488 "1.3.6.1.4.1.29836.1.10": nil, 489 // COMODO Certification Authority & USERTrust RSA Certification Authority & UTN-USERFirst-Hardware & AddTrust External CA Root 490 // https://secure.comodo.com/ 491 // https://usertrustrsacertificationauthority-ev.comodoca.com/ 492 // https://addtrustexternalcaroot-ev.comodoca.com 493 "1.3.6.1.4.1.6449.1.2.1.5.1": nil, 494 // Cybertrust Global Root & GTE CyberTrust Global Root & Baltimore CyberTrust Root 495 // https://evup.cybertrust.ne.jp/ctj-ev-upgrader/evseal.gif 496 // https://www.cybertrust.ne.jp/ 497 // https://secure.omniroot.com/repository/ 498 "1.3.6.1.4.1.6334.1.100.1": nil, 499 // DigiCert High Assurance EV Root CA 500 // https://www.digicert.com 501 "2.16.840.1.114412.2.1": nil, 502 // D-TRUST Root Class 3 CA 2 EV 2009 503 // https://certdemo-ev-valid.ssl.d-trust.net/ 504 "1.3.6.1.4.1.4788.2.202.1": nil, 505 // Entrust.net Secure Server Certification Authority 506 // https://www.entrust.net/ 507 "2.16.840.1.114028.10.1.2": nil, 508 // E-Tugra Certification Authority 509 // https://sslev.e-tugra.com.tr 510 "2.16.792.3.0.4.1.1.4": nil, 511 // GeoTrust Primary Certification Authority 512 // https://www.geotrust.com/ 513 "1.3.6.1.4.1.14370.1.6": nil, 514 // GlobalSign Root CA - R2 515 // https://www.globalsign.com/ 516 "1.3.6.1.4.1.4146.1.1": nil, 517 // Go Daddy Class 2 Certification Authority & Go Daddy Root Certificate Authority - G2 518 // https://www.godaddy.com/ 519 // https://valid.gdig2.catest.godaddy.com/ 520 "2.16.840.1.114413.1.7.23.3": nil, 521 // Izenpe.com - SHA256 root 522 // The first OID is for businesses and the second for government entities. 523 // These are the test sites, respectively: 524 // https://servicios.izenpe.com 525 // https://servicios1.izenpe.com 526 // Windows XP finds this, SHA1, root instead. The policy OIDs are the same 527 // as for the SHA256 root, above. 528 "1.3.6.1.4.1.14777.6.1.1": nil, 529 "1.3.6.1.4.1.14777.6.1.2": nil, 530 // Network Solutions Certificate Authority 531 // https://www.networksolutions.com/website-packages/index.jsp 532 "1.3.6.1.4.1.782.1.2.1.8.1": nil, 533 // QuoVadis Root CA 2 534 // https://www.quovadis.bm/ 535 "1.3.6.1.4.1.8024.0.2.100.1.2": nil, 536 // SecureTrust CA, SecureTrust Corporation 537 // https://www.securetrust.com 538 // https://www.trustwave.com/ 539 "2.16.840.1.114404.1.1.2.4.1": nil, 540 // Security Communication RootCA1 541 // https://www.secomtrust.net/contact/form.html 542 "1.2.392.200091.100.721.1": nil, 543 // Staat der Nederlanden EV Root CA 544 // https://pkioevssl-v.quovadisglobal.com/ 545 "2.16.528.1.1003.1.2.7": nil, 546 // StartCom Certification Authority 547 // https://www.startssl.com/ 548 "1.3.6.1.4.1.23223.1.1.1": nil, 549 // Starfield Class 2 Certification Authority 550 // https://www.starfieldtech.com/ 551 "2.16.840.1.114414.1.7.23.3": nil, 552 // Starfield Services Root Certificate Authority - G2 553 // https://valid.sfsg2.catest.starfieldtech.com/ 554 "2.16.840.1.114414.1.7.24.3": nil, 555 // SwissSign Gold CA - G2 556 // https://testevg2.swisssign.net/ 557 "2.16.756.1.89.1.2.1.1": nil, 558 // Swisscom Root EV CA 2 559 // https://test-quarz-ev-ca-2.pre.swissdigicert.ch 560 "2.16.756.1.83.21.0": nil, 561 // thawte Primary Root CA 562 // https://www.thawte.com/ 563 "2.16.840.1.113733.1.7.48.1": nil, 564 // TWCA Global Root CA 565 // https://evssldemo3.twca.com.tw/index.html 566 "1.3.6.1.4.1.40869.1.1.22.3": nil, 567 // T-TeleSec GlobalRoot Class 3 568 // http://www.telesec.de/ / https://root-class3.test.telesec.de/ 569 "1.3.6.1.4.1.7879.13.24.1": nil, 570 // VeriSign Class 3 Public Primary Certification Authority - G5 571 // https://www.verisign.com/ 572 "2.16.840.1.113733.1.7.23.6": nil, 573 // Wells Fargo WellsSecure Public Root Certificate Authority 574 // https://nerys.wellsfargo.com/test.html 575 "2.16.840.1.114171.500.9": nil, 576 // CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN 577 // https://www.cfca.com.cn/ 578 "2.16.156.112554.3": nil, 579 // CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH 580 // https://www.wisekey.com/repository/cacertificates/ 581 "2.16.756.5.14.7.4.8": nil, 582 // CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6,O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A...,L=Ankara,C=TR 583 // https://www.turktrust.com.tr/ 584 "2.16.792.3.0.3.1.1.5": nil, 585 } 586 587 // OrganizationValidationOIDs contains CA specific OV OIDs from 588 // https://cabforum.org/object-registry/ 589 var OrganizationValidationOIDs = map[string]interface{}{ 590 // CA/Browser Forum OV OID standard 591 // https://cabforum.org/object-registry/ 592 "2.23.140.1.2.2": nil, 593 // CA/Browser Forum individually validated 594 "2.23.140.1.2.3": nil, 595 // Digicert 596 "2.16.840.1.114412.1.1": nil, 597 // D-Trust 598 "1.3.6.1.4.1.4788.2.200.1": nil, 599 // GoDaddy 600 "2.16.840.1.114413.1.7.23.2": nil, 601 // Logius 602 "2.16.528.1.1003.1.2.5.6": nil, 603 // QuoVadis 604 "1.3.6.1.4.1.8024.0.2.100.1.1": nil, 605 // Starfield 606 "2.16.840.1.114414.1.7.23.2": nil, 607 // TurkTrust 608 "2.16.792.3.0.3.1.1.2": nil, 609 } 610 611 // DomainValidationOIDs contain OIDs that identify DV certs. 612 var DomainValidationOIDs = map[string]interface{}{ 613 // Globalsign 614 "1.3.6.1.4.1.4146.1.10.10": nil, 615 // Let's Encrypt 616 "1.3.6.1.4.1.44947.1.1.1": nil, 617 // Comodo (eNom) 618 "1.3.6.1.4.1.6449.1.2.2.10": nil, 619 // Comodo (WoTrust) 620 "1.3.6.1.4.1.6449.1.2.2.15": nil, 621 // Comodo (RBC SOFT) 622 "1.3.6.1.4.1.6449.1.2.2.16": nil, 623 // Comodo (RegisterFly) 624 "1.3.6.1.4.1.6449.1.2.2.17": nil, 625 // Comodo (Central Security Patrols) 626 "1.3.6.1.4.1.6449.1.2.2.18": nil, 627 // Comodo (eBiz Networks) 628 "1.3.6.1.4.1.6449.1.2.2.19": nil, 629 // Comodo (OptimumSSL) 630 "1.3.6.1.4.1.6449.1.2.2.21": nil, 631 // Comodo (WoSign) 632 "1.3.6.1.4.1.6449.1.2.2.22": nil, 633 // Comodo (Register.com) 634 "1.3.6.1.4.1.6449.1.2.2.24": nil, 635 // Comodo (The Code Project) 636 "1.3.6.1.4.1.6449.1.2.2.25": nil, 637 // Comodo (Gandi) 638 "1.3.6.1.4.1.6449.1.2.2.26": nil, 639 // Comodo (GlobeSSL) 640 "1.3.6.1.4.1.6449.1.2.2.27": nil, 641 // Comodo (DreamHost) 642 "1.3.6.1.4.1.6449.1.2.2.28": nil, 643 // Comodo (TERENA) 644 "1.3.6.1.4.1.6449.1.2.2.29": nil, 645 // Comodo (GlobalSSL) 646 "1.3.6.1.4.1.6449.1.2.2.31": nil, 647 // Comodo (IceWarp) 648 "1.3.6.1.4.1.6449.1.2.2.35": nil, 649 // Comodo (Dotname Korea) 650 "1.3.6.1.4.1.6449.1.2.2.37": nil, 651 // Comodo (TrustSign) 652 "1.3.6.1.4.1.6449.1.2.2.38": nil, 653 // Comodo (Formidable) 654 "1.3.6.1.4.1.6449.1.2.2.39": nil, 655 // Comodo (SSL Blindado) 656 "1.3.6.1.4.1.6449.1.2.2.40": nil, 657 // Comodo (Dreamscape Networks) 658 "1.3.6.1.4.1.6449.1.2.2.41": nil, 659 // Comodo (K Software) 660 "1.3.6.1.4.1.6449.1.2.2.42": nil, 661 // Comodo (FBS) 662 "1.3.6.1.4.1.6449.1.2.2.44": nil, 663 // Comodo (ReliaSite) 664 "1.3.6.1.4.1.6449.1.2.2.45": nil, 665 // Comodo (CertAssure) 666 "1.3.6.1.4.1.6449.1.2.2.47": nil, 667 // Comodo (TrustAsia) 668 "1.3.6.1.4.1.6449.1.2.2.49": nil, 669 // Comodo (SecureCore) 670 "1.3.6.1.4.1.6449.1.2.2.50": nil, 671 // Comodo (Western Digital) 672 "1.3.6.1.4.1.6449.1.2.2.51": nil, 673 // Comodo (cPanel) 674 "1.3.6.1.4.1.6449.1.2.2.52": nil, 675 // Comodo (BlackCert) 676 "1.3.6.1.4.1.6449.1.2.2.53": nil, 677 // Comodo (KeyNet Systems) 678 "1.3.6.1.4.1.6449.1.2.2.54": nil, 679 // Comodo 680 "1.3.6.1.4.1.6449.1.2.2.7": nil, 681 // Comodo (CSC) 682 "1.3.6.1.4.1.6449.1.2.2.8": nil, 683 // Digicert 684 "2.16.840.1.114412.1.2": nil, 685 // GoDaddy 686 "2.16.840.1.114413.1.7.23.1": nil, 687 // Starfield 688 "2.16.840.1.114414.1.7.23.1": nil, 689 // CA/B Forum 690 "2.23.140.1.2.1": nil, 691 } 692 693 // TODO pull out other types 694 type AuthorityInfoAccess struct { 695 OCSPServer []string `json:"ocsp_urls,omitempty"` 696 IssuingCertificateURL []string `json:"issuer_urls,omitempty"` 697 } 698 699 /* 700 id-CABFOrganizationIdentifier OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) international-organizations(23) ca-browser-forum(140) certificate-extensions(3) cabf-organization-identifier(1) } 701 702 ext-CABFOrganizationIdentifier EXTENSION ::= { SYNTAX CABFOrganizationIdentifier IDENTIFIED BY id-CABFOrganizationIdentifier } 703 704 CABFOrganizationIdentifier ::= SEQUENCE { 705 706 registrationSchemeIdentifier PrintableString (SIZE(3)), 707 708 registrationCountry PrintableString (SIZE(2)), 709 710 registrationStateOrProvince [0] IMPLICIT PrintableString OPTIONAL (SIZE(0..128)), 711 712 registrationReference UTF8String 713 714 } 715 */ 716 type CABFOrganizationIDASN struct { 717 RegistrationSchemeIdentifier string `asn1:"printable"` 718 RegistrationCountry string `asn1:"printable"` 719 RegistrationStateOrProvince string `asn1:"printable,optional,tag:0"` 720 RegistrationReference string `asn1:"utf8"` 721 } 722 723 type CABFOrganizationIdentifier struct { 724 Scheme string `json:"scheme,omitempty"` 725 Country string `json:"country,omitempty"` 726 State string `json:"state,omitempty"` 727 Reference string `json:"reference,omitempty"` 728 } 729 730 func (c *Certificate) jsonifyExtensions() (*CertificateExtensions, UnknownCertificateExtensions) { 731 exts := new(CertificateExtensions) 732 unk := make([]pkix.Extension, 0, 2) 733 for _, e := range c.Extensions { 734 if e.Id.Equal(oidExtKeyUsage) { 735 exts.KeyUsage = c.KeyUsage 736 } else if e.Id.Equal(oidExtBasicConstraints) { 737 exts.BasicConstraints = new(BasicConstraints) 738 exts.BasicConstraints.IsCA = c.IsCA 739 if c.MaxPathLen > 0 || c.MaxPathLenZero { 740 exts.BasicConstraints.MaxPathLen = new(int) 741 *exts.BasicConstraints.MaxPathLen = c.MaxPathLen 742 } 743 } else if e.Id.Equal(oidExtSubjectAltName) { 744 exts.SubjectAltName = new(GeneralNames) 745 exts.SubjectAltName.DirectoryNames = c.DirectoryNames 746 exts.SubjectAltName.DNSNames = c.DNSNames 747 exts.SubjectAltName.EDIPartyNames = c.EDIPartyNames 748 exts.SubjectAltName.EmailAddresses = c.EmailAddresses 749 exts.SubjectAltName.IPAddresses = c.IPAddresses 750 exts.SubjectAltName.OtherNames = c.OtherNames 751 exts.SubjectAltName.RegisteredIDs = c.RegisteredIDs 752 exts.SubjectAltName.URIs = c.URIs 753 } else if e.Id.Equal(oidExtIssuerAltName) { 754 exts.IssuerAltName = new(GeneralNames) 755 exts.IssuerAltName.DirectoryNames = c.IANDirectoryNames 756 exts.IssuerAltName.DNSNames = c.IANDNSNames 757 exts.IssuerAltName.EDIPartyNames = c.IANEDIPartyNames 758 exts.IssuerAltName.EmailAddresses = c.IANEmailAddresses 759 exts.IssuerAltName.IPAddresses = c.IANIPAddresses 760 exts.IssuerAltName.OtherNames = c.IANOtherNames 761 exts.IssuerAltName.RegisteredIDs = c.IANRegisteredIDs 762 exts.IssuerAltName.URIs = c.IANURIs 763 } else if e.Id.Equal(oidExtNameConstraints) { 764 exts.NameConstraints = new(NameConstraints) 765 exts.NameConstraints.Critical = c.NameConstraintsCritical 766 767 exts.NameConstraints.PermittedDNSNames = c.PermittedDNSNames 768 exts.NameConstraints.PermittedEmailAddresses = c.PermittedEmailAddresses 769 exts.NameConstraints.PermittedURIs = c.PermittedURIs 770 exts.NameConstraints.PermittedIPAddresses = c.PermittedIPAddresses 771 exts.NameConstraints.PermittedDirectoryNames = c.PermittedDirectoryNames 772 exts.NameConstraints.PermittedEdiPartyNames = c.PermittedEdiPartyNames 773 exts.NameConstraints.PermittedRegisteredIDs = c.PermittedRegisteredIDs 774 775 exts.NameConstraints.ExcludedEmailAddresses = c.ExcludedEmailAddresses 776 exts.NameConstraints.ExcludedDNSNames = c.ExcludedDNSNames 777 exts.NameConstraints.ExcludedURIs = c.ExcludedURIs 778 exts.NameConstraints.ExcludedIPAddresses = c.ExcludedIPAddresses 779 exts.NameConstraints.ExcludedDirectoryNames = c.ExcludedDirectoryNames 780 exts.NameConstraints.ExcludedEdiPartyNames = c.ExcludedEdiPartyNames 781 exts.NameConstraints.ExcludedRegisteredIDs = c.ExcludedRegisteredIDs 782 } else if e.Id.Equal(oidCRLDistributionPoints) { 783 exts.CRLDistributionPoints = c.CRLDistributionPoints 784 } else if e.Id.Equal(oidExtAuthKeyId) { 785 exts.AuthKeyID = c.AuthorityKeyId 786 } else if e.Id.Equal(oidExtExtendedKeyUsage) { 787 exts.ExtendedKeyUsage = new(ExtendedKeyUsageExtension) 788 exts.ExtendedKeyUsage.Known = c.ExtKeyUsage 789 exts.ExtendedKeyUsage.Unknown = c.UnknownExtKeyUsage 790 } else if e.Id.Equal(oidExtCertificatePolicy) { 791 exts.CertificatePolicies = new(CertificatePoliciesData) 792 exts.CertificatePolicies.PolicyIdentifiers = c.PolicyIdentifiers 793 exts.CertificatePolicies.NoticeRefNumbers = c.NoticeRefNumbers 794 exts.CertificatePolicies.NoticeRefOrganization = c.ParsedNoticeRefOrganization 795 exts.CertificatePolicies.ExplicitTexts = c.ParsedExplicitTexts 796 exts.CertificatePolicies.QualifierId = c.QualifierId 797 exts.CertificatePolicies.CPSUri = c.CPSuri 798 799 } else if e.Id.Equal(oidExtAuthorityInfoAccess) { 800 exts.AuthorityInfoAccess = new(AuthorityInfoAccess) 801 exts.AuthorityInfoAccess.OCSPServer = c.OCSPServer 802 exts.AuthorityInfoAccess.IssuingCertificateURL = c.IssuingCertificateURL 803 } else if e.Id.Equal(oidExtSubjectKeyId) { 804 exts.SubjectKeyID = c.SubjectKeyId 805 } else if e.Id.Equal(oidExtSignedCertificateTimestampList) { 806 exts.SignedCertificateTimestampList = c.SignedCertificateTimestampList 807 } else if e.Id.Equal(oidExtensionCTPrecertificatePoison) { 808 exts.IsPrecert = true 809 } else if e.Id.Equal(oidBRTorServiceDescriptor) { 810 exts.TorServiceDescriptors = c.TorServiceDescriptors 811 } else if e.Id.Equal(oidExtCABFOrganizationID) { 812 exts.CABFOrganizationIdentifier = c.CABFOrganizationIdentifier 813 } else if e.Id.Equal(oidExtQCStatements) { 814 exts.QCStatements = c.QCStatements 815 } else { 816 // Unknown extension 817 unk = append(unk, e) 818 } 819 } 820 return exts, unk 821 }