1 // swiftlint:disable all
2 //
3 //  ASN1Identifier.swift
4 //
5 //  Copyright © 2017 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 public class ASN1Identifier: CustomStringConvertible {
28 
29     public enum Class: UInt8 {
30         case universal = 0x00
31         case application = 0x40
32         case contextSpecific = 0x80
33         case `private` = 0xC0
34     }
35 
36     public enum TagNumber: UInt8 {
37         case endOfContent = 0x00
38         case boolean = 0x01
39         case integer = 0x02
40         case bitString = 0x03
41         case octetString = 0x04
42         case null = 0x05
43         case objectIdentifier = 0x06
44         case objectDescriptor = 0x07
45         case external = 0x08
46         case read = 0x09
47         case enumerated = 0x0A
48         case embeddedPdv = 0x0B
49         case utf8String = 0x0C
50         case relativeOid = 0x0D
51         case sequence = 0x10
52         case set = 0x11
53         case numericString = 0x12
54         case printableString = 0x13
55         case t61String = 0x14
56         case videotexString = 0x15
57         case ia5String = 0x16
58         case utcTime = 0x17
59         case generalizedTime = 0x18
60         case graphicString = 0x19
61         case visibleString = 0x1A
62         case generalString = 0x1B
63         case universalString = 0x1C
64         case characterString = 0x1D
65         case bmpString = 0x1E
66     }
67 
68     public static let constructedTag: UInt8 = 0x20
69 
70     var rawValue: UInt8
71 
72     init(rawValue: UInt8) {
73         self.rawValue = rawValue
74     }
75 
typeClassnull76     public func typeClass() -> Class {
77         for tc in [Class.application, Class.contextSpecific, Class.private] where (rawValue & tc.rawValue) == tc.rawValue {
78             return tc
79         }
80         return .universal
81     }
82 
isPrimitivenull83     public func isPrimitive() -> Bool {
84         return (rawValue & ASN1Identifier.constructedTag) == 0
85     }
isConstructednull86     public func isConstructed() -> Bool {
87         return (rawValue & ASN1Identifier.constructedTag) != 0
88     }
89 
tagNumbernull90     public func tagNumber() -> TagNumber {
91         return TagNumber(rawValue: rawValue & 0x1F) ?? .endOfContent
92     }
93 
94     public var description: String {
95         if typeClass() == .universal {
96             return String(describing: tagNumber())
97         } else {
98             return "\(typeClass())(\(tagNumber().rawValue))"
99         }
100     }
101 }
102 // swiftlint:enable all
103