|
|
@@ -0,0 +1,122 @@
|
|
|
+//
|
|
|
+// CryptoSwift
|
|
|
+//
|
|
|
+// Copyright (C) Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
|
|
+// This software is provided 'as-is', without any express or implied warranty.
|
|
|
+//
|
|
|
+// In no event will the authors be held liable for any damages arising from the use of this software.
|
|
|
+//
|
|
|
+// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
|
|
+//
|
|
|
+// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
|
|
+// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
|
|
+// - This notice may not be removed or altered from any source or binary distribution.
|
|
|
+//
|
|
|
+// ASN1 Code inspired by Asn1Parser.swift from SwiftyRSA
|
|
|
+
|
|
|
+import Foundation
|
|
|
+
|
|
|
+extension ASN1 {
|
|
|
+ /// A simple ASN1 parser that will recursively iterate over a root node and return a Node tree.
|
|
|
+ /// The root node can be any of the supported nodes described in `Node`. If the parser encounters a sequence
|
|
|
+ /// it will recursively parse its children.
|
|
|
+ enum Decoder {
|
|
|
+
|
|
|
+ enum DecodingError: Error {
|
|
|
+ case noType
|
|
|
+ case invalidType(value: UInt8)
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Parses ASN1 data and returns its root node.
|
|
|
+ ///
|
|
|
+ /// - Parameter data: ASN1 data to parse
|
|
|
+ /// - Returns: Root ASN1 Node
|
|
|
+ /// - Throws: A DecodingError if anything goes wrong, or if an unknown node was encountered
|
|
|
+ static func decode(data: Data) throws -> Node {
|
|
|
+ let scanner = ASN1.Scanner(data: data)
|
|
|
+ let node = try decodeNode(scanner: scanner)
|
|
|
+ return node
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Parses an ASN1 given an existing scanner.
|
|
|
+ /// @warning: this will modify the state (ie: position) of the provided scanner.
|
|
|
+ ///
|
|
|
+ /// - Parameter scanner: Scanner to use to consume the data
|
|
|
+ /// - Returns: Parsed node
|
|
|
+ /// - Throws: A DecodingError if anything goes wrong, or if an unknown node was encountered
|
|
|
+ private static func decodeNode(scanner: ASN1.Scanner) throws -> Node {
|
|
|
+
|
|
|
+ let firstByte = try scanner.consume(length: 1).firstByte
|
|
|
+
|
|
|
+ switch firstByte {
|
|
|
+ case IDENTIFIERS.SEQUENCE.rawValue:
|
|
|
+ let length = try scanner.consumeLength()
|
|
|
+ let data = try scanner.consume(length: length)
|
|
|
+ let nodes = try decodeSequence(data: data)
|
|
|
+ return .sequence(nodes: nodes)
|
|
|
+
|
|
|
+ case IDENTIFIERS.INTERGER.rawValue:
|
|
|
+ let length = try scanner.consumeLength()
|
|
|
+ let data = try scanner.consume(length: length)
|
|
|
+ return .integer(data: data)
|
|
|
+
|
|
|
+ case IDENTIFIERS.OBJECTID.rawValue:
|
|
|
+ let length = try scanner.consumeLength()
|
|
|
+ let data = try scanner.consume(length: length)
|
|
|
+ return .objectIdentifier(data: data)
|
|
|
+
|
|
|
+ case IDENTIFIERS.NULL.rawValue:
|
|
|
+ _ = try scanner.consume(length: 1)
|
|
|
+ return .null
|
|
|
+
|
|
|
+ case IDENTIFIERS.BITSTRING.rawValue:
|
|
|
+ let length = try scanner.consumeLength()
|
|
|
+
|
|
|
+ // There's an extra byte (0x00) after the bit string length in all the keys I've encountered.
|
|
|
+ // I couldn't find a specification that referenced this extra byte, but let's consume it and discard it.
|
|
|
+ _ = try scanner.consume(length: 1)
|
|
|
+
|
|
|
+ let data = try scanner.consume(length: length - 1)
|
|
|
+ return .bitString(data: data)
|
|
|
+
|
|
|
+ case IDENTIFIERS.OCTETSTRING.rawValue:
|
|
|
+ let length = try scanner.consumeLength()
|
|
|
+ let data = try scanner.consume(length: length)
|
|
|
+ return .octetString(data: data)
|
|
|
+
|
|
|
+ case IDENTIFIERS.EC_OBJECT.rawValue:
|
|
|
+ let length = try scanner.consumeLength()
|
|
|
+ let data = try scanner.consume(length: length)
|
|
|
+ return .objectIdentifier(data: data)
|
|
|
+
|
|
|
+ case IDENTIFIERS.EC_BITS.rawValue:
|
|
|
+ let length = try scanner.consumeLength()
|
|
|
+
|
|
|
+ // There's an extra byte (0x00) after the bit string length in all the keys I've encountered.
|
|
|
+ // I couldn't find a specification that referenced this extra byte, but let's consume it and discard it.
|
|
|
+ _ = try scanner.consume(length: 1)
|
|
|
+
|
|
|
+ let data = try scanner.consume(length: length - 1)
|
|
|
+ return .ecBits(data: data)
|
|
|
+
|
|
|
+ default:
|
|
|
+ throw DecodingError.invalidType(value: firstByte)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Parses an ASN1 sequence and returns its child nodes
|
|
|
+ ///
|
|
|
+ /// - Parameter data: ASN1 data
|
|
|
+ /// - Returns: A list of ASN1 nodes
|
|
|
+ /// - Throws: A DecodingError if anything goes wrong, or if an unknown node was encountered
|
|
|
+ private static func decodeSequence(data: Data) throws -> [Node] {
|
|
|
+ let scanner = ASN1.Scanner(data: data)
|
|
|
+ var nodes: [Node] = []
|
|
|
+ while !scanner.isComplete {
|
|
|
+ let node = try decodeNode(scanner: scanner)
|
|
|
+ nodes.append(node)
|
|
|
+ }
|
|
|
+ return nodes
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|