Skip to content

Commit 84fc2fa

Browse files
authored
Signing of the prebuilts manifest file. (#8284)
To ensure confidence that the manifest file and zip files are the ones that were published, we use checksums for the zip files which are listed in the manifest file. We now add signing for the manifest file to ensure it isn't compromised. We use the same scheme as we used for package collections where a signature is generated for the core manifest data and then injected into the JSON file at the top level. Note that we are adding the ManifestSigning to the Workspace module with the eventual intention of making this a module we can reuse with package collections once we forward port to main. We don't want to make changes to the package collections on the 6.1 branch. Also added a quick fix to the host platform computation that was causing compile errors if not the two major ones (i.e. 32-bit Android ARM hosts).
1 parent 8fc6467 commit 84fc2fa

17 files changed

+2495
-752
lines changed

Sources/Basics/FileSystem/FileSystem+Extensions.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,3 +677,17 @@ extension FileSystem {
677677
}
678678
}
679679
}
680+
681+
extension FileSystem {
682+
/// Do a deep enumeration, passing each file to block
683+
public func enumerate(directory: AbsolutePath, block: (AbsolutePath) throws -> ()) throws {
684+
for file in try getDirectoryContents(directory) {
685+
let path = directory.appending(file)
686+
if isDirectory(path) {
687+
try enumerate(directory: path, block: block)
688+
} else {
689+
try block(path)
690+
}
691+
}
692+
}
693+
}

Sources/CoreCommands/Options.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ public struct CachingOptions: ParsableArguments {
201201
help: .hidden
202202
)
203203
public var prebuiltsDownloadURL: String?
204+
205+
@Option(
206+
name: .customLong("experimental-prebuilts-root-cert"),
207+
help: .hidden
208+
)
209+
public var prebuiltsRootCertPath: String?
204210
}
205211

206212
public struct LoggingOptions: ParsableArguments {

Sources/CoreCommands/SwiftCommandState.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,8 @@ public final class SwiftCommandState {
473473
},
474474
manifestImportRestrictions: .none,
475475
usePrebuilts: options.caching.usePrebuilts,
476-
prebuiltsDownloadURL: options.caching.prebuiltsDownloadURL
476+
prebuiltsDownloadURL: options.caching.prebuiltsDownloadURL,
477+
prebuiltsRootCertPath: options.caching.prebuiltsRootCertPath
477478
),
478479
cancellator: self.cancellator,
479480
initializationWarningHandler: { self.observabilityScope.emit(warning: $0) },

Sources/Workspace/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ add_library(Workspace
1414
ManagedArtifact.swift
1515
ManagedDependency.swift
1616
ManagedPrebuilt.swift
17+
ManifestSigning/Base64URL.swift
18+
ManifestSigning/CertificatePolicy.swift
19+
ManifestSigning/embedded_resources.swift
20+
ManifestSigning/ManifestSigning.swift
21+
ManifestSigning/Signature.swift
22+
ManifestSigning/Utilities.swift
23+
ManifestSigning/X509Extensions.swift
1724
PackageContainer/FileSystemPackageContainer.swift
1825
PackageContainer/RegistryPackageContainer.swift
1926
PackageContainer/SourceControlPackageContainer.swift
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2021-2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
//===----------------------------------------------------------------------===//
14+
//
15+
// This source file is part of the Vapor open source project
16+
//
17+
// Copyright (c) 2017-2020 Vapor project authors
18+
// Licensed under MIT
19+
//
20+
// See LICENSE for license information
21+
//
22+
// SPDX-License-Identifier: MIT
23+
//
24+
//===----------------------------------------------------------------------===//
25+
26+
import Foundation
27+
28+
// Source: https://github.com/vapor/jwt-kit/blob/master/Sources/JWTKit/Utilities/Base64URL.swift
29+
30+
extension DataProtocol {
31+
func base64URLDecodedBytes() -> Data? {
32+
var data = Data(self)
33+
data.base64URLUnescape()
34+
return Data(base64Encoded: data)
35+
}
36+
37+
func base64URLEncodedBytes() -> Data {
38+
var data = Data(self).base64EncodedData()
39+
data.base64URLEscape()
40+
return data
41+
}
42+
}
43+
44+
extension Data {
45+
/// Converts base64-url encoded data to a base64 encoded data.
46+
///
47+
/// https://tools.ietf.org/html/rfc4648#page-7
48+
mutating func base64URLUnescape() {
49+
for i in 0 ..< self.count {
50+
switch self[i] {
51+
case 0x2D: self[self.index(self.startIndex, offsetBy: i)] = 0x2B
52+
case 0x5F: self[self.index(self.startIndex, offsetBy: i)] = 0x2F
53+
default: break
54+
}
55+
}
56+
/// https://stackoverflow.com/questions/43499651/decode-base64url-to-base64-swift
57+
let padding = count % 4
58+
if padding > 0 {
59+
self += Data(repeating: 0x3D, count: 4 - padding)
60+
}
61+
}
62+
63+
/// Converts base64 encoded data to a base64-url encoded data.
64+
///
65+
/// https://tools.ietf.org/html/rfc4648#page-7
66+
mutating func base64URLEscape() {
67+
for i in 0 ..< self.count {
68+
switch self[i] {
69+
case 0x2B: self[self.index(self.startIndex, offsetBy: i)] = 0x2D
70+
case 0x2F: self[self.index(self.startIndex, offsetBy: i)] = 0x5F
71+
default: break
72+
}
73+
}
74+
self = split(separator: 0x3D).first ?? .init()
75+
}
76+
}

0 commit comments

Comments
 (0)