1 // swiftlint:disable all 2 // 3 // X509ExtensionClasses.swift 4 // 5 // Copyright © 2020 Filippo Maguolo. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in all 15 // copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 // SOFTWARE. 24 25 import Foundation 26 27 extension X509Certificate { 28 29 /// Recognition for Basic Constraint Extension (2.5.29.19) 30 public class BasicConstraintExtension: X509Extension { 31 32 public var isCA: Bool { 33 return (valueAsBlock?.sub(0)?.sub(0)?.value as? Bool) ?? false 34 } 35 36 public var pathLenConstraint: UInt64? { 37 guard let data = valueAsBlock?.sub(0)?.sub(1)?.value as? Data else { 38 return nil 39 } 40 return data.uint64Value 41 } 42 } 43 44 /// Recognition for Subject Key Identifier Extension (2.5.29.14) 45 public class SubjectKeyIdentifierExtension: X509Extension { 46 47 public override var value: Any? { 48 guard let rawValue = valueAsBlock?.rawValue else { 49 return nil 50 } 51 return rawValue.sequenceContent 52 } 53 } 54 55 // MARK: - Authority Extensions 56 57 public struct AuthorityInfoAccess { 58 public let method: String 59 public let location: String 60 } 61 62 /// Recognition for Authority Info Access Extension (1.3.6.1.5.5.7.1.1) 63 public class AuthorityInfoAccessExtension: X509Extension { 64 65 public var infoAccess: [AuthorityInfoAccess]? { 66 guard let valueAsBlock = valueAsBlock else { 67 return nil 68 } 69 let subs = valueAsBlock.sub(0)?.sub ?? [] 70 71 return subs.compactMap { sub in 72 guard var oidData = sub.sub(0)?.rawValue, 73 let nameBlock = sub.sub(1) else { 74 return nil 75 } 76 if 77 let oid = ASN1DERDecoder.decodeOid(contentData: &oidData), 78 let location = generalName(of: nameBlock) { 79 return AuthorityInfoAccess(method: oid, location: location) 80 } else { 81 return nil 82 } 83 } 84 } 85 } 86 87 /// Recognition for Authority Key Identifier Extension (2.5.29.35) 88 public class AuthorityKeyIdentifierExtension: X509Extension { 89 90 /* 91 AuthorityKeyIdentifier ::= SEQUENCE { 92 keyIdentifier [0] KeyIdentifier OPTIONAL, 93 authorityCertIssuer [1] GeneralNames OPTIONAL, 94 authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } 95 */ 96 97 public var keyIdentifier: Data? { 98 guard let sequence = valueAsBlock?.sub(0)?.sub else { 99 return nil 100 } 101 if let sub = sequence.first(where: { $0.identifier?.tagNumber().rawValue == 0 }) { 102 return sub.rawValue 103 } 104 return nil 105 } 106 107 public var certificateIssuer: [String]? { 108 guard let sequence = valueAsBlock?.sub(0)?.sub else { 109 return nil 110 } 111 if let sub = sequence.first(where: { $0.identifier?.tagNumber().rawValue == 1 }) { 112 return sub.sub?.compactMap { generalName(of: $0) } 113 } 114 return nil 115 } 116 117 public var serialNumber: Data? { 118 guard let sequence = valueAsBlock?.sub(0)?.sub else { 119 return nil 120 } 121 if let sub = sequence.first(where: { $0.identifier?.tagNumber().rawValue == 2 }) { 122 return sub.rawValue 123 } 124 return nil 125 } 126 } 127 128 // MARK: - Certificate Policies Extension 129 130 public struct CertificatePolicyQualifier { 131 public let oid: String 132 public let value: String? 133 } 134 public struct CertificatePolicy { 135 public let oid: String 136 public let qualifiers: [CertificatePolicyQualifier]? 137 } 138 139 /// Recognition for Certificate Policies Extension (2.5.29.32) 140 public class CertificatePoliciesExtension: X509Extension { 141 142 public var policies: [CertificatePolicy]? { 143 guard let valueAsBlock = valueAsBlock else { 144 return nil 145 } 146 let subs = valueAsBlock.sub(0)?.sub ?? [] 147 148 return subs.compactMap { sub in 149 guard 150 var data = sub.sub(0)?.rawValue, 151 let oid = ASN1DERDecoder.decodeOid(contentData: &data) else { 152 return nil 153 } 154 var qualifiers: [CertificatePolicyQualifier]? 155 if let subQualifiers = sub.sub(1) { 156 qualifiers = subQualifiers.sub?.compactMap { sub in 157 if var rawValue = sub.sub(0)?.rawValue, let oid = ASN1DERDecoder.decodeOid(contentData: &rawValue) { 158 let value = sub.sub(1)?.asString 159 return CertificatePolicyQualifier(oid: oid, value: value) 160 } else { 161 return nil 162 } 163 } 164 } 165 return CertificatePolicy(oid: oid, qualifiers: qualifiers) 166 } 167 } 168 } 169 170 // MARK: - CRL Distribution Points 171 172 public class CRLDistributionPointsExtension: X509Extension { 173 174 public var crls: [String]? { 175 guard let valueAsBlock = valueAsBlock else { 176 return nil 177 } 178 let subs = valueAsBlock.sub(0)?.sub ?? [] 179 return subs.compactMap { $0.asString } 180 } 181 } 182 } 183 // swiftlint:enable all 184