File: TBSCertificate.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (173 lines) | stat: -rw-r--r-- 6,749 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftCertificates open source project
//
// Copyright (c) 2022 Apple Inc. and the SwiftCertificates project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftCertificates project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import SwiftASN1

// TBSCertificate  ::=  SEQUENCE  {
//      version         [0]  Version DEFAULT v1,
//      serialNumber         CertificateSerialNumber,
//      signature            AlgorithmIdentifier,
//      issuer               Name,
//      validity             Validity,
//      subject              Name,
//      subjectPublicKeyInfo SubjectPublicKeyInfo,
//      issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
//                           -- If present, version MUST be v2 or v3
//      subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
//                           -- If present, version MUST be v2 or v3
//      extensions      [3]  Extensions OPTIONAL
//                           -- If present, version MUST be v3 --  }
//
// Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
//
// CertificateSerialNumber  ::=  INTEGER
//
// UniqueIdentifier  ::=  BIT STRING
//
// Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
@usableFromInline
typealias UniqueIdentifier = ASN1BitString

@usableFromInline
struct TBSCertificate: DERImplicitlyTaggable, Hashable, Sendable {
    @inlinable
    static var defaultIdentifier: ASN1Identifier {
        .sequence
    }

    @usableFromInline
    var version: Certificate.Version

    @usableFromInline
    var serialNumber: Certificate.SerialNumber

    @usableFromInline
    var signature: Certificate.SignatureAlgorithm

    @usableFromInline
    var issuer: DistinguishedName

    @usableFromInline
    var validity: Validity

    @usableFromInline
    var subject: DistinguishedName

    @usableFromInline
    var publicKey: Certificate.PublicKey

    @usableFromInline
    var issuerUniqueID: UniqueIdentifier?

    @usableFromInline
    var subjectUniqueID: UniqueIdentifier?

    @usableFromInline
    var extensions: Certificate.Extensions

    @inlinable
    internal init(
        version: Certificate.Version,
        serialNumber: Certificate.SerialNumber,
        signature: Certificate.SignatureAlgorithm,
        issuer: DistinguishedName,
        validity: Validity,
        subject: DistinguishedName,
        publicKey: Certificate.PublicKey,
        issuerUniqueID: UniqueIdentifier? = nil,
        subjectUniqueID: UniqueIdentifier? = nil,
        extensions: Certificate.Extensions
    ) {
        self.version = version
        self.serialNumber = serialNumber
        self.signature = signature
        self.issuer = issuer
        self.validity = validity
        self.subject = subject
        self.publicKey = publicKey
        self.issuerUniqueID = issuerUniqueID
        self.subjectUniqueID = subjectUniqueID
        self.extensions = extensions
    }

    @inlinable
    init(derEncoded rootNode: ASN1Node, withIdentifier identifier: ASN1Identifier) throws {
        self = try DER.sequence(rootNode, identifier: identifier) { nodes in
            let version = try DER.decodeDefaultExplicitlyTagged(
                &nodes,
                tagNumber: 0,
                tagClass: .contextSpecific,
                defaultValue: Int(0)
            )
            guard (0...2).contains(version) else {
                throw ASN1Error.invalidASN1Object(reason: "Invalid X.509 version \(version)")
            }

            let serialNumber = try ArraySlice<UInt8>(derEncoded: &nodes)
            let signature = try AlgorithmIdentifier(derEncoded: &nodes)
            let issuer = try DistinguishedName(derEncoded: &nodes)
            let validity = try Validity(derEncoded: &nodes)
            let subject = try DistinguishedName(derEncoded: &nodes)
            let subjectPublicKeyInfo = try SubjectPublicKeyInfo(derEncoded: &nodes)
            let issuerUniqueID = try DER.optionalExplicitlyTagged(&nodes, tagNumber: 1, tagClass: .contextSpecific) {
                try UniqueIdentifier(derEncoded: $0)
            }
            let subjectUniqueID = try DER.optionalExplicitlyTagged(&nodes, tagNumber: 2, tagClass: .contextSpecific) {
                try UniqueIdentifier(derEncoded: $0)
            }
            let extensions = try DER.optionalExplicitlyTagged(&nodes, tagNumber: 3, tagClass: .contextSpecific) {
                try DER.sequence(of: Certificate.Extension.self, identifier: .sequence, rootNode: $0)
            }

            return TBSCertificate(
                version: Certificate.Version(rawValue: version),
                serialNumber: Certificate.SerialNumber(bytes: serialNumber),
                signature: Certificate.SignatureAlgorithm(algorithmIdentifier: signature),
                issuer: issuer,
                validity: validity,
                subject: subject,
                publicKey: try Certificate.PublicKey(spki: subjectPublicKeyInfo),
                issuerUniqueID: issuerUniqueID,
                subjectUniqueID: subjectUniqueID,
                extensions: try Certificate.Extensions(extensions ?? [])
            )
        }
    }

    @inlinable
    func serialize(into coder: inout DER.Serializer, withIdentifier identifier: ASN1Identifier) throws {
        try coder.appendConstructedNode(identifier: identifier) { coder in
            if self.version != .v1 {
                try coder.serialize(self.version.rawValue, explicitlyTaggedWithTagNumber: 0, tagClass: .contextSpecific)
            }
            try coder.serialize(self.serialNumber.bytes)
            try coder.serialize(AlgorithmIdentifier(self.signature))
            try coder.serialize(self.issuer)
            try coder.serialize(self.validity)
            try coder.serialize(self.subject)
            try coder.serialize(SubjectPublicKeyInfo(self.publicKey))
            if let issuerUniqueID = self.issuerUniqueID {
                try coder.serialize(issuerUniqueID, explicitlyTaggedWithTagNumber: 1, tagClass: .contextSpecific)
            }
            if let subjectUniqueID = self.subjectUniqueID {
                try coder.serialize(subjectUniqueID, explicitlyTaggedWithTagNumber: 2, tagClass: .contextSpecific)
            }
            if self.extensions.count > 0 {
                try coder.serialize(explicitlyTaggedWithTagNumber: 3, tagClass: .contextSpecific) { coder in
                    try coder.serializeSequenceOf(extensions)
                }
            }
        }
    }
}