@@ -132,11 +132,11 @@ extension ASN1.ASN1ParserNode: CustomStringConvertible {
132
132
}
133
133
}
134
134
135
- // MARK: - Sequence
135
+ // MARK: - Sequence, SequenceOf, and Set
136
136
extension ASN1 {
137
137
/// Parse the node as an ASN.1 sequence.
138
- internal static func sequence< T> ( _ node: ASN1Node , _ builder: ( inout ASN1 . ASN1NodeCollection . Iterator ) throws -> T ) throws -> T {
139
- guard node. identifier == . sequence , case . constructed( let nodes) = node. content else {
138
+ internal static func sequence< T> ( _ node: ASN1Node , identifier : ASN1 . ASN1Identifier , _ builder: ( inout ASN1 . ASN1NodeCollection . Iterator ) throws -> T ) throws -> T {
139
+ guard node. identifier == identifier , case . constructed( let nodes) = node. content else {
140
140
throw CryptoKitASN1Error . unexpectedFieldType
141
141
}
142
142
@@ -150,6 +150,29 @@ extension ASN1 {
150
150
151
151
return result
152
152
}
153
+
154
+ internal static func sequence< T: ASN1Parseable > ( of: T . Type = T . self, identifier: ASN1 . ASN1Identifier , rootNode: ASN1Node ) throws -> [ T ] {
155
+ guard rootNode. identifier == identifier, case . constructed( let nodes) = rootNode. content else {
156
+ throw CryptoKitASN1Error . unexpectedFieldType
157
+ }
158
+
159
+ return try nodes. map { try T ( asn1Encoded: $0) }
160
+ }
161
+
162
+ internal static func sequence< T: ASN1Parseable > ( of: T . Type = T . self, identifier: ASN1 . ASN1Identifier , nodes: inout ASN1 . ASN1NodeCollection . Iterator ) throws -> [ T ] {
163
+ guard let node = nodes. next ( ) else {
164
+ // Not present, throw.
165
+ throw CryptoKitASN1Error . invalidASN1Object
166
+ }
167
+
168
+ return try sequence ( of: T . self, identifier: identifier, rootNode: node)
169
+ }
170
+
171
+ /// Parse the node as an ASN.1 set.
172
+ internal static func set< T> ( _ node: ASN1Node , identifier: ASN1 . ASN1Identifier , _ builder: ( inout ASN1 . ASN1NodeCollection . Iterator ) throws -> T ) throws -> T {
173
+ // Shhhh these two are secretly the same with identifier.
174
+ return try sequence ( node, identifier: identifier, builder)
175
+ }
153
176
}
154
177
155
178
// MARK: - Optional explicitly tagged
@@ -189,6 +212,54 @@ extension ASN1 {
189
212
}
190
213
}
191
214
215
+ // MARK: - DEFAULT
216
+ extension ASN1 {
217
+ /// Parses a value that is encoded with a DEFAULT. Such a value is optional, and if absent will
218
+ /// be replaced with its default.
219
+ ///
220
+ /// Expects to be used with the `ASN1.sequence` helper function.
221
+ internal static func decodeDefault< T: ASN1Parseable & Equatable > ( _ nodes: inout ASN1 . ASN1NodeCollection . Iterator , identifier: ASN1 . ASN1Identifier , defaultValue: T , _ builder: ( ASN1Node ) throws -> T ) throws -> T {
222
+ // A weird trick here: we only want to consume the next node _if_ it has the right tag. To achieve that,
223
+ // we work on a copy.
224
+ var localNodesCopy = nodes
225
+ guard let node = localNodesCopy. next ( ) else {
226
+ // Whoops, nothing here.
227
+ return defaultValue
228
+ }
229
+
230
+ guard node. identifier == identifier else {
231
+ // Node is a mismatch, with the wrong identifier. Our optional isn't present.
232
+ return defaultValue
233
+ }
234
+
235
+ // We have the right optional, so let's consume it.
236
+ nodes = localNodesCopy
237
+ let parsed = try builder ( node)
238
+
239
+ // DER forbids encoding DEFAULT values at their default state.
240
+ // We can lift this in BER.
241
+ guard parsed != defaultValue else {
242
+ throw CryptoKitASN1Error . invalidASN1Object
243
+ }
244
+
245
+ return parsed
246
+ }
247
+
248
+ internal static func decodeDefaultExplicitlyTagged< T: ASN1Parseable & Equatable > ( _ nodes: inout ASN1 . ASN1NodeCollection . Iterator , tagNumber: Int , tagClass: ASN1 . ASN1Identifier . TagClass , defaultValue: T , _ builder: ( ASN1Node ) throws -> T ) throws -> T {
249
+ if let result = try optionalExplicitlyTagged ( & nodes, tagNumber: tagNumber, tagClass: tagClass, builder) {
250
+ guard result != defaultValue else {
251
+ // DER forbids encoding DEFAULT values at their default state.
252
+ // We can lift this in BER.
253
+ throw CryptoKitASN1Error . invalidASN1Object
254
+ }
255
+
256
+ return result
257
+ } else {
258
+ return defaultValue
259
+ }
260
+ }
261
+ }
262
+
192
263
// MARK: - Parsing
193
264
extension ASN1 {
194
265
/// A parsed representation of ASN.1.
@@ -369,7 +440,7 @@ extension ASN1.ASN1Node {
369
440
// MARK: - Serializing
370
441
extension ASN1 {
371
442
struct Serializer {
372
- private ( set ) var serializedBytes : [ UInt8 ]
443
+ var serializedBytes : [ UInt8 ]
373
444
374
445
init ( ) {
375
446
// We allocate a 1kB array because that should cover us most of the time.
@@ -393,9 +464,37 @@ extension ASN1 {
393
464
}
394
465
395
466
mutating func serialize< T: ASN1Serializable > ( _ node: T , explicitlyTaggedWithTagNumber tagNumber: Int , tagClass: ASN1 . ASN1Identifier . TagClass ) throws {
467
+ return try self . serialize ( explicitlyTaggedWithTagNumber: tagNumber, tagClass: tagClass) { coder in
468
+ try coder. serialize ( node)
469
+ }
470
+ }
471
+
472
+ mutating func serialize( explicitlyTaggedWithTagNumber tagNumber: Int , tagClass: ASN1 . ASN1Identifier . TagClass , _ block: ( inout Serializer ) throws -> Void ) rethrows {
396
473
let identifier = ASN1Identifier ( explicitTagWithNumber: tagNumber, tagClass: tagClass)
397
474
try self . appendConstructedNode ( identifier: identifier) { coder in
398
- try coder. serialize ( node)
475
+ try block ( & coder)
476
+ }
477
+ }
478
+
479
+ mutating func serializeSequenceOf< Elements: Sequence > ( _ elements: Elements , identifier: ASN1 . ASN1Identifier = . sequence) throws where Elements. Element: ASN1Serializable {
480
+ try self . appendConstructedNode ( identifier: identifier) { coder in
481
+ for element in elements {
482
+ try coder. serialize ( element)
483
+ }
484
+ }
485
+ }
486
+
487
+ mutating func serialize( _ node: ASN1 . ASN1Node ) {
488
+ let identifier = node. identifier
489
+ self . _appendNode ( identifier: identifier) { coder in
490
+ switch node. content {
491
+ case . constructed( let nodes) :
492
+ for node in nodes {
493
+ coder. serialize ( node)
494
+ }
495
+ case . primitive( let baseData) :
496
+ coder. serializedBytes. append ( contentsOf: baseData)
497
+ }
399
498
}
400
499
}
401
500
@@ -438,7 +537,7 @@ extension ASN1 {
438
537
for shift in ( 0 ..< ( lengthBytesNeeded - 1 ) ) . reversed ( ) {
439
538
// Shift and mask the integer.
440
539
self . serializedBytes. formIndex ( after: & writeIndex)
441
- self . serializedBytes [ writeIndex] = UInt8 ( truncatingIfNeeded: contentLength >> ( shift * 8 ) )
540
+ self . serializedBytes [ writeIndex] = UInt8 ( truncatingIfNeeded: ( contentLength >> ( shift * 8 ) ) )
442
541
}
443
542
444
543
assert ( writeIndex == self . serializedBytes. index ( lengthIndex, offsetBy: lengthBytesNeeded - 1 ) )
@@ -463,12 +562,54 @@ extension ASN1Parseable {
463
562
internal init ( asn1Encoded: [ UInt8 ] ) throws {
464
563
self = try . init( asn1Encoded: ASN1 . parse ( asn1Encoded) )
465
564
}
565
+
566
+ internal init ( asn1Encoded: ArraySlice < UInt8 > ) throws {
567
+ self = try . init( asn1Encoded: ASN1 . parse ( asn1Encoded) )
568
+ }
466
569
}
467
570
468
571
internal protocol ASN1Serializable {
469
572
func serialize( into coder: inout ASN1 . Serializer ) throws
470
573
}
471
574
575
+ /// Covers ASN.1 types that may be implicitly tagged. Not all nodes can be!
576
+ internal protocol ASN1ImplicitlyTaggable : ASN1Parseable , ASN1Serializable {
577
+ /// The tag that the first node will use "by default" if the grammar omits
578
+ /// any more specific tag definition.
579
+ static var defaultIdentifier : ASN1 . ASN1Identifier { get }
580
+
581
+ init ( asn1Encoded: ASN1 . ASN1Node , withIdentifier identifier: ASN1 . ASN1Identifier ) throws
582
+
583
+ func serialize( into coder: inout ASN1 . Serializer , withIdentifier identifier: ASN1 . ASN1Identifier ) throws
584
+ }
585
+
586
+ extension ASN1ImplicitlyTaggable {
587
+ internal init ( asn1Encoded sequenceNodeIterator: inout ASN1 . ASN1NodeCollection . Iterator ,
588
+ withIdentifier identifier: ASN1 . ASN1Identifier = Self . defaultIdentifier) throws {
589
+ guard let node = sequenceNodeIterator. next ( ) else {
590
+ throw CryptoKitASN1Error . invalidASN1Object
591
+ }
592
+
593
+ self = try . init( asn1Encoded: node, withIdentifier: identifier)
594
+ }
595
+
596
+ internal init ( asn1Encoded: [ UInt8 ] , withIdentifier identifier: ASN1 . ASN1Identifier = Self . defaultIdentifier) throws {
597
+ self = try . init( asn1Encoded: ASN1 . parse ( asn1Encoded) , withIdentifier: identifier)
598
+ }
599
+
600
+ internal init ( asn1Encoded: ArraySlice < UInt8 > , withIdentifier identifier: ASN1 . ASN1Identifier = Self . defaultIdentifier) throws {
601
+ self = try . init( asn1Encoded: ASN1 . parse ( asn1Encoded) , withIdentifier: identifier)
602
+ }
603
+
604
+ init ( asn1Encoded: ASN1 . ASN1Node ) throws {
605
+ try self . init ( asn1Encoded: asn1Encoded, withIdentifier: Self . defaultIdentifier)
606
+ }
607
+
608
+ func serialize( into coder: inout ASN1 . Serializer ) throws {
609
+ try self . serialize ( into: & coder, withIdentifier: Self . defaultIdentifier)
610
+ }
611
+ }
612
+
472
613
extension ArraySlice where Element == UInt8 {
473
614
fileprivate mutating func readASN1Length( ) throws -> UInt ? {
474
615
guard let firstByte = self . popFirst ( ) else {
0 commit comments