More spm fixes

This commit is contained in:
Joe Mattiello
2023-03-01 08:52:01 -05:00
parent f3a70e1e47
commit 364b11ec9d
516 changed files with 154395 additions and 803 deletions

8
.gitmodules vendored
View File

@@ -1,14 +1,14 @@
[submodule "Dependencies/libimobiledevice"]
path = Dependencies/libimobiledevice
path = Sources/libmobiledevice/libimobiledevice
url = https://github.com/libimobiledevice/libimobiledevice
[submodule "Dependencies/libusbmuxd"]
path = Dependencies/libusbmuxd
path = Sources/libmobiledevice/libusbmuxd
url = https://github.com/libimobiledevice/libusbmuxd.git
[submodule "Dependencies/libplist"]
path = Dependencies/libplist
path = Sources/libmobiledevice/libplist
url = https://github.com/libimobiledevice/libplist.git
[submodule "Dependencies/libimobiledevice-glue"]
path = Dependencies/libimobiledevice-glue
path = Sources/libmobiledevice/libimobiledevice-glue
url = https://github.com/libimobiledevice/libimobiledevice-glue
[submodule "Sources/libfragmentzip"]
path = Sources/libfragmentzip/libfragmentzip-source

View File

@@ -1,3 +0,0 @@
#include "Build.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER).AltBackup

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -1,3 +0,0 @@
#include "Build.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER).AltStoreCore

View File

@@ -1,3 +0,0 @@
#include "Build.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER).AltWidget

View File

@@ -0,0 +1,3 @@
#include "../Build.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER).SideBackup

View File

@@ -1,3 +1,3 @@
#include "Build.xcconfig"
#include "../Build.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(ORG_PREFIX).$(PRODUCT_NAME)

View File

@@ -0,0 +1,3 @@
#include "../Build.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER).SideStoreCore

View File

@@ -0,0 +1,3 @@
#include "../Build.xcconfig"
PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER).SideWidget

Submodule Dependencies/libplist deleted from 17546f53ac

Submodule Dependencies/libusbmuxd deleted from 8b82ef166e

View File

@@ -84,12 +84,12 @@ let dependencies: [Package.Dependency] = [
] // + dependencies_cargo
let package = Package(
name: "SideStoreCore",
name: "SideStore",
defaultLocalization: "en",
platforms: [
.iOS(.v12),
// .tvOS(.v12),
// .macOS(.v12),
.iOS(.v13),
.tvOS(.v13),
.macCatalyst(.v13),
],
products: [
@@ -117,7 +117,7 @@ let package = Package(
.executableTarget(
name: "SideStore",
dependencies: [
"AltPatcher",
"SidePatcher",
"EmotionalDamage",
"MiniMuxerSwift",
"SideStoreCore",
@@ -175,16 +175,19 @@ let package = Package(
dependencies: ["EmotionalDamage"]
),
// MARK: - AltPatcher
// MARK: - SidePatcher
.target(
name: "AltPatcher",
dependencies: []
name: "SidePatcher",
dependencies: [
.product(name: "Roxas", package: "Roxas"),
.product(name: "RoxasUI", package: "Roxas"),
]
),
.testTarget(
name: "AltPatcherTests",
dependencies: ["AltPatcher"]
name: "SidePatcherTests",
dependencies: ["SidePatcher"]
),
// MARK: - MiniMuxer
@@ -287,6 +290,55 @@ let package = Package(
name: "libfragmentzipTests",
dependencies: ["libfragmentzip"]
),
// MARK: - libmobiledevice
.target(
name: "libimobiledevice",
dependencies: [
"libimobiledevice-glue",
"libplist",
"libusbmuxd"
],
path: "Sources/libimobiledevice/libimobiledevice/",
exclude: [
"include/asprintf.h",
"include/Makefile.am",
"include/endianness.h"
],
publicHeadersPath: "include/libimobiledevice/"
),
.target(
name: "libimobiledevice-glue",
dependencies: [
],
path: "Sources/libimobiledevice/libimobiledevice-glue/",
exclude: [
"include/Makefile.am",
"include/endianness.h"
],
publicHeadersPath: "include/libimobiledevice-glue/"
),
.target(
name: "libplist",
dependencies: [
],
path: "Sources/libimobiledevice/libplist/",
exclude: [
"include/Makefile.am",
],
publicHeadersPath: "include/plist"
),
.target(
name: "libusbmuxd",
dependencies: [
],
path: "Sources/libimobiledevice/libusbmuxd/",
exclude: [
"include/Makefile.am",
"include/usbmuxd-proto.h"
],
publicHeadersPath: "include"
),
],
swiftLanguageVersions: [.v5],
cLanguageStandard: .c2x,

View File

@@ -7,14 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
191E6087290C7B50001A3B7C /* libminimuxer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 191E5FB5290A5E1F001A3B7C /* libminimuxer.a */; };
4879A9622861049C00FC1BBD /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A9612861049C00FC1BBD /* OpenSSL */; };
B34AFD0A29A9CEDD00E637B4 /* SideKit in Frameworks */ = {isa = PBXBuildFile; productRef = B34AFD0929A9CEDD00E637B4 /* SideKit */; };
B34AFD0D29A9CF4000E637B4 /* Roxas in Frameworks */ = {isa = PBXBuildFile; productRef = B34AFD0C29A9CF4000E637B4 /* Roxas */; };
B34AFD0F29A9CF4000E637B4 /* RoxasUI in Frameworks */ = {isa = PBXBuildFile; productRef = B34AFD0E29A9CF4000E637B4 /* RoxasUI */; };
B3C395F4284F35DD00DA9E2F /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = B3C395F3284F35DD00DA9E2F /* Nuke */; };
B3C395F7284F362400DA9E2F /* AppCenterAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = B3C395F6284F362400DA9E2F /* AppCenterAnalytics */; };
B3C395F9284F362400DA9E2F /* AppCenterCrashes in Frameworks */ = {isa = PBXBuildFile; productRef = B3C395F8284F362400DA9E2F /* AppCenterCrashes */; };
B3CD301C29AF87EE00374AF8 /* SideStore in Frameworks */ = {isa = PBXBuildFile; productRef = B3CD301B29AF87EE00374AF8 /* SideStore */; };
BF989177250AABF4002ACF50 /* SideWidgetExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = BF989167250AABF3002ACF50 /* SideWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
D533E8B72727841800A9B5DD /* libAppleArchive.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D533E8B62727841800A9B5DD /* libAppleArchive.tbd */; settings = {ATTRIBUTES = (Weak, ); }; };
/* End PBXBuildFile section */
@@ -55,16 +48,20 @@
/* Begin PBXFileReference section */
191E5FB5290A5E1F001A3B7C /* libminimuxer.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libminimuxer.a; path = "Dependencies/minimuxer/target/aarch64-apple-ios/debug/libminimuxer.a"; sourceTree = "<group>"; };
B32C055D29AF6867004789CF /* SideStore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = SideStore; sourceTree = "<group>"; };
B343F86C295F759E002B1159 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk/usr/lib/libresolv.tbd; sourceTree = DEVELOPER_DIR; };
B39575F4284F29E20080B4FF /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B3C39606284F4C8400DA9E2F /* CodeSigning.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = CodeSigning.xcconfig; sourceTree = "<group>"; };
B3C39607284F4C8400DA9E2F /* Build.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Build.xcconfig; sourceTree = "<group>"; };
B3C39608284F4C8400DA9E2F /* CodeSigning.xcconfig.sample */ = {isa = PBXFileReference; lastKnownFileType = text; path = CodeSigning.xcconfig.sample; sourceTree = "<group>"; };
B3C3960B284F4C9800DA9E2F /* AltStore.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AltStore.xcconfig; sourceTree = "<group>"; };
B3C3960D284F4E4B00DA9E2F /* AltWidgetExtension.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AltWidgetExtension.xcconfig; sourceTree = "<group>"; };
B3C3960E284F4F9100DA9E2F /* AltStoreCore.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AltStoreCore.xcconfig; sourceTree = "<group>"; };
B3C3960F284F53E900DA9E2F /* AltBackup.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AltBackup.xcconfig; sourceTree = "<group>"; };
B3CD301129AF854600374AF8 /* SideStore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = SideStore; sourceTree = "<group>"; };
B3CD301329AF876000374AF8 /* SideBackup.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SideBackup.xcconfig; sourceTree = "<group>"; };
B3CD301429AF876000374AF8 /* SideWidgetExtension.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SideWidgetExtension.xcconfig; sourceTree = "<group>"; };
B3CD301529AF876000374AF8 /* Shared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
B3CD301629AF876000374AF8 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
B3CD301729AF876000374AF8 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
B3CD301829AF876000374AF8 /* SideStore.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SideStore.xcconfig; sourceTree = "<group>"; };
B3CD301929AF876000374AF8 /* Archive.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Archive.xcconfig; sourceTree = "<group>"; };
B3CD301A29AF876000374AF8 /* SideStoreCore.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SideStoreCore.xcconfig; sourceTree = "<group>"; };
BF4588872298DD3F00BD7491 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/lib/libxml2.tbd; sourceTree = DEVELOPER_DIR; };
BF580497246A3D19008AE704 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
BF989167250AABF3002ACF50 /* SideWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SideWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -85,25 +82,33 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
191E6087290C7B50001A3B7C /* libminimuxer.a in Frameworks */,
B34AFD0F29A9CF4000E637B4 /* RoxasUI in Frameworks */,
D533E8B72727841800A9B5DD /* libAppleArchive.tbd in Frameworks */,
B3C395F9284F362400DA9E2F /* AppCenterCrashes in Frameworks */,
B34AFD0A29A9CEDD00E637B4 /* SideKit in Frameworks */,
4879A9622861049C00FC1BBD /* OpenSSL in Frameworks */,
B3C395F4284F35DD00DA9E2F /* Nuke in Frameworks */,
B34AFD0D29A9CF4000E637B4 /* Roxas in Frameworks */,
B3C395F7284F362400DA9E2F /* AppCenterAnalytics in Frameworks */,
B3CD301C29AF87EE00374AF8 /* SideStore in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
B3CD301229AF876000374AF8 /* Configurations */ = {
isa = PBXGroup;
children = (
B3CD301329AF876000374AF8 /* SideBackup.xcconfig */,
B3CD301429AF876000374AF8 /* SideWidgetExtension.xcconfig */,
B3CD301529AF876000374AF8 /* Shared.xcconfig */,
B3CD301629AF876000374AF8 /* Debug.xcconfig */,
B3CD301729AF876000374AF8 /* Release.xcconfig */,
B3CD301829AF876000374AF8 /* SideStore.xcconfig */,
B3CD301929AF876000374AF8 /* Archive.xcconfig */,
B3CD301A29AF876000374AF8 /* SideStoreCore.xcconfig */,
);
path = Configurations;
sourceTree = "<group>";
};
B3E8749729AF639C00745374 /* Packages */ = {
isa = PBXGroup;
children = (
B32C055D29AF6867004789CF /* SideStore */,
B3CD301129AF854600374AF8 /* SideStore */,
);
name = Packages;
sourceTree = "<group>";
@@ -115,10 +120,7 @@
B3C39607284F4C8400DA9E2F /* Build.xcconfig */,
B3C39606284F4C8400DA9E2F /* CodeSigning.xcconfig */,
B3C39608284F4C8400DA9E2F /* CodeSigning.xcconfig.sample */,
B3C3960B284F4C9800DA9E2F /* AltStore.xcconfig */,
B3C3960F284F53E900DA9E2F /* AltBackup.xcconfig */,
B3C3960D284F4E4B00DA9E2F /* AltWidgetExtension.xcconfig */,
B3C3960E284F4F9100DA9E2F /* AltStoreCore.xcconfig */,
B3CD301229AF876000374AF8 /* Configurations */,
BFD247852284BB3300981D42 /* Frameworks */,
BFD2476B2284B9A500981D42 /* Products */,
);
@@ -184,13 +186,7 @@
);
name = SideStore;
packageProductDependencies = (
B3C395F3284F35DD00DA9E2F /* Nuke */,
B3C395F6284F362400DA9E2F /* AppCenterAnalytics */,
B3C395F8284F362400DA9E2F /* AppCenterCrashes */,
4879A9612861049C00FC1BBD /* OpenSSL */,
B34AFD0929A9CEDD00E637B4 /* SideKit */,
B34AFD0C29A9CF4000E637B4 /* Roxas */,
B34AFD0E29A9CF4000E637B4 /* RoxasUI */,
B3CD301B29AF87EE00374AF8 /* SideStore */,
);
productName = AltStore;
productReference = BFD2476A2284B9A500981D42 /* SideStore.app */;
@@ -224,7 +220,7 @@
};
};
};
buildConfigurationList = BFD247652284B9A500981D42 /* Build configuration list for PBXProject "AltStore" */;
buildConfigurationList = BFD247652284B9A500981D42 /* Build configuration list for PBXProject "SideStore-SPM" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
@@ -234,17 +230,6 @@
);
mainGroup = BFD247612284B9A500981D42;
packageReferences = (
D58D5F2C26DFE68E00E55E38 /* XCRemoteSwiftPackageReference "LaunchAtLogin" */,
B3C395EF284F2DE700DA9E2F /* XCRemoteSwiftPackageReference "KeychainAccess" */,
B3C395F2284F35DD00DA9E2F /* XCRemoteSwiftPackageReference "Nuke" */,
B3C395F5284F362400DA9E2F /* XCRemoteSwiftPackageReference "appcenter-sdk-apple" */,
B3C395FA284F3B2400DA9E2F /* XCRemoteSwiftPackageReference "Sparkle" */,
B3C395FD284F3C0900DA9E2F /* XCRemoteSwiftPackageReference "STPrivilegedTask" */,
4879A95D2861046500FC1BBD /* XCRemoteSwiftPackageReference "AltSign" */,
4879A9602861049C00FC1BBD /* XCRemoteSwiftPackageReference "OpenSSL" */,
99C4EF472978D52400CB538D /* XCRemoteSwiftPackageReference "SemanticVersion" */,
B34AFD0829A9CEDD00E637B4 /* XCRemoteSwiftPackageReference "SideKit" */,
B34AFD0B29A9CF4000E637B4 /* XCRemoteSwiftPackageReference "Roxas" */,
);
productRefGroup = BFD2476B2284B9A500981D42 /* Products */;
projectDirPath = "";
@@ -301,20 +286,20 @@
/* Begin XCBuildConfiguration section */
BF989179250AABF4002ACF50 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = B3C3960D284F4E4B00DA9E2F /* AltWidgetExtension.xcconfig */;
baseConfigurationReference = B3CD301429AF876000374AF8 /* SideWidgetExtension.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CODE_SIGN_ENTITLEMENTS = AltWidget/AltWidgetExtension.entitlements;
CODE_SIGN_ENTITLEMENTS = Sources/SideWidget/Resources/SideWidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = AltWidget/Info.plist;
INFOPLIST_FILE = Sources/SideWidget/Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -332,19 +317,19 @@
};
BF98917A250AABF4002ACF50 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = B3C3960D284F4E4B00DA9E2F /* AltWidgetExtension.xcconfig */;
baseConfigurationReference = B3CD301429AF876000374AF8 /* SideWidgetExtension.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CODE_SIGN_ENTITLEMENTS = AltWidget/AltWidgetExtension.entitlements;
CODE_SIGN_ENTITLEMENTS = Sources/SideWidget/Resources/SideWidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = AltWidget/Info.plist;
INFOPLIST_FILE = Sources/SideWidget/Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -492,16 +477,16 @@
};
BFD2477F2284B9A700981D42 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = B3C3960B284F4C9800DA9E2F /* AltStore.xcconfig */;
baseConfigurationReference = B3CD301829AF876000374AF8 /* SideStore.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = AltStore/AltStore.entitlements;
CODE_SIGN_ENTITLEMENTS = Sources/SideStore/Resources/SideStore.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = AltStore/Info.plist;
INFOPLIST_FILE = Sources/SideStore/Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -516,7 +501,6 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_OBJC_BRIDGING_HEADER = "AltStore/AltStore-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -525,16 +509,16 @@
};
BFD247802284B9A700981D42 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = B3C3960B284F4C9800DA9E2F /* AltStore.xcconfig */;
baseConfigurationReference = B3CD301829AF876000374AF8 /* SideStore.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = AltStore/AltStore.entitlements;
CODE_SIGN_ENTITLEMENTS = Sources/SideStore/Resources/SideStore.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = AltStore/Info.plist;
INFOPLIST_FILE = Sources/SideStore/Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -549,7 +533,6 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_OBJC_BRIDGING_HEADER = "AltStore/AltStore-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -567,7 +550,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
BFD247652284B9A500981D42 /* Build configuration list for PBXProject "AltStore" */ = {
BFD247652284B9A500981D42 /* Build configuration list for PBXProject "SideStore-SPM" */ = {
isa = XCConfigurationList;
buildConfigurations = (
BFD2477C2284B9A700981D42 /* Debug */,
@@ -587,132 +570,10 @@
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
4879A95D2861046500FC1BBD /* XCRemoteSwiftPackageReference "AltSign" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SideStore/AltSign";
requirement = {
branch = master;
kind = branch;
};
};
4879A9602861049C00FC1BBD /* XCRemoteSwiftPackageReference "OpenSSL" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/krzyzanowskim/OpenSSL";
requirement = {
kind = upToNextMinorVersion;
minimumVersion = 1.1.180;
};
};
99C4EF472978D52400CB538D /* XCRemoteSwiftPackageReference "SemanticVersion" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SwiftPackageIndex/SemanticVersion.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.3.5;
};
};
B34AFD0829A9CEDD00E637B4 /* XCRemoteSwiftPackageReference "SideKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SideStore/SideKit.git";
requirement = {
kind = upToNextMinorVersion;
minimumVersion = 0.1.0;
};
};
B34AFD0B29A9CF4000E637B4 /* XCRemoteSwiftPackageReference "Roxas" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/JoeMatt/Roxas.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.2.2;
};
};
B3C395EF284F2DE700DA9E2F /* XCRemoteSwiftPackageReference "KeychainAccess" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.2.0;
};
};
B3C395F2284F35DD00DA9E2F /* XCRemoteSwiftPackageReference "Nuke" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/kean/Nuke.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 7.0.0;
};
};
B3C395F5284F362400DA9E2F /* XCRemoteSwiftPackageReference "appcenter-sdk-apple" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/microsoft/appcenter-sdk-apple.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.2.0;
};
};
B3C395FA284F3B2400DA9E2F /* XCRemoteSwiftPackageReference "Sparkle" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/sparkle-project/Sparkle.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.1.0;
};
};
B3C395FD284F3C0900DA9E2F /* XCRemoteSwiftPackageReference "STPrivilegedTask" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/JoeMatt/STPrivilegedTask.git";
requirement = {
branch = master;
kind = branch;
};
};
D58D5F2C26DFE68E00E55E38 /* XCRemoteSwiftPackageReference "LaunchAtLogin" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/sindresorhus/LaunchAtLogin.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.1.0;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
4879A9612861049C00FC1BBD /* OpenSSL */ = {
B3CD301B29AF87EE00374AF8 /* SideStore */ = {
isa = XCSwiftPackageProductDependency;
package = 4879A9602861049C00FC1BBD /* XCRemoteSwiftPackageReference "OpenSSL" */;
productName = OpenSSL;
};
B34AFD0929A9CEDD00E637B4 /* SideKit */ = {
isa = XCSwiftPackageProductDependency;
package = B34AFD0829A9CEDD00E637B4 /* XCRemoteSwiftPackageReference "SideKit" */;
productName = SideKit;
};
B34AFD0C29A9CF4000E637B4 /* Roxas */ = {
isa = XCSwiftPackageProductDependency;
package = B34AFD0B29A9CF4000E637B4 /* XCRemoteSwiftPackageReference "Roxas" */;
productName = Roxas;
};
B34AFD0E29A9CF4000E637B4 /* RoxasUI */ = {
isa = XCSwiftPackageProductDependency;
package = B34AFD0B29A9CF4000E637B4 /* XCRemoteSwiftPackageReference "Roxas" */;
productName = RoxasUI;
};
B3C395F3284F35DD00DA9E2F /* Nuke */ = {
isa = XCSwiftPackageProductDependency;
package = B3C395F2284F35DD00DA9E2F /* XCRemoteSwiftPackageReference "Nuke" */;
productName = Nuke;
};
B3C395F6284F362400DA9E2F /* AppCenterAnalytics */ = {
isa = XCSwiftPackageProductDependency;
package = B3C395F5284F362400DA9E2F /* XCRemoteSwiftPackageReference "appcenter-sdk-apple" */;
productName = AppCenterAnalytics;
};
B3C395F8284F362400DA9E2F /* AppCenterCrashes */ = {
isa = XCSwiftPackageProductDependency;
package = B3C395F5284F362400DA9E2F /* XCRemoteSwiftPackageReference "appcenter-sdk-apple" */;
productName = AppCenterCrashes;
productName = SideStore;
};
/* End XCSwiftPackageProductDependency section */
};

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:/Users/jmattiello/Workspace/Provenance/SideStoreRepos/SideStore/SideStore-SPM.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -18,6 +18,15 @@
"version" : "4.4.3"
}
},
{
"identity" : "down",
"kind" : "remoteSourceControl",
"location" : "https://github.com/johnxnguyen/Down",
"state" : {
"branch" : "master",
"revision" : "e754ab1c80920dd51a8e08290c912ac1c2ac8b58"
}
},
{
"identity" : "keychainaccess",
"kind" : "remoteSourceControl",
@@ -86,26 +95,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/SideStore/SideKit",
"state" : {
"revision" : "7ea34a09b52c104077dea8e0b90f8dc55d43b36b",
"version" : "0.1.0"
}
},
{
"identity" : "sparkle",
"kind" : "remoteSourceControl",
"location" : "https://github.com/sparkle-project/Sparkle.git",
"state" : {
"revision" : "dda155c7d3ef38c53d29f8584cb2aad2a1a54dba",
"version" : "2.3.2"
}
},
{
"identity" : "stprivilegedtask",
"kind" : "remoteSourceControl",
"location" : "https://github.com/JoeMatt/STPrivilegedTask.git",
"state" : {
"branch" : "master",
"revision" : "10a9150ef32d444af326beba76356ae9af95a3e7"
"branch" : "main",
"revision" : "7ea34a09b52c104077dea8e0b90f8dc55d43b36b"
}
}
],

View File

@@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "self:">
location = "self:/Users/jmattiello/Workspace/Provenance/SideStoreRepos/SideStore/SideStore.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -31,7 +31,7 @@
BlueprintIdentifier = "BF1E314F22A0616100370A3C"
BuildableName = "libAltKit.a"
BlueprintName = "AltKit"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
@@ -45,7 +45,7 @@
BlueprintIdentifier = "BF18BFE624857D7900DD5981"
BuildableName = "SideDaemon"
BlueprintName = "SideDaemon"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -74,7 +74,7 @@
BlueprintIdentifier = "BF18BFE624857D7900DD5981"
BuildableName = "SideDaemon"
BlueprintName = "SideDaemon"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<EnvironmentVariables>
@@ -97,7 +97,7 @@
BlueprintIdentifier = "BF18BFE624857D7900DD5981"
BuildableName = "SideDaemon"
BlueprintName = "SideDaemon"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>

View File

@@ -17,7 +17,7 @@
BlueprintIdentifier = "BF5C5FC4237DF5AE00EDD0C6"
BuildableName = "AltPlugin.mailbundle"
BlueprintName = "AltPlugin"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -53,7 +53,7 @@
BlueprintIdentifier = "BF5C5FC4237DF5AE00EDD0C6"
BuildableName = "AltPlugin.mailbundle"
BlueprintName = "AltPlugin"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>

View File

@@ -17,7 +17,7 @@
BlueprintIdentifier = "BF45868C229872EA00BD7491"
BuildableName = "AltServer.app"
BlueprintName = "AltServer"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -27,19 +27,17 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "BF45868C229872EA00BD7491"
BuildableName = "AltServer.app"
BlueprintName = "AltServer"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -58,11 +56,9 @@
BlueprintIdentifier = "BF45868C229872EA00BD7491"
BuildableName = "AltServer.app"
BlueprintName = "AltServer"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
@@ -77,7 +73,7 @@
BlueprintIdentifier = "BF45868C229872EA00BD7491"
BuildableName = "AltServer.app"
BlueprintName = "AltServer"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>

View File

@@ -17,7 +17,7 @@
BlueprintIdentifier = "BFD247692284B9A500981D42"
BuildableName = "SideStore.app"
BlueprintName = "SideStore"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -47,7 +47,7 @@
BlueprintIdentifier = "BFD247692284B9A500981D42"
BuildableName = "SideStore.app"
BlueprintName = "SideStore"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
@@ -70,7 +70,7 @@
BlueprintIdentifier = "BFD247692284B9A500981D42"
BuildableName = "SideStore.app"
BlueprintName = "SideStore"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>

View File

@@ -17,7 +17,7 @@
BlueprintIdentifier = "BFD247692284B9A500981D42"
BuildableName = "SideStore.app"
BlueprintName = "SideStore"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -47,7 +47,7 @@
BlueprintIdentifier = "BFD247692284B9A500981D42"
BuildableName = "SideStore.app"
BlueprintName = "SideStore"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
@@ -70,7 +70,7 @@
BlueprintIdentifier = "BFD247692284B9A500981D42"
BuildableName = "SideStore.app"
BlueprintName = "SideStore"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>

View File

@@ -17,7 +17,7 @@
BlueprintIdentifier = "BFF7C903257844C900E55F36"
BuildableName = "AltXPC.xpc"
BlueprintName = "AltXPC"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -47,7 +47,7 @@
BlueprintIdentifier = "BF45868C229872EA00BD7491"
BuildableName = "AltServer.app"
BlueprintName = "AltServer"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
@@ -63,7 +63,7 @@
BlueprintIdentifier = "BFF7C903257844C900E55F36"
BuildableName = "AltXPC.xpc"
BlueprintName = "AltXPC"
ReferencedContainer = "container:AltStore.xcodeproj">
ReferencedContainer = "container:SideStore.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>

View File

@@ -1 +0,0 @@
../../ALTAppPatcher.h

View File

@@ -8,10 +8,6 @@
import Foundation
#if canImport(Shared)
import Shared
#endif
public extension Bundle {
enum Info {
public static let deviceID = "ALTDeviceID"

View File

@@ -1,6 +1,6 @@
//
// ALTAppPatcher.h
// AltStore
// SidePatcher.h
// SidePatcher
//
// Created by Riley Testut on 10/18/21.
// Copyright © 2021 Riley Testut. All rights reserved.

View File

@@ -1,18 +1,18 @@
//
// ALTAppPatcher.m
// AltStore
// SidePatcher.m
// SidePatcher
//
// Created by Riley Testut on 10/18/21.
// Copied with minor modifications from sample code provided by Linus Henze.
//
#import "ALTAppPatcher.h"
#import <SidePatcher/SidePatcher.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@import RoxasUI;
@import RoxasUIKit;
#define CPU_SUBTYPE_PAC 0x80000000
#define FAT_MAGIC 0xcafebabe

View File

@@ -1,6 +1,6 @@
//
// ALTAppPatcher.h
// ALTAppPatcher
// SidePatcher.h
// SidePatcher
//
// Created by Joseph Mattiello on 03/01/23.
// Copyright © 2023 Provenance Emu. All rights reserved.
@@ -15,5 +15,5 @@ FOUNDATION_EXPORT double ALTAppPatcherVersionNumber;
FOUNDATION_EXPORT const unsigned char ALTAppPatcherVersionString[];
# pragma mark - ALTAppPatcher
#import <ALTAppPatcher/_ALTAppPatcher.h>
# pragma mark - SidePatcher
#import <SidePatcher/_SidePatcher.h>

View File

@@ -0,0 +1 @@
../../SidePatcher.h

View File

@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -38,32 +36,32 @@
<objects>
<viewController storyboardIdentifier="authenticationViewController" id="yO1-iT-7NP" customClass="AuthenticationViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="mjy-4S-hyH">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oyW-Fd-ojD" userLabel="Sizing View">
<rect key="frame" x="0.0" y="44" width="375" height="623"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
</view>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" alwaysBounceVertical="YES" indicatorStyle="white" keyboardDismissMode="onDrag" translatesAutoresizingMaskIntoConstraints="NO" id="WXx-hX-AXv">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<subviews>
<view contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2wp-qG-f0Z">
<rect key="frame" x="0.0" y="0.0" width="375" height="623"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" axis="vertical" spacing="50" translatesAutoresizingMaskIntoConstraints="NO" id="YmX-7v-pxh">
<rect key="frame" x="16" y="6" width="343" height="359.5"/>
<rect key="frame" x="20" y="6" width="560" height="360"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" spacing="6" translatesAutoresizingMaskIntoConstraints="NO" id="Yfu-hI-0B7" userLabel="Welcome">
<rect key="frame" x="0.0" y="0.0" width="343" height="67.5"/>
<rect key="frame" x="0.0" y="0.0" width="560" height="68"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Welcome to SideStore." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="EI2-V3-zQZ">
<rect key="frame" x="0.0" y="0.0" width="332" height="41"/>
<rect key="frame" x="0.0" y="0.0" width="358" height="41"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="34"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Sign in with your Apple ID to get started." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="SNU-tv-8Au">
<rect key="frame" x="0.0" y="47" width="306.5" height="20.5"/>
<rect key="frame" x="0.0" y="47" width="307" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@@ -71,19 +69,19 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="32" translatesAutoresizingMaskIntoConstraints="NO" id="Aqh-MD-HFf">
<rect key="frame" x="0.0" y="117.5" width="343" height="242"/>
<rect key="frame" x="0.0" y="118" width="560" height="242"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="Oy6-xr-cZ7">
<rect key="frame" x="0.0" y="0.0" width="343" height="159"/>
<rect key="frame" x="0.0" y="0.0" width="560" height="159"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="H95-7V-Kk8" userLabel="Apple ID">
<rect key="frame" x="0.0" y="0.0" width="343" height="72"/>
<rect key="frame" x="0.0" y="0.0" width="560" height="72"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="KN1-Kp-M1q">
<rect key="frame" x="0.0" y="0.0" width="343" height="17"/>
<rect key="frame" x="0.0" y="0.0" width="560" height="17"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="APPLE ID" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="59N-O1-6bM">
<rect key="frame" x="14" y="0.0" width="329" height="17"/>
<rect key="frame" x="14" y="0.0" width="546" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" white="1" alpha="0.75" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@@ -92,10 +90,10 @@
<edgeInsets key="layoutMargins" top="0.0" left="14" bottom="0.0" right="0.0"/>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gNe-dC-oI1">
<rect key="frame" x="0.0" y="21" width="343" height="51"/>
<rect key="frame" x="0.0" y="21" width="560" height="51"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="name@email.com" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="DBu-vt-hlo">
<rect key="frame" x="14" y="0.0" width="315" height="51"/>
<rect key="frame" x="14" y="0.0" width="532" height="51"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="19"/>
@@ -118,13 +116,13 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="hd5-yc-rcq" userLabel="Password">
<rect key="frame" x="0.0" y="87" width="343" height="72"/>
<rect key="frame" x="0.0" y="87" width="560" height="72"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="lvX-im-C95">
<rect key="frame" x="0.0" y="0.0" width="343" height="17"/>
<rect key="frame" x="0.0" y="0.0" width="560" height="17"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PASSWORD" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ava-XY-7vs">
<rect key="frame" x="14" y="0.0" width="329" height="17"/>
<rect key="frame" x="14" y="0.0" width="546" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" white="1" alpha="0.75" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@@ -133,10 +131,10 @@
<edgeInsets key="layoutMargins" top="0.0" left="14" bottom="0.0" right="0.0"/>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cLc-iA-yq5">
<rect key="frame" x="0.0" y="21" width="343" height="51"/>
<rect key="frame" x="0.0" y="21" width="560" height="51"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="••••••••" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="R77-TQ-lVT">
<rect key="frame" x="14" y="0.0" width="315" height="51"/>
<rect key="frame" x="14" y="0.0" width="532" height="51"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="19"/>
@@ -161,7 +159,7 @@
</subviews>
</stackView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2N5-zd-fUj">
<rect key="frame" x="0.0" y="191" width="343" height="51"/>
<rect key="frame" x="0.0" y="191" width="560" height="51"/>
<color key="backgroundColor" name="SettingsHighlighted"/>
<constraints>
<constraint firstAttribute="height" constant="51" id="4BK-Un-5pl"/>
@@ -179,16 +177,16 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="250" axis="vertical" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="DBk-rT-ZE8">
<rect key="frame" x="16" y="518.5" width="343" height="96.5"/>
<rect key="frame" x="20" y="513" width="560" height="79"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Why do we need this?" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p9U-0q-Kn8">
<rect key="frame" x="0.0" y="0.0" width="343" height="20.5"/>
<rect key="frame" x="0.0" y="0.0" width="560" height="21"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="249" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.25" translatesAutoresizingMaskIntoConstraints="NO" id="on2-62-waY">
<rect key="frame" x="0.0" y="24.5" width="343" height="72"/>
<rect key="frame" x="0.0" y="25" width="560" height="54"/>
<string key="text">Your Apple ID is used to configure apps so they can be installed on this device. Your credentials will be stored securely in this device's Keychain and sent only to Apple for authentication.</string>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" white="1" alpha="0.75" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -260,17 +258,17 @@
<objects>
<viewController storyboardIdentifier="instructionsViewController" hidesBottomBarWhenPushed="YES" id="aFi-fb-W0B" customClass="InstructionsViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" id="Otz-hn-WGS">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" axis="vertical" distribution="equalSpacing" translatesAutoresizingMaskIntoConstraints="NO" id="bp6-55-IG2">
<rect key="frame" x="0.0" y="44" width="375" height="564"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="541"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="FjP-tm-w7K">
<rect key="frame" x="16" y="35" width="343" height="95.5"/>
<rect key="frame" x="20" y="35" width="560" height="96"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="i9V-3h-B8f">
<rect key="frame" x="0.0" y="0.0" width="59" height="95.5"/>
<rect key="frame" x="0.0" y="0.0" width="59" height="96"/>
<constraints>
<constraint firstAttribute="width" constant="59" id="ILg-0e-PW8"/>
</constraints>
@@ -279,16 +277,16 @@
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Q20-ml-9D0">
<rect key="frame" x="79" y="16" width="264" height="64"/>
<rect key="frame" x="79" y="25" width="481" height="46"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Launch SideStore" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="XKD-XH-eB0">
<rect key="frame" x="0.0" y="0.0" width="264" height="20.5"/>
<rect key="frame" x="0.0" y="0.0" width="481" height="21"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Leave SideStore running in the background on your idevice." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="6HP-Xh-sAH">
<rect key="frame" x="0.0" y="25.5" width="264" height="38.5"/>
<rect key="frame" x="0.0" y="26" width="481" height="20"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" white="1" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@@ -298,10 +296,10 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="LpI-Jt-SzX">
<rect key="frame" x="16" y="168" width="343" height="95.5"/>
<rect key="frame" x="20" y="160" width="560" height="96"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0LW-eE-qHa">
<rect key="frame" x="0.0" y="0.0" width="59" height="95.5"/>
<rect key="frame" x="0.0" y="0.0" width="59" height="96"/>
<constraints>
<constraint firstAttribute="width" constant="59" id="HzE-AA-eE5"/>
</constraints>
@@ -310,16 +308,16 @@
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="dMu-eg-gIO">
<rect key="frame" x="79" y="17" width="264" height="61.5"/>
<rect key="frame" x="79" y="16" width="481" height="65"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Connect to Wi-Fi and VPN" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="esj-pD-D4A">
<rect key="frame" x="0.0" y="0.0" width="264" height="20.5"/>
<rect key="frame" x="0.0" y="0.0" width="481" height="21"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enable SideStore VPN in Wireguard and be able to use Sidestore on the go." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="4rk-ge-FSj">
<rect key="frame" x="0.0" y="25.5" width="264" height="36"/>
<rect key="frame" x="0.0" y="26" width="481" height="39"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" white="1" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@@ -329,10 +327,10 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="tfb-ja-9UC">
<rect key="frame" x="16" y="300.5" width="343" height="95.5"/>
<rect key="frame" x="20" y="285" width="560" height="96"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="3" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="nVr-El-Csi">
<rect key="frame" x="0.0" y="0.0" width="59" height="95.5"/>
<rect key="frame" x="0.0" y="0.0" width="59" height="96"/>
<constraints>
<constraint firstAttribute="width" constant="59" id="fRj-b4-VTe"/>
</constraints>
@@ -341,16 +339,16 @@
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="z6Y-zi-teL">
<rect key="frame" x="79" y="16" width="264" height="64"/>
<rect key="frame" x="79" y="25" width="481" height="46"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Download Apps" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="JeJ-bk-UCA">
<rect key="frame" x="0.0" y="0.0" width="264" height="20.5"/>
<rect key="frame" x="0.0" y="0.0" width="481" height="21"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Browse and download apps directly from SideStore." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="M7T-9j-uyt">
<rect key="frame" x="0.0" y="25.5" width="264" height="38.5"/>
<rect key="frame" x="0.0" y="26" width="481" height="20"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" white="1" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@@ -360,10 +358,10 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="X3r-G1-vf2">
<rect key="frame" x="16" y="433.5" width="343" height="95.5"/>
<rect key="frame" x="20" y="410" width="560" height="96"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="4" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="i2U-NL-plG">
<rect key="frame" x="0.0" y="0.0" width="59" height="95.5"/>
<rect key="frame" x="0.0" y="0.0" width="59" height="96"/>
<constraints>
<constraint firstAttribute="width" constant="59" id="4Qg-s9-p7s"/>
</constraints>
@@ -372,16 +370,16 @@
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Xs6-pJ-PUz">
<rect key="frame" x="79" y="17" width="264" height="62"/>
<rect key="frame" x="79" y="16" width="481" height="65"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Apps Refresh Automatically" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="nvb-Aq-sYa">
<rect key="frame" x="0.0" y="0.0" width="264" height="20.5"/>
<rect key="frame" x="0.0" y="0.0" width="481" height="21"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Apps are refreshed in the background while you are on SideStore VPN!" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="HU5-Hv-E3d">
<rect key="frame" x="0.0" y="25.5" width="264" height="36.5"/>
<rect key="frame" x="0.0" y="26" width="481" height="39"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" white="1" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@@ -394,7 +392,7 @@
<edgeInsets key="layoutMargins" top="35" left="0.0" bottom="35" right="0.0"/>
</stackView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qZ9-AR-2zK">
<rect key="frame" x="16" y="608" width="343" height="51"/>
<rect key="frame" x="20" y="541" width="560" height="51"/>
<color key="backgroundColor" name="SettingsHighlighted"/>
<constraints>
<constraint firstAttribute="height" constant="51" id="LQz-qG-ZJK"/>
@@ -431,22 +429,22 @@
</objects>
<point key="canvasLocation" x="1353" y="736"/>
</scene>
<!--Refresh AltStore-->
<!--Refresh SideStore-->
<scene sceneID="9Vh-dM-OqX">
<objects>
<viewController storyboardIdentifier="refreshAltStoreViewController" id="aoK-yE-UVT" customClass="RefreshAltStoreViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" id="R83-kV-365">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fpO-Bf-gFY" customClass="RSTPlaceholderView">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
</view>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="tDQ-ao-1Jg">
<rect key="frame" x="16" y="570" width="343" height="89"/>
<rect key="frame" x="20" y="503" width="560" height="89"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xcg-hT-tDe" customClass="PillButton" customModule="AltStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="343" height="51"/>
<rect key="frame" x="0.0" y="0.0" width="560" height="51"/>
<color key="backgroundColor" name="SettingsHighlighted"/>
<constraints>
<constraint firstAttribute="height" constant="51" id="SJA-N9-Z6u"/>
@@ -461,7 +459,7 @@
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qua-VA-asJ">
<rect key="frame" x="0.0" y="59" width="343" height="30"/>
<rect key="frame" x="0.0" y="59" width="560" height="30"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Refresh Later">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -485,7 +483,7 @@
<constraint firstItem="tDQ-ao-1Jg" firstAttribute="leading" secondItem="R83-kV-365" secondAttribute="leadingMargin" id="zEt-Xr-kJx"/>
</constraints>
</view>
<navigationItem key="navigationItem" title="Refresh AltStore" largeTitleDisplayMode="always" id="5nk-NR-jtV"/>
<navigationItem key="navigationItem" title="Refresh SideStore" largeTitleDisplayMode="always" id="5nk-NR-jtV"/>
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
<connections>
<outlet property="placeholderView" destination="fpO-Bf-gFY" id="q7d-au-d94"/>
@@ -500,28 +498,28 @@
<objects>
<viewController storyboardIdentifier="selectTeamViewController" hidesBottomBarWhenPushed="YES" id="kOD-4P-a6L" customClass="SelectTeamViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" indicatorStyle="white" dataMode="prototypes" style="grouped" separatorStyle="none" rowHeight="60" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="fWW-kX-ifH">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" name="SettingsBackground"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="separatorColor" white="1" alpha="0.25" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="TeamCell" textLabel="6ip-34-gmM" detailTextLabel="knk-Wf-PKf" style="IBUITableViewCellStyleSubtitle" id="qeQ-eb-2SC" customClass="InsetGroupTableViewCell" customModule="AltStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="55.5" width="375" height="60"/>
<rect key="frame" x="0.0" y="35" width="375" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="qeQ-eb-2SC" id="bT4-Fc-u6I">
<rect key="frame" x="0.0" y="0.0" width="334" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Team 1" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="6ip-34-gmM">
<rect key="frame" x="30" y="10" width="56.5" height="20.5"/>
<rect key="frame" x="-46" y="85" width="89" height="31"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Description" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="knk-Wf-PKf">
<rect key="frame" x="30" y="33.5" width="70" height="14.5"/>
<rect key="frame" x="3" y="51" width="45" height="89"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="12"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -551,14 +549,13 @@
<placeholder placeholderIdentifier="IBFirstResponder" id="yH5-jU-aez" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1401" y="734"/>
</scene>
</scenes>
<color key="tintColor" name="Primary"/>
<resources>
<namedColor name="Primary">
<color red="0.0040000001899898052" green="0.50199997425079346" blue="0.51800000667572021" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
</scenes>
<color key="tintColor" name="Primary"/>
<resources>
<namedColor name="Primary">
<color red="0.0040000001899898052" green="0.50199997425079346" blue="0.51800000667572021" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="SettingsBackground">
<color red="0.0039215686274509803" green="0.50196078431372548" blue="0.51764705882352946" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>

View File

@@ -0,0 +1,164 @@
name: build
on:
push:
schedule:
- cron: '0 0 1 * *'
jobs:
build-linux-ubuntu:
runs-on: ubuntu-latest
steps:
- name: install dependencies
run: |
#sudo apt-get install cython
- name: prepare environment
run: |
echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV
- name: fetch libplist
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libplist-latest_${{env.target_triplet}}
repo: libimobiledevice/libplist
- name: install external dependencies
run: |
mkdir extract
for I in *.tar; do
tar -C extract -xvf $I
done
sudo cp -r extract/* /
sudo ldconfig
- uses: actions/checkout@v2
- name: autogen
run: ./autogen.sh PKG_CONFIG_PATH=/usr/local/lib/pkgconfig LDFLAGS="-Wl,-rpath=/usr/local/lib"
- name: make
run: make
- name: make install
run: sudo make install
- name: prepare artifact
run: |
mkdir -p dest
DESTDIR=`pwd`/dest make install
tar -C dest -cf libimobiledevice-glue.tar usr
- name: publish artifact
uses: actions/upload-artifact@v2
with:
name: libimobiledevice-glue-latest_${{env.target_triplet}}
path: libimobiledevice-glue.tar
build-macOS:
runs-on: macOS-latest
steps:
- name: install dependencies
run: |
if test -x "`which port`"; then
sudo port install libtool autoconf automake pkgconfig
else
brew install libtool autoconf automake pkgconfig
fi
shell: bash
- name: fetch libplist
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libplist-latest_macOS
repo: libimobiledevice/libplist
- name: install external dependencies
run: |
mkdir extract
for I in *.tar; do
tar -C extract -xvf $I
done
sudo cp -r extract/* /
- uses: actions/checkout@v2
- name: autogen
run: |
SDKDIR=`xcrun --sdk macosx --show-sdk-path`
TESTARCHS="arm64 x86_64"
USEARCHS=
for ARCH in $TESTARCHS; do
if echo "int main(int argc, char **argv) { return 0; }" |clang -arch $ARCH -o /dev/null -isysroot $SDKDIR -x c - 2>/dev/null; then
USEARCHS="$USEARCHS -arch $ARCH"
fi
done
export CFLAGS="$USEARCHS -isysroot $SDKDIR"
echo "Using CFLAGS: $CFLAGS"
./autogen.sh PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
- name: make
run: make
- name: make install
run: sudo make install
- name: prepare artifact
run: |
mkdir -p dest
DESTDIR=`pwd`/dest make install
tar -C dest -cf libimobiledevice-glue.tar usr
- name: publish artifact
uses: actions/upload-artifact@v2
with:
name: libimobiledevice-glue-latest_macOS
path: libimobiledevice-glue.tar
build-windows:
runs-on: windows-2019
defaults:
run:
shell: msys2 {0}
strategy:
fail-fast: false
matrix:
include: [
{ msystem: MINGW64, arch: x86_64 },
{ msystem: MINGW32, arch: i686 }
]
steps:
- uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
release: false
update: false
install: >-
base-devel
git
mingw-w64-${{ matrix.arch }}-gcc
make
libtool
autoconf
automake-wrapper
- name: prepare environment
run: |
dest=`echo ${{ matrix.msystem }} |tr [:upper:] [:lower:]`
echo "dest=$dest" >> $GITHUB_ENV
echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV
- name: fetch libplist
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libplist-latest_${{ matrix.arch }}-${{ env.dest }}
repo: libimobiledevice/libplist
- name: install external dependencies
run: |
mkdir extract
for I in *.tar; do
tar -C extract -xvf $I
done
cp -r extract/* /
- uses: actions/checkout@v2
- name: autogen
run: ./autogen.sh CC=gcc CXX=g++
- name: make
run: make
- name: make install
run: make install
- name: prepare artifact
run: |
mkdir -p dest
DESTDIR=`pwd`/dest make install
tar -C dest -cf libimobiledevice-glue.tar ${{ env.dest }}
- name: publish artifact
uses: actions/upload-artifact@v2
with:
name: libimobiledevice-glue-latest_${{ matrix.arch }}-${{ env.dest }}
path: libimobiledevice-glue.tar

View File

@@ -0,0 +1,39 @@
# git-ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
*.[oa]
*~
*.po
*.lo
*.la
autom4te.cache/*
*.in
*/.deps/*
m4/*
swig/*
*.swp
*.patch
aclocal.m4
config.h
config.log
config.sub
config.guess
config.status
configure
depcomp
install-sh
compile
main
ltmain.sh
missing
mkinstalldirs
libtool
*Makefile
py-compile
stamp-h1
src/.libs
src/libimobiledevice-glue-1.0.pc
.idea/
.DS_Store
.vscode/

View File

@@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@@ -0,0 +1,10 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src include
EXTRA_DIST = \
README.md
indent:
indent -kr -ut -ts4 -l120 src/*.c src/*.h

View File

@@ -0,0 +1,107 @@
# libimobiledevice-glue
Library with common code used by the libraries and tools around the
**libimobiledevice** project.
![](https://github.com/libimobiledevice/libimobiledevice-glue/workflows/build/badge.svg)
## Features
The main functionality provided by this library are **socket** helper
functions and a platform independent **thread/mutex** implementation.
Besides that it comes with a number of string, file, and plist helper
functions, as well as some other commonly used code that was originally
duplicated in the dedicated projects.
Test on Linux, macOS, Windows.
## Projects using this library
- [libusbmuxd](https://github.com/libimobiledevice/libusbmuxd)
- [libimobiledevice](https://github.com/libimobiledevice/libimobiledevice)
- [usbmuxd](https://github.com/libimobiledevice/usbmuxd)
- [libirecovery](https://github.com/libimobiledevice/libirecovery)
- [idevicerestore](https://github.com/libimobiledevice/idevicerestore)
## Installation / Getting started
### Debian / Ubuntu Linux
First install all required dependencies and build tools:
```shell
sudo apt-get install \
build-essential \
pkg-config \
checkinstall \
git \
autoconf \
automake \
libtool-bin \
libplist-dev \
```
Then clone the actual project repository:
```shell
git clone https://github.com/libimobiledevice/libimobiledevice-glue.git
cd libimobiledevice-glue
```
Now you can build and install it:
```shell
./autogen.sh
make
sudo make install
```
If you require a custom prefix or other option being passed to `./configure`
you can pass them directly to `./autogen.sh` like this:
```bash
./autogen.sh --prefix=/opt/local
make
sudo make install
```
## Usage
This library is directly used by libusbmuxd, libimobiledevice, etc., so there
is no need to do anything in particular.
## Contributing
We welcome contributions from anyone and are grateful for every pull request!
If you'd like to contribute, please fork the `master` branch, change, commit and
send a pull request for review. Once approved it can be merged into the main
code base.
If you plan to contribute larger changes or a major refactoring, please create a
ticket first to discuss the idea upfront to ensure less effort for everyone.
Please make sure your contribution adheres to:
* Try to follow the code style of the project
* Commit messages should describe the change well without being too short
* Try to split larger changes into individual commits of a common domain
## Links
* Homepage: https://libimobiledevice.org/
* Repository: https://git.libimobiledevice.org/libimobiledevice-glue.git
* Repository (Mirror): https://github.com/libimobiledevice/libimobiledevice-glue.git
* Issue Tracker: https://github.com/libimobiledevice/libimobiledevice-glue/issues
* Mailing List: https://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel
* Twitter: https://twitter.com/libimobiledev
## License
This library and utilities are licensed under the [GNU Lesser General Public License v2.1](https://www.gnu.org/licenses/lgpl-2.1.en.html),
also included in the repository in the `COPYING` file.
## Credits
Apple, iPhone, iPad, iPod, iPod Touch, Apple TV, Apple Watch, Mac, iOS,
iPadOS, tvOS, watchOS, and macOS are trademarks of Apple Inc.
This project is an independent software and has not been authorized, sponsored,
or otherwise approved by Apple Inc.
README Updated on: 2022-04-04

View File

@@ -0,0 +1,26 @@
#!/bin/sh
olddir=`pwd`
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
(
cd "$srcdir"
gprefix=`which glibtoolize 2>&1 >/dev/null`
if [ $? -eq 0 ]; then
glibtoolize --force
else
libtoolize --force
fi
aclocal -I m4
autoheader
automake --add-missing
autoconf
cd "$olddir"
)
if [ -z "$NOCONFIGURE" ]; then
$srcdir/configure "$@"
fi

View File

@@ -0,0 +1,136 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.68)
AC_INIT([libimobiledevice-glue], [1.0.0], [https://github.com/libimobiledevice/libimobiledevice-glue/issues],, [https://libimobiledevice.org])
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip check-news])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
AC_CONFIG_SRCDIR([src/])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
dnl libtool versioning
# +1 : 0 : +1 == adds new functions to the interface
# +1 : 0 : 0 == changes or removes functions (changes include both
# changes to the signature and the semantic)
# ? :+1 : ? == just internal changes
# CURRENT : REVISION : AGE
LIBIMOBILEDEVICE_GLUE_SO_VERSION=0:0:0
dnl Minimum package versions
LIBPLIST_VERSION=2.2.0
AC_SUBST(LIBIMOBILEDEVICE_GLUE_SO_VERSION)
AC_SUBST(LIBPLIST_VERSION)
# Checks for programs.
AC_PROG_CC
#AC_PROG_CXX
AM_PROG_CC_C_O
LT_INIT
# Checks for libraries.
PKG_CHECK_MODULES(libplist, libplist-2.0 >= $LIBPLIST_VERSION)
# Checks for header files.
AC_CHECK_HEADERS([stdint.h stdlib.h string.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
AC_TYPE_UINT8_T
# Checks for library functions.
AC_CHECK_FUNCS([asprintf strcasecmp strdup strerror strndup stpcpy vasprintf getifaddrs])
AC_CHECK_HEADER(endian.h, [ac_cv_have_endian_h="yes"], [ac_cv_have_endian_h="no"])
if test "x$ac_cv_have_endian_h" = "xno"; then
AC_DEFINE(__LITTLE_ENDIAN,1234,[little endian])
AC_DEFINE(__BIG_ENDIAN,4321,[big endian])
AC_C_BIGENDIAN([ac_cv_c_bigendian="yes"], [ac_cv_c_bigendian="no"], [], [])
if test "x$ac_cv_c_bigendian" = "xyes"; then
AC_DEFINE(__BYTE_ORDER,4321,[big endian byte order])
else
AC_DEFINE(__BYTE_ORDER,1234,[little endian byte order])
fi
fi
# Check for operating system
AC_MSG_CHECKING([for platform-specific build settings])
case ${host_os} in
*mingw32*|*cygwin*)
AC_MSG_RESULT([${host_os}])
win32=true
AC_DEFINE(WINVER, 0x0501, [minimum Windows version])
;;
darwin*)
AC_MSG_RESULT([${host_os}])
AX_PTHREAD([], [AC_MSG_ERROR([pthread is required to build $PACKAGE])])
AC_CHECK_FUNCS([pthread_once pthread_cancel])
;;
*)
AC_MSG_RESULT([${host_os}])
AX_PTHREAD([], [AC_MSG_ERROR([pthread is required to build $PACKAGE_NAME])])
AC_CHECK_FUNC(pthread_cancel, [AC_DEFINE(HAVE_PTHREAD_CANCEL)], [
AC_CHECK_LIB(pthread, [pthread_cancel],[AC_DEFINE(HAVE_PTHREAD_CANCEL)])
])
AC_CHECK_FUNC(pthread_once, [AC_DEFINE(HAVE_PTHREAD_ONCE)], [
AC_CHECK_LIB(pthread, [pthread_once], [], [AC_MSG_ERROR([pthread with pthread_once required to build $PACKAGE_NAME])])
])
;;
esac
AM_CONDITIONAL(WIN32, test x$win32 = xtrue)
# Check if the C compiler supports __attribute__((constructor))
AC_CACHE_CHECK([wether the C compiler supports constructor/destructor attributes],
ac_cv_attribute_constructor, [
ac_cv_attribute_constructor=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[
static void __attribute__((constructor)) test_constructor(void) {
}
static void __attribute__((destructor)) test_destructor(void) {
}
]], [])],
[ac_cv_attribute_constructor=yes]
)]
)
if test "$ac_cv_attribute_constructor" = "yes"; then
AC_DEFINE(HAVE_ATTRIBUTE_CONSTRUCTOR, 1, [Define if the C compiler supports constructor/destructor attributes])
fi
AC_CHECK_MEMBER(struct dirent.d_type, AC_DEFINE(HAVE_DIRENT_D_TYPE, 1, [define if struct dirent has member d_type]),, [#include <dirent.h>])
AS_COMPILER_FLAGS(GLOBAL_CFLAGS, "-Wall -Wextra -Wmissing-declarations -Wredundant-decls -Wshadow -Wpointer-arith -Wwrite-strings -Wswitch-default -Wno-unused-parameter -fsigned-char -fvisibility=hidden")
AC_SUBST(GLOBAL_CFLAGS)
case "$GLOBAL_CFLAGS" in
*-fvisibility=hidden*)
AC_DEFINE([HAVE_FVISIBILITY], [1], [Define if compiled with -fvisibility=hidden])
esac
# check for large file support
AC_SYS_LARGEFILE
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_CONFIG_FILES([
Makefile
src/Makefile
src/libimobiledevice-glue-1.0.pc
include/Makefile
])
AC_OUTPUT
echo "
Configuration for $PACKAGE $VERSION:
-------------------------------------------
Install prefix: .........: $prefix
Now type 'make' to build $PACKAGE $VERSION,
and then 'make install' for installation.
"

View File

@@ -0,0 +1,12 @@
EXTRA_DIST = \
endianness.h
nobase_include_HEADERS = \
libimobiledevice-glue/socket.h \
libimobiledevice-glue/thread.h \
libimobiledevice-glue/utils.h \
libimobiledevice-glue/collection.h \
libimobiledevice-glue/termcolors.h \
libimobiledevice-glue/cbuf.h \
libimobiledevice-glue/opack.h \
libimobiledevice-glue/tlv.h

View File

@@ -0,0 +1,123 @@
#ifndef ENDIANNESS_H
#define ENDIANNESS_H
#ifndef __LITTLE_ENDIAN
#define __LITTLE_ENDIAN 1234
#endif
#ifndef __BIG_ENDIAN
#define __BIG_ENDIAN 4321
#endif
#ifndef __BYTE_ORDER
#ifdef __LITTLE_ENDIAN__
#define __BYTE_ORDER __LITTLE_ENDIAN
#else
#ifdef __BIG_ENDIAN__
#define __BYTE_ORDER __BIG_ENDIAN
#endif
#endif
#endif
#ifndef be16toh
#if __BYTE_ORDER == __BIG_ENDIAN
#define be16toh(x) (x)
#else
#define be16toh(x) ((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))
#endif
#endif
#ifndef htobe16
#define htobe16 be16toh
#endif
#ifndef le16toh
#if __BYTE_ORDER == __BIG_ENDIAN
#define le16toh(x) ((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))
#else
#define le16toh(x) (x)
#endif
#endif
#ifndef htole16
#define htole16 le16toh
#endif
#ifndef __bswap_32
#define __bswap_32(x) ((((x) & 0xFF000000) >> 24) \
| (((x) & 0x00FF0000) >> 8) \
| (((x) & 0x0000FF00) << 8) \
| (((x) & 0x000000FF) << 24))
#endif
#ifndef be32toh
#if __BYTE_ORDER == __BIG_ENDIAN
#define be32toh(x) (x)
#else
#define be32toh(x) __bswap_32(x)
#endif
#endif
#ifndef htobe32
#define htobe32 be32toh
#endif
#ifndef le32toh
#if __BYTE_ORDER == __BIG_ENDIAN
#define le32toh(x) __bswap_32(x)
#else
#define le32toh(x) (x)
#endif
#endif
#ifndef htole32
#define htole32 le32toh
#endif
#ifndef __bswap_64
#define __bswap_64(x) ((((x) & 0xFF00000000000000ull) >> 56) \
| (((x) & 0x00FF000000000000ull) >> 40) \
| (((x) & 0x0000FF0000000000ull) >> 24) \
| (((x) & 0x000000FF00000000ull) >> 8) \
| (((x) & 0x00000000FF000000ull) << 8) \
| (((x) & 0x0000000000FF0000ull) << 24) \
| (((x) & 0x000000000000FF00ull) << 40) \
| (((x) & 0x00000000000000FFull) << 56))
#endif
#ifndef htobe64
#if __BYTE_ORDER == __BIG_ENDIAN
#define htobe64(x) (x)
#else
#define htobe64(x) __bswap_64(x)
#endif
#endif
#ifndef be64toh
#define be64toh htobe64
#endif
#ifndef le64toh
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define le64toh(x) (x)
#else
#define le64toh(x) __bswap_64(x)
#endif
#endif
#ifndef htole64
#define htole64 le64toh
#endif
#if (defined(__BIG_ENDIAN__) \
&& !defined(__FLOAT_WORD_ORDER__)) \
|| (defined(__FLOAT_WORD_ORDER__) \
&& __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
#define float_bswap64(x) __bswap_64(x)
#define float_bswap32(x) __bswap_32(x)
#else
#define float_bswap64(x) (x)
#define float_bswap32(x) (x)
#endif
#endif /* ENDIANNESS_H */

View File

@@ -0,0 +1,35 @@
/*
* cbuf.h
* Simple char buffer implementation.
*
* Copyright (c) 2021 Nikias Bassen, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __CBUF_H
#define __CBUF_H
struct char_buf {
unsigned char* data;
unsigned int length;
unsigned int capacity;
};
struct char_buf* char_buf_new();
void char_buf_free(struct char_buf* cbuf);
void char_buf_append(struct char_buf* cbuf, unsigned int length, unsigned char* data);
#endif /* __CBUF_H */

View File

@@ -0,0 +1,52 @@
/*
* collection.h
*
* Copyright (C) 2009 Hector Martin <hector@marcansoft.com>
* Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef COLLECTION_H
#define COLLECTION_H
struct collection {
void **list;
int capacity;
};
void collection_init(struct collection *col);
void collection_add(struct collection *col, void *element);
int collection_remove(struct collection *col, void *element);
int collection_count(struct collection *col);
void collection_free(struct collection *col);
void collection_copy(struct collection *dest, struct collection *src);
#define MERGE_(a,b) a ## _ ## b
#define LABEL_(a,b) MERGE_(a, b)
#define UNIQUE_VAR(a) LABEL_(a, __LINE__)
#define FOREACH(var, col) \
do { \
int UNIQUE_VAR(_iter); \
for(UNIQUE_VAR(_iter)=0; UNIQUE_VAR(_iter)<(col)->capacity; UNIQUE_VAR(_iter)++) { \
if(!(col)->list[UNIQUE_VAR(_iter)]) continue; \
var = (col)->list[UNIQUE_VAR(_iter)];
#define ENDFOREACH \
} \
} while(0);
#endif

View File

@@ -0,0 +1,29 @@
/*
* opack.h
* "opack" format encoder/decoder implementation.
*
* Copyright (c) 2021 Nikias Bassen, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __OPACK_H
#define __OPACK_H
#include <plist/plist.h>
void opack_encode_from_plist(plist_t plist, unsigned char** out, unsigned int* out_len);
int opack_decode_to_plist(unsigned char* buf, unsigned int buf_len, plist_t* plist_out);
#endif /* __OPACK_H */

View File

@@ -0,0 +1,70 @@
/*
* socket.h
*
* Copyright (C) 2012-2020 Nikias Bassen <nikias@gmx.li>
* Copyright (C) 2012 Martin Szulecki <m.szulecki@libimobiledevice.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SOCKET_SOCKET_H
#define SOCKET_SOCKET_H
#include <stdlib.h>
#include <stdint.h>
enum fd_mode {
FDM_READ,
FDM_WRITE,
FDM_EXCEPT
};
typedef enum fd_mode fd_mode;
#ifdef WIN32
#include <winsock2.h>
#define SHUT_RD SD_READ
#define SHUT_WR SD_WRITE
#define SHUT_RDWR SD_BOTH
#else
#include <sys/socket.h>
#endif
#ifndef WIN32
int socket_create_unix(const char *filename);
int socket_connect_unix(const char *filename);
#endif
int socket_create(const char *addr, uint16_t port);
int socket_connect_addr(struct sockaddr *addr, uint16_t port);
int socket_connect(const char *addr, uint16_t port);
int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout);
int socket_accept(int fd, uint16_t port);
int socket_shutdown(int fd, int how);
int socket_close(int fd);
int socket_receive(int fd, void *data, size_t length);
int socket_peek(int fd, void *data, size_t length);
int socket_receive_timeout(int fd, void *data, size_t length, int flags, unsigned int timeout);
int socket_send(int fd, void *data, size_t length);
int socket_get_socket_port(int fd, uint16_t *port);
void socket_set_verbose(int level);
const char *socket_addr_to_string(struct sockaddr *addr, char *addr_out, size_t addr_out_size);
int get_primary_mac_address(unsigned char mac_addr_buf[6]);
#endif /* SOCKET_SOCKET_H */

View File

@@ -0,0 +1,87 @@
/*
* termcolors.h
*
* Copyright (c) 2020-2021 Nikias Bassen, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef TERMCOLORS_H
#define TERMCOLORS_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdarg.h>
#include <stdio.h>
#define COLOR_RESET "\e[m"
#define STYLE_NORMAL "\e[0m"
#define STYLE_BRIGHT "\e[1m"
#define STYLE_DARK "\e[2m"
#define FG_BLACK "\e[0;30m"
#define FG_DARK_GRAY "\e[1;30m"
#define FG_RED "\e[0;31m"
#define FG_BRIGHT_RED "\e[1;31m"
#define FG_DARK_RED "\e[2;31m"
#define FG_GREEN "\e[0;32m"
#define FG_BRIGHT_GREEN "\e[1;32m"
#define FG_DARK_GREEN "\e[2;32m"
#define FG_YELLOW "\e[0;33m"
#define FG_BRIGHT_YELLOW "\e[1;33m"
#define FG_DARK_YELLOW "\e[2;33m"
#define FG_BLUE "\e[0;34m"
#define FG_BRIGHT_BLUE "\e[1;34m"
#define FG_DARK_BLUE "\e[2;34m"
#define FG_MAGENTA "\e[0;35m"
#define FG_BRIGHT_MAGENTA "\e[1;35m"
#define FG_DARK_MAGENTA "\e[2;35m"
#define FG_CYAN "\e[0;36m"
#define FG_BRIGHT_CYAN "\e[1;36m"
#define FG_DARK_CYAN "\e[2;36m"
#define FG_LIGHT_GRAY "\e[0;37m"
#define FG_WHITE "\e[1;37m"
#define FG_GRAY "\e[2;37m"
#define FG_DEFAULT "\e[39m"
#define BG_BLACK "\e[40m"
#define BG_GRAY "\e[100m"
#define BG_RED "\e[41m"
#define BG_BRIGHT_RED "\e[101m"
#define BG_GREEN "\e[42m"
#define BG_BRIGHT_GREEN "\e[102m"
#define BG_YELLOW "\e[43m"
#define BG_BRIGHT_YELLOW "\e[103m"
#define BG_BLUE "\e[44m"
#define BG_BRIGHT_BLUE "\e[104m"
#define BG_MAGENTA "\e[45m"
#define BG_BRIGHT_MAGENTA "\e[105m"
#define BG_CYAN "\e[46m"
#define BG_BRIGHT_CYAN "\e[106m"
#define BG_LIGHT_GRAY "\e[47m"
#define BG_WHITE "\e[107m"
#define BG_DEFAULT "\e[49m"
/* automatically called by library constructor */
void term_colors_init();
/* enable / disable terminal colors */
void term_colors_set_enabled(int en);
/* color-aware *printf variants */
int cprintf(const char* fmt, ...);
int cfprintf(FILE* stream, const char* fmt, ...);
int cvfprintf(FILE* stream, const char* fmt, va_list vargs);
#endif

View File

@@ -0,0 +1,87 @@
/*
* thread.h
*
* Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved.
* Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __THREAD_H
#define __THREAD_H
#include <stddef.h>
#ifdef WIN32
#include <windows.h>
typedef HANDLE THREAD_T;
typedef CRITICAL_SECTION mutex_t;
typedef struct {
HANDLE sem;
} cond_t;
typedef volatile struct {
LONG lock;
int state;
} thread_once_t;
#define THREAD_ONCE_INIT {0, 0}
#define THREAD_ID GetCurrentThreadId()
#define THREAD_T_NULL (THREAD_T)NULL
#else
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
typedef pthread_t THREAD_T;
typedef pthread_mutex_t mutex_t;
typedef pthread_cond_t cond_t;
typedef pthread_once_t thread_once_t;
#define THREAD_ONCE_INIT PTHREAD_ONCE_INIT
#define THREAD_ID pthread_self()
#define THREAD_T_NULL (THREAD_T)NULL
#endif
typedef void* (*thread_func_t)(void* data);
int thread_new(THREAD_T* thread, thread_func_t thread_func, void* data);
void thread_detach(THREAD_T thread);
void thread_free(THREAD_T thread);
int thread_join(THREAD_T thread);
int thread_alive(THREAD_T thread);
int thread_cancel(THREAD_T thread);
#ifdef WIN32
#undef HAVE_THREAD_CLEANUP
#else
#ifdef HAVE_PTHREAD_CANCEL
#define HAVE_THREAD_CLEANUP 1
#define thread_cleanup_push(routine, arg) pthread_cleanup_push(routine, arg)
#define thread_cleanup_pop(execute) pthread_cleanup_pop(execute)
#endif
#endif
void mutex_init(mutex_t* mutex);
void mutex_destroy(mutex_t* mutex);
void mutex_lock(mutex_t* mutex);
void mutex_unlock(mutex_t* mutex);
void thread_once(thread_once_t *once_control, void (*init_routine)(void));
void cond_init(cond_t* cond);
void cond_destroy(cond_t* cond);
int cond_signal(cond_t* cond);
int cond_wait(cond_t* cond, mutex_t* mutex);
int cond_wait_timeout(cond_t* cond, mutex_t* mutex, unsigned int timeout_ms);
#endif

View File

@@ -0,0 +1,42 @@
/*
* tlv.h
* Simple TLV implementation.
*
* Copyright (c) 2021 Nikias Bassen, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __TLV_H
#define __TLV_H
#include <stdint.h>
struct tlv_buf {
unsigned char* data;
unsigned int length;
unsigned int capacity;
};
typedef struct tlv_buf* tlv_buf_t;
tlv_buf_t tlv_buf_new();
void tlv_buf_free(tlv_buf_t tlv);
void tlv_buf_append(tlv_buf_t tlv, uint8_t tag, unsigned int length, void* data);
unsigned char* tlv_get_data_ptr(const void* tlv_data, void* tlv_end, uint8_t tag, uint8_t* length);
int tlv_data_get_uint(const void* tlv_data, unsigned int tlv_length, uint8_t tag, uint64_t* value);
int tlv_data_get_uint8(const void* tlv_data, unsigned int tlv_length, uint8_t tag, uint8_t* value);
int tlv_data_copy_data(const void* tlv_data, unsigned int tlv_length, uint8_t tag, void** out, unsigned int* out_len);
#endif /* __TLV_H */

View File

@@ -0,0 +1,62 @@
/*
* utils.h
* Miscellaneous utilities for string manipulation,
* file I/O and plist helper.
*
* Copyright (c) 2014-2019 Nikias Bassen, All Rights Reserved.
* Copyright (c) 2013-2014 Martin Szulecki, All Rights Reserved.
* Copyright (c) 2013 Federico Mena Quintero
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __UTILS_H
#define __UTILS_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <plist/plist.h>
#define MAC_EPOCH 978307200
char *string_concat(const char *str, ...);
char *string_append(char *str, ...);
char *string_build_path(const char *elem, ...);
char *string_format_size(uint64_t size);
char *string_toupper(char *str);
char *generate_uuid(void);
int buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length);
int buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length);
enum plist_format_t {
PLIST_FORMAT_XML,
PLIST_FORMAT_BINARY
};
int plist_read_from_filename(plist_t *plist, const char *filename);
int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format);
void plist_print_to_stream(plist_t plist, FILE* stream);
void plist_print_to_stream_with_indentation(plist_t plist, FILE* stream, unsigned int indentation);
#endif

View File

@@ -0,0 +1,28 @@
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)
AM_CFLAGS = $(GLOBAL_CFLAGS) $(PTHREAD_CFLAGS) $(libplist_CFLAGS)
AM_LDFLAGS = $(PTHREAD_LIBS) $(libplist_LIBS)
lib_LTLIBRARIES = libimobiledevice-glue-1.0.la
libimobiledevice_glue_1_0_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBIMOBILEDEVICE_GLUE_SO_VERSION) -no-undefined
libimobiledevice_glue_1_0_la_LIBADD =
libimobiledevice_glue_1_0_la_SOURCES = \
glue.c \
socket.c \
thread.c \
utils.c \
collection.c \
termcolors.c \
cbuf.c \
opack.c \
tlv.c \
common.h
if WIN32
libimobiledevice_glue_1_0_la_LDFLAGS += -avoid-version -static-libgcc
libimobiledevice_glue_1_0_la_LIBADD += -lws2_32 -lIphlpapi
endif
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libimobiledevice-glue-1.0.pc

View File

@@ -0,0 +1,67 @@
/*
* cbuf.c
* Simple char buffer implementation.
*
* Copyright (c) 2021 Nikias Bassen, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "common.h"
#include "libimobiledevice-glue/cbuf.h"
LIBIMOBILEDEVICE_GLUE_API struct char_buf* char_buf_new()
{
struct char_buf* cbuf = (struct char_buf*)malloc(sizeof(struct char_buf));
cbuf->capacity = 256;
cbuf->length = 0;
cbuf->data = (unsigned char*)malloc(cbuf->capacity);
return cbuf;
}
LIBIMOBILEDEVICE_GLUE_API void char_buf_free(struct char_buf* cbuf)
{
if (cbuf) {
free(cbuf->data);
free(cbuf);
}
}
LIBIMOBILEDEVICE_GLUE_API void char_buf_append(struct char_buf* cbuf, unsigned int length, unsigned char* data)
{
if (!cbuf || !cbuf->data) {
return;
}
if (cbuf->length + length > cbuf->capacity) {
unsigned int newcapacity = cbuf->capacity + ((length / 256) + 1) * 256;
unsigned char* newdata = realloc(cbuf->data, newcapacity);
if (!newdata) {
fprintf(stderr, "%s: ERROR: Failed to realloc\n", __func__);
return;
}
cbuf->data = newdata;
cbuf->capacity = newcapacity;
}
memcpy(cbuf->data + cbuf->length, data, length);
cbuf->length += length;
}

View File

@@ -0,0 +1,101 @@
/*
* collection.c
*
* Copyright (C) 2009 Hector Martin <hector@marcansoft.com>
* Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "common.h"
#include "libimobiledevice-glue/collection.h"
#undef NDEBUG // we need to make sure we still get assertions because we can't handle memory allocation errors
#include <assert.h>
#define INIT_NULL(addr, count) { unsigned int i_ = 0; for (i_ = 0; i_ < (count); i_++) ((void**)(addr))[i_] = NULL; }
#define CAPACITY_STEP 8
LIBIMOBILEDEVICE_GLUE_API void collection_init(struct collection *col)
{
col->list = malloc(sizeof(void *) * CAPACITY_STEP);
assert(col->list);
INIT_NULL(col->list, CAPACITY_STEP);
col->capacity = CAPACITY_STEP;
}
LIBIMOBILEDEVICE_GLUE_API void collection_free(struct collection *col)
{
free(col->list);
col->list = NULL;
col->capacity = 0;
}
LIBIMOBILEDEVICE_GLUE_API void collection_add(struct collection *col, void *element)
{
int i;
for(i=0; i<col->capacity; i++) {
if(!col->list[i]) {
col->list[i] = element;
return;
}
}
void **newlist = realloc(col->list, sizeof(void*) * (col->capacity + CAPACITY_STEP));
assert(newlist);
col->list = newlist;
INIT_NULL(&col->list[col->capacity], CAPACITY_STEP);
col->list[col->capacity] = element;
col->capacity += CAPACITY_STEP;
}
LIBIMOBILEDEVICE_GLUE_API int collection_remove(struct collection *col, void *element)
{
int i;
for(i=0; i<col->capacity; i++) {
if(col->list[i] == element) {
col->list[i] = NULL;
return 0;
}
}
fprintf(stderr, "%s: WARNING: element %p not present in collection %p (cap %d)", __func__, element, col, col->capacity);
return -1;
}
LIBIMOBILEDEVICE_GLUE_API int collection_count(struct collection *col)
{
int i, cnt = 0;
for(i=0; i<col->capacity; i++) {
if(col->list[i])
cnt++;
}
return cnt;
}
LIBIMOBILEDEVICE_GLUE_API void collection_copy(struct collection *dest, struct collection *src)
{
if (!dest || !src) return;
dest->capacity = src->capacity;
dest->list = malloc(sizeof(void*) * src->capacity);
memcpy(dest->list, src->list, sizeof(void*) * src->capacity);
}

View File

@@ -0,0 +1,38 @@
/*
* common.h
*
* Copyright (c) 2020 Nikias Bassen, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __COMMON_H
#define __COMMON_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef WIN32
#define LIBIMOBILEDEVICE_GLUE_API __declspec( dllexport )
#else
#ifdef HAVE_FVISIBILITY
#define LIBIMOBILEDEVICE_GLUE_API __attribute__((visibility("default")))
#else
#define LIBIMOBILEDEVICE_GLUE_API
#endif
#endif
#endif

View File

@@ -0,0 +1,80 @@
/*
* glue.c
*
* Copyright (c) 2021 Nikias Bassen, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef WIN32
#include <windows.h>
#endif
#include "common.h"
#include "libimobiledevice-glue/thread.h"
extern void term_colors_init();
static void internal_glue_init(void)
{
term_colors_init();
}
static void internal_glue_deinit(void)
{
}
static thread_once_t init_once = THREAD_ONCE_INIT;
static thread_once_t deinit_once = THREAD_ONCE_INIT;
#ifndef HAVE_ATTRIBUTE_CONSTRUCTOR
#if defined(__llvm__) || defined(__GNUC__)
#define HAVE_ATTRIBUTE_CONSTRUCTOR
#endif
#endif
#ifdef HAVE_ATTRIBUTE_CONSTRUCTOR
static void __attribute__((constructor)) limd_glue_initialize(void)
{
thread_once(&init_once, internal_glue_init);
}
static void __attribute__((destructor)) limd_glue_deinitialize(void)
{
thread_once(&deinit_once, internal_glue_deinit);
}
#elif defined(WIN32)
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
thread_once(&init_once, internal_glue_init);
break;
case DLL_PROCESS_DETACH:
thread_once(&deinit_once, internal_glue_deinit);
break;
default:
break;
}
return 1;
}
#else
#warning No compiler support for constructor/destructor attributes, some features might not be available.
#endif

View File

@@ -0,0 +1,476 @@
/*
* opack.c
* "opack" format encoder/decoder implementation.
*
* Copyright (c) 2021 Nikias Bassen, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "common.h"
#include "libimobiledevice-glue/cbuf.h"
#include "libimobiledevice-glue/opack.h"
#include "endianness.h"
#define MAC_EPOCH 978307200
static void opack_encode_node(plist_t node, struct char_buf* cbuf)
{
plist_type type = plist_get_node_type(node);
switch (type) {
case PLIST_DICT: {
uint32_t count = plist_dict_get_size(node);
uint8_t blen = 0xEF;
if (count < 15)
blen = (uint8_t)count-32;
char_buf_append(cbuf, 1, &blen);
plist_dict_iter iter = NULL;
plist_dict_new_iter(node, &iter);
if (iter) {
plist_t sub = NULL;
do {
sub = NULL;
plist_dict_next_item(node, iter, NULL, &sub);
if (sub) {
plist_t key = plist_dict_item_get_key(sub);
opack_encode_node(key, cbuf);
opack_encode_node(sub, cbuf);
}
} while (sub);
free(iter);
if (count > 14) {
uint8_t term = 0x03;
char_buf_append(cbuf, 1, &term);
}
}
} break;
case PLIST_ARRAY: {
uint32_t count = plist_array_get_size(node);
uint8_t blen = 0xDF;
if (count < 15)
blen = (uint8_t)(count-48);
char_buf_append(cbuf, 1, &blen);
plist_array_iter iter = NULL;
plist_array_new_iter(node, &iter);
if (iter) {
plist_t sub = NULL;
do {
sub = NULL;
plist_array_next_item(node, iter, &sub);
if (sub) {
opack_encode_node(sub, cbuf);
}
} while (sub);
free(iter);
if (count > 14) {
uint8_t term = 0x03;
char_buf_append(cbuf, 1, &term);
}
}
} break;
case PLIST_BOOLEAN: {
uint8_t bval = 2 - plist_bool_val_is_true(node);
char_buf_append(cbuf, 1, &bval);
} break;
case PLIST_UINT: {
uint64_t u64val = 0;
plist_get_uint_val(node, &u64val);
if ((uint8_t)u64val == u64val) {
uint8_t u8val = (uint8_t)u64val;
if (u8val > 0x27) {
uint8_t blen = 0x30;
char_buf_append(cbuf, 1, &blen);
char_buf_append(cbuf, 1, &u8val);
} else {
u8val += 8;
char_buf_append(cbuf, 1, &u8val);
}
} else if ((uint32_t)u64val == u64val) {
uint8_t blen = 0x32;
char_buf_append(cbuf, 1, &blen);
uint32_t u32val = (uint32_t)u64val;
u32val = htole32(u32val);
char_buf_append(cbuf, 4, (unsigned char*)&u32val);
} else {
uint8_t blen = 0x33;
char_buf_append(cbuf, 1, &blen);
u64val = htole64(u64val);
char_buf_append(cbuf, 8, (unsigned char*)&u64val);
}
} break;
case PLIST_REAL: {
double dval = 0;
plist_get_real_val(node, &dval);
if ((float)dval == dval) {
float fval = (float)dval;
uint32_t u32val = 0;
memcpy(&u32val, &fval, 4);
u32val = float_bswap32(u32val);
uint8_t blen = 0x35;
char_buf_append(cbuf, 1, &blen);
char_buf_append(cbuf, 4, (unsigned char*)&u32val);
} else {
uint64_t u64val = 0;
memcpy(&u64val, &dval, 8);
u64val = float_bswap64(u64val);
uint8_t blen = 0x36;
char_buf_append(cbuf, 1, &blen);
char_buf_append(cbuf, 8, (unsigned char*)&u64val);
}
} break;
case PLIST_DATE: {
int32_t sec = 0;
int32_t usec = 0;
plist_get_date_val(node, &sec, &usec);
time_t tsec = sec;
tsec -= MAC_EPOCH;
double dval = (double)tsec + ((double)usec / 1000000);
uint8_t blen = 0x06;
char_buf_append(cbuf, 1, &blen);
uint64_t u64val = 0;
memcpy(&u64val, &dval, 8);
u64val = float_bswap64(u64val);
char_buf_append(cbuf, 8, (unsigned char*)&u64val);
} break;
case PLIST_STRING:
case PLIST_KEY: {
uint64_t len = 0;
char* str = NULL;
if (type == PLIST_KEY) {
plist_get_key_val(node, &str);
len = strlen(str);
} else {
str = (char*)plist_get_string_ptr(node, &len);
}
if (len > 0x20) {
if (len > 0xFF) {
if (len > 0xFFFF) {
if (len >> 32) {
uint8_t blen = 0x64;
char_buf_append(cbuf, 1, &blen);
uint64_t u64val = htole64(len);
char_buf_append(cbuf, 8, (unsigned char*)&u64val);
} else {
uint8_t blen = 0x63;
char_buf_append(cbuf, 1, &blen);
uint32_t u32val = htole32((uint32_t)len);
char_buf_append(cbuf, 4, (unsigned char*)&u32val);
}
} else {
uint8_t blen = 0x62;
char_buf_append(cbuf, 1, &blen);
uint16_t u16val = htole16((uint16_t)len);
char_buf_append(cbuf, 2, (unsigned char*)&u16val);
}
} else {
uint8_t blen = 0x61;
char_buf_append(cbuf, 1, &blen);
char_buf_append(cbuf, 1, (unsigned char*)&len);
}
} else {
uint8_t blen = 0x40 + len;
char_buf_append(cbuf, 1, &blen);
}
char_buf_append(cbuf, len, (unsigned char*)str);
if (type == PLIST_KEY) {
free(str);
}
} break;
case PLIST_DATA: {
uint64_t len = 0;
const char* data = plist_get_data_ptr(node, &len);
if (len > 0x20) {
if (len > 0xFF) {
if (len > 0xFFFF) {
if (len >> 32) {
uint8_t blen = 0x94;
char_buf_append(cbuf, 1, &blen);
uint32_t u64val = htole64(len);
char_buf_append(cbuf, 8, (unsigned char*)&u64val);
} else {
uint8_t blen = 0x93;
char_buf_append(cbuf, 1, &blen);
uint32_t u32val = htole32((uint32_t)len);
char_buf_append(cbuf, 4, (unsigned char*)&u32val);
}
} else {
uint8_t blen = 0x92;
char_buf_append(cbuf, 1, &blen);
uint16_t u16val = htole16((uint16_t)len);
char_buf_append(cbuf, 2, (unsigned char*)&u16val);
}
} else {
uint8_t blen = 0x91;
char_buf_append(cbuf, 1, &blen);
char_buf_append(cbuf, 1, (unsigned char*)&len);
}
} else {
uint8_t blen = 0x70 + len;
char_buf_append(cbuf, 1, &blen);
}
char_buf_append(cbuf, len, (unsigned char*)data);
} break;
default:
fprintf(stderr, "%s: ERROR: Unsupported data type in plist\n", __func__);
break;
}
}
LIBIMOBILEDEVICE_GLUE_API void opack_encode_from_plist(plist_t plist, unsigned char** out, unsigned int* out_len)
{
if (!plist || !out || !out_len) {
return;
}
struct char_buf* cbuf = char_buf_new();
opack_encode_node(plist, cbuf);
*out = cbuf->data;
*out_len = cbuf->length;
cbuf->data = NULL;
char_buf_free(cbuf);
}
static int opack_decode_obj(unsigned char** p, unsigned char* end, plist_t* plist_out, uint32_t level)
{
uint8_t type = **p;
if (type == 0x02) {
/* bool: false */
*plist_out = plist_new_bool(0);
(*p)++;
return 0;
} else if (type == 0x01) {
/* bool: true */
*plist_out = plist_new_bool(1);
(*p)++;
return 0;
} else if (type == 0x03) {
/* NULL / structured type child node terminator */
(*p)++;
return -2;
} else if (type == 0x06) {
/* date type */
(*p)++;
double value = *(double*)*p;
time_t sec = (time_t)value;
value -= sec;
uint32_t usec = value * 1000000;
(*p)+=8;
*plist_out = plist_new_date(sec, usec);
} else if (type >= 0x08 && type <= 0x36) {
/* numerical type */
(*p)++;
uint64_t value = 0;
if (type == 0x36) {
/* double */
uint64_t u64val = float_bswap64(*(uint64_t*)(*p));
(*p)+=8;
double dval = 0;
memcpy(&dval, &u64val, 8);
*plist_out = plist_new_real(dval);
return 0;
} else if (type == 0x35) {
/* float */
uint32_t u32val = float_bswap32(*(uint32_t*)(*p));
(*p)+=4;
float fval = 0;
memcpy(&fval, &u32val, 4);
*plist_out = plist_new_real((double)fval);
return 0;
} else if (type < 0x30) {
value = type - 8;
} else if (type == 0x30) {
value = (int8_t)**p;
(*p)++;
} else if (type == 0x32) {
uint32_t u32val = *(uint32_t*)*p;
value = (int32_t)le32toh(u32val);
(p)+=4;
} else if (type == 0x33) {
uint64_t u64val = *(uint64_t*)*p;
value = le64toh(u64val);
(p)+=8;
} else {
fprintf(stderr, "%s: ERROR: Invalid encoded byte '%02x'\n", __func__, type);
*p = end;
return -1;
}
*plist_out = plist_new_uint(value);
} else if (type >= 0x40 && type <= 0x64) {
/* string */
(*p)++;
size_t slen = 0;
if (type < 0x61) {
slen = type - 0x40;
} else {
if (type == 0x61) {
slen = **p;
(*p)++;
} else if (type == 0x62) {
uint16_t u16val = *(uint16_t*)*p;
slen = le16toh(u16val);
(*p)+=2;
} else if (type == 0x63) {
uint32_t u32val = *(uint32_t*)*p;
slen = le32toh(u32val);
(*p)+=4;
} else if (type == 0x64) {
uint64_t u64val = *(uint64_t*)*p;
slen = le64toh(u64val);
(*p)+=8;
}
}
if (*p + slen > end) {
fprintf(stderr, "%s: ERROR: Size points past end of data\n", __func__);
*p = end;
return -1;
}
char* str = malloc(slen+1);
strncpy(str, (const char*)*p, slen);
str[slen] = '\0';
*plist_out = plist_new_string(str);
(*p)+=slen;
free(str);
} else if (type >= 0x70 && type <= 0x94) {
/* data */
(*p)++;
size_t dlen = 0;
if (type < 0x91) {
dlen = type - 0x70;
} else {
if (type == 0x91) {
dlen = **p;
(*p)++;
} else if (type == 0x92) {
uint16_t u16val = *(uint16_t*)*p;
dlen = le16toh(u16val);
(*p)+=2;
} else if (type == 0x93) {
uint32_t u32val = *(uint32_t*)*p;
dlen = le32toh(u32val);
(*p)+=4;
} else if (type == 0x94) {
uint64_t u64val = *(uint64_t*)*p;
dlen = le64toh(u64val);
(*p)+=8;
}
}
if (*p + dlen > end) {
fprintf(stderr, "%s: ERROR: Size points past end of data\n", __func__);
*p = end;
return -1;
}
*plist_out = plist_new_data((const char*)*p, dlen);
(*p)+=dlen;
} else if (type >= 0xE0 && type <= 0xEF) {
/* dictionary */
(*p)++;
plist_t dict = plist_new_dict();
uint32_t num_children = 0xFFFFFFFF;
if (type < 0xEF) {
/* explicit number of children */
num_children = type - 0xE0;
}
if (!*plist_out) {
*plist_out = dict;
}
uint32_t i = 0;
while (i++ < num_children) {
plist_t keynode = NULL;
int res = opack_decode_obj(p, end, &keynode, level+1);
if (res == -2) {
break;
} else if (res < 0) {
return -1;
}
if (!PLIST_IS_STRING(keynode)) {
plist_free(keynode);
fprintf(stderr, "%s: ERROR: Invalid node type for dictionary key node\n", __func__);
*p = end;
return -1;
}
char* key = NULL;
plist_get_string_val(keynode, &key);
plist_free(keynode);
plist_t valnode = NULL;
if (opack_decode_obj(p, end, &valnode, level+1) < 0) {
free(key);
return -1;
}
plist_dict_set_item(dict, key, valnode);
}
if (level == 0) {
*p = end;
return 0;
}
} else if (type >= 0xD0 && type <= 0xDF) {
/* array */
(*p)++;
plist_t array = plist_new_array();
if (!*plist_out) {
*plist_out = array;
}
uint32_t num_children = 0xFFFFFFFF;
if (type < 0xDF) {
/* explicit number of children */
num_children = type - 0xD0;
}
uint32_t i = 0;
while (i++ < num_children) {
plist_t child = NULL;
int res = opack_decode_obj(p, end, &child, level+1);
if (res == -2) {
if (type < 0xDF) {
fprintf(stderr, "%s: ERROR: Expected child node, found terminator\n", __func__);
*p = end;
return -1;
}
break;
} else if (res < 0) {
return -1;
}
plist_array_append_item(array, child);
}
if (level == 0) {
*p = end;
return 0;
}
} else {
fprintf(stderr, "%s: ERROR: Unexpected character '%02x encountered\n", __func__, type);
*p = end;
return -1;
}
return 0;
}
LIBIMOBILEDEVICE_GLUE_API int opack_decode_to_plist(unsigned char* buf, unsigned int buf_len, plist_t* plist_out)
{
if (!buf || buf_len == 0 || !plist_out) {
return -1;
}
unsigned char* p = buf;
unsigned char* end = buf + buf_len;
while (p < end) {
opack_decode_obj(&p, end, plist_out, 0);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,319 @@
/*
* termcolors.c
*
* Copyright (c) 2020-2021 Nikias Bassen, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include "common.h"
#include "libimobiledevice-glue/termcolors.h"
static int use_colors = 0;
#ifdef WIN32
static int WIN32_LEGACY_MODE = 1;
static WORD COLOR_RESET_ATTR = 0;
static WORD DEFAULT_FG_ATTR = 0;
static WORD DEFAULT_BG_ATTR = 0;
static HANDLE h_stdout = INVALID_HANDLE_VALUE;
static HANDLE h_stderr = INVALID_HANDLE_VALUE;
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif
#define STYLE_DIM (1 << 16)
#define FG_COLOR_MASK (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
#define BG_COLOR_MASK (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
#define FG_COLOR_ATTR_MASK (FG_COLOR_MASK | FOREGROUND_INTENSITY)
#define BG_COLOR_ATTR_MASK (BG_COLOR_MASK | BACKGROUND_INTENSITY)
static int style_map[9] = {
/* RESET ALL */ 0,
/* BRIGHT */ FOREGROUND_INTENSITY,
/* DIM */ STYLE_DIM,
/* (n/a) */ 0,
/* UNDERLINED */ 0, // COMMON_LVB_UNDERSCORE ?
/* BLINK */ 0, // NOT SUPPORTED
/* (n/a) */ 0,
/* REVERSE CLR */ 0, // COMMON_LVB_REVERSE_VIDEO ?
/* HIDDEN */ 0 // NOT SUPPORTED
};
static int fgcolor_map[8] = {
/* BLACK */ 0,
/* RED */ FOREGROUND_RED,
/* GREEN */ FOREGROUND_GREEN,
/* YELLOW */ FOREGROUND_GREEN | FOREGROUND_RED,
/* BLUE */ FOREGROUND_BLUE,
/* MAGENTA */ FOREGROUND_BLUE | FOREGROUND_RED,
/* CYAN */ FOREGROUND_BLUE | FOREGROUND_GREEN,
/* WHITE */ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
};
static int bgcolor_map[8] = {
/* BLACK */ 0,
/* RED */ BACKGROUND_RED,
/* GREEN */ BACKGROUND_GREEN,
/* YELLOW */ BACKGROUND_GREEN | BACKGROUND_RED,
/* BLUE */ BACKGROUND_BLUE,
/* MAGENTA */ BACKGROUND_BLUE | BACKGROUND_RED,
/* CYAN */ BACKGROUND_BLUE | BACKGROUND_GREEN,
/* WHITE */ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
};
#else
static int WIN32_LEGACY_MODE = 0;
#endif
LIBIMOBILEDEVICE_GLUE_API void term_colors_init()
{
#ifdef WIN32
DWORD conmode = 0;
h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(h_stdout, &conmode);
if (conmode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) {
WIN32_LEGACY_MODE = 0;
} else {
conmode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (SetConsoleMode(h_stdout, conmode)) {
WIN32_LEGACY_MODE = 0;
} else {
WIN32_LEGACY_MODE = 1;
}
}
if (WIN32_LEGACY_MODE) {
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(h_stdout, &csbi)) {
COLOR_RESET_ATTR = csbi.wAttributes;
DEFAULT_FG_ATTR = csbi.wAttributes & FG_COLOR_ATTR_MASK;
DEFAULT_BG_ATTR = csbi.wAttributes & BG_COLOR_ATTR_MASK;
}
h_stderr = GetStdHandle(STD_ERROR_HANDLE);
}
#endif
use_colors = isatty(1);
const char* color_env = getenv("COLOR");
if (color_env) {
long val = strtol(color_env, NULL, 10);
use_colors = (val != 0);
}
}
LIBIMOBILEDEVICE_GLUE_API void term_colors_set_enabled(int en)
{
use_colors = en;
}
LIBIMOBILEDEVICE_GLUE_API int cvfprintf(FILE* stream, const char* fmt, va_list vargs)
{
int res = 0;
int colorize = use_colors;
#ifdef WIN32
struct esc_item {
int pos;
WORD attr;
};
HANDLE h_stream = h_stdout;
if (WIN32_LEGACY_MODE) {
if (stream == stdout) {
h_stream = h_stdout;
} else if (stream == stderr) {
h_stream = h_stderr;
} else {
colorize = 0;
}
}
#endif
if (!colorize || WIN32_LEGACY_MODE) {
// first, we need to print the string WITH escape sequences
va_list vargs_copy;
va_copy(vargs_copy, vargs);
int len = vsnprintf(NULL, 0, fmt, vargs);
char* newbuf = (char*)malloc(len+1);
res = vsnprintf(newbuf, len+1, fmt, vargs_copy);
va_end(vargs_copy);
// then, we need to remove the escape sequences, if any
#ifdef WIN32
// if colorize is on, we need to keep their positions for later
struct esc_item* esc_items = NULL;
int attr = 0;
if (colorize) {
esc_items = (struct esc_item*)malloc(sizeof(struct esc_item) * ((len/3)+1));
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(h_stream, &csbi)) {
attr = csbi.wAttributes;
}
}
#endif
int num_esc = 0;
char* start = &newbuf[0];
char* p = start;
char* end = start + len + 1;
while (p < end-1) {
char* cur = p;
if (*p == '\e' && end-p > 2 && *(p+1) == '[') {
p+=2;
if (*p == 'm') {
#ifdef WIN32
attr = COLOR_RESET_ATTR;
#endif
int move_by = (p+1)-cur;
int move_amount = end-(p+1);
memmove(cur, p+1, move_amount);
end -= move_by;
p = cur;
} else {
char* endp = NULL;
do {
long lval = strtol(p, &endp, 10);
if (!endp || (*endp != ';' && *endp != 'm')) {
fprintf(stderr, "\n*** %s: Invalid escape sequence in format string, expected ';' or 'm' ***\n", __func__);
#ifdef WIN32
free(esc_items);
#endif
free(newbuf);
return -1;
}
#ifdef WIN32
if (colorize) {
if (lval >= 0 && lval <= 8) {
/* style attributes */
attr &= ~FOREGROUND_INTENSITY;
attr |= style_map[lval];
} else if (lval >= 30 && lval <= 37) {
/* foreground color */
attr &= ~FG_COLOR_MASK;
attr |= fgcolor_map[lval-30];
} else if (lval == 39) {
/* default foreground color */
attr &= ~FG_COLOR_ATTR_MASK;
attr |= DEFAULT_FG_ATTR;
} else if (lval >= 40 && lval <= 47) {
/* background color */
attr &= ~BG_COLOR_MASK;
attr |= bgcolor_map[lval-40];
} else if (lval == 49) {
/* default background color */
attr &= ~BG_COLOR_ATTR_MASK;
attr |= DEFAULT_BG_ATTR;
} else if (lval >= 90 && lval <= 97) {
/* foreground color bright */
attr &= ~FG_COLOR_ATTR_MASK;
attr |= fgcolor_map[lval-90];
attr |= FOREGROUND_INTENSITY;
} else if (lval >= 100 && lval <= 107) {
/* background color bright */
attr &= ~BG_COLOR_MASK;
attr |= bgcolor_map[lval-100];
attr |= BACKGROUND_INTENSITY;
}
}
#else
(void)lval; // suppress compiler warning about unused variable
#endif
p = endp+1;
} while (p < end && *endp == ';');
int move_by = (endp+1)-cur;
int move_amount = end-(endp+1);
memmove(cur, endp+1, move_amount);
end -= move_by;
p = cur;
}
#ifdef WIN32
if (colorize) {
esc_items[num_esc].pos = p-start;
if (attr & STYLE_DIM) {
attr &= ~STYLE_DIM;
attr &= ~FOREGROUND_INTENSITY;
}
esc_items[num_esc].attr = (WORD)attr;
num_esc++;
}
#endif
} else {
p++;
}
}
if (num_esc == 0) {
res = fputs(newbuf, stream);
free(newbuf);
#ifdef WIN32
free(esc_items);
#endif
return res;
}
#ifdef WIN32
else {
p = &newbuf[0];
char* lastp = &newbuf[0];
int i;
for (i = 0; i < num_esc; i++) {
p = &newbuf[esc_items[i].pos];
if (lastp < p) {
fprintf(stream, "%.*s", (int)(p-lastp), lastp);
lastp = p;
}
SetConsoleTextAttribute(h_stream, esc_items[i].attr);
}
if (lastp < end) {
fprintf(stream, "%.*s", (int)(end-lastp), lastp);
}
return res;
}
#endif
} else {
res = vfprintf(stream, fmt, vargs);
}
return res;
}
LIBIMOBILEDEVICE_GLUE_API int cfprintf(FILE* stream, const char* fmt, ...)
{
int res = 0;
va_list va;
va_start(va, fmt);
res = cvfprintf(stream, fmt, va);
va_end(va);
return res;
}
LIBIMOBILEDEVICE_GLUE_API int cprintf(const char* fmt, ...)
{
int res = 0;
va_list va;
va_start(va, fmt);
res = cvfprintf(stdout, fmt, va);
va_end(va);
return res;
}

View File

@@ -0,0 +1,216 @@
/*
* thread.c
*
* Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved.
* Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "common.h"
#include "libimobiledevice-glue/thread.h"
LIBIMOBILEDEVICE_GLUE_API int thread_new(THREAD_T *thread, thread_func_t thread_func, void* data)
{
#ifdef WIN32
HANDLE th = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, data, 0, NULL);
if (th == NULL) {
return -1;
}
*thread = th;
return 0;
#else
int res = pthread_create(thread, NULL, thread_func, data);
return res;
#endif
}
LIBIMOBILEDEVICE_GLUE_API void thread_detach(THREAD_T thread)
{
#ifdef WIN32
CloseHandle(thread);
#else
pthread_detach(thread);
#endif
}
LIBIMOBILEDEVICE_GLUE_API void thread_free(THREAD_T thread)
{
#ifdef WIN32
CloseHandle(thread);
#endif
}
LIBIMOBILEDEVICE_GLUE_API int thread_join(THREAD_T thread)
{
/* wait for thread to complete */
#ifdef WIN32
return (int)WaitForSingleObject(thread, INFINITE);
#else
return pthread_join(thread, NULL);
#endif
}
LIBIMOBILEDEVICE_GLUE_API int thread_alive(THREAD_T thread)
{
if (!thread)
return 0;
#ifdef WIN32
return WaitForSingleObject(thread, 0) == WAIT_TIMEOUT;
#else
return pthread_kill(thread, 0) == 0;
#endif
}
LIBIMOBILEDEVICE_GLUE_API int thread_cancel(THREAD_T thread)
{
#ifdef WIN32
return -1;
#else
#ifdef HAVE_PTHREAD_CANCEL
return pthread_cancel(thread);
#else
return -1;
#endif
#endif
}
LIBIMOBILEDEVICE_GLUE_API void mutex_init(mutex_t* mutex)
{
#ifdef WIN32
InitializeCriticalSection(mutex);
#else
pthread_mutex_init(mutex, NULL);
#endif
}
LIBIMOBILEDEVICE_GLUE_API void mutex_destroy(mutex_t* mutex)
{
#ifdef WIN32
DeleteCriticalSection(mutex);
#else
pthread_mutex_destroy(mutex);
#endif
}
LIBIMOBILEDEVICE_GLUE_API void mutex_lock(mutex_t* mutex)
{
#ifdef WIN32
EnterCriticalSection(mutex);
#else
pthread_mutex_lock(mutex);
#endif
}
LIBIMOBILEDEVICE_GLUE_API void mutex_unlock(mutex_t* mutex)
{
#ifdef WIN32
LeaveCriticalSection(mutex);
#else
pthread_mutex_unlock(mutex);
#endif
}
LIBIMOBILEDEVICE_GLUE_API void thread_once(thread_once_t *once_control, void (*init_routine)(void))
{
#ifdef WIN32
while (InterlockedExchange(&(once_control->lock), 1) != 0) {
Sleep(1);
}
if (!once_control->state) {
once_control->state = 1;
init_routine();
}
InterlockedExchange(&(once_control->lock), 0);
#else
pthread_once(once_control, init_routine);
#endif
}
LIBIMOBILEDEVICE_GLUE_API void cond_init(cond_t* cond)
{
#ifdef WIN32
cond->sem = CreateSemaphore(NULL, 0, 32767, NULL);
#else
pthread_cond_init(cond, NULL);
#endif
}
LIBIMOBILEDEVICE_GLUE_API void cond_destroy(cond_t* cond)
{
#ifdef WIN32
CloseHandle(cond->sem);
#else
pthread_cond_destroy(cond);
#endif
}
LIBIMOBILEDEVICE_GLUE_API int cond_signal(cond_t* cond)
{
#ifdef WIN32
int result = 0;
if (!ReleaseSemaphore(cond->sem, 1, NULL)) {
result = -1;
}
return result;
#else
return pthread_cond_signal(cond);
#endif
}
LIBIMOBILEDEVICE_GLUE_API int cond_wait(cond_t* cond, mutex_t* mutex)
{
#ifdef WIN32
mutex_unlock(mutex);
DWORD res = WaitForSingleObject(cond->sem, INFINITE);
switch (res) {
case WAIT_OBJECT_0:
return 0;
default:
return -1;
}
#else
return pthread_cond_wait(cond, mutex);
#endif
}
LIBIMOBILEDEVICE_GLUE_API int cond_wait_timeout(cond_t* cond, mutex_t* mutex, unsigned int timeout_ms)
{
#ifdef WIN32
mutex_unlock(mutex);
DWORD res = WaitForSingleObject(cond->sem, timeout_ms);
switch (res) {
case WAIT_OBJECT_0:
case WAIT_TIMEOUT:
return 0;
default:
return -1;
}
#else
struct timespec ts;
struct timeval now;
gettimeofday(&now, NULL);
ts.tv_sec = now.tv_sec + timeout_ms / 1000;
ts.tv_nsec = now.tv_usec * 1000 + 1000 * 1000 * (timeout_ms % 1000);
ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
ts.tv_nsec %= (1000 * 1000 * 1000);
return pthread_cond_timedwait(cond, mutex, &ts);
#endif
}

View File

@@ -0,0 +1,196 @@
/*
* tlv.c
* Simple TLV implementation.
*
* Copyright (c) 2021 Nikias Bassen, All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "common.h"
#include "libimobiledevice-glue/tlv.h"
#include "endianness.h"
LIBIMOBILEDEVICE_GLUE_API tlv_buf_t tlv_buf_new()
{
tlv_buf_t tlv = malloc(sizeof(struct tlv_buf));
tlv->capacity = 1024;
tlv->length = 0;
tlv->data = malloc(tlv->capacity);
return tlv;
}
LIBIMOBILEDEVICE_GLUE_API void tlv_buf_free(tlv_buf_t tlv)
{
if (tlv) {
free(tlv->data);
free(tlv);
}
}
LIBIMOBILEDEVICE_GLUE_API void tlv_buf_append(tlv_buf_t tlv, uint8_t tag, unsigned int length, void* data)
{
if (!tlv || !tlv->data) {
return;
}
unsigned int req_len = (length > 255) ? (length / 255) * 257 + (2 + (length % 255)) : length;
if (tlv->length + req_len > tlv->capacity) {
unsigned int newcapacity = tlv->capacity + ((req_len / 1024) + 1) * 1024;
unsigned char* newdata = realloc(tlv->data, newcapacity);
if (!newdata) {
fprintf(stderr, "%s: ERROR: Failed to realloc\n", __func__);
return;
}
tlv->data = newdata;
tlv->capacity = newcapacity;
}
unsigned char* p = tlv->data + tlv->length;
unsigned int cur = 0;
while (length - cur > 0) {
if (length - cur > 255) {
*(p++) = tag;
*(p++) = 0xFF;
memcpy(p, (unsigned char*)data + cur, 255);
p += 255;
cur += 255;
} else {
uint8_t rem = length - cur;
*(p++) = tag;
*(p++) = rem;
memcpy(p, (unsigned char*)data + cur, rem);
p += rem;
cur += rem;
}
}
tlv->length = p - tlv->data;
}
LIBIMOBILEDEVICE_GLUE_API unsigned char* tlv_get_data_ptr(const void* tlv_data, void* tlv_end, uint8_t tag, uint8_t* length)
{
unsigned char* p = (unsigned char*)tlv_data;
unsigned char* end = (unsigned char*)tlv_end;
while (p < end) {
uint8_t cur_tag = *(p++);
uint8_t len = *(p++);
if (cur_tag == tag) {
*length = len;
return p;
}
p+=len;
}
return NULL;
}
LIBIMOBILEDEVICE_GLUE_API int tlv_data_get_uint(const void* tlv_data, unsigned int tlv_length, uint8_t tag, uint64_t* value)
{
if (!tlv_data || tlv_length < 2 || !value) {
return 0;
}
uint8_t length = 0;
unsigned char* ptr = tlv_get_data_ptr(tlv_data, (unsigned char*)tlv_data+tlv_length, tag, &length);
if (!ptr) {
return 0;
}
if (ptr + length > (unsigned char*)tlv_data + tlv_length) {
return 0;
}
if (length == 1) {
uint8_t val = *ptr;
*value = val;
} else if (length == 2) {
uint16_t val = *(uint16_t*)ptr;
val = le16toh(val);
*value = val;
} else if (length == 4) {
uint32_t val = *(uint32_t*)ptr;
val = le32toh(val);
*value = val;
} else if (length == 8) {
uint64_t val = *(uint64_t*)ptr;
val = le64toh(val);
*value = val;
} else {
return 0;
}
return 1;
}
LIBIMOBILEDEVICE_GLUE_API int tlv_data_get_uint8(const void* tlv_data, unsigned int tlv_length, uint8_t tag, uint8_t* value)
{
if (!tlv_data || tlv_length < 2 || !value) {
return 0;
}
uint8_t length = 0;
unsigned char* ptr = tlv_get_data_ptr(tlv_data, (unsigned char*)tlv_data+tlv_length, tag, &length);
if (!ptr) {
return 0;
}
if (length != 1) {
return 0;
}
if (ptr + length > (unsigned char*)tlv_data + tlv_length) {
return 0;
}
*value = *ptr;
return 1;
}
LIBIMOBILEDEVICE_GLUE_API int tlv_data_copy_data(const void* tlv_data, unsigned int tlv_length, uint8_t tag, void** out, unsigned int* out_len)
{
if (!tlv_data || tlv_length < 2 || !out || !out_len) {
return 0;
}
*out = NULL;
*out_len = 0;
unsigned char* dest = NULL;
unsigned int dest_len = 0;
unsigned char* ptr = (unsigned char*)tlv_data;
unsigned char* end = (unsigned char*)tlv_data + tlv_length;
while (ptr < end) {
uint8_t length = 0;
ptr = tlv_get_data_ptr(ptr, end, tag, &length);
if (!ptr) {
break;
}
unsigned char* newdest = realloc(dest, dest_len + length);
if (!newdest) {
free(dest);
return 0;
}
dest = newdest;
memcpy(dest + dest_len, ptr, length);
dest_len += length;
ptr += length;
}
if (!dest) {
return 0;
}
*out = (void*)dest;
*out_len = dest_len;
return 1;
}

View File

@@ -0,0 +1,558 @@
/*
* utils.c
* Miscellaneous utilities for string manipulation,
* file I/O and plist helper.
*
* Copyright (c) 2014-2019 Nikias Bassen, All Rights Reserved.
* Copyright (c) 2013-2014 Martin Szulecki, All Rights Reserved.
* Copyright (c) 2013 Federico Mena Quintero
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <inttypes.h>
#include <ctype.h>
#include <errno.h>
#include "common.h"
#include "libimobiledevice-glue/utils.h"
#ifndef HAVE_STPCPY
#undef stpcpy
char *stpcpy(char *s1, const char *s2);
/**
* Copy characters from one string into another
*
* @note: The strings should not overlap, as the behavior is undefined.
*
* @s1: The source string.
* @s2: The destination string.
*
* @return a pointer to the terminating `\0' character of @s1,
* or NULL if @s1 or @s2 is NULL.
*/
char *stpcpy(char *s1, const char *s2)
{
if (s1 == NULL || s2 == NULL)
return NULL;
strcpy(s1, s2);
return s1 + strlen(s2);
}
#endif
/**
* Concatenate strings into a newly allocated string
*
* @note: Specify NULL for the last string in the varargs list
*
* @str: The first string in the list
* @...: Subsequent strings. Use NULL for the last item.
*
* @return a newly allocated string, or NULL if @str is NULL. This will also
* return NULL and set errno to ENOMEM if memory is exhausted.
*/
LIBIMOBILEDEVICE_GLUE_API char *string_concat(const char *str, ...)
{
size_t len;
va_list args;
char *s;
char *result;
char *dest;
if (!str)
return NULL;
/* Compute final length */
len = strlen(str) + 1; /* plus 1 for the null terminator */
va_start(args, str);
s = va_arg(args, char *);
while (s) {
len += strlen(s);
s = va_arg(args, char*);
}
va_end(args);
/* Concat each string */
result = malloc(len);
if (!result)
return NULL; /* errno remains set */
dest = result;
dest = stpcpy(dest, str);
va_start(args, str);
s = va_arg(args, char *);
while (s) {
dest = stpcpy(dest, s);
s = va_arg(args, char *);
}
va_end(args);
return result;
}
LIBIMOBILEDEVICE_GLUE_API char *string_append(char* str, ...)
{
size_t len = 0;
size_t slen;
va_list args;
char *s;
char *result;
char *dest;
/* Compute final length */
if (str) {
len = strlen(str);
}
slen = len;
len++; /* plus 1 for the null terminator */
va_start(args, str);
s = va_arg(args, char *);
while (s) {
len += strlen(s);
s = va_arg(args, char*);
}
va_end(args);
result = realloc(str, len);
if (!result)
return NULL; /* errno remains set */
dest = result + slen;
/* Concat additional strings */
va_start(args, str);
s = va_arg(args, char *);
while (s) {
dest = stpcpy(dest, s);
s = va_arg(args, char *);
}
va_end(args);
return result;
}
LIBIMOBILEDEVICE_GLUE_API char *string_build_path(const char *elem, ...)
{
if (!elem)
return NULL;
va_list args;
int len = strlen(elem)+1;
va_start(args, elem);
char *arg = va_arg(args, char*);
while (arg) {
len += strlen(arg)+1;
arg = va_arg(args, char*);
}
va_end(args);
char* out = (char*)malloc(len);
strcpy(out, elem);
va_start(args, elem);
arg = va_arg(args, char*);
while (arg) {
strcat(out, "/");
strcat(out, arg);
arg = va_arg(args, char*);
}
va_end(args);
return out;
}
LIBIMOBILEDEVICE_GLUE_API char *string_format_size(uint64_t size)
{
char buf[80];
double sz;
if (size >= 1000000000000LL) {
sz = ((double)size / 1000000000000.0F);
sprintf(buf, "%0.1f TB", sz);
} else if (size >= 1000000000LL) {
sz = ((double)size / 1000000000.0F);
sprintf(buf, "%0.1f GB", sz);
} else if (size >= 1000000LL) {
sz = ((double)size / 1000000.0F);
sprintf(buf, "%0.1f MB", sz);
} else if (size >= 1000LL) {
sz = ((double)size / 1000.0F);
sprintf(buf, "%0.1f KB", sz);
} else {
sprintf(buf, "%d Bytes", (int)size);
}
return strdup(buf);
}
LIBIMOBILEDEVICE_GLUE_API char *string_toupper(char* str)
{
char *res = strdup(str);
size_t i;
for (i = 0; i < strlen(res); i++) {
res[i] = toupper(res[i]);
}
return res;
}
static int get_rand(int min, int max)
{
int retval = (rand() % (max - min)) + min;
return retval;
}
LIBIMOBILEDEVICE_GLUE_API char *generate_uuid()
{
const char *chars = "ABCDEF0123456789";
int i = 0;
char *uuid = (char *) malloc(sizeof(char) * 37);
srand(time(NULL));
for (i = 0; i < 36; i++) {
if (i == 8 || i == 13 || i == 18 || i == 23) {
uuid[i] = '-';
continue;
}
uuid[i] = chars[get_rand(0, 16)];
}
/* make it a real string */
uuid[36] = '\0';
return uuid;
}
LIBIMOBILEDEVICE_GLUE_API int buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length)
{
FILE *f;
uint64_t size;
if (!filename || !buffer || !length) {
return 0;
}
*length = 0;
f = fopen(filename, "rb");
if (!f) {
return 0;
}
fseek(f, 0, SEEK_END);
size = ftell(f);
rewind(f);
if (size == 0) {
fclose(f);
return 0;
}
*buffer = (char*)malloc(sizeof(char)*(size+1));
if (*buffer == NULL) {
fclose(f);
return 0;
}
int ret = 1;
if (fread(*buffer, sizeof(char), size, f) != size) {
free(*buffer);
ret = 0;
errno = EIO;
}
fclose(f);
*length = size;
return ret;
}
LIBIMOBILEDEVICE_GLUE_API int buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length)
{
FILE *f;
f = fopen(filename, "wb");
if (f) {
size_t written = fwrite(buffer, sizeof(char), length, f);
fclose(f);
if (written == length) {
return 1;
}
else {
// Not all data could be written.
errno = EIO;
return 0;
}
}
else {
// Failed to open the file, let the caller know.
return 0;
}
}
LIBIMOBILEDEVICE_GLUE_API int plist_read_from_filename(plist_t *plist, const char *filename)
{
char *buffer = NULL;
uint64_t length;
if (!filename)
return 0;
if (!buffer_read_from_filename(filename, &buffer, &length)) {
return 0;
}
plist_from_memory(buffer, length, plist);
free(buffer);
return 1;
}
LIBIMOBILEDEVICE_GLUE_API int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format)
{
char *buffer = NULL;
uint32_t length;
if (!plist || !filename)
return 0;
if (format == PLIST_FORMAT_XML)
plist_to_xml(plist, &buffer, &length);
else if (format == PLIST_FORMAT_BINARY)
plist_to_bin(plist, &buffer, &length);
else
return 0;
int res = buffer_write_to_filename(filename, buffer, length);
free(buffer);
return res;
}
static const char base64_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char base64_pad = '=';
static char *base64encode(const unsigned char *buf, size_t size)
{
if (!buf || !(size > 0)) return NULL;
int outlen = (size / 3) * 4;
char *outbuf = (char*)malloc(outlen+5); // 4 spare bytes + 1 for '\0'
size_t n = 0;
size_t m = 0;
unsigned char input[3];
unsigned int output[4];
while (n < size) {
input[0] = buf[n];
input[1] = (n+1 < size) ? buf[n+1] : 0;
input[2] = (n+2 < size) ? buf[n+2] : 0;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 3) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 15) << 2) + (input[2] >> 6);
output[3] = input[2] & 63;
outbuf[m++] = base64_str[(int)output[0]];
outbuf[m++] = base64_str[(int)output[1]];
outbuf[m++] = (n+1 < size) ? base64_str[(int)output[2]] : base64_pad;
outbuf[m++] = (n+2 < size) ? base64_str[(int)output[3]] : base64_pad;
n+=3;
}
outbuf[m] = 0; // 0-termination!
return outbuf;
}
static void plist_node_print_to_stream(plist_t node, int* indent_level, FILE* stream);
static void plist_array_print_to_stream(plist_t node, int* indent_level, FILE* stream)
{
/* iterate over items */
int i, count;
plist_t subnode = NULL;
count = plist_array_get_size(node);
for (i = 0; i < count; i++) {
subnode = plist_array_get_item(node, i);
fprintf(stream, "%*s", *indent_level, "");
fprintf(stream, "%d: ", i);
plist_node_print_to_stream(subnode, indent_level, stream);
}
}
static void plist_dict_print_to_stream(plist_t node, int* indent_level, FILE* stream)
{
/* iterate over key/value pairs */
plist_dict_iter it = NULL;
char* key = NULL;
plist_t subnode = NULL;
plist_dict_new_iter(node, &it);
plist_dict_next_item(node, it, &key, &subnode);
while (subnode)
{
fprintf(stream, "%*s", *indent_level, "");
fprintf(stream, "%s", key);
if (plist_get_node_type(subnode) == PLIST_ARRAY)
fprintf(stream, "[%d]: ", plist_array_get_size(subnode));
else
fprintf(stream, ": ");
free(key);
key = NULL;
plist_node_print_to_stream(subnode, indent_level, stream);
plist_dict_next_item(node, it, &key, &subnode);
}
free(it);
}
static void plist_node_print_to_stream(plist_t node, int* indent_level, FILE* stream)
{
char *s = NULL;
char *data = NULL;
double d;
uint8_t b;
uint64_t u = 0;
struct timeval tv = { 0, 0 };
plist_type t;
if (!node)
return;
t = plist_get_node_type(node);
switch (t) {
case PLIST_BOOLEAN:
plist_get_bool_val(node, &b);
fprintf(stream, "%s\n", (b ? "true" : "false"));
break;
case PLIST_UINT:
plist_get_uint_val(node, &u);
fprintf(stream, "%"PRIu64"\n", u);
break;
case PLIST_REAL:
plist_get_real_val(node, &d);
fprintf(stream, "%f\n", d);
break;
case PLIST_STRING:
plist_get_string_val(node, &s);
fprintf(stream, "%s\n", s);
free(s);
break;
case PLIST_KEY:
plist_get_key_val(node, &s);
fprintf(stream, "%s: ", s);
free(s);
break;
case PLIST_DATA:
plist_get_data_val(node, &data, &u);
if (u > 0) {
s = base64encode((unsigned char*)data, u);
free(data);
if (s) {
fprintf(stream, "%s\n", s);
free(s);
} else {
fprintf(stream, "\n");
}
} else {
fprintf(stream, "\n");
}
break;
case PLIST_DATE:
plist_get_date_val(node, (int32_t*)&tv.tv_sec, (int32_t*)&tv.tv_usec);
{
time_t ti = (time_t)tv.tv_sec + MAC_EPOCH;
struct tm *btime = localtime(&ti);
if (btime) {
s = (char*)malloc(24);
memset(s, 0, 24);
if (strftime(s, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) {
free (s);
s = NULL;
}
}
}
if (s) {
fprintf(stream, "%s\n", s);
free(s);
} else {
fprintf(stream, "\n");
}
break;
case PLIST_ARRAY:
fprintf(stream, "\n");
(*indent_level)++;
plist_array_print_to_stream(node, indent_level, stream);
(*indent_level)--;
break;
case PLIST_DICT:
fprintf(stream, "\n");
(*indent_level)++;
plist_dict_print_to_stream(node, indent_level, stream);
(*indent_level)--;
break;
default:
break;
}
}
LIBIMOBILEDEVICE_GLUE_API void plist_print_to_stream_with_indentation(plist_t plist, FILE* stream, unsigned int indentation)
{
if (!plist || !stream)
return;
int indent = indentation;
switch (plist_get_node_type(plist)) {
case PLIST_DICT:
plist_dict_print_to_stream(plist, &indent, stream);
break;
case PLIST_ARRAY:
plist_array_print_to_stream(plist, &indent, stream);
break;
default:
plist_node_print_to_stream(plist, &indent, stream);
}
}
LIBIMOBILEDEVICE_GLUE_API void plist_print_to_stream(plist_t plist, FILE* stream)
{
plist_print_to_stream_with_indentation(plist, stream, 0);
}

View File

@@ -0,0 +1 @@
* text=auto

View File

@@ -0,0 +1,229 @@
name: build
on:
push:
schedule:
- cron: '0 0 1 * *'
jobs:
build-linux-ubuntu:
runs-on: ubuntu-latest
steps:
- name: install dependencies
run: |
sudo apt-get update
sudo apt-get install cython3
- name: prepare environment
run: |
echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV
- name: fetch libplist
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libplist-latest_${{env.target_triplet}}
repo: libimobiledevice/libplist
- name: fetch libusbmuxd
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libusbmuxd-latest_${{env.target_triplet}}
repo: libimobiledevice/libusbmuxd
- name: fetch libimobiledevice-glue
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libimobiledevice-glue-latest_${{env.target_triplet}}
repo: libimobiledevice/libimobiledevice-glue
- name: install external dependencies
run: |
mkdir extract
for I in *.tar; do
tar -C extract -xvf $I
done
sudo cp -r extract/* /
sudo ldconfig
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: autogen
run: ./autogen.sh PKG_CONFIG_PATH=/usr/local/lib/pkgconfig LDFLAGS="-Wl,-rpath=/usr/local/lib" --enable-debug
- name: make
run: make
- name: make install
run: sudo make install
- name: prepare artifact
run: |
mkdir -p dest
DESTDIR=`pwd`/dest make install
tar -C dest -cf libimobiledevice.tar usr
- name: publish artifact
uses: actions/upload-artifact@v2
with:
name: libimobiledevice-latest_${{env.target_triplet}}
path: libimobiledevice.tar
build-macOS:
runs-on: macOS-latest
steps:
- name: install dependencies
run: |
if test -x "`which port`"; then
sudo port install libtool autoconf automake pkgconfig
else
brew install libtool autoconf automake pkgconfig
fi
pip install cython
shell: bash
- name: fetch libplist
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libplist-latest_macOS
repo: libimobiledevice/libplist
- name: fetch libusbmuxd
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libusbmuxd-latest_macOS
repo: libimobiledevice/libusbmuxd
- name: fetch libimobiledevice-glue
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libimobiledevice-glue-latest_macOS
repo: libimobiledevice/libimobiledevice-glue
- name: install external dependencies
run: |
mkdir extract
for I in *.tar; do
tar -C extract -xvf $I
done
sudo cp -r extract/* /
- uses: actions/checkout@v2
- name: install additional requirements
run: |
mkdir -p lib
curl -o lib/libcrypto.35.tbd -Ls \
https://gist.github.com/nikias/94c99fd145a75a5104415e5117b0cafa/raw/5209dfbff5a871a14272afe4794e76eb4cf6f062/libcrypto.35.tbd
curl -o lib/libssl.35.tbd -Ls \
https://gist.github.com/nikias/94c99fd145a75a5104415e5117b0cafa/raw/5209dfbff5a871a14272afe4794e76eb4cf6f062/libssl.35.tbd
echo "LIBSSL=`pwd`/lib/libssl.35.tbd" >> $GITHUB_ENV
echo "LIBCRYPTO=`pwd`/lib/libcrypto.35.tbd" >> $GITHUB_ENV
LIBRESSL_VER=2.2.7
echo "LIBRESSL_VER=$LIBRESSL_VER" >> $GITHUB_ENV
FILENAME="libressl-$LIBRESSL_VER.tar.gz"
curl -o $FILENAME -Ls "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/$FILENAME"
mkdir -p deps
tar -C deps -xzf $FILENAME
echo "DEPSDIR=`pwd`/deps" >> $GITHUB_ENV
- name: autogen
run: |
SDKDIR=`xcrun --sdk macosx --show-sdk-path`
TESTARCHS="arm64 x86_64"
USEARCHS=
for ARCH in $TESTARCHS; do
if echo "int main(int argc, char **argv) { return 0; }" |clang -arch $ARCH -o /dev/null -isysroot $SDKDIR -x c - 2>/dev/null; then
USEARCHS="$USEARCHS -arch $ARCH"
fi
done
export CFLAGS="$USEARCHS -isysroot $SDKDIR"
echo "Using CFLAGS: $CFLAGS"
./autogen.sh PKG_CONFIG_PATH=/usr/local/lib/pkgconfig --enable-debug \
openssl_CFLAGS="-I${{ env.DEPSDIR }}/libressl-${{ env.LIBRESSL_VER }}/include" \
openssl_LIBS="-Xlinker ${{ env.LIBSSL }} -Xlinker ${{ env.LIBCRYPTO }}"
- name: make
run: make
- name: make install
run: sudo make install
- name: prepare artifact
run: |
mkdir -p dest
DESTDIR=`pwd`/dest make install
tar -C dest -cf libimobiledevice.tar usr
- name: publish artifact
uses: actions/upload-artifact@v2
with:
name: libimobiledevice-latest_macOS
path: libimobiledevice.tar
build-windows:
runs-on: windows-2019
defaults:
run:
shell: msys2 {0}
strategy:
fail-fast: false
matrix:
include: [
{ msystem: MINGW64, arch: x86_64 },
{ msystem: MINGW32, arch: i686 }
]
steps:
- uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
release: false
update: false
install: >-
base-devel
git
mingw-w64-${{ matrix.arch }}-gcc
make
libtool
autoconf
automake-wrapper
- name: prepare environment
run: |
dest=`echo ${{ matrix.msystem }} |tr [:upper:] [:lower:]`
echo "dest=$dest" >> $GITHUB_ENV
echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV
git config --global core.autocrlf false
- name: fetch libplist
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libplist-latest_${{ matrix.arch }}-${{ env.dest }}
repo: libimobiledevice/libplist
- name: fetch libusbmuxd
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libusbmuxd-latest_${{ matrix.arch }}-${{ env.dest }}
repo: libimobiledevice/libusbmuxd
- name: fetch libimobiledevice-glue
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml
name: libimobiledevice-glue-latest_${{ matrix.arch }}-${{ env.dest }}
repo: libimobiledevice/libimobiledevice-glue
- name: install external dependencies
run: |
mkdir extract
for I in *.tar; do
tar -C extract -xvf $I
done
cp -r extract/* /
- uses: actions/checkout@v2
- name: autogen
run: ./autogen.sh CC=gcc CXX=g++ --enable-debug
- name: make
run: make
- name: make install
run: make install
- name: prepare artifact
run: |
mkdir -p dest
DESTDIR=`pwd`/dest make install
tar -C dest -cf libimobiledevice.tar ${{ env.dest }}
- name: publish artifact
uses: actions/upload-artifact@v2
with:
name: libimobiledevice-latest_${{ matrix.arch }}-${{ env.dest }}
path: libimobiledevice.tar

View File

@@ -0,0 +1,43 @@
# git-ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
*.[oa]
*~
*.po
*.lo
*.la
autom4te.cache/*
*.in
*/.deps/*
m4/*
swig/*
*.swp
*.patch
aclocal.m4
config.h
config.log
config.sub
config.guess
config.status
configure
depcomp
install-sh
compile
main
ltmain.sh
missing
mkinstalldirs
libtool
*Makefile
py-compile
stamp-h1
src/.libs
docs/html
libimobiledevice-1.0.pc
tools/.libs/*
tools/idevice*
!tools/idevice*.[ch]
cython/.libs/*
cython/*.c
doxygen.cfg

View File

@@ -0,0 +1,6 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
SUBDIRS =
if HAVE_WIRELESS_PAIRING
SUBDIRS += ed25519 libsrp6a-sha512
endif

View File

@@ -0,0 +1,36 @@
# Third party components/libraries
This folder contains third party components or libraries that are used
within the libimobiledevice project. They have been bundled since they
are either not readily available on the intended target platforms and/or
have been modified.
Their respective licenses are provided in each corresponding folder in a
file called LICENSE.
## ed25519
Source: https://github.com/orlp/ed25519
Based on commit 7fa6712ef5d581a6981ec2b08ee623314cd1d1c4.
[LICENCE](ed25519/LICENSE)
The original source has not been modified, except that the file `test.c`
and the contained DLL files have been removed. To allow building within
libimobiledevice, a `Makefile.am` has been added.
## libsrp6a-sha512
Source: https://github.com/secure-remote-password/stanford-srp
Based on commit 587900d32777348f98477cb25123d5761fbe3725.
[LICENCE](libsrp6a-sha512/LICENSE)
For the usage within libimobiledevice, only [libsrp](https://github.com/secure-remote-password/stanford-srp/tree/master/libsrp)
has been used as a basis.
It has been adapted to the needs of the libimobiledevice project, and
contains just a part of the original code; it only supports the SRP6a
client method which has been modified to use SHA512 instead of SHA1,
hence the name was changed to `libsrp6a-sha512`.
More details about the modifications can be found in [libsrp6a-sha512/README.md](libsrp6a-sha512/README.md).

View File

@@ -0,0 +1,16 @@
Copyright (c) 2015 Orson Peters <orsonpeters@gmail.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:
1. 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 would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as
being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@@ -0,0 +1,26 @@
AUTOMAKE_OPTIONS = foreign no-dependencies
AM_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)
AM_CFLAGS = \
$(GLOBAL_CFLAGS) \
$(openssl_CFLAGS)
AM_LDFLAGS =
noinst_LTLIBRARIES = libed25519.la
libed25519_la_LIBADD =
libed25519_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined
libed25519_la_SOURCES = \
add_scalar.c \
fe.c \
ge.c \
keypair.c \
key_exchange.c \
sc.c \
seed.c \
sign.c \
sha512.c \
verify.c

View File

@@ -0,0 +1,165 @@
Ed25519
=======
This is a portable implementation of [Ed25519](http://ed25519.cr.yp.to/) based
on the SUPERCOP "ref10" implementation. Additionally there is key exchanging
and scalar addition included to further aid building a PKI using Ed25519. All
code is licensed under the permissive zlib license.
All code is pure ANSI C without any dependencies, except for the random seed
generation which uses standard OS cryptography APIs (`CryptGenRandom` on
Windows, `/dev/urandom` on nix). If you wish to be entirely portable define
`ED25519_NO_SEED`. This disables the `ed25519_create_seed` function, so if your
application requires key generation you must supply your own seeding function
(which is simply a 256 bit (32 byte) cryptographic random number generator).
Performance
-----------
On a Windows machine with an Intel Pentium B970 @ 2.3GHz I got the following
speeds (running on only one a single core):
Seed generation: 64us (15625 per second)
Key generation: 88us (11364 per second)
Message signing (short message): 87us (11494 per second)
Message verifying (short message): 228us (4386 per second)
Scalar addition: 100us (10000 per second)
Key exchange: 220us (4545 per second)
The speeds on other machines may vary. Sign/verify times will be higher with
longer messages. The implementation significantly benefits from 64 bit
architectures, if possible compile as 64 bit.
Usage
-----
Simply add all .c and .h files in the `src/` folder to your project and include
`ed25519.h` in any file you want to use the API. If you prefer to use a shared
library, only copy `ed25519.h` and define `ED25519_DLL` before importing.
There are no defined types for seeds, private keys, public keys, shared secrets
or signatures. Instead simple `unsigned char` buffers are used with the
following sizes:
```c
unsigned char seed[32];
unsigned char signature[64];
unsigned char public_key[32];
unsigned char private_key[64];
unsigned char scalar[32];
unsigned char shared_secret[32];
```
API
---
```c
int ed25519_create_seed(unsigned char *seed);
```
Creates a 32 byte random seed in `seed` for key generation. `seed` must be a
writable 32 byte buffer. Returns 0 on success, and nonzero on failure.
```c
void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key,
const unsigned char *seed);
```
Creates a new key pair from the given seed. `public_key` must be a writable 32
byte buffer, `private_key` must be a writable 64 byte buffer and `seed` must be
a 32 byte buffer.
```c
void ed25519_sign(unsigned char *signature,
const unsigned char *message, size_t message_len,
const unsigned char *public_key, const unsigned char *private_key);
```
Creates a signature of the given message with the given key pair. `signature`
must be a writable 64 byte buffer. `message` must have at least `message_len`
bytes to be read.
```c
int ed25519_verify(const unsigned char *signature,
const unsigned char *message, size_t message_len,
const unsigned char *public_key);
```
Verifies the signature on the given message using `public_key`. `signature`
must be a readable 64 byte buffer. `message` must have at least `message_len`
bytes to be read. Returns 1 if the signature matches, 0 otherwise.
```c
void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key,
const unsigned char *scalar);
```
Adds `scalar` to the given key pair where scalar is a 32 byte buffer (possibly
generated with `ed25519_create_seed`), generating a new key pair. You can
calculate the public key sum without knowing the private key and vice versa by
passing in `NULL` for the key you don't know. This is useful for enforcing
randomness on a key pair by a third party while only knowing the public key,
among other things. Warning: the last bit of the scalar is ignored - if
comparing scalars make sure to clear it with `scalar[31] &= 127`.
```c
void ed25519_key_exchange(unsigned char *shared_secret,
const unsigned char *public_key, const unsigned char *private_key);
```
Performs a key exchange on the given public key and private key, producing a
shared secret. It is recommended to hash the shared secret before using it.
`shared_secret` must be a 32 byte writable buffer where the shared secret will
be stored.
Example
-------
```c
unsigned char seed[32], public_key[32], private_key[64], signature[64];
unsigned char other_public_key[32], other_private_key[64], shared_secret[32];
const unsigned char message[] = "TEST MESSAGE";
/* create a random seed, and a key pair out of that seed */
if (ed25519_create_seed(seed)) {
printf("error while generating seed\n");
exit(1);
}
ed25519_create_keypair(public_key, private_key, seed);
/* create signature on the message with the key pair */
ed25519_sign(signature, message, strlen(message), public_key, private_key);
/* verify the signature */
if (ed25519_verify(signature, message, strlen(message), public_key)) {
printf("valid signature\n");
} else {
printf("invalid signature\n");
}
/* create a dummy keypair to use for a key exchange, normally you'd only have
the public key and receive it through some communication channel */
if (ed25519_create_seed(seed)) {
printf("error while generating seed\n");
exit(1);
}
ed25519_create_keypair(other_public_key, other_private_key, seed);
/* do a key exchange with other_public_key */
ed25519_key_exchange(shared_secret, other_public_key, private_key);
/*
the magic here is that ed25519_key_exchange(shared_secret, public_key,
other_private_key); would result in the same shared_secret
*/
```
License
-------
All code is released under the zlib license. See LICENSE for details.

View File

@@ -0,0 +1,69 @@
#include "ed25519.h"
#include "ge.h"
#include "sc.h"
#include "sha512.h"
/* see http://crypto.stackexchange.com/a/6215/4697 */
void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) {
const unsigned char SC_1[32] = {1}; /* scalar with value 1 */
unsigned char n[32];
ge_p3 nB;
ge_p1p1 A_p1p1;
ge_p3 A;
ge_p3 public_key_unpacked;
ge_cached T;
sha512_context hash;
unsigned char hashbuf[64];
int i;
/* copy the scalar and clear highest bit */
for (i = 0; i < 31; ++i) {
n[i] = scalar[i];
}
n[31] = scalar[31] & 127;
/* private key: a = n + t */
if (private_key) {
sc_muladd(private_key, SC_1, n, private_key);
// https://github.com/orlp/ed25519/issues/3
sha512_init(&hash);
sha512_update(&hash, private_key + 32, 32);
sha512_update(&hash, scalar, 32);
sha512_final(&hash, hashbuf);
for (i = 0; i < 32; ++i) {
private_key[32 + i] = hashbuf[i];
}
}
/* public key: A = nB + T */
if (public_key) {
/* if we know the private key we don't need a point addition, which is faster */
/* using a "timing attack" you could find out wether or not we know the private
key, but this information seems rather useless - if this is important pass
public_key and private_key seperately in 2 function calls */
if (private_key) {
ge_scalarmult_base(&A, private_key);
} else {
/* unpack public key into T */
ge_frombytes_negate_vartime(&public_key_unpacked, public_key);
fe_neg(public_key_unpacked.X, public_key_unpacked.X); /* undo negate */
fe_neg(public_key_unpacked.T, public_key_unpacked.T); /* undo negate */
ge_p3_to_cached(&T, &public_key_unpacked);
/* calculate n*B */
ge_scalarmult_base(&nB, n);
/* A = n*B + T */
ge_add(&A_p1p1, &nB, &T);
ge_p1p1_to_p3(&A, &A_p1p1);
}
/* pack public key */
ge_p3_tobytes(public_key, &A);
}
}

View File

@@ -0,0 +1,38 @@
#ifndef ED25519_H
#define ED25519_H
#include <stddef.h>
#if defined(_WIN32)
#if defined(ED25519_BUILD_DLL)
#define ED25519_DECLSPEC __declspec(dllexport)
#elif defined(ED25519_DLL)
#define ED25519_DECLSPEC __declspec(dllimport)
#else
#define ED25519_DECLSPEC
#endif
#else
#define ED25519_DECLSPEC
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ED25519_NO_SEED
int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed);
#endif
void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key);
void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
#ifndef FE_H
#define FE_H
#include "fixedint.h"
/*
fe means field element.
Here the field is \Z/(2^255-19).
An element t, entries t[0]...t[9], represents the integer
t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
Bounds on each t[i] vary depending on context.
*/
typedef int32_t fe[10];
void fe_0(fe h);
void fe_1(fe h);
void fe_frombytes(fe h, const unsigned char *s);
void fe_tobytes(unsigned char *s, const fe h);
void fe_copy(fe h, const fe f);
int fe_isnegative(const fe f);
int fe_isnonzero(const fe f);
void fe_cmov(fe f, const fe g, unsigned int b);
void fe_cswap(fe f, fe g, unsigned int b);
void fe_neg(fe h, const fe f);
void fe_add(fe h, const fe f, const fe g);
void fe_invert(fe out, const fe z);
void fe_sq(fe h, const fe f);
void fe_sq2(fe h, const fe f);
void fe_mul(fe h, const fe f, const fe g);
void fe_mul121666(fe h, fe f);
void fe_pow22523(fe out, const fe z);
void fe_sub(fe h, const fe f, const fe g);
#endif

View File

@@ -0,0 +1,72 @@
/*
Portable header to provide the 32 and 64 bits type.
Not a compatible replacement for <stdint.h>, do not blindly use it as such.
*/
#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED)
#include <stdint.h>
#define FIXEDINT_H_INCLUDED
#if defined(__WATCOMC__) && __WATCOMC__ >= 1250 && !defined(UINT64_C)
#include <limits.h>
#define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
#endif
#endif
#ifndef FIXEDINT_H_INCLUDED
#define FIXEDINT_H_INCLUDED
#include <limits.h>
/* (u)int32_t */
#ifndef uint32_t
#if (ULONG_MAX == 0xffffffffUL)
typedef unsigned long uint32_t;
#elif (UINT_MAX == 0xffffffffUL)
typedef unsigned int uint32_t;
#elif (USHRT_MAX == 0xffffffffUL)
typedef unsigned short uint32_t;
#endif
#endif
#ifndef int32_t
#if (LONG_MAX == 0x7fffffffL)
typedef signed long int32_t;
#elif (INT_MAX == 0x7fffffffL)
typedef signed int int32_t;
#elif (SHRT_MAX == 0x7fffffffL)
typedef signed short int32_t;
#endif
#endif
/* (u)int64_t */
#if (defined(__STDC__) && defined(__STDC_VERSION__) && __STDC__ && __STDC_VERSION__ >= 199901L)
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif defined(__GNUC__)
__extension__ typedef long long int64_t;
__extension__ typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC)
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC)
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define UINT64_C(v) v ##UI64
#define INT64_C(v) v ##I64
#endif
#endif

View File

@@ -0,0 +1,467 @@
#include "ge.h"
#include "precomp_data.h"
/*
r = p + q
*/
void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YplusX);
fe_mul(r->Y, r->Y, q->YminusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
}
static void slide(signed char *r, const unsigned char *a) {
int i;
int b;
int k;
for (i = 0; i < 256; ++i) {
r[i] = 1 & (a[i >> 3] >> (i & 7));
}
for (i = 0; i < 256; ++i)
if (r[i]) {
for (b = 1; b <= 6 && i + b < 256; ++b) {
if (r[i + b]) {
if (r[i] + (r[i + b] << b) <= 15) {
r[i] += r[i + b] << b;
r[i + b] = 0;
} else if (r[i] - (r[i + b] << b) >= -15) {
r[i] -= r[i + b] << b;
for (k = i + b; k < 256; ++k) {
if (!r[k]) {
r[k] = 1;
break;
}
r[k] = 0;
}
} else {
break;
}
}
}
}
}
/*
r = a * A + b * B
where a = a[0]+256*a[1]+...+256^31 a[31].
and b = b[0]+256*b[1]+...+256^31 b[31].
B is the Ed25519 base point (x,4/5) with x positive.
*/
void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) {
signed char aslide[256];
signed char bslide[256];
ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
ge_p1p1 t;
ge_p3 u;
ge_p3 A2;
int i;
slide(aslide, a);
slide(bslide, b);
ge_p3_to_cached(&Ai[0], A);
ge_p3_dbl(&t, A);
ge_p1p1_to_p3(&A2, &t);
ge_add(&t, &A2, &Ai[0]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[1], &u);
ge_add(&t, &A2, &Ai[1]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[2], &u);
ge_add(&t, &A2, &Ai[2]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[3], &u);
ge_add(&t, &A2, &Ai[3]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[4], &u);
ge_add(&t, &A2, &Ai[4]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[5], &u);
ge_add(&t, &A2, &Ai[5]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[6], &u);
ge_add(&t, &A2, &Ai[6]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[7], &u);
ge_p2_0(r);
for (i = 255; i >= 0; --i) {
if (aslide[i] || bslide[i]) {
break;
}
}
for (; i >= 0; --i) {
ge_p2_dbl(&t, r);
if (aslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_add(&t, &u, &Ai[aslide[i] / 2]);
} else if (aslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
}
if (bslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_madd(&t, &u, &Bi[bslide[i] / 2]);
} else if (bslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
}
ge_p1p1_to_p2(r, &t);
}
}
static const fe d = {
-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116
};
static const fe sqrtm1 = {
-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482
};
int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) {
fe u;
fe v;
fe v3;
fe vxx;
fe check;
fe_frombytes(h->Y, s);
fe_1(h->Z);
fe_sq(u, h->Y);
fe_mul(v, u, d);
fe_sub(u, u, h->Z); /* u = y^2-1 */
fe_add(v, v, h->Z); /* v = dy^2+1 */
fe_sq(v3, v);
fe_mul(v3, v3, v); /* v3 = v^3 */
fe_sq(h->X, v3);
fe_mul(h->X, h->X, v);
fe_mul(h->X, h->X, u); /* x = uv^7 */
fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
fe_mul(h->X, h->X, v3);
fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
fe_sq(vxx, h->X);
fe_mul(vxx, vxx, v);
fe_sub(check, vxx, u); /* vx^2-u */
if (fe_isnonzero(check)) {
fe_add(check, vxx, u); /* vx^2+u */
if (fe_isnonzero(check)) {
return -1;
}
fe_mul(h->X, h->X, sqrtm1);
}
if (fe_isnegative(h->X) == (s[31] >> 7)) {
fe_neg(h->X, h->X);
}
fe_mul(h->T, h->X, h->Y);
return 0;
}
/*
r = p + q
*/
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yplusx);
fe_mul(r->Y, r->Y, q->yminusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
}
/*
r = p - q
*/
void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yminusx);
fe_mul(r->Y, r->Y, q->yplusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
}
/*
r = p
*/
void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
}
/*
r = p
*/
void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
fe_mul(r->T, p->X, p->Y);
}
void ge_p2_0(ge_p2 *h) {
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
}
/*
r = 2 * p
*/
void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
fe t0;
fe_sq(r->X, p->X);
fe_sq(r->Z, p->Y);
fe_sq2(r->T, p->Z);
fe_add(r->Y, p->X, p->Y);
fe_sq(t0, r->Y);
fe_add(r->Y, r->Z, r->X);
fe_sub(r->Z, r->Z, r->X);
fe_sub(r->X, t0, r->Y);
fe_sub(r->T, r->T, r->Z);
}
void ge_p3_0(ge_p3 *h) {
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
fe_0(h->T);
}
/*
r = 2 * p
*/
void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) {
ge_p2 q;
ge_p3_to_p2(&q, p);
ge_p2_dbl(r, &q);
}
/*
r = p
*/
static const fe d2 = {
-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199
};
void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
fe_add(r->YplusX, p->Y, p->X);
fe_sub(r->YminusX, p->Y, p->X);
fe_copy(r->Z, p->Z);
fe_mul(r->T2d, p->T, d2);
}
/*
r = p
*/
void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) {
fe_copy(r->X, p->X);
fe_copy(r->Y, p->Y);
fe_copy(r->Z, p->Z);
}
void ge_p3_tobytes(unsigned char *s, const ge_p3 *h) {
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
}
static unsigned char equal(signed char b, signed char c) {
unsigned char ub = b;
unsigned char uc = c;
unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
uint64_t y = x; /* 0: yes; 1..255: no */
y -= 1; /* large: yes; 0..254: no */
y >>= 63; /* 1: yes; 0: no */
return (unsigned char) y;
}
static unsigned char negative(signed char b) {
uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
x >>= 63; /* 1: yes; 0: no */
return (unsigned char) x;
}
static void cmov(ge_precomp *t, const ge_precomp *u, unsigned char b) {
fe_cmov(t->yplusx, u->yplusx, b);
fe_cmov(t->yminusx, u->yminusx, b);
fe_cmov(t->xy2d, u->xy2d, b);
}
static void select(ge_precomp *t, int pos, signed char b) {
ge_precomp minust;
unsigned char bnegative = negative(b);
unsigned char babs = b - (((-bnegative) & b) << 1);
fe_1(t->yplusx);
fe_1(t->yminusx);
fe_0(t->xy2d);
cmov(t, &base[pos][0], equal(babs, 1));
cmov(t, &base[pos][1], equal(babs, 2));
cmov(t, &base[pos][2], equal(babs, 3));
cmov(t, &base[pos][3], equal(babs, 4));
cmov(t, &base[pos][4], equal(babs, 5));
cmov(t, &base[pos][5], equal(babs, 6));
cmov(t, &base[pos][6], equal(babs, 7));
cmov(t, &base[pos][7], equal(babs, 8));
fe_copy(minust.yplusx, t->yminusx);
fe_copy(minust.yminusx, t->yplusx);
fe_neg(minust.xy2d, t->xy2d);
cmov(t, &minust, bnegative);
}
/*
h = a * B
where a = a[0]+256*a[1]+...+256^31 a[31]
B is the Ed25519 base point (x,4/5) with x positive.
Preconditions:
a[31] <= 127
*/
void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) {
signed char e[64];
signed char carry;
ge_p1p1 r;
ge_p2 s;
ge_precomp t;
int i;
for (i = 0; i < 32; ++i) {
e[2 * i + 0] = (a[i] >> 0) & 15;
e[2 * i + 1] = (a[i] >> 4) & 15;
}
/* each e[i] is between 0 and 15 */
/* e[63] is between 0 and 7 */
carry = 0;
for (i = 0; i < 63; ++i) {
e[i] += carry;
carry = e[i] + 8;
carry >>= 4;
e[i] -= carry << 4;
}
e[63] += carry;
/* each e[i] is between -8 and 8 */
ge_p3_0(h);
for (i = 1; i < 64; i += 2) {
select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
ge_p3_dbl(&r, h);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p3(h, &r);
for (i = 0; i < 64; i += 2) {
select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
}
/*
r = p - q
*/
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YminusX);
fe_mul(r->Y, r->Y, q->YplusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
}
void ge_tobytes(unsigned char *s, const ge_p2 *h) {
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
}

View File

@@ -0,0 +1,74 @@
#ifndef GE_H
#define GE_H
#include "fe.h"
/*
ge means group element.
Here the group is the set of pairs (x,y) of field elements (see fe.h)
satisfying -x^2 + y^2 = 1 + d x^2y^2
where d = -121665/121666.
Representations:
ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
ge_precomp (Duif): (y+x,y-x,2dxy)
*/
typedef struct {
fe X;
fe Y;
fe Z;
} ge_p2;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p3;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p1p1;
typedef struct {
fe yplusx;
fe yminusx;
fe xy2d;
} ge_precomp;
typedef struct {
fe YplusX;
fe YminusX;
fe Z;
fe T2d;
} ge_cached;
void ge_p3_tobytes(unsigned char *s, const ge_p3 *h);
void ge_tobytes(unsigned char *s, const ge_p2 *h);
int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s);
void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b);
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
void ge_scalarmult_base(ge_p3 *h, const unsigned char *a);
void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p);
void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p);
void ge_p2_0(ge_p2 *h);
void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p);
void ge_p3_0(ge_p3 *h);
void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p);
void ge_p3_to_cached(ge_cached *r, const ge_p3 *p);
void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p);
#endif

View File

@@ -0,0 +1,79 @@
#include "ed25519.h"
#include "fe.h"
void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) {
unsigned char e[32];
unsigned int i;
fe x1;
fe x2;
fe z2;
fe x3;
fe z3;
fe tmp0;
fe tmp1;
int pos;
unsigned int swap;
unsigned int b;
/* copy the private key and make sure it's valid */
for (i = 0; i < 32; ++i) {
e[i] = private_key[i];
}
e[0] &= 248;
e[31] &= 63;
e[31] |= 64;
/* unpack the public key and convert edwards to montgomery */
/* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */
fe_frombytes(x1, public_key);
fe_1(tmp1);
fe_add(tmp0, x1, tmp1);
fe_sub(tmp1, tmp1, x1);
fe_invert(tmp1, tmp1);
fe_mul(x1, tmp0, tmp1);
fe_1(x2);
fe_0(z2);
fe_copy(x3, x1);
fe_1(z3);
swap = 0;
for (pos = 254; pos >= 0; --pos) {
b = e[pos / 8] >> (pos & 7);
b &= 1;
swap ^= b;
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
swap = b;
/* from montgomery.h */
fe_sub(tmp0, x3, z3);
fe_sub(tmp1, x2, z2);
fe_add(x2, x2, z2);
fe_add(z2, x3, z3);
fe_mul(z3, tmp0, x2);
fe_mul(z2, z2, tmp1);
fe_sq(tmp0, tmp1);
fe_sq(tmp1, x2);
fe_add(x3, z3, z2);
fe_sub(z2, z3, z2);
fe_mul(x2, tmp1, tmp0);
fe_sub(tmp1, tmp1, tmp0);
fe_sq(z2, z2);
fe_mul121666(z3, tmp1);
fe_sq(x3, x3);
fe_add(tmp0, tmp0, z3);
fe_mul(z3, x1, z2);
fe_mul(z2, tmp1, tmp0);
}
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
fe_invert(z2, z2);
fe_mul(x2, x2, z2);
fe_tobytes(shared_secret, x2);
}

View File

@@ -0,0 +1,16 @@
#include "ed25519.h"
#include "sha512.h"
#include "ge.h"
void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) {
ge_p3 A;
sha512(seed, 32, private_key);
private_key[0] &= 248;
private_key[31] &= 63;
private_key[31] |= 64;
ge_scalarmult_base(&A, private_key);
ge_p3_tobytes(public_key, &A);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,809 @@
#include "fixedint.h"
#include "sc.h"
static uint64_t load_3(const unsigned char *in) {
uint64_t result;
result = (uint64_t) in[0];
result |= ((uint64_t) in[1]) << 8;
result |= ((uint64_t) in[2]) << 16;
return result;
}
static uint64_t load_4(const unsigned char *in) {
uint64_t result;
result = (uint64_t) in[0];
result |= ((uint64_t) in[1]) << 8;
result |= ((uint64_t) in[2]) << 16;
result |= ((uint64_t) in[3]) << 24;
return result;
}
/*
Input:
s[0]+256*s[1]+...+256^63*s[63] = s
Output:
s[0]+256*s[1]+...+256^31*s[31] = s mod l
where l = 2^252 + 27742317777372353535851937790883648493.
Overwrites s in place.
*/
void sc_reduce(unsigned char *s) {
int64_t s0 = 2097151 & load_3(s);
int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
int64_t s3 = 2097151 & (load_4(s + 7) >> 7);
int64_t s4 = 2097151 & (load_4(s + 10) >> 4);
int64_t s5 = 2097151 & (load_3(s + 13) >> 1);
int64_t s6 = 2097151 & (load_4(s + 15) >> 6);
int64_t s7 = 2097151 & (load_3(s + 18) >> 3);
int64_t s8 = 2097151 & load_3(s + 21);
int64_t s9 = 2097151 & (load_4(s + 23) >> 5);
int64_t s10 = 2097151 & (load_3(s + 26) >> 2);
int64_t s11 = 2097151 & (load_4(s + 28) >> 7);
int64_t s12 = 2097151 & (load_4(s + 31) >> 4);
int64_t s13 = 2097151 & (load_3(s + 34) >> 1);
int64_t s14 = 2097151 & (load_4(s + 36) >> 6);
int64_t s15 = 2097151 & (load_3(s + 39) >> 3);
int64_t s16 = 2097151 & load_3(s + 42);
int64_t s17 = 2097151 & (load_4(s + 44) >> 5);
int64_t s18 = 2097151 & (load_3(s + 47) >> 2);
int64_t s19 = 2097151 & (load_4(s + 49) >> 7);
int64_t s20 = 2097151 & (load_4(s + 52) >> 4);
int64_t s21 = 2097151 & (load_3(s + 55) >> 1);
int64_t s22 = 2097151 & (load_4(s + 57) >> 6);
int64_t s23 = (load_4(s + 60) >> 3);
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
int64_t carry10;
int64_t carry11;
int64_t carry12;
int64_t carry13;
int64_t carry14;
int64_t carry15;
int64_t carry16;
s11 += s23 * 666643;
s12 += s23 * 470296;
s13 += s23 * 654183;
s14 -= s23 * 997805;
s15 += s23 * 136657;
s16 -= s23 * 683901;
s23 = 0;
s10 += s22 * 666643;
s11 += s22 * 470296;
s12 += s22 * 654183;
s13 -= s22 * 997805;
s14 += s22 * 136657;
s15 -= s22 * 683901;
s22 = 0;
s9 += s21 * 666643;
s10 += s21 * 470296;
s11 += s21 * 654183;
s12 -= s21 * 997805;
s13 += s21 * 136657;
s14 -= s21 * 683901;
s21 = 0;
s8 += s20 * 666643;
s9 += s20 * 470296;
s10 += s20 * 654183;
s11 -= s20 * 997805;
s12 += s20 * 136657;
s13 -= s20 * 683901;
s20 = 0;
s7 += s19 * 666643;
s8 += s19 * 470296;
s9 += s19 * 654183;
s10 -= s19 * 997805;
s11 += s19 * 136657;
s12 -= s19 * 683901;
s19 = 0;
s6 += s18 * 666643;
s7 += s18 * 470296;
s8 += s18 * 654183;
s9 -= s18 * 997805;
s10 += s18 * 136657;
s11 -= s18 * 683901;
s18 = 0;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 << 21;
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 << 21;
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 << 21;
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 << 21;
s5 += s17 * 666643;
s6 += s17 * 470296;
s7 += s17 * 654183;
s8 -= s17 * 997805;
s9 += s17 * 136657;
s10 -= s17 * 683901;
s17 = 0;
s4 += s16 * 666643;
s5 += s16 * 470296;
s6 += s16 * 654183;
s7 -= s16 * 997805;
s8 += s16 * 136657;
s9 -= s16 * 683901;
s16 = 0;
s3 += s15 * 666643;
s4 += s15 * 470296;
s5 += s15 * 654183;
s6 -= s15 * 997805;
s7 += s15 * 136657;
s8 -= s15 * 683901;
s15 = 0;
s2 += s14 * 666643;
s3 += s14 * 470296;
s4 += s14 * 654183;
s5 -= s14 * 997805;
s6 += s14 * 136657;
s7 -= s14 * 683901;
s14 = 0;
s1 += s13 * 666643;
s2 += s13 * 470296;
s3 += s13 * 654183;
s4 -= s13 * 997805;
s5 += s13 * 136657;
s6 -= s13 * 683901;
s13 = 0;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry11 = s11 >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
s[0] = (unsigned char) (s0 >> 0);
s[1] = (unsigned char) (s0 >> 8);
s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5));
s[3] = (unsigned char) (s1 >> 3);
s[4] = (unsigned char) (s1 >> 11);
s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2));
s[6] = (unsigned char) (s2 >> 6);
s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7));
s[8] = (unsigned char) (s3 >> 1);
s[9] = (unsigned char) (s3 >> 9);
s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4));
s[11] = (unsigned char) (s4 >> 4);
s[12] = (unsigned char) (s4 >> 12);
s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1));
s[14] = (unsigned char) (s5 >> 7);
s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6));
s[16] = (unsigned char) (s6 >> 2);
s[17] = (unsigned char) (s6 >> 10);
s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3));
s[19] = (unsigned char) (s7 >> 5);
s[20] = (unsigned char) (s7 >> 13);
s[21] = (unsigned char) (s8 >> 0);
s[22] = (unsigned char) (s8 >> 8);
s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5));
s[24] = (unsigned char) (s9 >> 3);
s[25] = (unsigned char) (s9 >> 11);
s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2));
s[27] = (unsigned char) (s10 >> 6);
s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7));
s[29] = (unsigned char) (s11 >> 1);
s[30] = (unsigned char) (s11 >> 9);
s[31] = (unsigned char) (s11 >> 17);
}
/*
Input:
a[0]+256*a[1]+...+256^31*a[31] = a
b[0]+256*b[1]+...+256^31*b[31] = b
c[0]+256*c[1]+...+256^31*c[31] = c
Output:
s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
where l = 2^252 + 27742317777372353535851937790883648493.
*/
void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) {
int64_t a0 = 2097151 & load_3(a);
int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
int64_t a8 = 2097151 & load_3(a + 21);
int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
int64_t a11 = (load_4(a + 28) >> 7);
int64_t b0 = 2097151 & load_3(b);
int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
int64_t b8 = 2097151 & load_3(b + 21);
int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
int64_t b11 = (load_4(b + 28) >> 7);
int64_t c0 = 2097151 & load_3(c);
int64_t c1 = 2097151 & (load_4(c + 2) >> 5);
int64_t c2 = 2097151 & (load_3(c + 5) >> 2);
int64_t c3 = 2097151 & (load_4(c + 7) >> 7);
int64_t c4 = 2097151 & (load_4(c + 10) >> 4);
int64_t c5 = 2097151 & (load_3(c + 13) >> 1);
int64_t c6 = 2097151 & (load_4(c + 15) >> 6);
int64_t c7 = 2097151 & (load_3(c + 18) >> 3);
int64_t c8 = 2097151 & load_3(c + 21);
int64_t c9 = 2097151 & (load_4(c + 23) >> 5);
int64_t c10 = 2097151 & (load_3(c + 26) >> 2);
int64_t c11 = (load_4(c + 28) >> 7);
int64_t s0;
int64_t s1;
int64_t s2;
int64_t s3;
int64_t s4;
int64_t s5;
int64_t s6;
int64_t s7;
int64_t s8;
int64_t s9;
int64_t s10;
int64_t s11;
int64_t s12;
int64_t s13;
int64_t s14;
int64_t s15;
int64_t s16;
int64_t s17;
int64_t s18;
int64_t s19;
int64_t s20;
int64_t s21;
int64_t s22;
int64_t s23;
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
int64_t carry10;
int64_t carry11;
int64_t carry12;
int64_t carry13;
int64_t carry14;
int64_t carry15;
int64_t carry16;
int64_t carry17;
int64_t carry18;
int64_t carry19;
int64_t carry20;
int64_t carry21;
int64_t carry22;
s0 = c0 + a0 * b0;
s1 = c1 + a0 * b1 + a1 * b0;
s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0;
s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0;
s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3;
s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4;
s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
s20 = a9 * b11 + a10 * b10 + a11 * b9;
s21 = a10 * b11 + a11 * b10;
s22 = a11 * b11;
s23 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 << 21;
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 << 21;
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 << 21;
carry18 = (s18 + (1 << 20)) >> 21;
s19 += carry18;
s18 -= carry18 << 21;
carry20 = (s20 + (1 << 20)) >> 21;
s21 += carry20;
s20 -= carry20 << 21;
carry22 = (s22 + (1 << 20)) >> 21;
s23 += carry22;
s22 -= carry22 << 21;
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 << 21;
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 << 21;
carry17 = (s17 + (1 << 20)) >> 21;
s18 += carry17;
s17 -= carry17 << 21;
carry19 = (s19 + (1 << 20)) >> 21;
s20 += carry19;
s19 -= carry19 << 21;
carry21 = (s21 + (1 << 20)) >> 21;
s22 += carry21;
s21 -= carry21 << 21;
s11 += s23 * 666643;
s12 += s23 * 470296;
s13 += s23 * 654183;
s14 -= s23 * 997805;
s15 += s23 * 136657;
s16 -= s23 * 683901;
s23 = 0;
s10 += s22 * 666643;
s11 += s22 * 470296;
s12 += s22 * 654183;
s13 -= s22 * 997805;
s14 += s22 * 136657;
s15 -= s22 * 683901;
s22 = 0;
s9 += s21 * 666643;
s10 += s21 * 470296;
s11 += s21 * 654183;
s12 -= s21 * 997805;
s13 += s21 * 136657;
s14 -= s21 * 683901;
s21 = 0;
s8 += s20 * 666643;
s9 += s20 * 470296;
s10 += s20 * 654183;
s11 -= s20 * 997805;
s12 += s20 * 136657;
s13 -= s20 * 683901;
s20 = 0;
s7 += s19 * 666643;
s8 += s19 * 470296;
s9 += s19 * 654183;
s10 -= s19 * 997805;
s11 += s19 * 136657;
s12 -= s19 * 683901;
s19 = 0;
s6 += s18 * 666643;
s7 += s18 * 470296;
s8 += s18 * 654183;
s9 -= s18 * 997805;
s10 += s18 * 136657;
s11 -= s18 * 683901;
s18 = 0;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 << 21;
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 << 21;
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 << 21;
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 << 21;
s5 += s17 * 666643;
s6 += s17 * 470296;
s7 += s17 * 654183;
s8 -= s17 * 997805;
s9 += s17 * 136657;
s10 -= s17 * 683901;
s17 = 0;
s4 += s16 * 666643;
s5 += s16 * 470296;
s6 += s16 * 654183;
s7 -= s16 * 997805;
s8 += s16 * 136657;
s9 -= s16 * 683901;
s16 = 0;
s3 += s15 * 666643;
s4 += s15 * 470296;
s5 += s15 * 654183;
s6 -= s15 * 997805;
s7 += s15 * 136657;
s8 -= s15 * 683901;
s15 = 0;
s2 += s14 * 666643;
s3 += s14 * 470296;
s4 += s14 * 654183;
s5 -= s14 * 997805;
s6 += s14 * 136657;
s7 -= s14 * 683901;
s14 = 0;
s1 += s13 * 666643;
s2 += s13 * 470296;
s3 += s13 * 654183;
s4 -= s13 * 997805;
s5 += s13 * 136657;
s6 -= s13 * 683901;
s13 = 0;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry11 = s11 >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
s[0] = (unsigned char) (s0 >> 0);
s[1] = (unsigned char) (s0 >> 8);
s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5));
s[3] = (unsigned char) (s1 >> 3);
s[4] = (unsigned char) (s1 >> 11);
s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2));
s[6] = (unsigned char) (s2 >> 6);
s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7));
s[8] = (unsigned char) (s3 >> 1);
s[9] = (unsigned char) (s3 >> 9);
s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4));
s[11] = (unsigned char) (s4 >> 4);
s[12] = (unsigned char) (s4 >> 12);
s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1));
s[14] = (unsigned char) (s5 >> 7);
s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6));
s[16] = (unsigned char) (s6 >> 2);
s[17] = (unsigned char) (s6 >> 10);
s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3));
s[19] = (unsigned char) (s7 >> 5);
s[20] = (unsigned char) (s7 >> 13);
s[21] = (unsigned char) (s8 >> 0);
s[22] = (unsigned char) (s8 >> 8);
s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5));
s[24] = (unsigned char) (s9 >> 3);
s[25] = (unsigned char) (s9 >> 11);
s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2));
s[27] = (unsigned char) (s10 >> 6);
s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7));
s[29] = (unsigned char) (s11 >> 1);
s[30] = (unsigned char) (s11 >> 9);
s[31] = (unsigned char) (s11 >> 17);
}

View File

@@ -0,0 +1,12 @@
#ifndef SC_H
#define SC_H
/*
The set of scalars is \Z/l
where l = 2^252 + 27742317777372353535851937790883648493.
*/
void sc_reduce(unsigned char *s);
void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c);
#endif

View File

@@ -0,0 +1,40 @@
#include "ed25519.h"
#ifndef ED25519_NO_SEED
#ifdef _WIN32
#include <windows.h>
#include <wincrypt.h>
#else
#include <stdio.h>
#endif
int ed25519_create_seed(unsigned char *seed) {
#ifdef _WIN32
HCRYPTPROV prov;
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
return 1;
}
if (!CryptGenRandom(prov, 32, seed)) {
CryptReleaseContext(prov, 0);
return 1;
}
CryptReleaseContext(prov, 0);
#else
FILE *f = fopen("/dev/urandom", "rb");
if (f == NULL) {
return 1;
}
fread(seed, 1, 32, f);
fclose(f);
#endif
return 0;
}
#endif

View File

@@ -0,0 +1,275 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "fixedint.h"
#include "sha512.h"
/* the K array */
static const uint64_t K[80] = {
UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd),
UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc),
UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019),
UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118),
UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe),
UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2),
UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1),
UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694),
UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3),
UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65),
UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483),
UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5),
UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210),
UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4),
UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725),
UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70),
UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926),
UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df),
UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8),
UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b),
UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001),
UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30),
UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910),
UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8),
UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53),
UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8),
UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb),
UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3),
UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60),
UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec),
UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9),
UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b),
UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207),
UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178),
UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6),
UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b),
UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493),
UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c),
UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a),
UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817)
};
/* Various logical functions */
#define ROR64c(x, y) \
( ((((x)&UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)(y)&UINT64_C(63))) | \
((x)<<((uint64_t)(64-((y)&UINT64_C(63)))))) & UINT64_C(0xFFFFFFFFFFFFFFFF))
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \
(((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \
(((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \
(((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); }
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
#define Maj(x,y,z) (((x | y) & z) | (x & y))
#define S(x, n) ROR64c(x, n)
#define R(x, n) (((x) &UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)n))
#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
#ifndef MIN
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
#endif
/* compress 1024-bits */
static int sha512_compress(sha512_context *md, unsigned char *buf)
{
uint64_t S[8], W[80], t0, t1;
int i;
/* copy state into S */
for (i = 0; i < 8; i++) {
S[i] = md->state[i];
}
/* copy the state into 1024-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD64H(W[i], buf + (8*i));
}
/* fill W[16..79] */
for (i = 16; i < 80; i++) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
}
/* Compress */
#define RND(a,b,c,d,e,f,g,h,i) \
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c);\
d += t0; \
h = t0 + t1;
for (i = 0; i < 80; i += 8) {
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
}
#undef RND
/* feedback */
for (i = 0; i < 8; i++) {
md->state[i] = md->state[i] + S[i];
}
return 0;
}
/**
Initialize the hash state
@param md The hash state you wish to initialize
@return 0 if successful
*/
int sha512_init(sha512_context * md) {
if (md == NULL) return 1;
md->curlen = 0;
md->length = 0;
md->state[0] = UINT64_C(0x6a09e667f3bcc908);
md->state[1] = UINT64_C(0xbb67ae8584caa73b);
md->state[2] = UINT64_C(0x3c6ef372fe94f82b);
md->state[3] = UINT64_C(0xa54ff53a5f1d36f1);
md->state[4] = UINT64_C(0x510e527fade682d1);
md->state[5] = UINT64_C(0x9b05688c2b3e6c1f);
md->state[6] = UINT64_C(0x1f83d9abfb41bd6b);
md->state[7] = UINT64_C(0x5be0cd19137e2179);
return 0;
}
/**
Process a block of memory though the hash
@param md The hash state
@param in The data to hash
@param inlen The length of the data (octets)
@return 0 if successful
*/
int sha512_update (sha512_context * md, const unsigned char *in, size_t inlen)
{
size_t n;
size_t i;
int err;
if (md == NULL) return 1;
if (in == NULL) return 1;
if (md->curlen > sizeof(md->buf)) {
return 1;
}
while (inlen > 0) {
if (md->curlen == 0 && inlen >= 128) {
if ((err = sha512_compress (md, (unsigned char *)in)) != 0) {
return err;
}
md->length += 128 * 8;
in += 128;
inlen -= 128;
} else {
n = MIN(inlen, (128 - md->curlen));
for (i = 0; i < n; i++) {
md->buf[i + md->curlen] = in[i];
}
md->curlen += n;
in += n;
inlen -= n;
if (md->curlen == 128) {
if ((err = sha512_compress (md, md->buf)) != 0) {
return err;
}
md->length += 8*128;
md->curlen = 0;
}
}
}
return 0;
}
/**
Terminate the hash to get the digest
@param md The hash state
@param out [out] The destination of the hash (64 bytes)
@return 0 if successful
*/
int sha512_final(sha512_context * md, unsigned char *out)
{
int i;
if (md == NULL) return 1;
if (out == NULL) return 1;
if (md->curlen >= sizeof(md->buf)) {
return 1;
}
/* increase the length of the message */
md->length += md->curlen * UINT64_C(8);
/* append the '1' bit */
md->buf[md->curlen++] = (unsigned char)0x80;
/* if the length is currently above 112 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->curlen > 112) {
while (md->curlen < 128) {
md->buf[md->curlen++] = (unsigned char)0;
}
sha512_compress(md, md->buf);
md->curlen = 0;
}
/* pad upto 120 bytes of zeroes
* note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash
* > 2^64 bits of data... :-)
*/
while (md->curlen < 120) {
md->buf[md->curlen++] = (unsigned char)0;
}
/* store length */
STORE64H(md->length, md->buf+120);
sha512_compress(md, md->buf);
/* copy output */
for (i = 0; i < 8; i++) {
STORE64H(md->state[i], out+(8*i));
}
return 0;
}
int sha512(const unsigned char *message, size_t message_len, unsigned char *out)
{
sha512_context ctx;
int ret;
if ((ret = sha512_init(&ctx))) return ret;
if ((ret = sha512_update(&ctx, message, message_len))) return ret;
if ((ret = sha512_final(&ctx, out))) return ret;
return 0;
}

View File

@@ -0,0 +1,21 @@
#ifndef SHA512_H
#define SHA512_H
#include <stddef.h>
#include "fixedint.h"
/* state */
typedef struct sha512_context_ {
uint64_t length, state[8];
size_t curlen;
unsigned char buf[128];
} sha512_context;
int sha512_init(sha512_context * md);
int sha512_final(sha512_context * md, unsigned char *out);
int sha512_update(sha512_context * md, const unsigned char *in, size_t inlen);
int sha512(const unsigned char *message, size_t message_len, unsigned char *out);
#endif

View File

@@ -0,0 +1,31 @@
#include "ed25519.h"
#include "sha512.h"
#include "ge.h"
#include "sc.h"
void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) {
sha512_context hash;
unsigned char hram[64];
unsigned char r[64];
ge_p3 R;
sha512_init(&hash);
sha512_update(&hash, private_key + 32, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, r);
sc_reduce(r);
ge_scalarmult_base(&R, r);
ge_p3_tobytes(signature, &R);
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, public_key, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, hram);
sc_reduce(hram);
sc_muladd(signature + 32, hram, private_key, r);
}

View File

@@ -0,0 +1,77 @@
#include "ed25519.h"
#include "sha512.h"
#include "ge.h"
#include "sc.h"
static int consttime_equal(const unsigned char *x, const unsigned char *y) {
unsigned char r = 0;
r = x[0] ^ y[0];
#define F(i) r |= x[i] ^ y[i]
F(1);
F(2);
F(3);
F(4);
F(5);
F(6);
F(7);
F(8);
F(9);
F(10);
F(11);
F(12);
F(13);
F(14);
F(15);
F(16);
F(17);
F(18);
F(19);
F(20);
F(21);
F(22);
F(23);
F(24);
F(25);
F(26);
F(27);
F(28);
F(29);
F(30);
F(31);
#undef F
return !r;
}
int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) {
unsigned char h[64];
unsigned char checker[32];
sha512_context hash;
ge_p3 A;
ge_p2 R;
if (signature[63] & 224) {
return 0;
}
if (ge_frombytes_negate_vartime(&A, public_key) != 0) {
return 0;
}
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, public_key, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, h);
sc_reduce(h);
ge_double_scalarmult_vartime(&R, h, &A, signature + 32);
ge_tobytes(checker, &R);
if (!consttime_equal(checker, signature)) {
return 0;
}
return 1;
}

View File

@@ -0,0 +1,62 @@
Licensing
---------
SRP is royalty-free worldwide for commercial and non-commercial use.
The SRP library has been carefully written not to depend on any
encumbered algorithms, and it is distributed under a standard
BSD-style Open Source license which is shown below. This license
covers implementations based on the SRP library as well as
independent implementations based on RFC 2945.
The SRP distribution itself contains algorithms and code from
various freeware packages; these parts fall under both the SRP
Open Source license and the packages' own licenses. Care has
been taken to ensure that these licenses are compatible with
Open Source distribution, but it is the responsibility of the
licensee to comply with the terms of these licenses. This
disclaimer also applies to third-party libraries that may be
linked into the distribution, since they may contain patented
intellectual property. The file "Copyrights" contains a list
of the copyrights incorporated by portions of the software.
Broader use of the SRP authentication technology, such as variants
incorporating the use of an explicit server secret (SRP-Z), may
require a license; please contact the Stanford Office of Technology
Licensing (http://otl.stanford.edu/) for more information about
terms and conditions.
This software is covered under the following copyright:
/*
* Copyright (c) 1997-2007 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Redistributions in source or binary form must retain an intact copy
* of this copyright notice.
*/
Address all questions regarding this license to:
Tom Wu
tjw@cs.Stanford.EDU

View File

@@ -0,0 +1,31 @@
AUTOMAKE_OPTIONS = foreign no-dependencies
AM_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir) \
-Wno-incompatible-pointer-types
include_HEADERS = srp.h srp_aux.h cstr.h
AM_CFLAGS = -DHAVE_CONFIG_H
if HAVE_OPENSSL
AM_CFLAGS += -DOPENSSL=1 $(openssl_CFLAGS)
else
if HAVE_GCRYPT
AM_CFLAGS += -DGCRYPT=1 $(libgcrypt_CFLAGS)
else
if HAVE_MBEDTLS
AM_CFLAGS += -DMBEDTLS=1 $(mbedtls_CFLAGS)
endif
endif
endif
noinst_LTLIBRARIES = libsrp6a-sha512.la
libsrp6a_sha512_la_SOURCES = \
t_conv.c t_math.c t_misc.c \
t_truerand.c cstr.c \
srp.c srp6a_sha512_client.c
if !HAVE_OPENSSL
libsrp6a_sha512_la_SOURCES += t_sha.c
endif

View File

@@ -0,0 +1,35 @@
# SRP6a-sha512 library
## About
This library is based on Stanford's Secure Remote Password (SRP) protocol
implementation, or more precise on the `libsrp` part thereof.
The entire source code for the SRP project can be obtained from [here](https://github.com/secure-remote-password/stanford-srp).
It has been adapted to the needs of the libimobiledevice project, and
contains just a part of the original code; it only supports the SRP6a
client method which has been modified to use SHA512 instead of SHA1.
The only supported SRP method is `SRP6a_sha512_client_method()`.
Besides that, support for MbedTLS has been added.
Also, all server-side code has been removed, and the client-side code
has been reduced to a minimum, so that basically only the following
functions remain operational:
- `SRP_initialize_library`
- `SRP_new`
- `SRP_free`
- `SRP_set_user_raw`
- `SRP_set_params`
- `SRP_set_auth_password`
- `SRP_gen_pub`
- `SRP_compute_key`
- `SRP_respond`
- `SRP_verify`
Anything else has not been tested and must be considered non-functional.
## License
The license of the original work does still apply and can be found in the
LICENSE file that comes with the code.

View File

@@ -0,0 +1,226 @@
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "cstr.h"
#define EXPFACTOR 2 /* Minimum expansion factor */
#define MINSIZE 4 /* Absolute minimum - one word */
static char cstr_empty_string[] = { '\0' };
static cstr_allocator * default_alloc = NULL;
/*
* It is assumed, for efficiency, that it is okay to pass more arguments
* to a function than are called for, as long as the required arguments
* are in proper form. If extra arguments to malloc() and free() cause
* problems, define PEDANTIC_ARGS below.
*/
#ifdef PEDANTIC_ARGS
static void * Cmalloc(int n, void * heap) { return malloc(n); }
static void Cfree(void * p, void * heap) { free(p); }
static cstr_allocator malloc_allocator = { Cmalloc, Cfree, NULL };
#else
static cstr_allocator malloc_allocator = { malloc, free, NULL };
#endif
_TYPE( void )
cstr_set_allocator(cstr_allocator * alloc)
{
default_alloc = alloc;
}
_TYPE( cstr * )
cstr_new_alloc(cstr_allocator * alloc)
{
cstr * str;
if(alloc == NULL) {
if(default_alloc == NULL) {
default_alloc = &malloc_allocator;
}
alloc = default_alloc;
}
str = (cstr *) (*alloc->alloc)(sizeof(cstr), alloc->heap);
if(str) {
str->data = cstr_empty_string;
str->length = str->cap = 0;
str->ref = 1;
str->allocator = alloc;
}
return str;
}
_TYPE( cstr * )
cstr_new()
{
return cstr_new_alloc(NULL);
}
_TYPE( cstr * )
cstr_dup_alloc(const cstr * str, cstr_allocator * alloc)
{
cstr * nstr = cstr_new_alloc(alloc);
if(nstr)
cstr_setn(nstr, str->data, str->length);
return nstr;
}
_TYPE( cstr * )
cstr_dup(const cstr * str)
{
return cstr_dup_alloc(str, NULL);
}
_TYPE( cstr * )
cstr_create(const char * s)
{
return cstr_createn(s, strlen(s));
}
_TYPE( cstr * )
cstr_createn(const char * s, int len)
{
cstr * str = cstr_new();
if(str) {
cstr_setn(str, s, len);
}
return str;
}
_TYPE( void )
cstr_use(cstr * str)
{
++str->ref;
}
_TYPE( void )
cstr_clear_free(cstr * str)
{
if(--str->ref == 0) {
if(str->cap > 0) {
memset(str->data, 0, str->cap);
(*str->allocator->free)(str->data, str->allocator->heap);
}
(*str->allocator->free)(str, str->allocator->heap);
}
}
_TYPE( void )
cstr_free(cstr * str)
{
if(--str->ref == 0) {
if(str->cap > 0)
(*str->allocator->free)(str->data, str->allocator->heap);
(*str->allocator->free)(str, str->allocator->heap);
}
}
_TYPE( void )
cstr_empty(cstr * str)
{
if(str->cap > 0)
(*str->allocator->free)(str->data, str->allocator->heap);
str->data = cstr_empty_string;
str->length = str->cap = 0;
}
static int
cstr_alloc(cstr * str, int len)
{
char * t;
if(len > str->cap) {
if(len < EXPFACTOR * str->cap)
len = EXPFACTOR * str->cap;
if(len < MINSIZE)
len = MINSIZE;
t = (char *) (*str->allocator->alloc)(len * sizeof(char),
str->allocator->heap);
if(t) {
if(str->data) {
t[str->length] = 0;
if(str->cap > 0) {
if(str->length > 0)
memcpy(t, str->data, str->length);
free(str->data);
}
}
str->data = t;
str->cap = len;
return 1;
}
else
return -1;
}
else
return 0;
}
_TYPE( int )
cstr_copy(cstr * dst, const cstr * src)
{
return cstr_setn(dst, src->data, src->length);
}
_TYPE( int )
cstr_set(cstr * str, const char * s)
{
return cstr_setn(str, s, strlen(s));
}
_TYPE( int )
cstr_setn(cstr * str, const char * s, int len)
{
if(cstr_alloc(str, len + 1) < 0)
return -1;
str->data[len] = 0;
if(s != NULL && len > 0)
memmove(str->data, s, len);
str->length = len;
return 1;
}
_TYPE( int )
cstr_set_length(cstr * str, int len)
{
if(len < str->length) {
str->data[len] = 0;
str->length = len;
return 1;
}
else if(len > str->length) {
if(cstr_alloc(str, len + 1) < 0)
return -1;
memset(str->data + str->length, 0, len - str->length + 1);
str->length = len;
return 1;
}
else
return 0;
}
_TYPE( int )
cstr_append(cstr * str, const char * s)
{
return cstr_appendn(str, s, strlen(s));
}
_TYPE( int )
cstr_appendn(cstr * str, const char * s, int len)
{
if(cstr_alloc(str, str->length + len + 1) < 0)
return -1;
memcpy(str->data + str->length, s, len);
str->length += len;
str->data[str->length] = 0;
return 1;
}
_TYPE( int )
cstr_append_str(cstr * dst, const cstr * src)
{
return cstr_appendn(dst, src->data, src->length);
}

View File

@@ -0,0 +1,94 @@
#ifndef _CSTR_H_
#define _CSTR_H_
/* A general-purpose string "class" for C */
#if !defined(P)
#ifdef __STDC__
#define P(x) x
#else
#define P(x) ()
#endif
#endif
/* For building dynamic link libraries under windows, windows NT
* using MSVC1.5 or MSVC2.0
*/
#ifndef _DLLDECL
#define _DLLDECL
#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
#define _MSVC15EXPORT _export
#define _MSVC20EXPORT
#define _DLLAPI _export _pascal
#define _CDECL
#define _TYPE(a) a _MSVC15EXPORT
#define DLLEXPORT 1
#elif defined(MSVC20) || (defined(_USRDLL) && defined(SRP_EXPORTS))
#define _MSVC15EXPORT
#define _MSVC20EXPORT _declspec(dllexport)
#define _DLLAPI
#define _CDECL
#define _TYPE(a) _MSVC20EXPORT a
#define DLLEXPORT 1
#else /* Default, non-dll. Use this for Unix or DOS */
#define _MSVC15DEXPORT
#define _MSVC20EXPORT
#define _DLLAPI
#if defined(WINDOWS) || defined(WIN32)
#define _CDECL _cdecl
#else
#define _CDECL
#endif
#define _TYPE(a) a _CDECL
#endif
#endif /* _DLLDECL */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Arguments to allocator methods ordered this way for compatibility */
typedef struct cstr_alloc_st {
void * (_CDECL * alloc)(size_t n, void * heap);
void (_CDECL * free)(void * p, void * heap);
void * heap;
} cstr_allocator;
typedef struct cstr_st {
char * data; /* Okay to access data and length fields directly */
int length;
int cap;
int ref; /* Simple reference counter */
cstr_allocator * allocator;
} cstr;
_TYPE( void ) cstr_set_allocator P((cstr_allocator * alloc));
_TYPE( cstr * ) cstr_new P((void));
_TYPE( cstr * ) cstr_new_alloc P((cstr_allocator * alloc));
_TYPE( cstr * ) cstr_dup P((const cstr * str));
_TYPE( cstr * ) cstr_dup_alloc P((const cstr * str, cstr_allocator * alloc));
_TYPE( cstr * ) cstr_create P((const char * s));
_TYPE( cstr * ) cstr_createn P((const char * s, int len));
_TYPE( void ) cstr_free P((cstr * str));
_TYPE( void ) cstr_clear_free P((cstr * str));
_TYPE( void ) cstr_use P((cstr * str));
_TYPE( void ) cstr_empty P((cstr * str));
_TYPE( int ) cstr_copy P((cstr * dst, const cstr * src));
_TYPE( int ) cstr_set P((cstr * str, const char * s));
_TYPE( int ) cstr_setn P((cstr * str, const char * s, int len));
_TYPE( int ) cstr_set_length P((cstr * str, int len));
_TYPE( int ) cstr_append P((cstr * str, const char * s));
_TYPE( int ) cstr_appendn P((cstr * str, const char * s, int len));
_TYPE( int ) cstr_append_str P((cstr * dst, const cstr * src));
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _CSTR_H_ */

View File

@@ -0,0 +1,274 @@
/*
* Copyright (c) 1997-2007 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Redistributions in source or binary form must retain an intact copy
* of this copyright notice.
*/
#include "t_defines.h"
#include "srp.h"
static int library_initialized = 0;
_TYPE( SRP_RESULT )
SRP_initialize_library()
{
if(library_initialized == 0) {
BigIntegerInitialize();
t_stronginitrand();
library_initialized = 1;
}
return SRP_SUCCESS;
}
_TYPE( SRP_RESULT )
SRP_finalize_library()
{
if(library_initialized > 0) {
library_initialized = 0;
BigIntegerFinalize();
}
return SRP_SUCCESS;
}
static int srp_modulus_min_bits = SRP_DEFAULT_MIN_BITS;
_TYPE( SRP_RESULT )
SRP_set_modulus_min_bits(int minbits)
{
srp_modulus_min_bits = minbits;
return SRP_SUCCESS;
}
_TYPE( int )
SRP_get_modulus_min_bits()
{
return srp_modulus_min_bits;
}
static int
default_secret_bits_cb(int modsize)
{
return 256;
/*return modsize;*/ /* Warning: Very Slow */
}
static SRP_SECRET_BITS_CB srp_sb_cb = default_secret_bits_cb;
_TYPE( SRP_RESULT )
SRP_set_secret_bits_cb(SRP_SECRET_BITS_CB cb)
{
srp_sb_cb = cb;
return SRP_SUCCESS;
}
_TYPE( int )
SRP_get_secret_bits(int modsize)
{
return (*srp_sb_cb)(modsize);
}
_TYPE( SRP * )
SRP_new(SRP_METHOD * meth)
{
SRP * srp = (SRP *) malloc(sizeof(SRP));
if(srp == NULL)
return NULL;
srp->flags = 0;
srp->username = cstr_new();
srp->bctx = BigIntegerCtxNew();
srp->modulus = NULL;
srp->accel = NULL;
srp->generator = NULL;
srp->salt = NULL;
srp->verifier = NULL;
srp->password = NULL;
srp->pubkey = NULL;
srp->secret = NULL;
srp->u = NULL;
srp->key = NULL;
srp->ex_data = cstr_new();
srp->param_cb = NULL;
srp->meth = meth;
srp->meth_data = NULL;
//srp->slu = NULL;
if(srp->meth->init == NULL || (*srp->meth->init)(srp) == SRP_SUCCESS)
return srp;
free(srp);
return NULL;
}
_TYPE( SRP_RESULT )
SRP_free(SRP * srp)
{
if(srp->meth->finish)
(*srp->meth->finish)(srp);
if(srp->username)
cstr_clear_free(srp->username);
if(srp->modulus)
BigIntegerFree(srp->modulus);
if(srp->accel)
BigIntegerModAccelFree(srp->accel);
if(srp->generator)
BigIntegerFree(srp->generator);
if(srp->salt)
cstr_clear_free(srp->salt);
if(srp->verifier)
BigIntegerClearFree(srp->verifier);
if(srp->password)
BigIntegerClearFree(srp->password);
if(srp->pubkey)
BigIntegerFree(srp->pubkey);
if(srp->secret)
BigIntegerClearFree(srp->secret);
if(srp->u)
BigIntegerFree(srp->u);
if(srp->key)
BigIntegerClearFree(srp->key);
if(srp->bctx)
BigIntegerCtxFree(srp->bctx);
if(srp->ex_data)
cstr_clear_free(srp->ex_data);
free(srp);
return SRP_SUCCESS;
}
_TYPE( SRP_RESULT )
SRP_set_client_param_verify_cb(SRP * srp, SRP_CLIENT_PARAM_VERIFY_CB cb)
{
srp->param_cb = cb;
return SRP_SUCCESS;
}
_TYPE( SRP_RESULT )
SRP_set_username(SRP * srp, const char * username)
{
cstr_set(srp->username, username);
return SRP_SUCCESS;
}
_TYPE( SRP_RESULT )
SRP_set_user_raw(SRP * srp, const unsigned char * user, int userlen)
{
cstr_setn(srp->username, (const char*)user, userlen);
return SRP_SUCCESS;
}
_TYPE( SRP_RESULT )
SRP_set_params(SRP * srp, const unsigned char * modulus, int modlen,
const unsigned char * generator, int genlen,
const unsigned char * salt, int saltlen)
{
SRP_RESULT rc;
if(modulus == NULL || generator == NULL || salt == NULL)
return SRP_ERROR;
/* Set fields in SRP context */
srp->modulus = BigIntegerFromBytes(modulus, modlen);
if(srp->flags & SRP_FLAG_MOD_ACCEL)
srp->accel = BigIntegerModAccelNew(srp->modulus, srp->bctx);
srp->generator = BigIntegerFromBytes(generator, genlen);
if(srp->salt == NULL)
srp->salt = cstr_new();
cstr_setn(srp->salt, (const char*)salt, saltlen);
/* Now attempt to validate parameters */
if(BigIntegerBitLen(srp->modulus) < SRP_get_modulus_min_bits())
return SRP_ERROR;
if(srp->param_cb) {
rc = (*srp->param_cb)(srp, modulus, modlen, generator, genlen);
if(!SRP_OK(rc))
return rc;
}
return (*srp->meth->params)(srp, modulus, modlen, generator, genlen,
salt, saltlen);
}
_TYPE( SRP_RESULT )
SRP_set_authenticator(SRP * srp, const unsigned char * a, int alen)
{
return (*srp->meth->auth)(srp, a, alen);
}
_TYPE( SRP_RESULT )
SRP_set_auth_password(SRP * srp, const char * password)
{
return (*srp->meth->passwd)(srp, (const unsigned char *)password,
strlen(password));
}
_TYPE( SRP_RESULT )
SRP_set_auth_password_raw(SRP * srp,
const unsigned char * password, int passlen)
{
return (*srp->meth->passwd)(srp, password, passlen);
}
_TYPE( SRP_RESULT )
SRP_gen_pub(SRP * srp, cstr ** result)
{
return (*srp->meth->genpub)(srp, result);
}
_TYPE( SRP_RESULT )
SRP_add_ex_data(SRP * srp, const unsigned char * data, int datalen)
{
cstr_appendn(srp->ex_data, (const char*)data, datalen);
return SRP_SUCCESS;
}
_TYPE( SRP_RESULT )
SRP_compute_key(SRP * srp, cstr ** result,
const unsigned char * pubkey, int pubkeylen)
{
return (*srp->meth->key)(srp, result, pubkey, pubkeylen);
}
_TYPE( SRP_RESULT )
SRP_verify(SRP * srp, const unsigned char * proof, int prooflen)
{
return (*srp->meth->verify)(srp, proof, prooflen);
}
_TYPE( SRP_RESULT )
SRP_respond(SRP * srp, cstr ** proof)
{
return (*srp->meth->respond)(srp, proof);
}
_TYPE( SRP_RESULT )
SRP_use_engine(const char * engine)
{
if(BigIntegerOK(BigIntegerUseEngine(engine)))
return SRP_SUCCESS;
else
return SRP_ERROR;
}

View File

@@ -0,0 +1,372 @@
/*
* Copyright (c) 1997-2007 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Redistributions in source or binary form must retain an intact copy
* of this copyright notice.
*/
#ifndef _SRP_H_
#define _SRP_H_
#include "cstr.h"
#include "srp_aux.h"
#ifdef __cplusplus
extern "C" {
#endif
/* SRP library version identification */
#define SRP_VERSION_MAJOR 2
#define SRP_VERSION_MINOR 0
#define SRP_VERSION_PATCHLEVEL 1
typedef int SRP_RESULT;
/* Returned codes for SRP API functions */
#define SRP_OK(v) ((v) == SRP_SUCCESS)
#define SRP_SUCCESS 0
#define SRP_ERROR -1
/* Set the minimum number of bits acceptable in an SRP modulus */
#define SRP_DEFAULT_MIN_BITS 512
_TYPE( SRP_RESULT ) SRP_set_modulus_min_bits P((int minbits));
_TYPE( int ) SRP_get_modulus_min_bits P((void));
/*
* Sets the "secret size callback" function.
* This function is called with the modulus size in bits,
* and returns the size of the secret exponent in bits.
* The default function always returns 256 bits.
*/
typedef int (_CDECL * SRP_SECRET_BITS_CB)(int modsize);
_TYPE( SRP_RESULT ) SRP_set_secret_bits_cb P((SRP_SECRET_BITS_CB cb));
_TYPE( int ) SRP_get_secret_bits P((int modsize));
typedef struct srp_st SRP;
#if 0
/* Server Lookup API */
typedef struct srp_server_lu_st SRP_SERVER_LOOKUP;
typedef struct srp_s_lu_meth_st {
const char * name;
SRP_RESULT (_CDECL * init)(SRP_SERVER_LOOKUP * slu);
SRP_RESULT (_CDECL * finish)(SRP_SERVER_LOOKUP * slu);
SRP_RESULT (_CDECL * lookup)(SRP_SERVER_LOOKUP * slu, SRP * srp, cstr * username);
void * meth_data;
} SRP_SERVER_LOOKUP_METHOD;
struct srp_server_lu_st {
SRP_SERVER_LOOKUP_METHOD * meth;
void * data;
};
/*
* The Server Lookup API deals with the server-side issue of
* mapping usernames to verifiers. Given a username, a lookup
* mechanism needs to provide parameters (N, g), salt (s), and
* password verifier (v) for that user.
*
* A SRP_SERVER_LOOKUP_METHOD describes the general mechanism
* for performing lookups (e.g. files, LDAP, database, etc.)
* A SRP_SERVER_LOOKUP is an active "object" that is actually
* called to do lookups.
*/
_TYPE( SRP_SERVER_LOOKUP * )
SRP_SERVER_LOOKUP_new P((SRP_SERVER_LOOKUP_METHOD * meth));
_TYPE( SRP_RESULT ) SRP_SERVER_LOOKUP_free P((SRP_SERVER_LOOKUP * slu));
_TYPE( SRP_RESULT ) SRP_SERVER_do_lookup P((SRP_SERVER_LOOKUP * slu,
SRP * srp, cstr * username));
/*
* SRP_SERVER_system_lookup supercedes SRP_server_init_user.
*/
_TYPE( SRP_SERVER_LOOKUP * ) SRP_SERVER_system_lookup P((void));
#endif
/*
* Client Parameter Verification API
*
* This callback is called from the SRP client when the
* parameters (modulus and generator) are set. The callback
* should return SRP_SUCCESS if the parameters are okay,
* otherwise some error code to indicate that the parameters
* should be rejected.
*/
typedef SRP_RESULT (_CDECL * SRP_CLIENT_PARAM_VERIFY_CB)(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen);
#if 0
/* The default parameter verifier function */
_TYPE( SRP_RESULT ) SRP_CLIENT_default_param_verify_cb(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen);
/* A parameter verifier that only accepts builtin params (no prime test) */
_TYPE( SRP_RESULT ) SRP_CLIENT_builtin_param_verify_cb(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen);
/* The "classic" parameter verifier that accepts either builtin params
* immediately, and performs safe-prime tests on N and primitive-root
* tests on g otherwise. SECURITY WARNING: This may allow for certain
* attacks based on "trapdoor" moduli, so this is not recommended. */
_TYPE( SRP_RESULT ) SRP_CLIENT_compat_param_verify_cb(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen);
#endif
/*
* Main SRP API - SRP and SRP_METHOD
*/
/* SRP method definitions */
typedef struct srp_meth_st {
const char * name;
SRP_RESULT (_CDECL * init)(SRP * srp);
SRP_RESULT (_CDECL * finish)(SRP * srp);
SRP_RESULT (_CDECL * params)(SRP * srp,
const unsigned char * modulus, int modlen,
const unsigned char * generator, int genlen,
const unsigned char * salt, int saltlen);
SRP_RESULT (_CDECL * auth)(SRP * srp, const unsigned char * a, int alen);
SRP_RESULT (_CDECL * passwd)(SRP * srp,
const unsigned char * pass, int passlen);
SRP_RESULT (_CDECL * genpub)(SRP * srp, cstr ** result);
SRP_RESULT (_CDECL * key)(SRP * srp, cstr ** result,
const unsigned char * pubkey, int pubkeylen);
SRP_RESULT (_CDECL * verify)(SRP * srp,
const unsigned char * proof, int prooflen);
SRP_RESULT (_CDECL * respond)(SRP * srp, cstr ** proof);
void * data;
} SRP_METHOD;
/* Magic numbers for the SRP context header */
#define SRP_MAGIC_CLIENT 12
#define SRP_MAGIC_SERVER 28
/* Flag bits for SRP struct */
#define SRP_FLAG_MOD_ACCEL 0x1 /* accelerate modexp operations */
#define SRP_FLAG_LEFT_PAD 0x2 /* left-pad to length-of-N inside hashes */
/*
* A hybrid structure that represents either client or server state.
*/
struct srp_st {
int magic; /* To distinguish client from server (and for sanity) */
int flags;
cstr * username;
BigInteger modulus;
BigInteger generator;
cstr * salt;
BigInteger verifier;
BigInteger password;
BigInteger pubkey;
BigInteger secret;
BigInteger u;
BigInteger key;
cstr * ex_data;
SRP_METHOD * meth;
void * meth_data;
BigIntegerCtx bctx; /* to cache temporaries if available */
BigIntegerModAccel accel; /* to accelerate modexp if available */
SRP_CLIENT_PARAM_VERIFY_CB param_cb; /* to verify params */
//SRP_SERVER_LOOKUP * slu; /* to look up users */
};
/*
* Global initialization/de-initialization functions.
* Call SRP_initialize_library before using the library,
* and SRP_finalize_library when done.
*/
_TYPE( SRP_RESULT ) SRP_initialize_library();
_TYPE( SRP_RESULT ) SRP_finalize_library();
/*
* SRP_new() creates a new SRP context object -
* the method determines which "sense" (client or server)
* the object operates in. SRP_free() frees it.
* (See RFC2945 method definitions below.)
*/
_TYPE( SRP * ) SRP_new P((SRP_METHOD * meth));
_TYPE( SRP_RESULT ) SRP_free P((SRP * srp));
#if 0
/*
* Use the supplied lookup object to look up user parameters and
* password verifier. The lookup function gets called during
* SRP_set_username/SRP_set_user_raw below. Using this function
* means that the server can avoid calling SRP_set_params and
* SRP_set_authenticator, since the lookup function handles that
* internally.
*/
_TYPE( SRP_RESULT ) SRP_set_server_lookup P((SRP * srp,
SRP_SERVER_LOOKUP * lookup));
#endif
/*
* Use the supplied callback function to verify parameters
* (modulus, generator) given to the client.
*/
_TYPE( SRP_RESULT )
SRP_set_client_param_verify_cb P((SRP * srp,
SRP_CLIENT_PARAM_VERIFY_CB cb));
/*
* Both client and server must call both SRP_set_username and
* SRP_set_params, in that order, before calling anything else.
* SRP_set_user_raw is an alternative to SRP_set_username that
* accepts an arbitrary length-bounded octet string as input.
*/
_TYPE( SRP_RESULT ) SRP_set_username P((SRP * srp, const char * username));
_TYPE( SRP_RESULT ) SRP_set_user_raw P((SRP * srp, const unsigned char * user,
int userlen));
_TYPE( SRP_RESULT )
SRP_set_params P((SRP * srp,
const unsigned char * modulus, int modlen,
const unsigned char * generator, int genlen,
const unsigned char * salt, int saltlen));
/*
* On the client, SRP_set_authenticator, SRP_gen_exp, and
* SRP_add_ex_data can be called in any order.
* On the server, SRP_set_authenticator must come first,
* followed by SRP_gen_exp and SRP_add_ex_data in either order.
*/
/*
* The authenticator is the secret possessed by either side.
* For the server, this is the bigendian verifier, as an octet string.
* For the client, this is the bigendian raw secret, as an octet string.
* The server's authenticator must be the generator raised to the power
* of the client's raw secret modulo the common modulus for authentication
* to succeed.
*
* SRP_set_auth_password computes the authenticator from a plaintext
* password and then calls SRP_set_authenticator automatically. This is
* usually used on the client side, while the server usually uses
* SRP_set_authenticator (since it doesn't know the plaintext password).
*/
_TYPE( SRP_RESULT )
SRP_set_authenticator P((SRP * srp, const unsigned char * a, int alen));
_TYPE( SRP_RESULT )
SRP_set_auth_password P((SRP * srp, const char * password));
_TYPE( SRP_RESULT )
SRP_set_auth_password_raw P((SRP * srp,
const unsigned char * password,
int passlen));
/*
* SRP_gen_pub generates the random exponential residue to send
* to the other side. If using SRP-3/RFC2945, the server must
* withhold its result until it receives the client's number.
* If using SRP-6, the server can send its value immediately
* without waiting for the client.
*
* If "result" points to a NULL pointer, a new cstr object will be
* created to hold the result, and "result" will point to it.
* If "result" points to a non-NULL cstr pointer, the result will be
* placed there.
* If "result" itself is NULL, no result will be returned,
* although the big integer value will still be available
* through srp->pubkey in the SRP struct.
*/
_TYPE( SRP_RESULT ) SRP_gen_pub P((SRP * srp, cstr ** result));
/*
* Append the data to the extra data segment. Authentication will
* not succeed unless both sides add precisely the same data in
* the same order.
*/
_TYPE( SRP_RESULT ) SRP_add_ex_data P((SRP * srp, const unsigned char * data,
int datalen));
/*
* SRP_compute_key must be called after the previous three methods.
*/
_TYPE( SRP_RESULT ) SRP_compute_key P((SRP * srp, cstr ** result,
const unsigned char * pubkey,
int pubkeylen));
/*
* On the client, call SRP_respond first to get the response to send
* to the server, and call SRP_verify to verify the server's response.
* On the server, call SRP_verify first to verify the client's response,
* and call SRP_respond ONLY if verification succeeds.
*
* It is an error to call SRP_respond with a NULL pointer.
*/
_TYPE( SRP_RESULT ) SRP_verify P((SRP * srp,
const unsigned char * proof, int prooflen));
_TYPE( SRP_RESULT ) SRP_respond P((SRP * srp, cstr ** response));
/* RFC2945-style SRP authentication */
#define RFC2945_KEY_LEN 40 /* length of session key (bytes) */
#define RFC2945_RESP_LEN 20 /* length of proof hashes (bytes) */
/*
* RFC2945-style SRP authentication methods. Use these like:
* SRP * srp = SRP_new(SRP_RFC2945_client_method());
*/
_TYPE( SRP_METHOD * ) SRP_RFC2945_client_method P((void));
_TYPE( SRP_METHOD * ) SRP_RFC2945_server_method P((void));
/*
* SRP-6 and SRP-6a authentication methods.
* SRP-6a is recommended for better resistance to 2-for-1 attacks.
*/
_TYPE( SRP_METHOD * ) SRP6_client_method P((void));
_TYPE( SRP_METHOD * ) SRP6_server_method P((void));
_TYPE( SRP_METHOD * ) SRP6a_client_method P((void));
_TYPE( SRP_METHOD * ) SRP6a_server_method P((void));
_TYPE( SRP_METHOD * ) SRP6a_sha512_client_method P((void));
/*
* Convenience function - SRP_server_init_user
* Looks up the username from the system EPS configuration and calls
* SRP_set_username, SRP_set_params, and SRP_set_authenticator to
* initialize server state for that user.
*
* This is deprecated in favor of SRP_SERVER_system_lookup() and
* the Server Lookup API.
*/
_TYPE( SRP_RESULT ) SRP_server_init_user P((SRP * srp, const char * username));
/*
* Use the named engine for acceleration.
*/
_TYPE( SRP_RESULT ) SRP_use_engine P((const char * engine));
#ifdef __cplusplus
}
#endif
#endif /* _SRP_H_ */

View File

@@ -0,0 +1,363 @@
/*
* Copyright (c) 1997-2007 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Redistributions in source or binary form must retain an intact copy
* of this copyright notice.
*/
#include "t_defines.h"
#include "srp.h"
#include "t_sha.h"
/*
* SRP-6/6a has two minor refinements relative to SRP-3/RFC2945:
* 1. The "g^x" value is multipled by three in the client's
* calculation of its session key.
* SRP-6a: The "g^x" value is multiplied by the hash of
* N and g in the client's session key calculation.
* 2. The value of u is taken as the hash of A and B,
* instead of the top 32 bits of the hash of B.
* This eliminates the old restriction where the
* server had to receive A before it could send B.
*/
/****************************/
#define SHA512_DIGESTSIZE 64
#define SRP6_SHA512_KEY_LEN 64
/*
* The client keeps track of the running hash
* state via SHA512_CTX structures pointed to by the
* meth_data pointer. The "hash" member is the hash value that
* will be sent to the other side; the "ckhash" member is the
* hash value expected from the other side.
*/
struct sha512_client_meth_st {
SHA512_CTX hash;
SHA512_CTX ckhash;
unsigned char k[SRP6_SHA512_KEY_LEN];
};
#define SHA512_CLIENT_CTXP(srp) ((struct sha512_client_meth_st *)(srp)->meth_data)
static SRP_RESULT
srp6a_sha512_client_init(SRP * srp)
{
srp->magic = SRP_MAGIC_CLIENT;
srp->flags = SRP_FLAG_MOD_ACCEL | SRP_FLAG_LEFT_PAD;
srp->meth_data = malloc(sizeof(struct sha512_client_meth_st));
SHA512Init(&SHA512_CLIENT_CTXP(srp)->hash);
SHA512Init(&SHA512_CLIENT_CTXP(srp)->ckhash);
return SRP_SUCCESS;
}
static SRP_RESULT
srp6_sha512_client_finish(SRP * srp)
{
if(srp->meth_data) {
memset(srp->meth_data, 0, sizeof(struct sha512_client_meth_st));
free(srp->meth_data);
}
return SRP_SUCCESS;
}
static SRP_RESULT
srp6_sha512_client_params(SRP * srp, const unsigned char * modulus, int modlen,
const unsigned char * generator, int genlen,
const unsigned char * salt, int saltlen)
{
int i;
unsigned char buf1[SHA512_DIGESTSIZE], buf2[SHA512_DIGESTSIZE];
SHA512_CTX ctxt;
/* Fields set by SRP_set_params */
/* Update hash state */
SHA512Init(&ctxt);
SHA512Update(&ctxt, modulus, modlen);
SHA512Final(buf1, &ctxt); /* buf1 = H(modulus) */
SHA512Init(&ctxt);
SHA512Update(&ctxt, generator, genlen);
SHA512Final(buf2, &ctxt); /* buf2 = H(generator) */
for(i = 0; i < sizeof(buf1); ++i)
buf1[i] ^= buf2[i]; /* buf1 = H(modulus) xor H(generator) */
/* hash: H(N) xor H(g) */
SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, buf1, sizeof(buf1));
SHA512Init(&ctxt);
SHA512Update(&ctxt, srp->username->data, srp->username->length);
SHA512Final(buf1, &ctxt); /* buf1 = H(user) */
/* hash: (H(N) xor H(g)) | H(U) */
SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, buf1, sizeof(buf1));
/* hash: (H(N) xor H(g)) | H(U) | s */
SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, salt, saltlen);
return SRP_SUCCESS;
}
static SRP_RESULT
srp6_sha512_client_auth(SRP * srp, const unsigned char * a, int alen)
{
/* On the client, the authenticator is the raw password-derived hash */
srp->password = BigIntegerFromBytes(a, alen);
/* verifier = g^x mod N */
srp->verifier = BigIntegerFromInt(0);
BigIntegerModExp(srp->verifier, srp->generator, srp->password, srp->modulus, srp->bctx, srp->accel);
return SRP_SUCCESS;
}
static SRP_RESULT
srp6_sha512_client_passwd(SRP * srp, const unsigned char * p, int plen)
{
SHA512_CTX ctxt;
unsigned char dig[SHA512_DIGESTSIZE];
int r;
SHA512Init(&ctxt);
SHA512Update(&ctxt, srp->username->data, srp->username->length);
SHA512Update(&ctxt, ":", 1);
SHA512Update(&ctxt, p, plen);
SHA512Final(dig, &ctxt); /* dig = H(U | ":" | P) */
SHA512Init(&ctxt);
SHA512Update(&ctxt, srp->salt->data, srp->salt->length);
SHA512Update(&ctxt, dig, sizeof(dig));
SHA512Final(dig, &ctxt); /* dig = H(s | H(U | ":" | P)) */
memset(&ctxt, 0, sizeof(ctxt));
r = SRP_set_authenticator(srp, dig, sizeof(dig));
memset(dig, 0, sizeof(dig));
return r;
}
static SRP_RESULT
srp6_sha512_client_genpub(SRP * srp, cstr ** result)
{
cstr * astr;
int slen = (SRP_get_secret_bits(BigIntegerBitLen(srp->modulus)) + 7) / 8;
if(result == NULL)
astr = cstr_new();
else {
if(*result == NULL)
*result = cstr_new();
astr = *result;
}
cstr_set_length(astr, BigIntegerByteLen(srp->modulus));
t_random((unsigned char*)astr->data, slen);
srp->secret = BigIntegerFromBytes((const unsigned char*)astr->data, slen);
/* Force g^a mod n to "wrap around" by adding log[2](n) to "a". */
BigIntegerAddInt(srp->secret, srp->secret, BigIntegerBitLen(srp->modulus));
/* A = g^a mod n */
srp->pubkey = BigIntegerFromInt(0);
BigIntegerModExp(srp->pubkey, srp->generator, srp->secret, srp->modulus, srp->bctx, srp->accel);
BigIntegerToCstr(srp->pubkey, astr);
/* hash: (H(N) xor H(g)) | H(U) | s | A */
SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, astr->data, astr->length);
/* ckhash: A */
SHA512Update(&SHA512_CLIENT_CTXP(srp)->ckhash, astr->data, astr->length);
if(result == NULL) /* astr was a temporary */
cstr_clear_free(astr);
return SRP_SUCCESS;
}
static SRP_RESULT
srp6_sha512_client_key_ex(SRP * srp, cstr ** result,
const unsigned char * pubkey, int pubkeylen, BigInteger k)
{
SHA512_CTX ctxt;
unsigned char dig[SHA512_DIGESTSIZE];
BigInteger gb, e;
cstr * s;
int modlen;
modlen = BigIntegerByteLen(srp->modulus);
if(pubkeylen > modlen)
return SRP_ERROR;
/* Compute u from client's and server's values */
SHA512Init(&ctxt);
/* Use s as a temporary to store client's value */
s = cstr_new();
if(srp->flags & SRP_FLAG_LEFT_PAD) {
BigIntegerToCstrEx(srp->pubkey, s, modlen);
SHA512Update(&ctxt, s->data, s->length);
if(pubkeylen < modlen) {
memcpy(s->data + (modlen - pubkeylen), pubkey, pubkeylen);
memset(s->data, 0, modlen - pubkeylen);
SHA512Update(&ctxt, s->data, modlen);
}
else
SHA512Update(&ctxt, pubkey, pubkeylen);
}
else {
BigIntegerToCstr(srp->pubkey, s);
SHA512Update(&ctxt, s->data, s->length);
SHA512Update(&ctxt, pubkey, pubkeylen);
}
SHA512Final(dig, &ctxt);
srp->u = BigIntegerFromBytes(dig, SHA512_DIGESTSIZE);
/* hash: (H(N) xor H(g)) | H(U) | s | A | B */
SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, pubkey, pubkeylen);
gb = BigIntegerFromBytes(pubkey, pubkeylen);
/* reject B == 0, B >= modulus */
if(BigIntegerCmp(gb, srp->modulus) >= 0 || BigIntegerCmpInt(gb, 0) == 0) {
BigIntegerFree(gb);
cstr_clear_free(s);
return SRP_ERROR;
}
e = BigIntegerFromInt(0);
srp->key = BigIntegerFromInt(0);
/* unblind g^b (mod N) */
BigIntegerSub(srp->key, srp->modulus, srp->verifier);
/* use e as temporary, e == -k*v (mod N) */
BigIntegerMul(e, k, srp->key, srp->bctx);
BigIntegerAdd(e, e, gb);
BigIntegerMod(gb, e, srp->modulus, srp->bctx);
/* compute gb^(a + ux) (mod N) */
BigIntegerMul(e, srp->password, srp->u, srp->bctx);
BigIntegerAdd(e, e, srp->secret); /* e = a + ux */
BigIntegerModExp(srp->key, gb, e, srp->modulus, srp->bctx, srp->accel);
BigIntegerClearFree(e);
BigIntegerClearFree(gb);
/* convert srp->key into a session key, update hash states */
BigIntegerToCstr(srp->key, s);
SHA512Init(&ctxt);
SHA512Update(&ctxt, s->data, s->length);
SHA512Final((unsigned char*)&SHA512_CLIENT_CTXP(srp)->k, &ctxt);
cstr_clear_free(s);
/* hash: (H(N) xor H(g)) | H(U) | s | A | B | K */
SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, SHA512_CLIENT_CTXP(srp)->k, SRP6_SHA512_KEY_LEN);
/* hash: (H(N) xor H(g)) | H(U) | s | A | B | K | ex_data */
if(srp->ex_data->length > 0)
SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash,
srp->ex_data->data, srp->ex_data->length);
if(result) {
if(*result == NULL)
*result = cstr_new();
cstr_setn(*result, (const char*)SHA512_CLIENT_CTXP(srp)->k, SRP6_SHA512_KEY_LEN);
}
return SRP_SUCCESS;
}
static SRP_RESULT
srp6a_sha512_client_key(SRP * srp, cstr ** result,
const unsigned char * pubkey, int pubkeylen)
{
SRP_RESULT ret;
BigInteger k;
cstr * s;
SHA512_CTX ctxt;
unsigned char dig[SHA512_DIGESTSIZE];
SHA512Init(&ctxt);
s = cstr_new();
BigIntegerToCstr(srp->modulus, s);
SHA512Update(&ctxt, s->data, s->length);
if(srp->flags & SRP_FLAG_LEFT_PAD)
BigIntegerToCstrEx(srp->generator, s, s->length);
else
BigIntegerToCstr(srp->generator, s);
SHA512Update(&ctxt, s->data, s->length);
SHA512Final(dig, &ctxt);
cstr_free(s);
k = BigIntegerFromBytes(dig, SHA512_DIGESTSIZE);
if(BigIntegerCmpInt(k, 0) == 0)
ret = SRP_ERROR;
else
ret = srp6_sha512_client_key_ex(srp, result, pubkey, pubkeylen, k);
BigIntegerClearFree(k);
return ret;
}
static SRP_RESULT
srp6_sha512_client_verify(SRP * srp, const unsigned char * proof, int prooflen)
{
unsigned char expected[SHA512_DIGESTSIZE];
SHA512Final(expected, &SHA512_CLIENT_CTXP(srp)->ckhash);
if(prooflen == SHA512_DIGESTSIZE && memcmp(expected, proof, prooflen) == 0)
return SRP_SUCCESS;
else
return SRP_ERROR;
}
static SRP_RESULT
srp6_sha512_client_respond(SRP * srp, cstr ** proof)
{
if(proof == NULL)
return SRP_ERROR;
if(*proof == NULL)
*proof = cstr_new();
/* proof contains client's response */
cstr_set_length(*proof, SHA512_DIGESTSIZE);
SHA512Final((unsigned char*)(*proof)->data, &SHA512_CLIENT_CTXP(srp)->hash);
/* ckhash: A | M | K */
SHA512Update(&SHA512_CLIENT_CTXP(srp)->ckhash, (*proof)->data, (*proof)->length);
SHA512Update(&SHA512_CLIENT_CTXP(srp)->ckhash, SHA512_CLIENT_CTXP(srp)->k, SRP6_SHA512_KEY_LEN);
return SRP_SUCCESS;
}
static SRP_METHOD srp6a_sha512_client_meth = {
"SRP-6a sha512 client (tjw)",
srp6a_sha512_client_init,
srp6_sha512_client_finish,
srp6_sha512_client_params,
srp6_sha512_client_auth,
srp6_sha512_client_passwd,
srp6_sha512_client_genpub,
srp6a_sha512_client_key,
srp6_sha512_client_verify,
srp6_sha512_client_respond,
NULL
};
_TYPE( SRP_METHOD * )
SRP6a_sha512_client_method()
{
return &srp6a_sha512_client_meth;
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 1997-2007 The Stanford SRP Authentication Project
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Redistributions in source or binary form must retain an intact copy
* of this copyright notice.
*/
#ifndef SRP_AUX_H
#define SRP_AUX_H
#include "cstr.h"
#ifdef __cplusplus
extern "C" {
#endif
/* BigInteger abstraction API */
#ifndef MATH_PRIV
typedef void * BigInteger;
typedef void * BigIntegerCtx;
typedef void * BigIntegerModAccel;
#endif
/*
* Some functions return a BigIntegerResult.
* Use BigIntegerOK to test for success.
*/
#define BIG_INTEGER_SUCCESS 0
#define BIG_INTEGER_ERROR -1
#define BigIntegerOK(v) ((v) == BIG_INTEGER_SUCCESS)
typedef int BigIntegerResult;
_TYPE( BigInteger ) BigIntegerFromInt P((unsigned int number));
_TYPE( BigInteger ) BigIntegerFromBytes P((const unsigned char * bytes,
int length));
#define BigIntegerByteLen(X) ((BigIntegerBitLen(X)+7)/8)
_TYPE( int ) BigIntegerToBytes P((BigInteger src,
unsigned char * dest, int destlen));
_TYPE( BigIntegerResult ) BigIntegerToCstr P((BigInteger src, cstr * dest));
_TYPE( BigIntegerResult ) BigIntegerToCstrEx P((BigInteger src, cstr * dest, int len));
_TYPE( BigIntegerResult ) BigIntegerToHex P((BigInteger src,
char * dest, int destlen));
_TYPE( BigIntegerResult ) BigIntegerToString P((BigInteger src,
char * dest, int destlen,
unsigned int radix));
_TYPE( int ) BigIntegerBitLen P((BigInteger b));
_TYPE( int ) BigIntegerCmp P((BigInteger c1, BigInteger c2));
_TYPE( int ) BigIntegerCmpInt P((BigInteger c1, unsigned int c2));
_TYPE( BigIntegerResult ) BigIntegerLShift P((BigInteger result, BigInteger x,
unsigned int bits));
_TYPE( BigIntegerResult ) BigIntegerAdd P((BigInteger result,
BigInteger a1, BigInteger a2));
_TYPE( BigIntegerResult ) BigIntegerAddInt P((BigInteger result,
BigInteger a1, unsigned int a2));
_TYPE( BigIntegerResult ) BigIntegerSub P((BigInteger result,
BigInteger s1, BigInteger s2));
_TYPE( BigIntegerResult ) BigIntegerSubInt P((BigInteger result,
BigInteger s1, unsigned int s2));
/* For BigIntegerMul{,Int}: result != m1, m2 */
_TYPE( BigIntegerResult ) BigIntegerMul P((BigInteger result, BigInteger m1,
BigInteger m2, BigIntegerCtx ctx));
_TYPE( BigIntegerResult ) BigIntegerMulInt P((BigInteger result,
BigInteger m1, unsigned int m2,
BigIntegerCtx ctx));
_TYPE( BigIntegerResult ) BigIntegerDivInt P((BigInteger result,
BigInteger d, unsigned int m,
BigIntegerCtx ctx));
_TYPE( BigIntegerResult ) BigIntegerMod P((BigInteger result, BigInteger d,
BigInteger m, BigIntegerCtx ctx));
_TYPE( unsigned int ) BigIntegerModInt P((BigInteger d, unsigned int m,
BigIntegerCtx ctx));
_TYPE( BigIntegerResult ) BigIntegerModMul P((BigInteger result,
BigInteger m1, BigInteger m2,
BigInteger m, BigIntegerCtx ctx));
_TYPE( BigIntegerResult ) BigIntegerModExp P((BigInteger result,
BigInteger base, BigInteger expt,
BigInteger modulus,
BigIntegerCtx ctx,
BigIntegerModAccel accel));
_TYPE( int ) BigIntegerCheckPrime P((BigInteger n, BigIntegerCtx ctx));
_TYPE( BigIntegerResult ) BigIntegerFree P((BigInteger b));
_TYPE( BigIntegerResult ) BigIntegerClearFree P((BigInteger b));
_TYPE( BigIntegerCtx ) BigIntegerCtxNew();
_TYPE( BigIntegerResult ) BigIntegerCtxFree P((BigIntegerCtx ctx));
_TYPE( BigIntegerModAccel ) BigIntegerModAccelNew P((BigInteger m,
BigIntegerCtx ctx));
_TYPE( BigIntegerResult ) BigIntegerModAccelFree P((BigIntegerModAccel accel));
_TYPE( BigIntegerResult ) BigIntegerInitialize();
_TYPE( BigIntegerResult ) BigIntegerFinalize();
_TYPE( BigIntegerResult ) BigIntegerUseEngine P((const char * engine));
_TYPE( BigIntegerResult ) BigIntegerReleaseEngine();
/* Miscellaneous functions - formerly in t_pwd.h */
/*
* "t_random" is a cryptographic random number generator, which is seeded
* from various high-entropy sources and uses a one-way hash function
* in a feedback configuration.
* "t_sessionkey" is the interleaved hash used to generate session keys
* from a large integer.
* "t_mgf1" is an implementation of MGF1 using SHA1 to generate session
* keys from large integers, and is preferred over the older
* interleaved hash, and is used with SRP6.
* "t_getpass" reads a password from the terminal without echoing.
*/
_TYPE( void ) t_random P((unsigned char *, unsigned));
_TYPE( void ) t_stronginitrand();
_TYPE( unsigned char * )
t_sessionkey P((unsigned char *, unsigned char *, unsigned));
_TYPE( void ) t_mgf1 P((unsigned char *, unsigned,
const unsigned char *, unsigned));
_TYPE( int ) t_getpass P((char *, unsigned, const char *));
#ifdef __cplusplus
}
#endif
#endif /* SRP_AUX_H */

Some files were not shown because too many files have changed in this diff Show More