refs #4904 Remove old apps code

This commit is contained in:
Sergio De la torre 2023-04-27 13:53:50 +02:00
parent 5267f60023
commit e841a88215
3862 changed files with 0 additions and 703393 deletions

3
.gitignore vendored
View File

@ -1,3 +0,0 @@
BaseLibrary
Verdnaturaventas/VerdnaturaventasTests
Verdnaturaventas/VerdnaturaventasuiTests

View File

@ -1,621 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
A60259071C58FFE500A7695F /* UIImageViewAsync.swift in Sources */ = {isa = PBXBuildFile; fileRef = A60259061C58FFE500A7695F /* UIImageViewAsync.swift */; };
A649BF311C96ED5F00024538 /* LocalizableBase.strings in Resources */ = {isa = PBXBuildFile; fileRef = A649BF261C96ED5F00024538 /* LocalizableBase.strings */; };
A649BF321C96ED5F00024538 /* LocalizableBase.strings in Resources */ = {isa = PBXBuildFile; fileRef = A649BF291C96ED5F00024538 /* LocalizableBase.strings */; };
A649BF331C96ED5F00024538 /* LocalizableBase.strings in Resources */ = {isa = PBXBuildFile; fileRef = A649BF2C1C96ED5F00024538 /* LocalizableBase.strings */; };
A649BF341C96ED5F00024538 /* LocalizableBase.strings in Resources */ = {isa = PBXBuildFile; fileRef = A649BF2F1C96ED5F00024538 /* LocalizableBase.strings */; };
A66EDF391C8985ED008EF663 /* CommandBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66EDF2F1C8985ED008EF663 /* CommandBase.swift */; };
A66EDF3C1C8985ED008EF663 /* FacadeBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66EDF331C8985ED008EF663 /* FacadeBase.swift */; };
A66EDF3D1C8985ED008EF663 /* FacadeClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66EDF341C8985ED008EF663 /* FacadeClient.swift */; };
A66EDF3E1C8985ED008EF663 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66EDF351C8985ED008EF663 /* Parser.swift */; };
A66EDF3F1C8985ED008EF663 /* ParserBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66EDF361C8985ED008EF663 /* ParserBool.swift */; };
A66EDF401C8985ED008EF663 /* ParserVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66EDF371C8985ED008EF663 /* ParserVoid.swift */; };
A66EDF421C89861E008EF663 /* Ejecutador.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66EDF411C89861E008EF663 /* Ejecutador.swift */; };
A66EDF441C899CDB008EF663 /* CommandCallbacks.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66EDF431C899CDB008EF663 /* CommandCallbacks.swift */; };
A66EDF461C899F07008EF663 /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66EDF451C899F07008EF663 /* Reachability.swift */; };
A69B43061C6CA8E3009F69B4 /* UtilsNumbers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A69B43051C6CA8E3009F69B4 /* UtilsNumbers.swift */; };
A69CEE5A1C3A9E4D00482F9B /* MyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A69CEE591C3A9E4D00482F9B /* MyView.swift */; };
A6B028581C574F2900D679EF /* UtilsIos.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6B028571C574F2900D679EF /* UtilsIos.swift */; };
A6BABF571C33F80B0082BADE /* BaseLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = A6BABF561C33F80B0082BADE /* BaseLibrary.h */; settings = {ATTRIBUTES = (Public, ); }; };
A6BABF5E1C33F80B0082BADE /* BaseLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6BABF531C33F80B0082BADE /* BaseLibrary.framework */; };
A6BABF631C33F80B0082BADE /* BaseLibraryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6BABF621C33F80B0082BADE /* BaseLibraryTests.swift */; };
A6CC9CE01C633117009BD820 /* ModelBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6CC9CDF1C633117009BD820 /* ModelBase.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
A6BABF5F1C33F80B0082BADE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A6BABF4A1C33F80B0082BADE /* Project object */;
proxyType = 1;
remoteGlobalIDString = A6BABF521C33F80B0082BADE;
remoteInfo = BaseLibrary;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
A60259061C58FFE500A7695F /* UIImageViewAsync.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UIImageViewAsync.swift; path = Core/UIImageViewAsync.swift; sourceTree = "<group>"; };
A649BF271C96ED5F00024538 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = LocalizableBase.strings; sourceTree = "<group>"; };
A649BF2A1C96ED5F00024538 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = LocalizableBase.strings; sourceTree = "<group>"; };
A649BF2D1C96ED5F00024538 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = LocalizableBase.strings; sourceTree = "<group>"; };
A649BF301C96ED5F00024538 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = LocalizableBase.strings; sourceTree = "<group>"; };
A66EDF2F1C8985ED008EF663 /* CommandBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandBase.swift; sourceTree = "<group>"; };
A66EDF331C8985ED008EF663 /* FacadeBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FacadeBase.swift; sourceTree = "<group>"; };
A66EDF341C8985ED008EF663 /* FacadeClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FacadeClient.swift; sourceTree = "<group>"; };
A66EDF351C8985ED008EF663 /* Parser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = "<group>"; };
A66EDF361C8985ED008EF663 /* ParserBool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParserBool.swift; sourceTree = "<group>"; };
A66EDF371C8985ED008EF663 /* ParserVoid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParserVoid.swift; sourceTree = "<group>"; };
A66EDF411C89861E008EF663 /* Ejecutador.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Ejecutador.swift; sourceTree = "<group>"; };
A66EDF431C899CDB008EF663 /* CommandCallbacks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandCallbacks.swift; sourceTree = "<group>"; };
A66EDF451C899F07008EF663 /* Reachability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reachability.swift; sourceTree = "<group>"; };
A69B43051C6CA8E3009F69B4 /* UtilsNumbers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UtilsNumbers.swift; path = Core/UtilsNumbers.swift; sourceTree = "<group>"; };
A69CEE591C3A9E4D00482F9B /* MyView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MyView.swift; path = Views/MyView.swift; sourceTree = "<group>"; };
A6B028571C574F2900D679EF /* UtilsIos.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UtilsIos.swift; path = Core/UtilsIos.swift; sourceTree = "<group>"; };
A6BABF531C33F80B0082BADE /* BaseLibrary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BaseLibrary.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A6BABF561C33F80B0082BADE /* BaseLibrary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseLibrary.h; sourceTree = "<group>"; };
A6BABF581C33F80B0082BADE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = BaseLibrary/Info.plist; sourceTree = "<group>"; };
A6BABF5D1C33F80B0082BADE /* BaseLibraryTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BaseLibraryTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A6BABF621C33F80B0082BADE /* BaseLibraryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseLibraryTests.swift; sourceTree = "<group>"; };
A6BABF641C33F80B0082BADE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A6CC9CDF1C633117009BD820 /* ModelBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ModelBase.swift; path = Model/ModelBase.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
A6BABF4F1C33F80B0082BADE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
A6BABF5A1C33F80B0082BADE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A6BABF5E1C33F80B0082BADE /* BaseLibrary.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
A649BF251C96ED5F00024538 /* ca.lproj */ = {
isa = PBXGroup;
children = (
A649BF261C96ED5F00024538 /* LocalizableBase.strings */,
);
name = ca.lproj;
path = Resources/Strings/ca.lproj;
sourceTree = "<group>";
};
A649BF281C96ED5F00024538 /* en.lproj */ = {
isa = PBXGroup;
children = (
A649BF291C96ED5F00024538 /* LocalizableBase.strings */,
);
name = en.lproj;
path = Resources/Strings/en.lproj;
sourceTree = "<group>";
};
A649BF2B1C96ED5F00024538 /* es.lproj */ = {
isa = PBXGroup;
children = (
A649BF2C1C96ED5F00024538 /* LocalizableBase.strings */,
);
name = es.lproj;
path = Resources/Strings/es.lproj;
sourceTree = "<group>";
};
A649BF2E1C96ED5F00024538 /* pt.lproj */ = {
isa = PBXGroup;
children = (
A649BF2F1C96ED5F00024538 /* LocalizableBase.strings */,
);
name = pt.lproj;
path = Resources/Strings/pt.lproj;
sourceTree = "<group>";
};
A65F5E7C1C47D107004FEAE1 /* Core */ = {
isa = PBXGroup;
children = (
A60259061C58FFE500A7695F /* UIImageViewAsync.swift */,
A6B028571C574F2900D679EF /* UtilsIos.swift */,
A69B43051C6CA8E3009F69B4 /* UtilsNumbers.swift */,
);
name = Core;
sourceTree = "<group>";
};
A66EDF2C1C8985ED008EF663 /* Communicacion */ = {
isa = PBXGroup;
children = (
A66EDF2D1C8985ED008EF663 /* Command */,
A66EDF321C8985ED008EF663 /* Facade */,
A66EDF411C89861E008EF663 /* Ejecutador.swift */,
);
path = Communicacion;
sourceTree = "<group>";
};
A66EDF2D1C8985ED008EF663 /* Command */ = {
isa = PBXGroup;
children = (
A66EDF2F1C8985ED008EF663 /* CommandBase.swift */,
A66EDF431C899CDB008EF663 /* CommandCallbacks.swift */,
A66EDF451C899F07008EF663 /* Reachability.swift */,
);
path = Command;
sourceTree = "<group>";
};
A66EDF321C8985ED008EF663 /* Facade */ = {
isa = PBXGroup;
children = (
A66EDF331C8985ED008EF663 /* FacadeBase.swift */,
A66EDF341C8985ED008EF663 /* FacadeClient.swift */,
A66EDF351C8985ED008EF663 /* Parser.swift */,
A66EDF361C8985ED008EF663 /* ParserBool.swift */,
A66EDF371C8985ED008EF663 /* ParserVoid.swift */,
);
path = Facade;
sourceTree = "<group>";
};
A66EDF471C89A443008EF663 /* Resources */ = {
isa = PBXGroup;
children = (
A66EDF481C89A44B008EF663 /* Strings.bundle */,
);
name = Resources;
sourceTree = "<group>";
};
A66EDF481C89A44B008EF663 /* Strings.bundle */ = {
isa = PBXGroup;
children = (
A649BF251C96ED5F00024538 /* ca.lproj */,
A649BF281C96ED5F00024538 /* en.lproj */,
A649BF2B1C96ED5F00024538 /* es.lproj */,
A649BF2E1C96ED5F00024538 /* pt.lproj */,
);
name = Strings.bundle;
sourceTree = "<group>";
};
A69CEE581C3A9E3700482F9B /* Views */ = {
isa = PBXGroup;
children = (
A69CEE591C3A9E4D00482F9B /* MyView.swift */,
);
name = Views;
sourceTree = "<group>";
};
A6B1E91D1C60BA6B00D3A0A5 /* Model */ = {
isa = PBXGroup;
children = (
A6CC9CDF1C633117009BD820 /* ModelBase.swift */,
);
name = Model;
sourceTree = "<group>";
};
A6BABF491C33F80B0082BADE = {
isa = PBXGroup;
children = (
A6BABF551C33F80B0082BADE /* BaseLibrary */,
A6BABF581C33F80B0082BADE /* Info.plist */,
A6BABF611C33F80B0082BADE /* BaseLibraryTests */,
A6BABF541C33F80B0082BADE /* Products */,
);
sourceTree = "<group>";
};
A6BABF541C33F80B0082BADE /* Products */ = {
isa = PBXGroup;
children = (
A6BABF531C33F80B0082BADE /* BaseLibrary.framework */,
A6BABF5D1C33F80B0082BADE /* BaseLibraryTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
A6BABF551C33F80B0082BADE /* BaseLibrary */ = {
isa = PBXGroup;
children = (
A66EDF471C89A443008EF663 /* Resources */,
A66EDF2C1C8985ED008EF663 /* Communicacion */,
A6BABF561C33F80B0082BADE /* BaseLibrary.h */,
A65F5E7C1C47D107004FEAE1 /* Core */,
A6B1E91D1C60BA6B00D3A0A5 /* Model */,
A69CEE581C3A9E3700482F9B /* Views */,
);
path = BaseLibrary;
sourceTree = "<group>";
};
A6BABF611C33F80B0082BADE /* BaseLibraryTests */ = {
isa = PBXGroup;
children = (
A6BABF621C33F80B0082BADE /* BaseLibraryTests.swift */,
A6BABF641C33F80B0082BADE /* Info.plist */,
);
path = BaseLibraryTests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
A6BABF501C33F80B0082BADE /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
A6BABF571C33F80B0082BADE /* BaseLibrary.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
A6BABF521C33F80B0082BADE /* BaseLibrary */ = {
isa = PBXNativeTarget;
buildConfigurationList = A6BABF671C33F80B0082BADE /* Build configuration list for PBXNativeTarget "BaseLibrary" */;
buildPhases = (
A6BABF4E1C33F80B0082BADE /* Sources */,
A6BABF4F1C33F80B0082BADE /* Frameworks */,
A6BABF501C33F80B0082BADE /* Headers */,
A6BABF511C33F80B0082BADE /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = BaseLibrary;
productName = BaseLibrary;
productReference = A6BABF531C33F80B0082BADE /* BaseLibrary.framework */;
productType = "com.apple.product-type.framework";
};
A6BABF5C1C33F80B0082BADE /* BaseLibraryTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = A6BABF6A1C33F80B0082BADE /* Build configuration list for PBXNativeTarget "BaseLibraryTests" */;
buildPhases = (
A6BABF591C33F80B0082BADE /* Sources */,
A6BABF5A1C33F80B0082BADE /* Frameworks */,
A6BABF5B1C33F80B0082BADE /* Resources */,
);
buildRules = (
);
dependencies = (
A6BABF601C33F80B0082BADE /* PBXTargetDependency */,
);
name = BaseLibraryTests;
productName = BaseLibraryTests;
productReference = A6BABF5D1C33F80B0082BADE /* BaseLibraryTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
A6BABF4A1C33F80B0082BADE /* Project object */ = {
isa = PBXProject;
attributes = {
KnownAssetTags = (
New,
);
LastSwiftUpdateCheck = 0720;
LastUpgradeCheck = 0820;
ORGANIZATIONNAME = "Nelo Sanchez Gomiz";
TargetAttributes = {
A6BABF521C33F80B0082BADE = {
CreatedOnToolsVersion = 7.2;
LastSwiftMigration = 0820;
};
A6BABF5C1C33F80B0082BADE = {
CreatedOnToolsVersion = 7.2;
};
};
};
buildConfigurationList = A6BABF4D1C33F80B0082BADE /* Build configuration list for PBXProject "BaseLibrary" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
es,
Base,
ca,
pt,
);
mainGroup = A6BABF491C33F80B0082BADE;
productRefGroup = A6BABF541C33F80B0082BADE /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
A6BABF521C33F80B0082BADE /* BaseLibrary */,
A6BABF5C1C33F80B0082BADE /* BaseLibraryTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
A6BABF511C33F80B0082BADE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A649BF311C96ED5F00024538 /* LocalizableBase.strings in Resources */,
A649BF341C96ED5F00024538 /* LocalizableBase.strings in Resources */,
A649BF331C96ED5F00024538 /* LocalizableBase.strings in Resources */,
A649BF321C96ED5F00024538 /* LocalizableBase.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A6BABF5B1C33F80B0082BADE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
A6BABF4E1C33F80B0082BADE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A66EDF461C899F07008EF663 /* Reachability.swift in Sources */,
A69CEE5A1C3A9E4D00482F9B /* MyView.swift in Sources */,
A66EDF421C89861E008EF663 /* Ejecutador.swift in Sources */,
A66EDF3D1C8985ED008EF663 /* FacadeClient.swift in Sources */,
A66EDF3C1C8985ED008EF663 /* FacadeBase.swift in Sources */,
A66EDF401C8985ED008EF663 /* ParserVoid.swift in Sources */,
A66EDF391C8985ED008EF663 /* CommandBase.swift in Sources */,
A60259071C58FFE500A7695F /* UIImageViewAsync.swift in Sources */,
A66EDF3F1C8985ED008EF663 /* ParserBool.swift in Sources */,
A66EDF441C899CDB008EF663 /* CommandCallbacks.swift in Sources */,
A6B028581C574F2900D679EF /* UtilsIos.swift in Sources */,
A66EDF3E1C8985ED008EF663 /* Parser.swift in Sources */,
A69B43061C6CA8E3009F69B4 /* UtilsNumbers.swift in Sources */,
A6CC9CE01C633117009BD820 /* ModelBase.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A6BABF591C33F80B0082BADE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A6BABF631C33F80B0082BADE /* BaseLibraryTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
A6BABF601C33F80B0082BADE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = A6BABF521C33F80B0082BADE /* BaseLibrary */;
targetProxy = A6BABF5F1C33F80B0082BADE /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
A649BF261C96ED5F00024538 /* LocalizableBase.strings */ = {
isa = PBXVariantGroup;
children = (
A649BF271C96ED5F00024538 /* ca */,
);
name = LocalizableBase.strings;
sourceTree = "<group>";
};
A649BF291C96ED5F00024538 /* LocalizableBase.strings */ = {
isa = PBXVariantGroup;
children = (
A649BF2A1C96ED5F00024538 /* en */,
);
name = LocalizableBase.strings;
sourceTree = "<group>";
};
A649BF2C1C96ED5F00024538 /* LocalizableBase.strings */ = {
isa = PBXVariantGroup;
children = (
A649BF2D1C96ED5F00024538 /* es */,
);
name = LocalizableBase.strings;
sourceTree = "<group>";
};
A649BF2F1C96ED5F00024538 /* LocalizableBase.strings */ = {
isa = PBXVariantGroup;
children = (
A649BF301C96ED5F00024538 /* pt */,
);
name = LocalizableBase.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
A6BABF651C33F80B0082BADE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
A6BABF661C33F80B0082BADE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
A6BABF681C33F80B0082BADE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = BaseLibrary/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = nelosan.BaseLibrary;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
A6BABF691C33F80B0082BADE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = BaseLibrary/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = nelosan.BaseLibrary;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Release;
};
A6BABF6B1C33F80B0082BADE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = BaseLibraryTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = nelosan.BaseLibraryTests;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
A6BABF6C1C33F80B0082BADE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = BaseLibraryTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = nelosan.BaseLibraryTests;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
A6BABF4D1C33F80B0082BADE /* Build configuration list for PBXProject "BaseLibrary" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A6BABF651C33F80B0082BADE /* Debug */,
A6BABF661C33F80B0082BADE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A6BABF671C33F80B0082BADE /* Build configuration list for PBXNativeTarget "BaseLibrary" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A6BABF681C33F80B0082BADE /* Debug */,
A6BABF691C33F80B0082BADE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A6BABF6A1C33F80B0082BADE /* Build configuration list for PBXNativeTarget "BaseLibraryTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A6BABF6B1C33F80B0082BADE /* Debug */,
A6BABF6C1C33F80B0082BADE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = A6BABF4A1C33F80B0082BADE /* Project object */;
}

View File

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

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>BaseLibrary.xcscheme</key>
<dict>
<key>orderHint</key>
<<<<<<< HEAD
<integer>6</integer>
=======
<integer>16</integer>
>>>>>>> ee3e0c5c054e15cc67030a8b4f62773866bbd4ce
</dict>
<key>BaseLibrary.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<<<<<<< HEAD
<integer>6</integer>
=======
<integer>16</integer>
>>>>>>> ee3e0c5c054e15cc67030a8b4f62773866bbd4ce
</dict>
</dict>
</dict>
</plist>

View File

@ -1,99 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0820"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A6BABF521C33F80B0082BADE"
BuildableName = "BaseLibrary.framework"
BlueprintName = "BaseLibrary"
ReferencedContainer = "container:BaseLibrary.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A6BABF5C1C33F80B0082BADE"
BuildableName = "BaseLibraryTests.xctest"
BlueprintName = "BaseLibraryTests"
ReferencedContainer = "container:BaseLibrary.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A6BABF521C33F80B0082BADE"
BuildableName = "BaseLibrary.framework"
BlueprintName = "BaseLibrary"
ReferencedContainer = "container:BaseLibrary.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A6BABF521C33F80B0082BADE"
BuildableName = "BaseLibrary.framework"
BlueprintName = "BaseLibrary"
ReferencedContainer = "container:BaseLibrary.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A6BABF521C33F80B0082BADE"
BuildableName = "BaseLibrary.framework"
BlueprintName = "BaseLibrary"
ReferencedContainer = "container:BaseLibrary.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>BaseLibrary.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>A6BABF521C33F80B0082BADE</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>A6BABF5C1C33F80B0082BADE</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View File

@ -1,19 +0,0 @@
//
// BaseLibrary.h
// BaseLibrary
//
// Created by Verdnatura on 30/12/15.
// Copyright © 2015 Verdnatura. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for BaseLibrary.
FOUNDATION_EXPORT double BaseLibraryVersionNumber;
//! Project version string for BaseLibrary.
FOUNDATION_EXPORT const unsigned char BaseLibraryVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <BaseLibrary/PublicHeader.h>

View File

@ -1,135 +0,0 @@
//
// CommandBase.swift
// BaseLibrary
//
// Created by Verdnatura on 29/12/15.
// Copyright © 2015 Verdnatura. All rights reserved.
//
//
// FacadeClient.swift
// BaseLibrary
//
// Created by Verdnatura on 29/12/15.
// Copyright © 2015 Verdnatura. All rights reserved.
//
import UIKit
import CoreLocation
open class CommandBase: NSObject {
open var succesMessage: String = ""
open var needInternet: Bool = true
open var cancel = false
open var cancelable = true
open var error: String = ""
open var errorMessage: String = ""
open var view: UIViewController?
open var callbacks: CommandCallbacks?
var ejecutador = Ejecutador.getInstance()
open func executeTask(_ view: UIViewController)
{
self.view = view
//LANZA UNA TAREA EN SEGUNDO PLANO
DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default).async(execute: {
do{
try self.execute()
}
catch let error as NSError {
self.error = error.description
}
self.onPostExecute()
});
}
open func execute() throws {}
open func onPostExecute()
{
//EJECUTA LA FUNCIONALIDAD EN EL HILO PRINCIPAL
DispatchQueue.main.async(execute: {
if(!self.cancel)
{
if(self.error != "" && self.errorMessage != "")
{
self.mostrarAviso(self.errorMessage, showRetry: true)
}
else
{
self.Finished()
}
}
});
}
open func isNeedInternet() -> Bool {
return needInternet
}
func mostrarAviso(_ msg: String, showRetry: Bool)
{
let alert = UIAlertController(title: NSLocalizedString("error", comment: ""), message: msg, preferredStyle: UIAlertControllerStyle.alert)
let retry: UIAlertAction = UIAlertAction(title: NSLocalizedString("retry", comment: ""), style: .default) { action -> Void in
self.retry()
}
let accept: UIAlertAction = UIAlertAction(title: NSLocalizedString("accept", comment: ""), style: .default) { action -> Void in
self.accept()
}
alert.addAction(retry)
alert.addAction(accept)
view!.present(alert, animated: true, completion: nil)
}
open func onCancelled() {
if(cancelable)
{
cancel = true
}
}
open func Finished(){
if(callbacks != nil)
{
callbacks!.onFinish()
}
}
open func Start(){
if(callbacks != nil)
{
callbacks!.onStart()
}
}
open func retry()
{
if(callbacks != nil)
{
callbacks!.onRetry()
}
}
open func accept()
{
if(callbacks != nil)
{
callbacks!.onAccept()
}
}
}

View File

@ -1,50 +0,0 @@
//
// CommandCallbacks.swift
// BaseLibrary
//
// Created by Verdnatura on 4/3/16.
// Copyright © 2016 Verdnatura. All rights reserved.
//
import UIKit
open class CommandCallbacks {
var retry: (() -> Void)?
var accept: (() -> Void)?
var start: (() -> Void)?
var finish: (() -> Void)?
open func onRetry(){
if let _ = self.retry {
retry!()
}
}
open func onAccept(){
if let _ = self.accept {
accept!()
}
}
open func onFinish(){
if let _ = self.finish {
finish!()
}
}
open func onStart(){
if let _ = self.start {
start!()
}
}
public init(handlerStart: @escaping (() -> Void), handlerFinish: @escaping (() -> Void), handlerRetry: @escaping (() -> Void), handlerAccept: @escaping (() -> Void))
{
self.retry = handlerRetry
self.accept = handlerAccept
self.start = handlerStart
self.finish = handlerFinish
}
}

View File

@ -1,40 +0,0 @@
//
// Reachability.swift
// BaseLibrary
//
// Created by Verdnatura on 4/3/16.
// Copyright © 2016 Verdnatura. All rights reserved.
//
import Foundation
import SystemConfiguration
open class Reachability {
class func isConnectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
return false
}
var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == false {
return false
}
let isReachable = flags == .reachable
let needsConnection = flags == .connectionRequired
return isReachable && !needsConnection
}
}

View File

@ -1,73 +0,0 @@
//
// Ejecutador.swift
// BaseLibrary
//
// Created by Verdnatura on 4/3/16.
// Copyright © 2016 Verdnatura. All rights reserved.
//
import UIKit
open class Ejecutador: NSObject {
var commands = Array<CommandBase>()
static var INSTANCE: Ejecutador? = nil
override init (){}
static func createInstance() {
if (INSTANCE == nil) {
INSTANCE = Ejecutador()
}
}
open static func getInstance() -> Ejecutador {
if (INSTANCE == nil)
{
createInstance()
}
return INSTANCE!
}
open func exeute(_ cmd: CommandBase, view: UIViewController)
{
var existe = false
for c in commands
{
if(c == cmd)
{
existe = true
break
}
}
if(!existe)
{
commands.append(cmd)
}
cmd.executeTask(view)
}
func cancelCommad(_ cmd: CommandBase)
{
cmd.cancel = true
removeCommand(cmd)
}
open func removeCommand(_ cmd: CommandBase)
{
let index = commands.index(of: cmd)
commands.remove(at: index!)
}
open func removeCommands()
{
for cmd in commands{
cancelCommad(cmd)
}
}
}

View File

@ -1,21 +0,0 @@
//
// FacadeBase.swift
// BaseLibrary
//
// Created by Verdnatura on 30/12/15.
// Copyright © 2015 Verdnatura. All rights reserved.
//
import UIKit
open class FacadeBase: NSObject {
open var facadeName = ""
open var facade: FacadeClient?
open func Execute<T:Parser>(_ parser: T?, command: String, args: AnyObject...) throws -> AnyObject?
{
return try facade!.Execute(parser, facade: facadeName, command: command, args: args as AnyObject)
}
}

View File

@ -1,79 +0,0 @@
//
// FacadeClient.swift
// BaseLibrary
//
// Created by Verdnatura on 29/12/15.
// Copyright © 2015 Verdnatura. All rights reserved.
//
import UIKit
open class FacadeClient: NSObject
{
open let POST = "POST"
open let GET = "GET"
public enum ErrorFacade: Error {
case errorServidor(String)
}
func Execute<T:Parser>(_ parser: T?, facade: String, command: String, args: AnyObject...) throws -> AnyObject?
{
let jsonObject = try InnerExecute(facade, command: command, args: (args as AnyObject) as! Array<Any>, file: nil)
var data: AnyObject? = nil
if(parser != nil && jsonObject != nil)
{
data = parser!.parse(jsonObject!) as? AnyObject
}
else{
data = jsonObject
}
return data
}
fileprivate func InnerExecute(_ facade: String, command: String , args: Array<Any>, file: String?) throws -> AnyObject?
{
//FALTA CODIGO FICHEROS
var argsMessage: String? = ""
var datos: AnyObject? = nil
do {
let data = try JSONSerialization.data(withJSONObject: args[0], options: JSONSerialization.WritingOptions(rawValue: 0))
argsMessage = String(data: data, encoding: String.Encoding.utf8)
}catch let error as NSError{
print(error.description)
throw ErrorFacade.errorServidor(error.description)
}
do{
try WriteResponseToStream(facade, command: command, argsMessage: argsMessage, datos: &datos)
}
catch let error as NSError
{
throw ErrorFacade.errorServidor(error.description)
}
return datos
}
open func tratarJson(_ datos: Data) -> AnyObject?
{
do{
if let json = try JSONSerialization.jsonObject(with: datos, options: JSONSerialization.ReadingOptions.allowFragments) as AnyObject?
{
return json
}
}catch
{
return nil
}
return nil
}
open func WriteResponseToStream(_ facade: String, command: String, argsMessage: String!, datos: inout AnyObject?) throws {}
}

View File

@ -1,18 +0,0 @@
//
// Parser.swift
// BaseLibrary
//
// Created by Verdnatura on 4/1/16.
// Copyright © 2016 Verdnatura. All rights reserved.
//
import UIKit
public protocol Parser
{
associatedtype T
func parse(_: AnyObject) -> T
}

View File

@ -1,24 +0,0 @@
//
// ParserDictionary.swift
// BaseLibrary
//
// Created by Verdnatura on 17/2/16.
// Copyright © 2016 Verdnatura. All rights reserved.
//
import UIKit
open class ParserBool: Parser {
public typealias T = Bool
public init(){}
open func parse(_ jsonObject: AnyObject) -> Bool
{
return jsonObject as! Bool
}
}

View File

@ -1,20 +0,0 @@
//
// ParserDefault.swift
// BaseLibrary
//
// Created by Verdnatura on 11/1/16.
// Copyright © 2016 Verdnatura. All rights reserved.
//
import UIKit
open class ParserVoid: Parser {
public typealias T = Void
public init(){}
open func parse(_ jsonObject: AnyObject) -> Void
{
}
}

View File

@ -1,60 +0,0 @@
//
// UIImageViewAsync.swift
// ElTiempo
//
// Created by Jordi on 10/7/15.
// Copyright (c) 2015 EPSA UPV. All rights reserved.
//
import Foundation
import UIKit
open class UIImageViewAsync :UIImageView
{
override init(frame:CGRect)
{
super.init(frame:frame)
}
required public init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
open func getDataFromUrl(_ url:String, completion: @escaping ((_ data: Data?) -> Void)) {
if(verifyUrl(url)){
URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { (data, response, error) in
if(data != nil)
{
completion(NSData(data: data!) as Data)
}
}) .resume()
}
}
open func downloadImage(_ url:String){
getDataFromUrl(url) { data in
self.completion(data)
}
}
open func completion(_ data: Data?)
{
DispatchQueue.main.async {
self.contentMode = self.contentMode
self.image = UIImage(data: data!)
}
}
open func verifyUrl (_ urlString: String?) -> Bool {
//Check for nil
if let urlString = urlString {
// create NSURL instance
if let url = URL(string: urlString) {
// check if your application can open the NSURL instance
return UIApplication.shared.canOpenURL(url)
}
}
return false
}
}

View File

@ -1,69 +0,0 @@
//
// UtilsIos.swift
// BaseLibrary
//
// Created by Verdnatura on 26/1/16.
// Copyright © 2016 Verdnatura. All rights reserved.
//
import UIKit
open class UtilsIos: NSObject {
open static func registerNib(_ table: UITableView, cell: String)
{
let nib = UINib(nibName: cell, bundle: nil)
table.register(nib, forCellReuseIdentifier: cell)
}
open static func registerNibCollection(_ collection: UICollectionView, cell: String)
{
let nib = UINib(nibName: cell, bundle: nil)
collection.register(nib, forCellWithReuseIdentifier: cell)
}
open static func getColor(_ rgbValue: UInt) -> UIColor {
return UIColor(
red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
alpha: CGFloat(1.0)
)
}
open static func getColor(_ rgbValue: UInt, alpha: CGFloat) -> UIColor {
return UIColor(
red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
alpha: CGFloat(alpha)
)
}
open static func nullToNil(_ value : AnyObject?) -> AnyObject? {
if value is NSNull {
return nil
} else {
return value
}
}
open static func toString(_ value: AnyObject) -> String{
return "\(value)"
}
open static func toBool(_ value: String) -> Bool? {
switch (value){
case "True", "true", "yes", "1":
return true
case "False", "false", "no", "0":
return false
default:
return nil
}
}
}

View File

@ -1,19 +0,0 @@
//
// UtilsNumbers.swift
// BaseLibrary
//
// Created by Verdnatura on 11/2/16.
// Copyright © 2016 Verdnatura. All rights reserved.
//
import UIKit
open class UtilsNumbers: NSObject {
open static func roundDouble(_ number: NSNumber, decimals: Int) -> Double
{
let dec = "%.\(decimals)f"
return Double(String(format: dec, number.doubleValue))!
}
}

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleLocalizations</key>
<array>
<string>Portugues</string>
<string>Catalan</string>
<string>en</string>
<string>Spanish</string>
</array>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -1,112 +0,0 @@
//
// ModelBase.swift
// BaseLibrary
//
// Created by Verdnatura on 4/2/16.
// Copyright © 2016 Verdnatura. All rights reserved.
//
import UIKit
open class ModelBase: NSObject {
open func parseJson(_ json: NSDictionary)
{
let dictionary = generateDictionary()
for (key, value) in dictionary{
if let val = json[key]
{
castType(value, value: val as AnyObject?, property: key)
}
}
}
func generateDictionary() -> Dictionary<String,String>{
var dictionary = Dictionary<String, String>()
let mirror = Mirror(reflecting: self)
for child in mirror.children {
dictionary[child.label!] = String(describing: type(of: (child.value)))
if((dictionary[child.label!]?.lowercased().contains("optional")) != nil){
let typeArr = dictionary[child.label!]!.characters.split{$0 == "<"}.map(String.init)
let typeArr2 = typeArr[1].characters.split{$0 == ">"}.map(String.init)
dictionary[child.label!] = typeArr2[0]
}
}
return dictionary
}
func castType(_ type: String, value: AnyObject?, property: String){
let v = nullToNil(value)
if(v != nil){
var val = toString(value!)
switch(type){
case "String":
setValue(val, forKey: property)
break
case "String, String":
val = val.replacingOccurrences(of: "{\n", with: "")
val = val.replacingOccurrences(of: "\n}", with: "")
val = val.replacingOccurrences(of: " ", with: "")
let array = val.components(separatedBy: ";\n")
var dictionary: Dictionary<String, String> = Dictionary()
if property != "tags"{
for a in array{
let data = a.components(separatedBy: " = ")
dictionary[data[0].replacingOccurrences(of: ";", with: "")] = data[1].replacingOccurrences(of: ";", with: "")
}
}
break
case "NSNumber":
let nVal = Double(val)!
if(nVal.truncatingRemainder(dividingBy: 1) == 0)
{
setValue(NSNumber(value: Int(nVal) as Int), forKey: property)
}
else{
setValue(NSNumber(value: nVal as Double), forKey: property)
}
break
default:
break
}
}
}
func nullToNil(_ value : AnyObject?) -> AnyObject? {
if value is NSNull {
return nil
} else {
return value
}
}
func toString(_ value: AnyObject) -> String{
return "\(value)"
}
func toBool(_ value: String) -> Bool? {
switch (value){
case "True", "true", "yes", "1":
return true
case "False", "false", "no", "0":
return false
default:
return nil
}
}
}

View File

@ -1,20 +0,0 @@
/*
Localizable.strings
BaseLibrary
Created by Verdnatura on 4/3/16.
Copyright © 2016 Verdnatura. All rights reserved.
*/
/* */
"error" = "Error";
/* */
"accept" = "Aceptar";
/* */
"retry" = "Reintentar";
/* */
"no_internet" = "No hi ha connexió a internet";

View File

@ -1,20 +0,0 @@
/*
Localizable.strings
BaseLibrary
Created by Verdnatura on 4/3/16.
Copyright © 2016 Verdnatura. All rights reserved.
*/
/* */
"error" = "Error";
/* */
"accept" = "Acept";
/* */
"retry" = "Retry";
/* */
"no_internet" = "No internet";

View File

@ -1,20 +0,0 @@
/*
Localizable.strings
BaseLibrary
Created by Verdnatura on 4/3/16.
Copyright © 2016 Verdnatura. All rights reserved.
*/
/* */
"error" = "Error";
/* */
"accept" = "Aceptar";
/* */
"retry" = "Reintentar";
/* */
"no_internet" = "No hay conexión a internet";

View File

@ -1,20 +0,0 @@
/*
Localizable.strings
BaseLibrary
Created by Verdnatura on 4/3/16.
Copyright © 2016 Verdnatura. All rights reserved.
*/
/* */
"error" = "Error";
/* */
"accept" = "Aceptar";
/* */
"retry" = "Reintentar";
/* */
"no_internet" = "Sem conexão à Internet";

View File

@ -1,88 +0,0 @@
//
// MyView.swift
// BaseLibrary
//
// Created by Verdnatura on 4/1/16.
// Copyright © 2016 Verdnatura. All rights reserved.
//
import UIKit
open class MyView: UIViewController {
open var progress: UIActivityIndicatorView?
open var contenedor: UIView?
open var ejecutador: Ejecutador?
open override func viewDidLoad() {
ejecutador = Ejecutador.getInstance()
createView()
}
open override func viewWillAppear(_ animated: Bool) {
prepareView()
}
open override func viewWillDisappear(_ animated: Bool) {
ejecutador!.removeCommands()
}
open func showProgress(_ show: Bool) {
showProgressBar(show)
showContenedor(show)
}
open func showProgressBar(_ show: Bool)
{
if(progress != nil)
{
if(show)
{
progress!.startAnimating()
progress!.isHidden = false
}
else
{
progress!.stopAnimating()
progress!.isHidden = true
}
}
}
open func showContenedor(_ show: Bool)
{
if(contenedor != nil)
{
contenedor!.isHidden = show
}
}
open func createView(){
showProgress(false)
setTitles()
}
open func prepareView(){}
open func setTitles(){}
open func execute(_ cmd: CommandBase)
{
ejecutador!.exeute(cmd, view: self)
}
open func launchSegue(_ segue: String){
performSegue(withIdentifier: segue, sender: self)
}
open func launchSegue(_ segue: String, sender: AnyObject?)
{
performSegue(withIdentifier: segue, sender: sender)
}
}

View File

@ -1,36 +0,0 @@
//
// BaseLibraryTests.swift
// BaseLibraryTests
//
// Created by Verdnatura on 30/12/15.
// Copyright © 2015 Verdnatura. All rights reserved.
//
import XCTest
@testable import BaseLibrary
class BaseLibraryTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock {
// Put the code you want to measure the time of here.
}
}
}

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

Binary file not shown.

View File

@ -1,16 +0,0 @@
use_frameworks!
platform :ios, '9.0'
pod 'FSCalendar'
target "Verdnaturaventas" do
<<<<<<< HEAD
pod 'Firebase/Core'
=======
pod 'Firebase/Core'
pod 'Firebase/Firestore'
pod 'Firebase/Messaging'
pod 'Firebase/InAppMessagingDisplay'
>>>>>>> ee3e0c5c054e15cc67030a8b4f62773866bbd4ce
end

View File

@ -1,220 +0,0 @@
PODS:
<<<<<<< HEAD
- Firebase/Core (5.3.0):
- Firebase/CoreOnly
- FirebaseAnalytics (= 5.0.1)
- Firebase/CoreOnly (5.3.0):
- FirebaseCore (= 5.0.4)
- FirebaseAnalytics (5.0.1):
- FirebaseCore (~> 5.0)
- FirebaseInstanceID (~> 3.0)
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- nanopb (~> 0.3)
- FirebaseCore (5.0.4):
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- FirebaseInstanceID (3.1.1):
- FirebaseCore (~> 5.0)
- FSCalendar (2.7.9)
- GoogleToolboxForMac/Defines (2.1.4)
- "GoogleToolboxForMac/NSData+zlib (2.1.4)":
- GoogleToolboxForMac/Defines (= 2.1.4)
- nanopb (0.3.8):
- nanopb/decode (= 0.3.8)
- nanopb/encode (= 0.3.8)
- nanopb/decode (0.3.8)
- nanopb/encode (0.3.8)
DEPENDENCIES:
- Firebase/Core
=======
- BoringSSL (10.0.6):
- BoringSSL/Implementation (= 10.0.6)
- BoringSSL/Interface (= 10.0.6)
- BoringSSL/Implementation (10.0.6):
- BoringSSL/Interface (= 10.0.6)
- BoringSSL/Interface (10.0.6)
- Firebase/Core (5.15.0):
- Firebase/CoreOnly
- FirebaseAnalytics (= 5.4.0)
- Firebase/CoreOnly (5.15.0):
- FirebaseCore (= 5.1.10)
- Firebase/Firestore (5.15.0):
- Firebase/CoreOnly
- FirebaseFirestore (= 0.16.1)
- Firebase/InAppMessagingDisplay (5.15.0):
- Firebase/CoreOnly
- FirebaseInAppMessagingDisplay (= 0.12.2)
- Firebase/Messaging (5.15.0):
- Firebase/CoreOnly
- FirebaseMessaging (= 3.2.2)
- FirebaseAnalytics (5.4.0):
- FirebaseCore (~> 5.1)
- FirebaseInstanceID (~> 3.3)
- GoogleAppMeasurement (= 5.4.0)
- GoogleUtilities/AppDelegateSwizzler (~> 5.2)
- GoogleUtilities/MethodSwizzler (~> 5.2)
- GoogleUtilities/Network (~> 5.2)
- "GoogleUtilities/NSData+zlib (~> 5.2)"
- nanopb (~> 0.3)
- FirebaseAnalyticsInterop (1.1.0)
- FirebaseAuthInterop (1.0.0)
- FirebaseCore (5.1.10):
- GoogleUtilities/Logger (~> 5.2)
- FirebaseFirestore (0.16.1):
- FirebaseAuthInterop (~> 1.0)
- FirebaseCore (~> 5.1)
- FirebaseFirestore/abseil-cpp (= 0.16.1)
- "gRPC-C++ (= 0.0.5)"
- leveldb-library (~> 1.20)
- nanopb (~> 0.3.8)
- Protobuf (~> 3.1)
- FirebaseFirestore/abseil-cpp (0.16.1):
- FirebaseAuthInterop (~> 1.0)
- FirebaseCore (~> 5.1)
- "gRPC-C++ (= 0.0.5)"
- leveldb-library (~> 1.20)
- nanopb (~> 0.3.8)
- Protobuf (~> 3.1)
- FirebaseInAppMessaging (0.12.1):
- FirebaseAnalytics (~> 5.3)
- FirebaseCore (~> 5.1)
- FirebaseInstanceID (~> 3.3)
- GoogleUtilities/Environment (~> 5.0)
- FirebaseInAppMessagingDisplay (0.12.2):
- FirebaseCore
- FirebaseInAppMessaging (>= 0.12.0)
- FirebaseInstanceID (3.3.0):
- FirebaseCore (~> 5.1)
- GoogleUtilities/Environment (~> 5.3)
- GoogleUtilities/UserDefaults (~> 5.3)
- FirebaseMessaging (3.2.2):
- FirebaseAnalyticsInterop (~> 1.1)
- FirebaseCore (~> 5.1)
- FirebaseInstanceID (~> 3.0)
- GoogleUtilities/Environment (~> 5.2)
- GoogleUtilities/Reachability (~> 5.2)
- Protobuf (~> 3.1)
- FSCalendar (2.8.0)
- GoogleAppMeasurement (5.4.0):
- GoogleUtilities/AppDelegateSwizzler (~> 5.2)
- GoogleUtilities/MethodSwizzler (~> 5.2)
- GoogleUtilities/Network (~> 5.2)
- "GoogleUtilities/NSData+zlib (~> 5.2)"
- nanopb (~> 0.3)
- GoogleUtilities/AppDelegateSwizzler (5.3.6):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (5.3.6)
- GoogleUtilities/Logger (5.3.6):
- GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (5.3.6):
- GoogleUtilities/Logger
- GoogleUtilities/Network (5.3.6):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (5.3.6)"
- GoogleUtilities/Reachability (5.3.6):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (5.3.6):
- GoogleUtilities/Logger
- "gRPC-C++ (0.0.5)":
- "gRPC-C++/Implementation (= 0.0.5)"
- "gRPC-C++/Interface (= 0.0.5)"
- "gRPC-C++/Implementation (0.0.5)":
- "gRPC-C++/Interface (= 0.0.5)"
- gRPC-Core (= 1.14.0)
- nanopb (~> 0.3)
- "gRPC-C++/Interface (0.0.5)"
- gRPC-Core (1.14.0):
- gRPC-Core/Implementation (= 1.14.0)
- gRPC-Core/Interface (= 1.14.0)
- gRPC-Core/Implementation (1.14.0):
- BoringSSL (~> 10.0)
- gRPC-Core/Interface (= 1.14.0)
- nanopb (~> 0.3)
- gRPC-Core/Interface (1.14.0)
- leveldb-library (1.20)
- nanopb (0.3.901):
- nanopb/decode (= 0.3.901)
- nanopb/encode (= 0.3.901)
- nanopb/decode (0.3.901)
- nanopb/encode (0.3.901)
- Protobuf (3.6.1)
DEPENDENCIES:
- Firebase/Core
- Firebase/Firestore
- Firebase/InAppMessagingDisplay
- Firebase/Messaging
>>>>>>> ee3e0c5c054e15cc67030a8b4f62773866bbd4ce
- FSCalendar
SPEC REPOS:
https://github.com/cocoapods/specs.git:
<<<<<<< HEAD
- Firebase
- FirebaseAnalytics
- FirebaseCore
- FirebaseInstanceID
- FSCalendar
- GoogleToolboxForMac
- nanopb
SPEC CHECKSUMS:
Firebase: 68afeeb05461db02d7c9e3215cda28068670f4aa
FirebaseAnalytics: b3628aea54c50464c32c393fb2ea032566e7ecc2
FirebaseCore: 62f1b792a49bb9e8b4073f24606d2c93ffc352f0
FirebaseInstanceID: f3f0657372592ecdfdfe2cac604a5a75758376a6
FSCalendar: a04b09f16f811bc92e82f3cf852a15225233b9d5
GoogleToolboxForMac: 91c824d21e85b31c2aae9bb011c5027c9b4e738f
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
PODFILE CHECKSUM: 0645cd0766eb63ba97b1572c6e02dd27818977f2
=======
- BoringSSL
- Firebase
- FirebaseAnalytics
- FirebaseAnalyticsInterop
- FirebaseAuthInterop
- FirebaseCore
- FirebaseFirestore
- FirebaseInAppMessaging
- FirebaseInAppMessagingDisplay
- FirebaseInstanceID
- FirebaseMessaging
- FSCalendar
- GoogleAppMeasurement
- GoogleUtilities
- "gRPC-C++"
- gRPC-Core
- leveldb-library
- nanopb
- Protobuf
SPEC CHECKSUMS:
BoringSSL: e10f92a27043805c01071fe815a5cd98ae8212e7
Firebase: 8bb9268bff82374f2cbaaabb143e725743c316ae
FirebaseAnalytics: c06f9d70577d79074214700a71fd5d39de5550fb
FirebaseAnalyticsInterop: e5f21be9af6548372e2f0815834ff909bff395a2
FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc
FirebaseCore: 35747502d9e8c6ee217385ad04446c7c2aaf9c5c
FirebaseFirestore: 58043a1c2d2c91efdaa8d8f385cdbaa2ce750cfe
FirebaseInAppMessaging: aa04bdbbee12aa132156e6085b3bfad7d6e0dcbb
FirebaseInAppMessagingDisplay: 5591606580c1ed8040fbf55c938a1ccc0caad3ef
FirebaseInstanceID: e2fa4cb35ef5558c200f7f0ad8a53e212215f93e
FirebaseMessaging: b412996f6a09337d232bb3a6676ce4d1f353d024
FSCalendar: 3a5ed3636e2ba1b83ebebfcf0c2603105a6f5efe
GoogleAppMeasurement: 98b71f5e04142793729a5ef23e5b96651ff4b70f
GoogleUtilities: 95996bea7c7d9b8fb811b7507669a4a8762f80c7
"gRPC-C++": 19eec1ffd34de29453f5fab5b4697ad0f240ad51
gRPC-Core: f4836515817c0eb479aeeb9cc27c91c4ba62a9f6
leveldb-library: 08cba283675b7ed2d99629a4bc5fd052cd2bb6a5
nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
Protobuf: 1eb9700044745f00181c136ef21b8ff3ad5a0fd5
PODFILE CHECKSUM: d95fe7eb8e6da99e76c0f8da06d60e8cb598748a
>>>>>>> ee3e0c5c054e15cc67030a8b4f62773866bbd4ce
COCOAPODS: 1.5.3

View File

@ -1,251 +0,0 @@
BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
licensing. Files that are completely new have a Google copyright and an ISC
license. This license is reproduced at the bottom of this file.
Contributors to BoringSSL are required to follow the CLA rules for Chromium:
https://cla.developers.google.com/clas
Files in third_party/ have their own licenses, as described therein. The MIT
license, for third_party/fiat, which, unlike other third_party directories, is
compiled into non-test libraries, is included below.
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the
OpenSSL License and the original SSLeay license apply to the toolkit. See below
for the actual license texts. Actually both licenses are BSD-style Open Source
licenses. In case of any license issues related to OpenSSL please contact
openssl-core@openssl.org.
The following are Google-internal bug numbers where explicit permission from
some authors is recorded for use of their work. (This is purely for our own
record keeping.)
27287199
27287880
27287883
OpenSSL License
---------------
/* ====================================================================
* Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
Original SSLeay License
-----------------------
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
ISC license used for completely new code in BoringSSL:
/* Copyright (c) 2015, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
The code in third_party/fiat carries the MIT license:
Copyright (c) 2015-2016 the fiat-crypto authors (see
https://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS).
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", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Licenses for support code
-------------------------
Parts of the TLS test suite are under the Go license. This code is not included
in BoringSSL (i.e. libcrypto and libssl) when compiled, however, so
distributing code linked against BoringSSL does not trigger this license:
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
BoringSSL uses the Chromium test infrastructure to run a continuous build,
trybots etc. The scripts which manage this, and the script for generating build
metadata, are under the Chromium license. Distributing code linked against
BoringSSL does not trigger this license.
Copyright 2015 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,33 +0,0 @@
# BoringSSL
BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.
Although BoringSSL is an open source project, it is not intended for general
use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing
so is likely to be frustrating because there are no guarantees of API or ABI
stability.
Programs ship their own copies of BoringSSL when they use it and we update
everything as needed when deciding to make API changes. This allows us to
mostly avoid compromises in the name of compatibility. It works for us, but it
may not work for you.
BoringSSL arose because Google used OpenSSL for many years in various ways and,
over time, built up a large number of patches that were maintained while
tracking upstream OpenSSL. As Google's product portfolio became more complex,
more copies of OpenSSL sprung up and the effort involved in maintaining all
these patches in multiple places was growing steadily.
Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's
not part of the NDK) and a number of other apps/programs.
There are other files in this directory which might be helpful:
* [PORTING.md](/PORTING.md): how to port OpenSSL-using code to BoringSSL.
* [BUILDING.md](/BUILDING.md): how to build BoringSSL
* [INCORPORATING.md](/INCORPORATING.md): how to incorporate BoringSSL into a project.
* [API-CONVENTIONS.md](/API-CONVENTIONS.md): general API conventions for BoringSSL consumers and developers.
* [STYLE.md](/STYLE.md): rules and guidelines for coding style.
* include/openssl: public headers with API documentation in comments. Also [available online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html).
* [FUZZING.md](/FUZZING.md): information about fuzzing BoringSSL.
* [CONTRIBUTING.md](/CONTRIBUTING.md): how to contribute to BoringSSL.

View File

@ -1,271 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <limits.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
{
return M_ASN1_BIT_STRING_set(x, d, len);
}
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
{
int ret, j, bits, len;
unsigned char *p, *d;
if (a == NULL)
return (0);
len = a->length;
if (len > 0) {
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
bits = (int)a->flags & 0x07;
} else {
for (; len > 0; len--) {
if (a->data[len - 1])
break;
}
j = a->data[len - 1];
if (j & 0x01)
bits = 0;
else if (j & 0x02)
bits = 1;
else if (j & 0x04)
bits = 2;
else if (j & 0x08)
bits = 3;
else if (j & 0x10)
bits = 4;
else if (j & 0x20)
bits = 5;
else if (j & 0x40)
bits = 6;
else if (j & 0x80)
bits = 7;
else
bits = 0; /* should not happen */
}
} else
bits = 0;
ret = 1 + len;
if (pp == NULL)
return (ret);
p = *pp;
*(p++) = (unsigned char)bits;
d = a->data;
OPENSSL_memcpy(p, d, len);
p += len;
if (len > 0)
p[-1] &= (0xff << bits);
*pp = p;
return (ret);
}
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
const unsigned char **pp, long len)
{
ASN1_BIT_STRING *ret = NULL;
const unsigned char *p;
unsigned char *s;
int padding;
if (len < 1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
goto err;
}
if (len > INT_MAX) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
goto err;
}
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = M_ASN1_BIT_STRING_new()) == NULL)
return (NULL);
} else
ret = (*a);
p = *pp;
padding = *(p++);
if (padding > 7) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
goto err;
}
/*
* We do this to preserve the settings. If we modify the settings, via
* the _set_bit function, we will recalculate on output
*/
ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); /* set */
if (len-- > 1) { /* using one because of the bits left byte */
s = (unsigned char *)OPENSSL_malloc((int)len);
if (s == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_memcpy(s, p, (int)len);
s[len - 1] &= (0xff << padding);
p += len;
} else
s = NULL;
ret->length = (int)len;
if (ret->data != NULL)
OPENSSL_free(ret->data);
ret->data = s;
ret->type = V_ASN1_BIT_STRING;
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_BIT_STRING_free(ret);
return (NULL);
}
/*
* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
*/
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
{
int w, v, iv;
unsigned char *c;
w = n / 8;
v = 1 << (7 - (n & 0x07));
iv = ~v;
if (!value)
v = 0;
if (a == NULL)
return 0;
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
if ((a->length < (w + 1)) || (a->data == NULL)) {
if (!value)
return (1); /* Don't need to set */
if (a->data == NULL)
c = (unsigned char *)OPENSSL_malloc(w + 1);
else
c = (unsigned char *)OPENSSL_realloc(a->data, w + 1);
if (c == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
if (w + 1 - a->length > 0)
OPENSSL_memset(c + a->length, 0, w + 1 - a->length);
a->data = c;
a->length = w + 1;
}
a->data[w] = ((a->data[w]) & iv) | v;
while ((a->length > 0) && (a->data[a->length - 1] == 0))
a->length--;
return (1);
}
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
{
int w, v;
w = n / 8;
v = 1 << (7 - (n & 0x07));
if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
return (0);
return ((a->data[w] & v) != 0);
}
/*
* Checks if the given bit string contains only bits specified by
* the flags vector. Returns 0 if there is at least one bit set in 'a'
* which is not specified in 'flags', 1 otherwise.
* 'len' is the length of 'flags'.
*/
int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
unsigned char *flags, int flags_len)
{
int i, ok;
/* Check if there is one bit set at all. */
if (!a || !a->data)
return 1;
/*
* Check each byte of the internal representation of the bit string.
*/
ok = 1;
for (i = 0; i < a->length && ok; ++i) {
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
/* We are done if there is an unneeded bit set. */
ok = (a->data[i] & mask) == 0;
}
return ok;
}

View File

@ -1,110 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
{
int r;
unsigned char *p;
r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
if (pp == NULL)
return (r);
p = *pp;
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
*(p++) = (unsigned char)a;
*pp = p;
return (r);
}
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
{
int ret = -1;
const unsigned char *p;
long len;
int inf, tag, xclass;
int i = 0;
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
i = ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != V_ASN1_BOOLEAN) {
i = ASN1_R_EXPECTING_A_BOOLEAN;
goto err;
}
if (len != 1) {
i = ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
goto err;
}
ret = (int)*(p++);
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
OPENSSL_PUT_ERROR(ASN1, i);
return (ret);
}

View File

@ -1,297 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <limits.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
#ifndef NO_OLD_ASN1
# ifndef OPENSSL_NO_FP_API
void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x)
{
BIO *b;
void *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
return (NULL);
}
BIO_set_fp(b, in, BIO_NOCLOSE);
ret = ASN1_d2i_bio(xnew, d2i, b, x);
BIO_free(b);
return (ret);
}
# endif
void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret = NULL;
int len;
len = asn1_d2i_read_bio(in, &b);
if (len < 0)
goto err;
p = (unsigned char *)b->data;
ret = d2i(x, &p, len);
err:
if (b != NULL)
BUF_MEM_free(b);
return (ret);
}
#endif
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret = NULL;
int len;
len = asn1_d2i_read_bio(in, &b);
if (len < 0)
goto err;
p = (const unsigned char *)b->data;
ret = ASN1_item_d2i(x, &p, len, it);
err:
if (b != NULL)
BUF_MEM_free(b);
return (ret);
}
#ifndef OPENSSL_NO_FP_API
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
{
BIO *b;
char *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
return (NULL);
}
BIO_set_fp(b, in, BIO_NOCLOSE);
ret = ASN1_item_d2i_bio(it, b, x);
BIO_free(b);
return (ret);
}
#endif
typedef struct asn1_const_ctx_st
{
const unsigned char *p;/* work char pointer */
int eos; /* end of sequence read for indefinite encoding */
int error; /* error code to use when returning an error */
int inf; /* constructed if 0x20, indefinite is 0x21 */
int tag; /* tag from last 'get object' */
int xclass; /* class from last 'get object' */
long slen; /* length of last 'get object' */
const unsigned char *max; /* largest value of p allowed */
const unsigned char *q;/* temporary variable */
const unsigned char **pp;/* variable */
int line; /* used in error processing */
} ASN1_const_CTX;
#define HEADER_SIZE 8
#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
BUF_MEM *b;
unsigned char *p;
int i;
ASN1_const_CTX c;
size_t want = HEADER_SIZE;
int eos = 0;
size_t off = 0;
size_t len = 0;
b = BUF_MEM_new();
if (b == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
ERR_clear_error();
for (;;) {
if (want >= (len - off)) {
want -= (len - off);
if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
i = BIO_read(in, &(b->data[len]), want);
if ((i < 0) && ((len - off) == 0)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
if (i > 0) {
if (len + i < len) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
goto err;
}
len += i;
}
}
/* else data already loaded */
p = (unsigned char *)&(b->data[off]);
c.p = p;
c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass),
len - off);
if (c.inf & 0x80) {
uint32_t e;
e = ERR_GET_REASON(ERR_peek_error());
if (e != ASN1_R_TOO_LONG)
goto err;
else
ERR_clear_error(); /* clear error */
}
i = c.p - p; /* header length */
off += i; /* end of data */
if (c.inf & 1) {
/* no data body so go round again */
eos++;
if (eos < 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
goto err;
}
want = HEADER_SIZE;
} else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) {
/* eos value, so go back and read another header */
eos--;
if (eos <= 0)
break;
else
want = HEADER_SIZE;
} else {
/* suck in c.slen bytes of data */
want = c.slen;
if (want > (len - off)) {
size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;
want -= (len - off);
if (want > INT_MAX /* BIO_read takes an int length */ ||
len + want < len) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
goto err;
}
while (want > 0) {
/*
* Read content in chunks of increasing size
* so we can return an error for EOF without
* having to allocate the entire content length
* in one go.
*/
size_t chunk = want > chunk_max ? chunk_max : want;
if (!BUF_MEM_grow_clean(b, len + chunk)) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
want -= chunk;
while (chunk > 0) {
i = BIO_read(in, &(b->data[len]), chunk);
if (i <= 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
/*
* This can't overflow because |len+want| didn't
* overflow.
*/
len += i;
chunk -= i;
}
if (chunk_max < INT_MAX/2)
chunk_max *= 2;
}
}
if (off + c.slen < off) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
goto err;
}
off += c.slen;
if (eos <= 0) {
break;
} else
want = HEADER_SIZE;
}
}
if (off > INT_MAX) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
goto err;
}
*pb = b;
return off;
err:
if (b != NULL)
BUF_MEM_free(b);
return -1;
}

View File

@ -1,111 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
{
unsigned char *b, *p;
const unsigned char *p2;
int i;
char *ret;
if (x == NULL)
return (NULL);
i = i2d(x, NULL);
b = OPENSSL_malloc(i + 10);
if (b == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return (NULL);
}
p = b;
i = i2d(x, &p);
p2 = b;
ret = d2i(NULL, &p2, i);
OPENSSL_free(b);
return (ret);
}
/*
* ASN1_ITEM version of dup: this follows the model above except we don't
* need to allocate the buffer. At some point this could be rewritten to
* directly dup the underlying structure instead of doing and encode and
* decode.
*/
void *ASN1_item_dup(const ASN1_ITEM *it, void *x)
{
unsigned char *b = NULL;
const unsigned char *p;
long i;
void *ret;
if (x == NULL)
return (NULL);
i = ASN1_item_i2d(x, &b, it);
if (b == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return (NULL);
}
p = b;
ret = ASN1_item_d2i(NULL, &p, i, it);
OPENSSL_free(b);
return (ret);
}

View File

@ -1,195 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <limits.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
/*
* Code for ENUMERATED type: identical to INTEGER apart from a different tag.
* for comments on encoding see a_int.c
*/
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
{
int j, k;
unsigned int i;
unsigned char buf[sizeof(long) + 1];
long d;
a->type = V_ASN1_ENUMERATED;
if (a->length < (int)(sizeof(long) + 1)) {
if (a->data != NULL)
OPENSSL_free(a->data);
if ((a->data =
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
OPENSSL_memset((char *)a->data, 0, sizeof(long) + 1);
}
if (a->data == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return (0);
}
d = v;
if (d < 0) {
d = -d;
a->type = V_ASN1_NEG_ENUMERATED;
}
for (i = 0; i < sizeof(long); i++) {
if (d == 0)
break;
buf[i] = (int)d & 0xff;
d >>= 8;
}
j = 0;
for (k = i - 1; k >= 0; k--)
a->data[j++] = buf[k];
a->length = j;
return (1);
}
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
{
int neg = 0, i;
if (a == NULL)
return (0L);
i = a->type;
if (i == V_ASN1_NEG_ENUMERATED)
neg = 1;
else if (i != V_ASN1_ENUMERATED)
return -1;
OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) >= sizeof(long),
long_larger_than_uint64_t);
if (a->length > (int)sizeof(uint64_t)) {
/* hmm... a bit ugly */
return -1;
}
uint64_t r64 = 0;
if (a->data != NULL) {
for (i = 0; i < a->length; i++) {
r64 <<= 8;
r64 |= (unsigned char)a->data[i];
}
if (r64 > LONG_MAX) {
return -1;
}
}
long r = (long) r64;
if (neg)
r = -r;
return r;
}
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
{
ASN1_ENUMERATED *ret;
int len, j;
if (ai == NULL)
ret = M_ASN1_ENUMERATED_new();
else
ret = ai;
if (ret == NULL) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
goto err;
}
if (BN_is_negative(bn))
ret->type = V_ASN1_NEG_ENUMERATED;
else
ret->type = V_ASN1_ENUMERATED;
j = BN_num_bits(bn);
len = ((j == 0) ? 0 : ((j / 8) + 1));
if (ret->length < len + 4) {
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
if (!new_data) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->data = new_data;
}
ret->length = BN_bn2bin(bn, ret->data);
return (ret);
err:
if (ret != ai)
M_ASN1_ENUMERATED_free(ret);
return (NULL);
}
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
{
BIGNUM *ret;
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
else if (ai->type == V_ASN1_NEG_ENUMERATED)
BN_set_negative(ret, 1);
return (ret);
}

View File

@ -1,261 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <time.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "asn1_locl.h"
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
{
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
char *a;
int n, i, l, o;
if (d->type != V_ASN1_GENERALIZEDTIME)
return (0);
l = d->length;
a = (char *)d->data;
o = 0;
/*
* GENERALIZEDTIME is similar to UTCTIME except the year is represented
* as YYYY. This stuff treats everything as a two digit field so make
* first two fields 00 to 99
*/
if (l < 13)
goto err;
for (i = 0; i < 7; i++) {
if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
i++;
if (tm)
tm->tm_sec = 0;
break;
}
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = a[o] - '0';
if (++o > l)
goto err;
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = (n * 10) + a[o] - '0';
if (++o > l)
goto err;
if ((n < min[i]) || (n > max[i]))
goto err;
if (tm) {
switch (i) {
case 0:
tm->tm_year = n * 100 - 1900;
break;
case 1:
tm->tm_year += n;
break;
case 2:
tm->tm_mon = n - 1;
break;
case 3:
tm->tm_mday = n;
break;
case 4:
tm->tm_hour = n;
break;
case 5:
tm->tm_min = n;
break;
case 6:
tm->tm_sec = n;
break;
}
}
}
/*
* Optional fractional seconds: decimal point followed by one or more
* digits.
*/
if (a[o] == '.') {
if (++o > l)
goto err;
i = o;
while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
o++;
/* Must have at least one digit after decimal point */
if (i == o)
goto err;
}
if (a[o] == 'Z')
o++;
else if ((a[o] == '+') || (a[o] == '-')) {
int offsign = a[o] == '-' ? 1 : -1, offset = 0;
o++;
if (o + 4 > l)
goto err;
for (i = 7; i < 9; i++) {
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = a[o] - '0';
o++;
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = (n * 10) + a[o] - '0';
if ((n < min[i]) || (n > max[i]))
goto err;
if (tm) {
if (i == 7)
offset = n * 3600;
else if (i == 8)
offset += n * 60;
}
o++;
}
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
return 0;
} else if (a[o]) {
/* Missing time zone information. */
goto err;
}
return (o == l);
err:
return (0);
}
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
{
return asn1_generalizedtime_to_tm(NULL, d);
}
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
{
ASN1_GENERALIZEDTIME t;
t.type = V_ASN1_GENERALIZEDTIME;
t.length = strlen(str);
t.data = (unsigned char *)str;
if (ASN1_GENERALIZEDTIME_check(&t)) {
if (s != NULL) {
if (!ASN1_STRING_set((ASN1_STRING *)s,
(unsigned char *)str, t.length))
return 0;
s->type = V_ASN1_GENERALIZEDTIME;
}
return (1);
} else
return (0);
}
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
time_t t)
{
return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
}
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
time_t t, int offset_day,
long offset_sec)
{
char *p;
struct tm *ts;
struct tm data;
size_t len = 20;
ASN1_GENERALIZEDTIME *tmps = NULL;
if (s == NULL)
tmps = ASN1_GENERALIZEDTIME_new();
else
tmps = s;
if (tmps == NULL)
return NULL;
ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL)
goto err;
if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
goto err;
}
p = (char *)tmps->data;
if ((p == NULL) || ((size_t)tmps->length < len)) {
p = OPENSSL_malloc(len);
if (p == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_free(tmps->data);
tmps->data = (unsigned char *)p;
}
BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900,
ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
ts->tm_sec);
tmps->length = strlen(p);
tmps->type = V_ASN1_GENERALIZEDTIME;
return tmps;
err:
if (s == NULL)
ASN1_GENERALIZEDTIME_free(tmps);
return NULL;
}

View File

@ -1,150 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
return (0);
}
BIO_set_fp(b, out, BIO_NOCLOSE);
ret = ASN1_i2d_bio(i2d, b, x);
BIO_free(b);
return (ret);
}
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, void *x)
{
char *b;
unsigned char *p;
int i, j = 0, n, ret = 1;
n = i2d(x, NULL);
if (n <= 0)
return 0;
b = (char *)OPENSSL_malloc(n);
if (b == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return (0);
}
p = (unsigned char *)b;
i2d(x, &p);
for (;;) {
i = BIO_write(out, &(b[j]), n);
if (i == n)
break;
if (i <= 0) {
ret = 0;
break;
}
j += i;
n -= i;
}
OPENSSL_free(b);
return (ret);
}
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
return (0);
}
BIO_set_fp(b, out, BIO_NOCLOSE);
ret = ASN1_item_i2d_bio(it, b, x);
BIO_free(b);
return (ret);
}
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
{
unsigned char *b = NULL;
int i, j = 0, n, ret = 1;
n = ASN1_item_i2d(x, &b, it);
if (b == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return (0);
}
for (;;) {
i = BIO_write(out, &(b[j]), n);
if (i == n)
break;
if (i <= 0) {
ret = 0;
break;
}
j += i;
n -= i;
}
OPENSSL_free(b);
return (ret);
}

View File

@ -1,479 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <limits.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
{
return M_ASN1_INTEGER_dup(x);
}
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
{
int neg, ret;
/* Compare signs */
neg = x->type & V_ASN1_NEG;
if (neg != (y->type & V_ASN1_NEG)) {
if (neg)
return -1;
else
return 1;
}
ret = ASN1_STRING_cmp(x, y);
if (neg)
return -ret;
else
return ret;
}
/*
* This converts an ASN1 INTEGER into its content encoding.
* The internal representation is an ASN1_STRING whose data is a big endian
* representation of the value, ignoring the sign. The sign is determined by
* the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
*
* Positive integers are no problem: they are almost the same as the DER
* encoding, except if the first byte is >= 0x80 we need to add a zero pad.
*
* Negative integers are a bit trickier...
* The DER representation of negative integers is in 2s complement form.
* The internal form is converted by complementing each octet and finally
* adding one to the result. This can be done less messily with a little trick.
* If the internal form has trailing zeroes then they will become FF by the
* complement and 0 by the add one (due to carry) so just copy as many trailing
* zeros to the destination as there are in the source. The carry will add one
* to the last none zero octet: so complement this octet and add one and finally
* complement any left over until you get to the start of the string.
*
* Padding is a little trickier too. If the first bytes is > 0x80 then we pad
* with 0xff. However if the first byte is 0x80 and one of the following bytes
* is non-zero we pad with 0xff. The reason for this distinction is that 0x80
* followed by optional zeros isn't padded.
*/
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
{
int pad = 0, ret, i, neg;
unsigned char *p, *n, pb = 0;
if (a == NULL)
return (0);
neg = a->type & V_ASN1_NEG;
if (a->length == 0)
ret = 1;
else {
ret = a->length;
i = a->data[0];
if (ret == 1 && i == 0)
neg = 0;
if (!neg && (i > 127)) {
pad = 1;
pb = 0;
} else if (neg) {
if (i > 128) {
pad = 1;
pb = 0xFF;
} else if (i == 128) {
/*
* Special case: if any other bytes non zero we pad:
* otherwise we don't.
*/
for (i = 1; i < a->length; i++)
if (a->data[i]) {
pad = 1;
pb = 0xFF;
break;
}
}
}
ret += pad;
}
if (pp == NULL)
return (ret);
p = *pp;
if (pad)
*(p++) = pb;
if (a->length == 0)
*(p++) = 0;
else if (!neg)
OPENSSL_memcpy(p, a->data, (unsigned int)a->length);
else {
/* Begin at the end of the encoding */
n = a->data + a->length - 1;
p += a->length - 1;
i = a->length;
/* Copy zeros to destination as long as source is zero */
while (!*n && i > 1) {
*(p--) = 0;
n--;
i--;
}
/* Complement and increment next octet */
*(p--) = ((*(n--)) ^ 0xff) + 1;
i--;
/* Complement any octets left */
for (; i > 0; i--)
*(p--) = *(n--) ^ 0xff;
}
*pp += ret;
return (ret);
}
/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
long len)
{
ASN1_INTEGER *ret = NULL;
const unsigned char *p, *pend;
unsigned char *to, *s;
int i;
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = M_ASN1_INTEGER_new()) == NULL)
return (NULL);
ret->type = V_ASN1_INTEGER;
} else
ret = (*a);
p = *pp;
pend = p + len;
/*
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
* a missing NULL parameter.
*/
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
to = s;
if (!len) {
/*
* Strictly speaking this is an illegal INTEGER but we tolerate it.
*/
ret->type = V_ASN1_INTEGER;
} else if (*p & 0x80) { /* a negative number */
ret->type = V_ASN1_NEG_INTEGER;
if ((*p == 0xff) && (len != 1)) {
p++;
len--;
}
i = len;
p += i - 1;
to += i - 1;
while ((!*p) && i) {
*(to--) = 0;
i--;
p--;
}
/*
* Special case: if all zeros then the number will be of the form FF
* followed by n zero bytes: this corresponds to 1 followed by n zero
* bytes. We've already written n zeros so we just append an extra
* one and set the first byte to a 1. This is treated separately
* because it is the only case where the number of bytes is larger
* than len.
*/
if (!i) {
*s = 1;
s[len] = 0;
len++;
} else {
*(to--) = (*(p--) ^ 0xff) + 1;
i--;
for (; i > 0; i--)
*(to--) = *(p--) ^ 0xff;
}
} else {
ret->type = V_ASN1_INTEGER;
if ((*p == 0) && (len != 1)) {
p++;
len--;
}
OPENSSL_memcpy(s, p, (int)len);
}
if (ret->data != NULL)
OPENSSL_free(ret->data);
ret->data = s;
ret->length = (int)len;
if (a != NULL)
(*a) = ret;
*pp = pend;
return (ret);
err:
OPENSSL_PUT_ERROR(ASN1, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_INTEGER_free(ret);
return (NULL);
}
/*
* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1
* integers: some broken software can encode a positive INTEGER with its MSB
* set as negative (it doesn't add a padding zero).
*/
ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
long length)
{
ASN1_INTEGER *ret = NULL;
const unsigned char *p;
unsigned char *s;
long len;
int inf, tag, xclass;
int i;
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = M_ASN1_INTEGER_new()) == NULL)
return (NULL);
ret->type = V_ASN1_INTEGER;
} else
ret = (*a);
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
i = ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != V_ASN1_INTEGER) {
i = ASN1_R_EXPECTING_AN_INTEGER;
goto err;
}
/*
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
* a missing NULL parameter.
*/
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
ret->type = V_ASN1_INTEGER;
if (len) {
if ((*p == 0) && (len != 1)) {
p++;
len--;
}
OPENSSL_memcpy(s, p, (int)len);
p += len;
}
if (ret->data != NULL)
OPENSSL_free(ret->data);
ret->data = s;
ret->length = (int)len;
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
OPENSSL_PUT_ERROR(ASN1, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_INTEGER_free(ret);
return (NULL);
}
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
{
if (v >= 0) {
return ASN1_INTEGER_set_uint64(a, (uint64_t) v);
}
if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t) v)) {
return 0;
}
a->type = V_ASN1_NEG_INTEGER;
return 1;
}
int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v)
{
uint8_t *const newdata = OPENSSL_malloc(sizeof(uint64_t));
if (newdata == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
OPENSSL_free(out->data);
out->data = newdata;
v = CRYPTO_bswap8(v);
memcpy(out->data, &v, sizeof(v));
out->type = V_ASN1_INTEGER;
size_t leading_zeros;
for (leading_zeros = 0; leading_zeros < sizeof(uint64_t) - 1;
leading_zeros++) {
if (out->data[leading_zeros] != 0) {
break;
}
}
out->length = sizeof(uint64_t) - leading_zeros;
OPENSSL_memmove(out->data, out->data + leading_zeros, out->length);
return 1;
}
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
{
int neg = 0, i;
if (a == NULL)
return (0L);
i = a->type;
if (i == V_ASN1_NEG_INTEGER)
neg = 1;
else if (i != V_ASN1_INTEGER)
return -1;
OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) >= sizeof(long),
long_larger_than_uint64_t);
if (a->length > (int)sizeof(uint64_t)) {
/* hmm... a bit ugly, return all ones */
return -1;
}
uint64_t r64 = 0;
if (a->data != NULL) {
for (i = 0; i < a->length; i++) {
r64 <<= 8;
r64 |= (unsigned char)a->data[i];
}
if (r64 > LONG_MAX) {
return -1;
}
}
long r = (long) r64;
if (neg)
r = -r;
return r;
}
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
{
ASN1_INTEGER *ret;
int len, j;
if (ai == NULL)
ret = M_ASN1_INTEGER_new();
else
ret = ai;
if (ret == NULL) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
goto err;
}
if (BN_is_negative(bn) && !BN_is_zero(bn))
ret->type = V_ASN1_NEG_INTEGER;
else
ret->type = V_ASN1_INTEGER;
j = BN_num_bits(bn);
len = ((j == 0) ? 0 : ((j / 8) + 1));
if (ret->length < len + 4) {
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
if (!new_data) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->data = new_data;
}
ret->length = BN_bn2bin(bn, ret->data);
/* Correct zero case */
if (!ret->length) {
ret->data[0] = 0;
ret->length = 1;
}
return (ret);
err:
if (ret != ai)
M_ASN1_INTEGER_free(ret);
return (NULL);
}
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
{
BIGNUM *ret;
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
else if (ai->type == V_ASN1_NEG_INTEGER)
BN_set_negative(ret, 1);
return (ret);
}

View File

@ -1,411 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "asn1_locl.h"
static int traverse_string(const unsigned char *p, int len, int inform,
int (*rfunc) (uint32_t value, void *in),
void *arg);
static int in_utf8(uint32_t value, void *arg);
static int out_utf8(uint32_t value, void *arg);
static int type_str(uint32_t value, void *arg);
static int cpy_asc(uint32_t value, void *arg);
static int cpy_bmp(uint32_t value, void *arg);
static int cpy_univ(uint32_t value, void *arg);
static int cpy_utf8(uint32_t value, void *arg);
static int is_printable(uint32_t value);
/*
* These functions take a string in UTF8, ASCII or multibyte form and a mask
* of permissible ASN1 string types. It then works out the minimal type
* (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and
* creates a string of the correct type with the supplied data. Yes this is
* horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
* size limits too.
*/
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
int inform, unsigned long mask)
{
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
}
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
int inform, unsigned long mask,
long minsize, long maxsize)
{
int str_type;
int ret;
char free_out;
int outform, outlen = 0;
ASN1_STRING *dest;
unsigned char *p;
int nchar;
char strbuf[32];
int (*cpyfunc) (uint32_t, void *) = NULL;
if (len == -1)
len = strlen((const char *)in);
if (!mask)
mask = DIRSTRING_TYPE;
/* First do a string check and work out the number of characters */
switch (inform) {
case MBSTRING_BMP:
if (len & 1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
return -1;
}
nchar = len >> 1;
break;
case MBSTRING_UNIV:
if (len & 3) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
return -1;
}
nchar = len >> 2;
break;
case MBSTRING_UTF8:
nchar = 0;
/* This counts the characters and does utf8 syntax checking */
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
if (ret < 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING);
return -1;
}
break;
case MBSTRING_ASC:
nchar = len;
break;
default:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
if ((minsize > 0) && (nchar < minsize)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
ERR_add_error_data(2, "minsize=", strbuf);
return -1;
}
if ((maxsize > 0) && (nchar > maxsize)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
ERR_add_error_data(2, "maxsize=", strbuf);
return -1;
}
/* Now work out minimal type (if any) */
if (traverse_string(in, len, inform, type_str, &mask) < 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
return -1;
}
/* Now work out output format and string type */
outform = MBSTRING_ASC;
if (mask & B_ASN1_PRINTABLESTRING)
str_type = V_ASN1_PRINTABLESTRING;
else if (mask & B_ASN1_IA5STRING)
str_type = V_ASN1_IA5STRING;
else if (mask & B_ASN1_T61STRING)
str_type = V_ASN1_T61STRING;
else if (mask & B_ASN1_BMPSTRING) {
str_type = V_ASN1_BMPSTRING;
outform = MBSTRING_BMP;
} else if (mask & B_ASN1_UNIVERSALSTRING) {
str_type = V_ASN1_UNIVERSALSTRING;
outform = MBSTRING_UNIV;
} else {
str_type = V_ASN1_UTF8STRING;
outform = MBSTRING_UTF8;
}
if (!out)
return str_type;
if (*out) {
free_out = 0;
dest = *out;
if (dest->data) {
dest->length = 0;
OPENSSL_free(dest->data);
dest->data = NULL;
}
dest->type = str_type;
} else {
free_out = 1;
dest = ASN1_STRING_type_new(str_type);
if (!dest) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
*out = dest;
}
/* If both the same type just copy across */
if (inform == outform) {
if (!ASN1_STRING_set(dest, in, len)) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
return str_type;
}
/* Work out how much space the destination will need */
switch (outform) {
case MBSTRING_ASC:
outlen = nchar;
cpyfunc = cpy_asc;
break;
case MBSTRING_BMP:
outlen = nchar << 1;
cpyfunc = cpy_bmp;
break;
case MBSTRING_UNIV:
outlen = nchar << 2;
cpyfunc = cpy_univ;
break;
case MBSTRING_UTF8:
outlen = 0;
traverse_string(in, len, inform, out_utf8, &outlen);
cpyfunc = cpy_utf8;
break;
}
if (!(p = OPENSSL_malloc(outlen + 1))) {
if (free_out)
ASN1_STRING_free(dest);
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
dest->length = outlen;
dest->data = p;
p[outlen] = 0;
traverse_string(in, len, inform, cpyfunc, &p);
return str_type;
}
/*
* This function traverses a string and passes the value of each character to
* an optional function along with a void * argument.
*/
static int traverse_string(const unsigned char *p, int len, int inform,
int (*rfunc) (uint32_t value, void *in),
void *arg)
{
uint32_t value;
int ret;
while (len) {
if (inform == MBSTRING_ASC) {
value = *p++;
len--;
} else if (inform == MBSTRING_BMP) {
value = *p++ << 8;
value |= *p++;
len -= 2;
} else if (inform == MBSTRING_UNIV) {
value = ((uint32_t)*p++) << 24;
value |= ((uint32_t)*p++) << 16;
value |= *p++ << 8;
value |= *p++;
len -= 4;
} else {
ret = UTF8_getc(p, len, &value);
if (ret < 0)
return -1;
len -= ret;
p += ret;
}
if (rfunc) {
ret = rfunc(value, arg);
if (ret <= 0)
return ret;
}
}
return 1;
}
/* Various utility functions for traverse_string */
/* Just count number of characters */
static int in_utf8(uint32_t value, void *arg)
{
int *nchar;
nchar = arg;
(*nchar)++;
return 1;
}
/* Determine size of output as a UTF8 String */
static int out_utf8(uint32_t value, void *arg)
{
int *outlen;
outlen = arg;
*outlen += UTF8_putc(NULL, -1, value);
return 1;
}
/*
* Determine the "type" of a string: check each character against a supplied
* "mask".
*/
static int type_str(uint32_t value, void *arg)
{
unsigned long types;
types = *((unsigned long *)arg);
if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
types &= ~B_ASN1_PRINTABLESTRING;
if ((types & B_ASN1_IA5STRING) && (value > 127))
types &= ~B_ASN1_IA5STRING;
if ((types & B_ASN1_T61STRING) && (value > 0xff))
types &= ~B_ASN1_T61STRING;
if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
types &= ~B_ASN1_BMPSTRING;
if (!types)
return -1;
*((unsigned long *)arg) = types;
return 1;
}
/* Copy one byte per character ASCII like strings */
static int cpy_asc(uint32_t value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q = (unsigned char)value;
(*p)++;
return 1;
}
/* Copy two byte per character BMPStrings */
static int cpy_bmp(uint32_t value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q++ = (unsigned char)((value >> 8) & 0xff);
*q = (unsigned char)(value & 0xff);
*p += 2;
return 1;
}
/* Copy four byte per character UniversalStrings */
static int cpy_univ(uint32_t value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q++ = (unsigned char)((value >> 24) & 0xff);
*q++ = (unsigned char)((value >> 16) & 0xff);
*q++ = (unsigned char)((value >> 8) & 0xff);
*q = (unsigned char)(value & 0xff);
*p += 4;
return 1;
}
/* Copy to a UTF8String */
static int cpy_utf8(uint32_t value, void *arg)
{
unsigned char **p;
int ret;
p = arg;
/* We already know there is enough room so pass 0xff as the length */
ret = UTF8_putc(*p, 0xff, value);
*p += ret;
return 1;
}
/* Return 1 if the character is permitted in a PrintableString */
static int is_printable(uint32_t value)
{
int ch;
if (value > 0x7f)
return 0;
ch = (int)value;
/*
* Note: we can't use 'isalnum' because certain accented characters may
* count as alphanumeric in some environments.
*/
if ((ch >= 'a') && (ch <= 'z'))
return 1;
if ((ch >= 'A') && (ch <= 'Z'))
return 1;
if ((ch >= '0') && (ch <= '9'))
return 1;
if ((ch == ' ') || strchr("'()+,-./:=?", ch))
return 1;
return 0;
}

View File

@ -1,275 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <limits.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include "../internal.h"
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
{
unsigned char *p;
int objsize;
if ((a == NULL) || (a->data == NULL))
return (0);
objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
if (pp == NULL || objsize == -1)
return objsize;
p = *pp;
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
OPENSSL_memcpy(p, a->data, a->length);
p += a->length;
*pp = p;
return (objsize);
}
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
{
return OBJ_obj2txt(buf, buf_len, a, 0);
}
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
{
char buf[80], *p = buf;
int i;
if ((a == NULL) || (a->data == NULL))
return (BIO_write(bp, "NULL", 4));
i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
if (i > (int)(sizeof(buf) - 1)) {
p = OPENSSL_malloc(i + 1);
if (!p)
return -1;
i2t_ASN1_OBJECT(p, i + 1, a);
}
if (i <= 0)
return BIO_write(bp, "<INVALID>", 9);
BIO_write(bp, p, i);
if (p != buf)
OPENSSL_free(p);
return (i);
}
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long length)
{
const unsigned char *p;
long len;
int tag, xclass;
int inf, i;
ASN1_OBJECT *ret = NULL;
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
i = ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != V_ASN1_OBJECT) {
i = ASN1_R_EXPECTING_AN_OBJECT;
goto err;
}
ret = c2i_ASN1_OBJECT(a, &p, len);
if (ret)
*pp = p;
return ret;
err:
OPENSSL_PUT_ERROR(ASN1, i);
return (NULL);
}
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long len)
{
ASN1_OBJECT *ret = NULL;
const unsigned char *p;
unsigned char *data;
int i, length;
/*
* Sanity check OID encoding. Need at least one content octet. MSB must
* be clear in the last octet. can't have leading 0x80 in subidentifiers,
* see: X.690 8.19.2
*/
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
p[len - 1] & 0x80) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
return NULL;
}
/* Now 0 < len <= INT_MAX, so the cast is safe. */
length = (int)len;
for (i = 0; i < length; i++, p++) {
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
return NULL;
}
}
/*
* only the ASN1_OBJECTs from the 'table' will have values for ->sn or
* ->ln
*/
if ((a == NULL) || ((*a) == NULL) ||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
if ((ret = ASN1_OBJECT_new()) == NULL)
return (NULL);
} else
ret = (*a);
p = *pp;
/* detach data from object */
data = (unsigned char *)ret->data;
ret->data = NULL;
/* once detached we can change it */
if ((data == NULL) || (ret->length < length)) {
ret->length = 0;
if (data != NULL)
OPENSSL_free(data);
data = (unsigned char *)OPENSSL_malloc(length);
if (data == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
}
OPENSSL_memcpy(data, p, length);
/* reattach data to object, after which it remains const */
ret->data = data;
ret->length = length;
ret->sn = NULL;
ret->ln = NULL;
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
p += length;
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
OPENSSL_PUT_ERROR(ASN1, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
ASN1_OBJECT_free(ret);
return (NULL);
}
ASN1_OBJECT *ASN1_OBJECT_new(void)
{
ASN1_OBJECT *ret;
ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
if (ret == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->length = 0;
ret->data = NULL;
ret->nid = 0;
ret->sn = NULL;
ret->ln = NULL;
ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
return (ret);
}
void ASN1_OBJECT_free(ASN1_OBJECT *a)
{
if (a == NULL)
return;
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
#ifndef CONST_STRICT /* disable purely for compile-time strict
* const checking. Doing this on a "real"
* compile will cause memory leaks */
if (a->sn != NULL)
OPENSSL_free((void *)a->sn);
if (a->ln != NULL)
OPENSSL_free((void *)a->ln);
#endif
a->sn = a->ln = NULL;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
if (a->data != NULL)
OPENSSL_free((void *)a->data);
a->data = NULL;
a->length = 0;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
OPENSSL_free(a);
}
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
const char *sn, const char *ln)
{
ASN1_OBJECT o;
o.sn = sn;
o.ln = ln;
o.data = data;
o.nid = nid;
o.length = len;
o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
return (OBJ_dup(&o));
}

View File

@ -1,77 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
{
return M_ASN1_OCTET_STRING_dup(x);
}
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
const ASN1_OCTET_STRING *b)
{
return M_ASN1_OCTET_STRING_cmp(a, b);
}
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d,
int len)
{
return M_ASN1_OCTET_STRING_set(x, d, len);
}

View File

@ -1,93 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int ASN1_PRINTABLE_type(const unsigned char *s, int len)
{
int c;
int ia5 = 0;
int t61 = 0;
if (len <= 0)
len = -1;
if (s == NULL)
return (V_ASN1_PRINTABLESTRING);
while ((*s) && (len-- != 0)) {
c = *(s++);
if (!(((c >= 'a') && (c <= 'z')) ||
((c >= 'A') && (c <= 'Z')) ||
(c == ' ') ||
((c >= '0') && (c <= '9')) ||
(c == ' ') || (c == '\'') ||
(c == '(') || (c == ')') ||
(c == '+') || (c == ',') ||
(c == '-') || (c == '.') ||
(c == '/') || (c == ':') || (c == '=') || (c == '?')))
ia5 = 1;
if (c & 0x80)
t61 = 1;
}
if (t61)
return (V_ASN1_T61STRING);
if (ia5)
return (V_ASN1_IA5STRING);
return (V_ASN1_PRINTABLESTRING);
}

View File

@ -1,312 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <stdlib.h> /* For bsearch */
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/stack.h>
DEFINE_STACK_OF(ASN1_STRING_TABLE)
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
static void st_free(ASN1_STRING_TABLE *tbl);
/*
* This is the global mask for the mbstring functions: this is use to mask
* out certain types (such as BMPString and UTF8String) because certain
* software (e.g. Netscape) has problems with them.
*/
static unsigned long global_mask = B_ASN1_UTF8STRING;
void ASN1_STRING_set_default_mask(unsigned long mask)
{
global_mask = mask;
}
unsigned long ASN1_STRING_get_default_mask(void)
{
return global_mask;
}
/*
* This function sets the default to various "flavours" of configuration.
* based on an ASCII string. Currently this is: MASK:XXXX : a numerical mask
* value. nobmp : Don't use BMPStrings (just Printable, T61). pkix : PKIX
* recommendation in RFC2459. utf8only : only use UTF8Strings (RFC2459
* recommendation for 2004). default: the default value, Printable, T61, BMP.
*/
int ASN1_STRING_set_default_mask_asc(const char *p)
{
unsigned long mask;
char *end;
if (!strncmp(p, "MASK:", 5)) {
if (!p[5])
return 0;
mask = strtoul(p + 5, &end, 0);
if (*end)
return 0;
} else if (!strcmp(p, "nombstr"))
mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
else if (!strcmp(p, "pkix"))
mask = ~((unsigned long)B_ASN1_T61STRING);
else if (!strcmp(p, "utf8only"))
mask = B_ASN1_UTF8STRING;
else if (!strcmp(p, "default"))
mask = 0xFFFFFFFFL;
else
return 0;
ASN1_STRING_set_default_mask(mask);
return 1;
}
/*
* The following function generates an ASN1_STRING based on limits in a
* table. Frequently the types and length of an ASN1_STRING are restricted by
* a corresponding OID. For example certificates and certificate requests.
*/
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
const unsigned char *in, int inlen,
int inform, int nid)
{
ASN1_STRING_TABLE *tbl;
ASN1_STRING *str = NULL;
unsigned long mask;
int ret;
if (!out)
out = &str;
tbl = ASN1_STRING_TABLE_get(nid);
if (tbl) {
mask = tbl->mask;
if (!(tbl->flags & STABLE_NO_MASK))
mask &= global_mask;
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
tbl->minsize, tbl->maxsize);
} else
ret =
ASN1_mbstring_copy(out, in, inlen, inform,
DIRSTRING_TYPE & global_mask);
if (ret <= 0)
return NULL;
return *out;
}
/*
* Now the tables and helper functions for the string table:
*/
/* size limits: this stuff is taken straight from RFC3280 */
#define ub_name 32768
#define ub_common_name 64
#define ub_locality_name 128
#define ub_state_name 128
#define ub_organization_name 64
#define ub_organization_unit_name 64
#define ub_title 64
#define ub_email_address 128
#define ub_serial_number 64
/* This table must be kept in NID order */
static const ASN1_STRING_TABLE tbl_standard[] = {
{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
0},
{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
STABLE_NO_MASK},
{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
STABLE_NO_MASK},
{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
};
static int sk_table_cmp(const ASN1_STRING_TABLE **a,
const ASN1_STRING_TABLE **b)
{
return (*a)->nid - (*b)->nid;
}
static int table_cmp(const void *in_a, const void *in_b)
{
const ASN1_STRING_TABLE *a = in_a;
const ASN1_STRING_TABLE *b = in_b;
return a->nid - b->nid;
}
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
{
int found;
size_t idx;
ASN1_STRING_TABLE *ttmp;
ASN1_STRING_TABLE fnd;
fnd.nid = nid;
ttmp =
bsearch(&fnd, tbl_standard,
sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE),
sizeof(ASN1_STRING_TABLE), table_cmp);
if (ttmp)
return ttmp;
if (!stable)
return NULL;
found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
if (!found)
return NULL;
return sk_ASN1_STRING_TABLE_value(stable, idx);
}
int ASN1_STRING_TABLE_add(int nid,
long minsize, long maxsize, unsigned long mask,
unsigned long flags)
{
ASN1_STRING_TABLE *tmp;
char new_nid = 0;
flags &= ~STABLE_FLAGS_MALLOC;
if (!stable)
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
if (!stable) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
if (!tmp) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
tmp->flags = flags | STABLE_FLAGS_MALLOC;
tmp->nid = nid;
tmp->minsize = tmp->maxsize = -1;
new_nid = 1;
} else
tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
if (minsize != -1)
tmp->minsize = minsize;
if (maxsize != -1)
tmp->maxsize = maxsize;
tmp->mask = mask;
if (new_nid)
sk_ASN1_STRING_TABLE_push(stable, tmp);
return 1;
}
void ASN1_STRING_TABLE_cleanup(void)
{
STACK_OF(ASN1_STRING_TABLE) *tmp;
tmp = stable;
if (!tmp)
return;
stable = NULL;
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
}
static void st_free(ASN1_STRING_TABLE *tbl)
{
if (tbl->flags & STABLE_FLAGS_MALLOC)
OPENSSL_free(tbl);
}
#ifdef STRING_TABLE_TEST
int main(void)
{
ASN1_STRING_TABLE *tmp;
int i, last_nid = -1;
for (tmp = tbl_standard, i = 0;
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
if (tmp->nid < last_nid) {
last_nid = 0;
break;
}
last_nid = tmp->nid;
}
if (last_nid != 0) {
printf("Table order OK\n");
exit(0);
}
for (tmp = tbl_standard, i = 0;
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
OBJ_nid2ln(tmp->nid));
return 0;
}
#endif

View File

@ -1,213 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <time.h>
#include <openssl/asn1t.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "asn1_locl.h"
/*
* This is an implementation of the ASN1 Time structure which is: Time ::=
* CHOICE { utcTime UTCTime, generalTime GeneralizedTime } written by Steve
* Henson.
*/
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
{
return ASN1_TIME_adj(s, t, 0, 0);
}
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
int offset_day, long offset_sec)
{
struct tm *ts;
struct tm data;
ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
return NULL;
}
if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
return NULL;
}
if ((ts->tm_year >= 50) && (ts->tm_year < 150))
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
}
int ASN1_TIME_check(ASN1_TIME *t)
{
if (t->type == V_ASN1_GENERALIZEDTIME)
return ASN1_GENERALIZEDTIME_check(t);
else if (t->type == V_ASN1_UTCTIME)
return ASN1_UTCTIME_check(t);
return 0;
}
/* Convert an ASN1_TIME structure to GeneralizedTime */
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out)
{
ASN1_GENERALIZEDTIME *ret = NULL;
char *str;
int newlen;
if (!ASN1_TIME_check(t))
return NULL;
if (!out || !*out) {
if (!(ret = ASN1_GENERALIZEDTIME_new()))
goto err;
} else {
ret = *out;
}
/* If already GeneralizedTime just copy across */
if (t->type == V_ASN1_GENERALIZEDTIME) {
if (!ASN1_STRING_set(ret, t->data, t->length))
goto err;
goto done;
}
/* grow the string */
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
goto err;
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
newlen = t->length + 2 + 1;
str = (char *)ret->data;
/* Work out the century and prepend */
if (t->data[0] >= '5')
BUF_strlcpy(str, "19", newlen);
else
BUF_strlcpy(str, "20", newlen);
BUF_strlcat(str, (char *)t->data, newlen);
done:
if (out != NULL && *out == NULL)
*out = ret;
return ret;
err:
if (out == NULL || *out != ret)
ASN1_GENERALIZEDTIME_free(ret);
return NULL;
}
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
{
ASN1_TIME t;
t.length = strlen(str);
t.data = (unsigned char *)str;
t.flags = 0;
t.type = V_ASN1_UTCTIME;
if (!ASN1_TIME_check(&t)) {
t.type = V_ASN1_GENERALIZEDTIME;
if (!ASN1_TIME_check(&t))
return 0;
}
if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
return 0;
return 1;
}
static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t)
{
if (t == NULL) {
time_t now_t;
time(&now_t);
if (OPENSSL_gmtime(&now_t, tm))
return 1;
return 0;
}
if (t->type == V_ASN1_UTCTIME)
return asn1_utctime_to_tm(tm, t);
else if (t->type == V_ASN1_GENERALIZEDTIME)
return asn1_generalizedtime_to_tm(tm, t);
return 0;
}
int ASN1_TIME_diff(int *pday, int *psec,
const ASN1_TIME *from, const ASN1_TIME *to)
{
struct tm tm_from, tm_to;
if (!asn1_time_to_tm(&tm_from, from))
return 0;
if (!asn1_time_to_tm(&tm_to, to))
return 0;
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
}

View File

@ -1,151 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
int ASN1_TYPE_get(ASN1_TYPE *a)
{
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
return (a->type);
else
return (0);
}
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
{
if (a->value.ptr != NULL) {
ASN1_TYPE **tmp_a = &a;
ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
}
a->type = type;
if (type == V_ASN1_BOOLEAN)
a->value.boolean = value ? 0xff : 0;
else
a->value.ptr = value;
}
int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
{
if (!value || (type == V_ASN1_BOOLEAN)) {
void *p = (void *)value;
ASN1_TYPE_set(a, type, p);
} else if (type == V_ASN1_OBJECT) {
ASN1_OBJECT *odup;
odup = OBJ_dup(value);
if (!odup)
return 0;
ASN1_TYPE_set(a, type, odup);
} else {
ASN1_STRING *sdup;
sdup = ASN1_STRING_dup(value);
if (!sdup)
return 0;
ASN1_TYPE_set(a, type, sdup);
}
return 1;
}
/* Returns 0 if they are equal, != 0 otherwise. */
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
{
int result = -1;
if (!a || !b || a->type != b->type)
return -1;
switch (a->type) {
case V_ASN1_OBJECT:
result = OBJ_cmp(a->value.object, b->value.object);
break;
case V_ASN1_NULL:
result = 0; /* They do not have content. */
break;
case V_ASN1_BOOLEAN:
result = a->value.boolean - b->value.boolean;
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
case V_ASN1_BIT_STRING:
case V_ASN1_OCTET_STRING:
case V_ASN1_SEQUENCE:
case V_ASN1_SET:
case V_ASN1_NUMERICSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_T61STRING:
case V_ASN1_VIDEOTEXSTRING:
case V_ASN1_IA5STRING:
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
case V_ASN1_GRAPHICSTRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_GENERALSTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_BMPSTRING:
case V_ASN1_UTF8STRING:
case V_ASN1_OTHER:
default:
result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr,
(ASN1_STRING *)b->value.ptr);
break;
}
return result;
}

View File

@ -1,303 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <time.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "asn1_locl.h"
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
{
static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
char *a;
int n, i, l, o;
if (d->type != V_ASN1_UTCTIME)
return (0);
l = d->length;
a = (char *)d->data;
o = 0;
if (l < 11)
goto err;
for (i = 0; i < 6; i++) {
if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
i++;
if (tm)
tm->tm_sec = 0;
break;
}
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = a[o] - '0';
if (++o > l)
goto err;
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = (n * 10) + a[o] - '0';
if (++o > l)
goto err;
if ((n < min[i]) || (n > max[i]))
goto err;
if (tm) {
switch (i) {
case 0:
tm->tm_year = n < 50 ? n + 100 : n;
break;
case 1:
tm->tm_mon = n - 1;
break;
case 2:
tm->tm_mday = n;
break;
case 3:
tm->tm_hour = n;
break;
case 4:
tm->tm_min = n;
break;
case 5:
tm->tm_sec = n;
break;
}
}
}
if (a[o] == 'Z')
o++;
else if ((a[o] == '+') || (a[o] == '-')) {
int offsign = a[o] == '-' ? 1 : -1, offset = 0;
o++;
if (o + 4 > l)
goto err;
for (i = 6; i < 8; i++) {
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = a[o] - '0';
o++;
if ((a[o] < '0') || (a[o] > '9'))
goto err;
n = (n * 10) + a[o] - '0';
if ((n < min[i]) || (n > max[i]))
goto err;
if (tm) {
if (i == 6)
offset = n * 3600;
else if (i == 7)
offset += n * 60;
}
o++;
}
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
return 0;
}
return o == l;
err:
return 0;
}
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
{
return asn1_utctime_to_tm(NULL, d);
}
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
{
ASN1_UTCTIME t;
t.type = V_ASN1_UTCTIME;
t.length = strlen(str);
t.data = (unsigned char *)str;
if (ASN1_UTCTIME_check(&t)) {
if (s != NULL) {
if (!ASN1_STRING_set((ASN1_STRING *)s,
(unsigned char *)str, t.length))
return 0;
s->type = V_ASN1_UTCTIME;
}
return (1);
} else
return (0);
}
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
{
return ASN1_UTCTIME_adj(s, t, 0, 0);
}
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
int offset_day, long offset_sec)
{
char *p;
struct tm *ts;
struct tm data;
size_t len = 20;
int free_s = 0;
if (s == NULL) {
free_s = 1;
s = M_ASN1_UTCTIME_new();
}
if (s == NULL)
goto err;
ts = OPENSSL_gmtime(&t, &data);
if (ts == NULL)
goto err;
if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
goto err;
}
if ((ts->tm_year < 50) || (ts->tm_year >= 150))
goto err;
p = (char *)s->data;
if ((p == NULL) || ((size_t)s->length < len)) {
p = OPENSSL_malloc(len);
if (p == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
if (s->data != NULL)
OPENSSL_free(s->data);
s->data = (unsigned char *)p;
}
BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
ts->tm_sec);
s->length = strlen(p);
s->type = V_ASN1_UTCTIME;
return (s);
err:
if (free_s && s)
M_ASN1_UTCTIME_free(s);
return NULL;
}
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
{
struct tm stm, ttm;
int day, sec;
if (!asn1_utctime_to_tm(&stm, s))
return -2;
if (!OPENSSL_gmtime(&t, &ttm))
return -2;
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
return -2;
if (day > 0)
return 1;
if (day < 0)
return -1;
if (sec > 0)
return 1;
if (sec < 0)
return -1;
return 0;
}
#if 0
time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
{
struct tm tm;
int offset;
OPENSSL_memset(&tm, '\0', sizeof tm);
# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
tm.tm_year = g2(s->data);
if (tm.tm_year < 50)
tm.tm_year += 100;
tm.tm_mon = g2(s->data + 2) - 1;
tm.tm_mday = g2(s->data + 4);
tm.tm_hour = g2(s->data + 6);
tm.tm_min = g2(s->data + 8);
tm.tm_sec = g2(s->data + 10);
if (s->data[12] == 'Z')
offset = 0;
else {
offset = g2(s->data + 13) * 60 + g2(s->data + 15);
if (s->data[12] == '-')
offset = -offset;
}
# undef g2
return mktime(&tm) - offset * 60; /* FIXME: mktime assumes the current
* timezone instead of UTC, and unless
* we rewrite OpenSSL in Lisp we cannot
* locally change the timezone without
* possibly interfering with other
* parts of the program. timegm, which
* uses UTC, is non-standard. Also
* time_t is inappropriate for general
* UTC times because it may a 32 bit
* type. */
}
#endif

View File

@ -1,236 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "asn1_locl.h"
/* UTF8 utilities */
/*
* This parses a UTF8 string one character at a time. It is passed a pointer
* to the string and the length of the string. It sets 'value' to the value
* of the current character. It returns the number of characters read or a
* negative error code: -1 = string too short -2 = illegal character -3 =
* subsequent characters not of the form 10xxxxxx -4 = character encoded
* incorrectly (not minimal length).
*/
int UTF8_getc(const unsigned char *str, int len, uint32_t *val)
{
const unsigned char *p;
uint32_t value;
int ret;
if (len <= 0)
return 0;
p = str;
/* Check syntax and work out the encoded value (if correct) */
if ((*p & 0x80) == 0) {
value = *p++ & 0x7f;
ret = 1;
} else if ((*p & 0xe0) == 0xc0) {
if (len < 2)
return -1;
if ((p[1] & 0xc0) != 0x80)
return -3;
value = (*p++ & 0x1f) << 6;
value |= *p++ & 0x3f;
if (value < 0x80)
return -4;
ret = 2;
} else if ((*p & 0xf0) == 0xe0) {
if (len < 3)
return -1;
if (((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80))
return -3;
value = (*p++ & 0xf) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x800)
return -4;
ret = 3;
} else if ((*p & 0xf8) == 0xf0) {
if (len < 4)
return -1;
if (((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80)
|| ((p[3] & 0xc0) != 0x80))
return -3;
value = ((uint32_t)(*p++ & 0x7)) << 18;
value |= (*p++ & 0x3f) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x10000)
return -4;
ret = 4;
} else if ((*p & 0xfc) == 0xf8) {
if (len < 5)
return -1;
if (((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80)
|| ((p[3] & 0xc0) != 0x80)
|| ((p[4] & 0xc0) != 0x80))
return -3;
value = ((uint32_t)(*p++ & 0x3)) << 24;
value |= ((uint32_t)(*p++ & 0x3f)) << 18;
value |= ((uint32_t)(*p++ & 0x3f)) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x200000)
return -4;
ret = 5;
} else if ((*p & 0xfe) == 0xfc) {
if (len < 6)
return -1;
if (((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80)
|| ((p[3] & 0xc0) != 0x80)
|| ((p[4] & 0xc0) != 0x80)
|| ((p[5] & 0xc0) != 0x80))
return -3;
value = ((uint32_t)(*p++ & 0x1)) << 30;
value |= ((uint32_t)(*p++ & 0x3f)) << 24;
value |= ((uint32_t)(*p++ & 0x3f)) << 18;
value |= ((uint32_t)(*p++ & 0x3f)) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x4000000)
return -4;
ret = 6;
} else
return -2;
*val = value;
return ret;
}
/*
* This takes a character 'value' and writes the UTF8 encoded value in 'str'
* where 'str' is a buffer containing 'len' characters. Returns the number of
* characters written or -1 if 'len' is too small. 'str' can be set to NULL
* in which case it just returns the number of characters. It will need at
* most 6 characters.
*/
int UTF8_putc(unsigned char *str, int len, uint32_t value)
{
if (!str)
len = 6; /* Maximum we will need */
else if (len <= 0)
return -1;
if (value < 0x80) {
if (str)
*str = (unsigned char)value;
return 1;
}
if (value < 0x800) {
if (len < 2)
return -1;
if (str) {
*str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 2;
}
if (value < 0x10000) {
if (len < 3)
return -1;
if (str) {
*str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 3;
}
if (value < 0x200000) {
if (len < 4)
return -1;
if (str) {
*str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 4;
}
if (value < 0x4000000) {
if (len < 5)
return -1;
if (str) {
*str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 5;
}
if (len < 6)
return -1;
if (str) {
*str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
*str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 6;
}

View File

@ -1,442 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <limits.h>
#include <string.h>
#include <openssl/asn1_mac.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
/* Cross-module errors from crypto/x509/i2d_pr.c. */
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE)
/* Cross-module errors from crypto/x509/algorithm.c. */
OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED)
OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM)
OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE)
/*
* Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
* these once asn1_gen.c is gone.
*/
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE)
OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER)
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER)
OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR)
OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE)
OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG)
OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE)
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
long max);
static void asn1_put_length(unsigned char **pp, int length);
int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
int *pclass, long omax)
{
int i, ret;
long l;
const unsigned char *p = *pp;
int tag, xclass, inf;
long max = omax;
if (!max)
goto err;
ret = (*p & V_ASN1_CONSTRUCTED);
xclass = (*p & V_ASN1_PRIVATE);
i = *p & V_ASN1_PRIMITIVE_TAG;
if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */
p++;
if (--max == 0)
goto err;
l = 0;
while (*p & 0x80) {
l <<= 7L;
l |= *(p++) & 0x7f;
if (--max == 0)
goto err;
if (l > (INT_MAX >> 7L))
goto err;
}
l <<= 7L;
l |= *(p++) & 0x7f;
tag = (int)l;
if (--max == 0)
goto err;
} else {
tag = i;
p++;
if (--max == 0)
goto err;
}
/* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */
if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL)
goto err;
*ptag = tag;
*pclass = xclass;
if (!asn1_get_length(&p, &inf, plength, max))
goto err;
if (inf && !(ret & V_ASN1_CONSTRUCTED))
goto err;
#if 0
fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
(int)p, *plength, omax, (int)*pp, (int)(p + *plength),
(int)(omax + *pp));
#endif
if (*plength > (omax - (p - *pp))) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
/*
* Set this so that even if things are not long enough the values are
* set correctly
*/
ret |= 0x80;
}
*pp = p;
return (ret | inf);
err:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
return (0x80);
}
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
long max)
{
const unsigned char *p = *pp;
unsigned long ret = 0;
unsigned long i;
if (max-- < 1)
return 0;
if (*p == 0x80) {
*inf = 1;
ret = 0;
p++;
} else {
*inf = 0;
i = *p & 0x7f;
if (*(p++) & 0x80) {
if (i > sizeof(ret) || max < (long)i)
return 0;
while (i-- > 0) {
ret <<= 8L;
ret |= *(p++);
}
} else
ret = i;
}
if (ret > LONG_MAX)
return 0;
*pp = p;
*rl = (long)ret;
return 1;
}
/*
* class 0 is constructed constructed == 2 for indefinite length constructed
*/
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int xclass)
{
unsigned char *p = *pp;
int i, ttag;
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
i |= (xclass & V_ASN1_PRIVATE);
if (tag < 31)
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
else {
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
for (i = 0, ttag = tag; ttag > 0; i++)
ttag >>= 7;
ttag = i;
while (i-- > 0) {
p[i] = tag & 0x7f;
if (i != (ttag - 1))
p[i] |= 0x80;
tag >>= 7;
}
p += ttag;
}
if (constructed == 2)
*(p++) = 0x80;
else
asn1_put_length(&p, length);
*pp = p;
}
int ASN1_put_eoc(unsigned char **pp)
{
unsigned char *p = *pp;
*p++ = 0;
*p++ = 0;
*pp = p;
return 2;
}
static void asn1_put_length(unsigned char **pp, int length)
{
unsigned char *p = *pp;
int i, l;
if (length <= 127)
*(p++) = (unsigned char)length;
else {
l = length;
for (i = 0; l > 0; i++)
l >>= 8;
*(p++) = i | 0x80;
l = i;
while (i-- > 0) {
p[i] = length & 0xff;
length >>= 8;
}
p += l;
}
*pp = p;
}
int ASN1_object_size(int constructed, int length, int tag)
{
int ret = 1;
if (length < 0)
return -1;
if (tag >= 31) {
while (tag > 0) {
tag >>= 7;
ret++;
}
}
if (constructed == 2) {
ret += 3;
} else {
ret++;
if (length > 127) {
int tmplen = length;
while (tmplen > 0) {
tmplen >>= 8;
ret++;
}
}
}
if (ret >= INT_MAX - length)
return -1;
return ret + length;
}
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
{
if (str == NULL)
return 0;
dst->type = str->type;
if (!ASN1_STRING_set(dst, str->data, str->length))
return 0;
dst->flags = str->flags;
return 1;
}
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
{
ASN1_STRING *ret;
if (!str)
return NULL;
ret = ASN1_STRING_new();
if (!ret)
return NULL;
if (!ASN1_STRING_copy(ret, str)) {
ASN1_STRING_free(ret);
return NULL;
}
return ret;
}
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
{
unsigned char *c;
const char *data = _data;
if (len < 0) {
if (data == NULL)
return (0);
else
len = strlen(data);
}
if ((str->length <= len) || (str->data == NULL)) {
c = str->data;
if (c == NULL)
str->data = OPENSSL_malloc(len + 1);
else
str->data = OPENSSL_realloc(c, len + 1);
if (str->data == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
str->data = c;
return (0);
}
}
str->length = len;
if (data != NULL) {
OPENSSL_memcpy(str->data, data, len);
/* an allowance for strings :-) */
str->data[len] = '\0';
}
return (1);
}
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
{
if (str->data)
OPENSSL_free(str->data);
str->data = data;
str->length = len;
}
ASN1_STRING *ASN1_STRING_new(void)
{
return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
}
ASN1_STRING *ASN1_STRING_type_new(int type)
{
ASN1_STRING *ret;
ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
if (ret == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->length = 0;
ret->type = type;
ret->data = NULL;
ret->flags = 0;
return (ret);
}
void ASN1_STRING_free(ASN1_STRING *a)
{
if (a == NULL)
return;
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
OPENSSL_free(a->data);
OPENSSL_free(a);
}
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
{
int i;
i = (a->length - b->length);
if (i == 0) {
i = OPENSSL_memcmp(a->data, b->data, a->length);
if (i == 0)
return (a->type - b->type);
else
return (i);
} else
return (i);
}
int ASN1_STRING_length(const ASN1_STRING *x)
{
return M_ASN1_STRING_length(x);
}
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
{
M_ASN1_STRING_length_set(x, len);
return;
}
int ASN1_STRING_type(ASN1_STRING *x)
{
return M_ASN1_STRING_type(x);
}
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
{
return M_ASN1_STRING_data(x);
}
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
{
return x->data;
}

View File

@ -1,104 +0,0 @@
/* asn1t.h */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2006.
*/
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#ifndef OPENSSL_HEADER_ASN1_ASN1_LOCL_H
#define OPENSSL_HEADER_ASN1_ASN1_LOCL_H
#include <time.h>
#include <openssl/asn1.h>
#if defined(__cplusplus)
extern "C" {
#endif
/* Wrapper functions for time functions. */
/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result);
/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
* seconds. */
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and
* outputs the difference as a number of days and seconds in |*out_days| and
* |*out_secs|. */
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
const struct tm *to);
/* Internal ASN1 structures and functions: not for application use */
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);
int UTF8_getc(const unsigned char *str, int len, uint32_t *val);
int UTF8_putc(unsigned char *str, int len, uint32_t value);
#if defined(__cplusplus)
} /* extern C */
#endif
#endif /* OPENSSL_HEADER_ASN1_ASN1_LOCL_H */

View File

@ -1,80 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
const char *ASN1_tag2str(int tag)
{
static const char *const tag2str[] = {
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24
*/
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
};
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
tag &= ~0x100;
if (tag < 0 || tag > 30)
return "(unknown)";
return tag2str[tag];
}

View File

@ -1,105 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
/* ASN1_ITEM versions of the above */
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
{
ASN1_STRING *octmp;
if (!oct || !*oct) {
if (!(octmp = ASN1_STRING_new())) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (oct)
*oct = octmp;
} else
octmp = *oct;
if (octmp->data) {
OPENSSL_free(octmp->data);
octmp->data = NULL;
}
if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
return NULL;
}
if (!octmp->data) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
return octmp;
}
/* Extract an ASN1 object from an ASN1_STRING */
void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it)
{
const unsigned char *p;
void *ret;
p = oct->data;
if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
return ret;
}

View File

@ -1,93 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/bio.h>
/* Based on a_int.c: equivalent ENUMERATED functions */
int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a)
{
int i, n = 0;
static const char *h = "0123456789ABCDEF";
char buf[2];
if (a == NULL)
return (0);
if (a->length == 0) {
if (BIO_write(bp, "00", 2) != 2)
goto err;
n = 2;
} else {
for (i = 0; i < a->length; i++) {
if ((i != 0) && (i % 35 == 0)) {
if (BIO_write(bp, "\\\n", 2) != 2)
goto err;
n += 2;
}
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
if (BIO_write(bp, buf, 2) != 2)
goto err;
n += 2;
}
}
return (n);
err:
return (-1);
}

View File

@ -1,97 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/bio.h>
int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a)
{
int i, n = 0;
static const char *h = "0123456789ABCDEF";
char buf[2];
if (a == NULL)
return (0);
if (a->type & V_ASN1_NEG) {
if (BIO_write(bp, "-", 1) != 1)
goto err;
n = 1;
}
if (a->length == 0) {
if (BIO_write(bp, "00", 2) != 2)
goto err;
n += 2;
} else {
for (i = 0; i < a->length; i++) {
if ((i != 0) && (i % 35 == 0)) {
if (BIO_write(bp, "\\\n", 2) != 2)
goto err;
n += 2;
}
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
if (BIO_write(bp, buf, 2) != 2)
goto err;
n += 2;
}
}
return (n);
err:
return (-1);
}

View File

@ -1,91 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/bio.h>
int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
{
int i, n = 0;
static const char *h = "0123456789ABCDEF";
char buf[2];
if (a == NULL)
return (0);
if (a->length == 0) {
if (BIO_write(bp, "0", 1) != 1)
goto err;
n = 1;
} else {
for (i = 0; i < a->length; i++) {
if ((i != 0) && (i % 35 == 0)) {
if (BIO_write(bp, "\\\n", 2) != 2)
goto err;
n += 2;
}
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
if (BIO_write(bp, buf, 2) != 2)
goto err;
n += 2;
}
}
return (n);
err:
return (-1);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,662 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <limits.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/mem.h>
#include "../internal.h"
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass);
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
int skcontlen, const ASN1_ITEM *item,
int do_sort, int iclass);
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int aclass);
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it, int flags);
/*
* Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
* indefinite length constructed encoding, where appropriate
*/
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it)
{
return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
}
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
{
return asn1_item_flags_i2d(val, out, it, 0);
}
/*
* Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
* points to a buffer to output the data to. The new i2d has one additional
* feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
* allocated and populated with the encoding.
*/
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it, int flags)
{
if (out && !*out) {
unsigned char *p, *buf;
int len;
len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
if (len <= 0)
return len;
buf = OPENSSL_malloc(len);
if (!buf)
return -1;
p = buf;
ASN1_item_ex_i2d(&val, &p, it, -1, flags);
*out = buf;
return len;
}
return ASN1_item_ex_i2d(&val, out, it, -1, flags);
}
/*
* Encode an item, taking care of IMPLICIT tagging (if any). This function
* performs the normal item handling: it can be used in external types.
*/
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass)
{
const ASN1_TEMPLATE *tt = NULL;
unsigned char *p = NULL;
int i, seqcontlen, seqlen, ndef = 1;
const ASN1_COMPAT_FUNCS *cf;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb = 0;
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
return 0;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
switch (it->itype) {
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
return asn1_template_ex_i2d(pval, out, it->templates,
tag, aclass);
return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
break;
case ASN1_ITYPE_MSTRING:
return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
case ASN1_ITYPE_CHOICE:
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
return 0;
i = asn1_get_choice_selector(pval, it);
if ((i >= 0) && (i < it->tcount)) {
ASN1_VALUE **pchval;
const ASN1_TEMPLATE *chtt;
chtt = it->templates + i;
pchval = asn1_get_field_ptr(pval, chtt);
return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
}
/* Fixme: error condition if selector out of range */
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
return 0;
break;
case ASN1_ITYPE_EXTERN:
/* If new style i2d it does all the work */
ef = it->funcs;
return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
case ASN1_ITYPE_COMPAT:
/* old style hackery... */
cf = it->funcs;
if (out)
p = *out;
i = cf->asn1_i2d(*pval, out);
/*
* Fixup for IMPLICIT tag: note this messes up for tags > 30, but so
* did the old code. Tags > 30 are very rare anyway.
*/
if (out && (tag != -1))
*p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
return i;
case ASN1_ITYPE_NDEF_SEQUENCE:
/* Use indefinite length constructed if requested */
if (aclass & ASN1_TFLG_NDEF)
ndef = 2;
/* fall through */
case ASN1_ITYPE_SEQUENCE:
i = asn1_enc_restore(&seqcontlen, out, pval, it);
/* An error occurred */
if (i < 0)
return 0;
/* We have a valid cached encoding... */
if (i > 0)
return seqcontlen;
/* Otherwise carry on */
seqcontlen = 0;
/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
if (tag == -1) {
tag = V_ASN1_SEQUENCE;
/* Retain any other flags in aclass */
aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
| V_ASN1_UNIVERSAL;
}
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
return 0;
/* First work out sequence content length */
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval;
int tmplen;
seqtt = asn1_do_adb(pval, tt, 1);
if (!seqtt)
return 0;
pseqval = asn1_get_field_ptr(pval, seqtt);
tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
return -1;
seqcontlen += tmplen;
}
seqlen = ASN1_object_size(ndef, seqcontlen, tag);
if (!out || seqlen == -1)
return seqlen;
/* Output SEQUENCE header */
ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval;
seqtt = asn1_do_adb(pval, tt, 1);
if (!seqtt)
return 0;
pseqval = asn1_get_field_ptr(pval, seqtt);
/* FIXME: check for errors in enhanced version */
asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
}
if (ndef == 2)
ASN1_put_eoc(out);
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
return 0;
return seqlen;
default:
return 0;
}
return 0;
}
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int iclass)
{
int i, ret, flags, ttag, tclass, ndef;
size_t j;
flags = tt->flags;
/*
* Work out tag and class to use: tagging may come either from the
* template or the arguments, not both because this would create
* ambiguity. Additionally the iclass argument may contain some
* additional flags which should be noted and passed down to other
* levels.
*/
if (flags & ASN1_TFLG_TAG_MASK) {
/* Error if argument and template tagging */
if (tag != -1)
/* FIXME: error code here */
return -1;
/* Get tagging from template */
ttag = tt->tag;
tclass = flags & ASN1_TFLG_TAG_CLASS;
} else if (tag != -1) {
/* No template tagging, get from arguments */
ttag = tag;
tclass = iclass & ASN1_TFLG_TAG_CLASS;
} else {
ttag = -1;
tclass = 0;
}
/*
* Remove any class mask from iflag.
*/
iclass &= ~ASN1_TFLG_TAG_CLASS;
/*
* At this point 'ttag' contains the outer tag to use, 'tclass' is the
* class and iclass is any flags passed to this function.
*/
/* if template and arguments require ndef, use it */
if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
ndef = 2;
else
ndef = 1;
if (flags & ASN1_TFLG_SK_MASK) {
/* SET OF, SEQUENCE OF */
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
int isset, sktag, skaclass;
int skcontlen, sklen;
ASN1_VALUE *skitem;
if (!*pval)
return 0;
if (flags & ASN1_TFLG_SET_OF) {
isset = 1;
/* 2 means we reorder */
if (flags & ASN1_TFLG_SEQUENCE_OF)
isset = 2;
} else
isset = 0;
/*
* Work out inner tag value: if EXPLICIT or no tagging use underlying
* type.
*/
if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
sktag = ttag;
skaclass = tclass;
} else {
skaclass = V_ASN1_UNIVERSAL;
if (isset)
sktag = V_ASN1_SET;
else
sktag = V_ASN1_SEQUENCE;
}
/* Determine total length of items */
skcontlen = 0;
for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) {
int tmplen;
skitem = sk_ASN1_VALUE_value(sk, j);
tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
-1, iclass);
if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
return -1;
skcontlen += tmplen;
}
sklen = ASN1_object_size(ndef, skcontlen, sktag);
if (sklen == -1)
return -1;
/* If EXPLICIT need length of surrounding tag */
if (flags & ASN1_TFLG_EXPTAG)
ret = ASN1_object_size(ndef, sklen, ttag);
else
ret = sklen;
if (!out || ret == -1)
return ret;
/* Now encode this lot... */
/* EXPLICIT tag */
if (flags & ASN1_TFLG_EXPTAG)
ASN1_put_object(out, ndef, sklen, ttag, tclass);
/* SET or SEQUENCE and IMPLICIT tag */
ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
/* And the stuff itself */
asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
isset, iclass);
if (ndef == 2) {
ASN1_put_eoc(out);
if (flags & ASN1_TFLG_EXPTAG)
ASN1_put_eoc(out);
}
return ret;
}
if (flags & ASN1_TFLG_EXPTAG) {
/* EXPLICIT tagging */
/* Find length of tagged item */
i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
if (!i)
return 0;
/* Find length of EXPLICIT tag */
ret = ASN1_object_size(ndef, i, ttag);
if (out && ret != -1) {
/* Output tag and item */
ASN1_put_object(out, ndef, i, ttag, tclass);
ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
if (ndef == 2)
ASN1_put_eoc(out);
}
return ret;
}
/* Either normal or IMPLICIT tagging: combine class and flags */
return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
ttag, tclass | iclass);
}
/* Temporary structure used to hold DER encoding of items for SET OF */
typedef struct {
unsigned char *data;
int length;
ASN1_VALUE *field;
} DER_ENC;
static int der_cmp(const void *a, const void *b)
{
const DER_ENC *d1 = a, *d2 = b;
int cmplen, i;
cmplen = (d1->length < d2->length) ? d1->length : d2->length;
i = OPENSSL_memcmp(d1->data, d2->data, cmplen);
if (i)
return i;
return d1->length - d2->length;
}
/* Output the content octets of SET OF or SEQUENCE OF */
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
int skcontlen, const ASN1_ITEM *item,
int do_sort, int iclass)
{
size_t i;
ASN1_VALUE *skitem;
unsigned char *tmpdat = NULL, *p = NULL;
DER_ENC *derlst = NULL, *tder;
if (do_sort) {
/* Don't need to sort less than 2 items */
if (sk_ASN1_VALUE_num(sk) < 2)
do_sort = 0;
else {
derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
* sizeof(*derlst));
if (!derlst)
return 0;
tmpdat = OPENSSL_malloc(skcontlen);
if (!tmpdat) {
OPENSSL_free(derlst);
return 0;
}
}
}
/* If not sorting just output each item */
if (!do_sort) {
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
skitem = sk_ASN1_VALUE_value(sk, i);
ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
}
return 1;
}
p = tmpdat;
/* Doing sort: build up a list of each member's DER encoding */
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
skitem = sk_ASN1_VALUE_value(sk, i);
tder->data = p;
tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
tder->field = skitem;
}
/* Now sort them */
qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
/* Output sorted DER encoding */
p = *out;
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
OPENSSL_memcpy(p, tder->data, tder->length);
p += tder->length;
}
*out = p;
/* If do_sort is 2 then reorder the STACK */
if (do_sort == 2) {
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
(void)sk_ASN1_VALUE_set(sk, i, tder->field);
}
OPENSSL_free(derlst);
OPENSSL_free(tmpdat);
return 1;
}
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass)
{
int len;
int utype;
int usetag;
int ndef = 0;
utype = it->utype;
/*
* Get length of content octets and maybe find out the underlying type.
*/
len = asn1_ex_i2c(pval, NULL, &utype, it);
/*
* If SEQUENCE, SET or OTHER then header is included in pseudo content
* octets so don't include tag+length. We need to check here because the
* call to asn1_ex_i2c() could change utype.
*/
if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
(utype == V_ASN1_OTHER))
usetag = 0;
else
usetag = 1;
/* -1 means omit type */
if (len == -1)
return 0;
/* -2 return is special meaning use ndef */
if (len == -2) {
ndef = 2;
len = 0;
}
/* If not implicitly tagged get tag from underlying type */
if (tag == -1)
tag = utype;
/* Output tag+length followed by content octets */
if (out) {
if (usetag)
ASN1_put_object(out, ndef, len, tag, aclass);
asn1_ex_i2c(pval, *out, &utype, it);
if (ndef)
ASN1_put_eoc(out);
else
*out += len;
}
if (usetag)
return ASN1_object_size(ndef, len, tag);
return len;
}
/* Produce content octets from a structure */
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
const ASN1_ITEM *it)
{
ASN1_BOOLEAN *tbool = NULL;
ASN1_STRING *strtmp;
ASN1_OBJECT *otmp;
int utype;
const unsigned char *cont;
unsigned char c;
int len;
const ASN1_PRIMITIVE_FUNCS *pf;
pf = it->funcs;
if (pf && pf->prim_i2c)
return pf->prim_i2c(pval, cout, putype, it);
/* Should type be omitted? */
if ((it->itype != ASN1_ITYPE_PRIMITIVE)
|| (it->utype != V_ASN1_BOOLEAN)) {
if (!*pval)
return -1;
}
if (it->itype == ASN1_ITYPE_MSTRING) {
/* If MSTRING type set the underlying type */
strtmp = (ASN1_STRING *)*pval;
utype = strtmp->type;
*putype = utype;
} else if (it->utype == V_ASN1_ANY) {
/* If ANY set type and pointer to value */
ASN1_TYPE *typ;
typ = (ASN1_TYPE *)*pval;
utype = typ->type;
*putype = utype;
pval = &typ->value.asn1_value;
} else
utype = *putype;
switch (utype) {
case V_ASN1_OBJECT:
otmp = (ASN1_OBJECT *)*pval;
cont = otmp->data;
len = otmp->length;
break;
case V_ASN1_NULL:
cont = NULL;
len = 0;
break;
case V_ASN1_BOOLEAN:
tbool = (ASN1_BOOLEAN *)pval;
if (*tbool == -1)
return -1;
if (it->utype != V_ASN1_ANY) {
/*
* Default handling if value == size field then omit
*/
if (*tbool && (it->size > 0))
return -1;
if (!*tbool && !it->size)
return -1;
}
c = (unsigned char)*tbool;
cont = &c;
len = 1;
break;
case V_ASN1_BIT_STRING:
return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
cout ? &cout : NULL);
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
/*
* These are all have the same content format as ASN1_INTEGER
*/
return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
break;
case V_ASN1_OCTET_STRING:
case V_ASN1_NUMERICSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_T61STRING:
case V_ASN1_VIDEOTEXSTRING:
case V_ASN1_IA5STRING:
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
case V_ASN1_GRAPHICSTRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_GENERALSTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_BMPSTRING:
case V_ASN1_UTF8STRING:
case V_ASN1_SEQUENCE:
case V_ASN1_SET:
default:
/* All based on ASN1_STRING and handled the same */
strtmp = (ASN1_STRING *)*pval;
/* Special handling for NDEF */
if ((it->size == ASN1_TFLG_NDEF)
&& (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
if (cout) {
strtmp->data = cout;
strtmp->length = 0;
}
/* Special return code */
return -2;
}
cont = strtmp->data;
len = strtmp->length;
break;
}
if (cout && len)
OPENSSL_memcpy(cout, cont, len);
return len;
}

View File

@ -1,244 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/mem.h>
#include "asn1_locl.h"
/* Free up an ASN1 structure */
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
{
asn1_item_combine_free(&val, it, 0);
}
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
asn1_item_combine_free(pval, it, 0);
}
void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
{
const ASN1_TEMPLATE *tt = NULL, *seqtt;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_COMPAT_FUNCS *cf;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb;
int i;
if (!pval)
return;
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
return;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
else
asn1_cb = 0;
switch (it->itype) {
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
ASN1_template_free(pval, it->templates);
else
ASN1_primitive_free(pval, it);
break;
case ASN1_ITYPE_MSTRING:
ASN1_primitive_free(pval, it);
break;
case ASN1_ITYPE_CHOICE:
if (asn1_cb) {
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
if (i == 2)
return;
}
i = asn1_get_choice_selector(pval, it);
if ((i >= 0) && (i < it->tcount)) {
ASN1_VALUE **pchval;
tt = it->templates + i;
pchval = asn1_get_field_ptr(pval, tt);
ASN1_template_free(pchval, tt);
}
if (asn1_cb)
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
if (!combine) {
OPENSSL_free(*pval);
*pval = NULL;
}
break;
case ASN1_ITYPE_COMPAT:
cf = it->funcs;
if (cf && cf->asn1_free)
cf->asn1_free(*pval);
break;
case ASN1_ITYPE_EXTERN:
ef = it->funcs;
if (ef && ef->asn1_ex_free)
ef->asn1_ex_free(pval, it);
break;
case ASN1_ITYPE_NDEF_SEQUENCE:
case ASN1_ITYPE_SEQUENCE:
if (!asn1_refcount_dec_and_test_zero(pval, it))
return;
if (asn1_cb) {
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
if (i == 2)
return;
}
asn1_enc_free(pval, it);
/*
* If we free up as normal we will invalidate any ANY DEFINED BY
* field and we wont be able to determine the type of the field it
* defines. So free up in reverse order.
*/
tt = it->templates + it->tcount - 1;
for (i = 0; i < it->tcount; tt--, i++) {
ASN1_VALUE **pseqval;
seqtt = asn1_do_adb(pval, tt, 0);
if (!seqtt)
continue;
pseqval = asn1_get_field_ptr(pval, seqtt);
ASN1_template_free(pseqval, seqtt);
}
if (asn1_cb)
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
if (!combine) {
OPENSSL_free(*pval);
*pval = NULL;
}
break;
}
}
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
size_t i;
if (tt->flags & ASN1_TFLG_SK_MASK) {
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
ASN1_VALUE *vtmp;
vtmp = sk_ASN1_VALUE_value(sk, i);
asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0);
}
sk_ASN1_VALUE_free(sk);
*pval = NULL;
} else
asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
tt->flags & ASN1_TFLG_COMBINE);
}
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
int utype;
if (it) {
const ASN1_PRIMITIVE_FUNCS *pf;
pf = it->funcs;
if (pf && pf->prim_free) {
pf->prim_free(pval, it);
return;
}
}
/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
if (!it) {
ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
utype = typ->type;
pval = &typ->value.asn1_value;
if (!*pval)
return;
} else if (it->itype == ASN1_ITYPE_MSTRING) {
utype = -1;
if (!*pval)
return;
} else {
utype = it->utype;
if ((utype != V_ASN1_BOOLEAN) && !*pval)
return;
}
switch (utype) {
case V_ASN1_OBJECT:
ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
break;
case V_ASN1_BOOLEAN:
if (it)
*(ASN1_BOOLEAN *)pval = it->size;
else
*(ASN1_BOOLEAN *)pval = -1;
return;
case V_ASN1_NULL:
break;
case V_ASN1_ANY:
ASN1_primitive_free(pval, NULL);
OPENSSL_free(*pval);
break;
default:
ASN1_STRING_free((ASN1_STRING *)*pval);
*pval = NULL;
break;
}
*pval = NULL;
}

View File

@ -1,387 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include "asn1_locl.h"
#include "../internal.h"
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
{
ASN1_VALUE *ret = NULL;
if (ASN1_item_ex_new(&ret, it) > 0)
return ret;
return NULL;
}
/* Allocate an ASN1 structure */
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
return asn1_item_ex_combine_new(pval, it, 0);
}
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine)
{
const ASN1_TEMPLATE *tt = NULL;
const ASN1_COMPAT_FUNCS *cf;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb;
ASN1_VALUE **pseqval;
int i;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
else
asn1_cb = 0;
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_push_info(it->sname);
#endif
switch (it->itype) {
case ASN1_ITYPE_EXTERN:
ef = it->funcs;
if (ef && ef->asn1_ex_new) {
if (!ef->asn1_ex_new(pval, it))
goto memerr;
}
break;
case ASN1_ITYPE_COMPAT:
cf = it->funcs;
if (cf && cf->asn1_new) {
*pval = cf->asn1_new();
if (!*pval)
goto memerr;
}
break;
case ASN1_ITYPE_PRIMITIVE:
if (it->templates) {
if (!ASN1_template_new(pval, it->templates))
goto memerr;
} else if (!ASN1_primitive_new(pval, it))
goto memerr;
break;
case ASN1_ITYPE_MSTRING:
if (!ASN1_primitive_new(pval, it))
goto memerr;
break;
case ASN1_ITYPE_CHOICE:
if (asn1_cb) {
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
if (!i)
goto auxerr;
if (i == 2) {
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
}
}
if (!combine) {
*pval = OPENSSL_malloc(it->size);
if (!*pval)
goto memerr;
OPENSSL_memset(*pval, 0, it->size);
}
asn1_set_choice_selector(pval, -1, it);
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr2;
break;
case ASN1_ITYPE_NDEF_SEQUENCE:
case ASN1_ITYPE_SEQUENCE:
if (asn1_cb) {
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
if (!i)
goto auxerr;
if (i == 2) {
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
}
}
if (!combine) {
*pval = OPENSSL_malloc(it->size);
if (!*pval)
goto memerr;
OPENSSL_memset(*pval, 0, it->size);
asn1_refcount_set_one(pval, it);
asn1_enc_init(pval, it);
}
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
pseqval = asn1_get_field_ptr(pval, tt);
if (!ASN1_template_new(pseqval, tt))
goto memerr2;
}
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr2;
break;
}
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
memerr2:
asn1_item_combine_free(pval, it, combine);
memerr:
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 0;
auxerr2:
asn1_item_combine_free(pval, it, combine);
auxerr:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 0;
}
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
const ASN1_EXTERN_FUNCS *ef;
switch (it->itype) {
case ASN1_ITYPE_EXTERN:
ef = it->funcs;
if (ef && ef->asn1_ex_clear)
ef->asn1_ex_clear(pval, it);
else
*pval = NULL;
break;
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
asn1_template_clear(pval, it->templates);
else
asn1_primitive_clear(pval, it);
break;
case ASN1_ITYPE_MSTRING:
asn1_primitive_clear(pval, it);
break;
case ASN1_ITYPE_COMPAT:
case ASN1_ITYPE_CHOICE:
case ASN1_ITYPE_SEQUENCE:
case ASN1_ITYPE_NDEF_SEQUENCE:
*pval = NULL;
break;
}
}
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
int ret;
if (tt->flags & ASN1_TFLG_OPTIONAL) {
asn1_template_clear(pval, tt);
return 1;
}
/* If ANY DEFINED BY nothing to do */
if (tt->flags & ASN1_TFLG_ADB_MASK) {
*pval = NULL;
return 1;
}
#ifdef CRYPTO_MDEBUG
if (tt->field_name)
CRYPTO_push_info(tt->field_name);
#endif
/* If SET OF or SEQUENCE OF, its a STACK */
if (tt->flags & ASN1_TFLG_SK_MASK) {
STACK_OF(ASN1_VALUE) *skval;
skval = sk_ASN1_VALUE_new_null();
if (!skval) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
ret = 0;
goto done;
}
*pval = (ASN1_VALUE *)skval;
ret = 1;
goto done;
}
/* Otherwise pass it back to the item routine */
ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
done:
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return ret;
}
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
/* If ADB or STACK just NULL the field */
if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
*pval = NULL;
else
asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
}
/*
* NB: could probably combine most of the real XXX_new() behaviour and junk
* all the old functions.
*/
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
ASN1_TYPE *typ;
ASN1_STRING *str;
int utype;
if (!it)
return 0;
if (it->funcs) {
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
if (pf->prim_new)
return pf->prim_new(pval, it);
}
if (it->itype == ASN1_ITYPE_MSTRING)
utype = -1;
else
utype = it->utype;
switch (utype) {
case V_ASN1_OBJECT:
*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
return 1;
case V_ASN1_BOOLEAN:
*(ASN1_BOOLEAN *)pval = it->size;
return 1;
case V_ASN1_NULL:
*pval = (ASN1_VALUE *)1;
return 1;
case V_ASN1_ANY:
typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
if (!typ)
return 0;
typ->value.ptr = NULL;
typ->type = -1;
*pval = (ASN1_VALUE *)typ;
break;
default:
str = ASN1_STRING_type_new(utype);
if (it->itype == ASN1_ITYPE_MSTRING && str)
str->flags |= ASN1_STRING_FLAG_MSTRING;
*pval = (ASN1_VALUE *)str;
break;
}
if (*pval)
return 1;
return 0;
}
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
int utype;
if (it && it->funcs) {
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
if (pf->prim_clear)
pf->prim_clear(pval, it);
else
*pval = NULL;
return;
}
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
utype = -1;
else
utype = it->utype;
if (utype == V_ASN1_BOOLEAN)
*(ASN1_BOOLEAN *)pval = it->size;
else
*pval = NULL;
}

View File

@ -1,131 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
/* Declarations for string types */
#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
IMPLEMENT_ASN1_TYPE(sname) \
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
sname *sname##_new(void) \
{ \
return ASN1_STRING_type_new(V_##sname); \
} \
void sname##_free(sname *x) \
{ \
ASN1_STRING_free(x); \
}
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING)
IMPLEMENT_ASN1_TYPE(ASN1_NULL)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL)
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT)
IMPLEMENT_ASN1_TYPE(ASN1_ANY)
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE)
IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
/* Multistring types */
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE)
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT)
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING)
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */
IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1)
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1)
IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0)
/* Special, OCTET STRING with indefinite length constructed support */
IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, ASN1_TFLG_NDEF)
ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY)
ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY)
ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY)
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY)
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)

View File

@ -1,280 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <assert.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/err.h>
#include <openssl/thread.h>
#include "../internal.h"
/* Utility functions for manipulating fields and offsets */
/* Add 'offset' to 'addr' */
#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset))
/* Given an ASN1_ITEM CHOICE type return the selector value */
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) {
int *sel = offset2ptr(*pval, it->utype);
return *sel;
}
/* Given an ASN1_ITEM CHOICE type set the selector value, return old value. */
int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
const ASN1_ITEM *it) {
int *sel, ret;
sel = offset2ptr(*pval, it->utype);
ret = *sel;
*sel = value;
return ret;
}
static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval,
const ASN1_ITEM *it) {
if (it->itype != ASN1_ITYPE_SEQUENCE &&
it->itype != ASN1_ITYPE_NDEF_SEQUENCE) {
return NULL;
}
const ASN1_AUX *aux = it->funcs;
if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) {
return NULL;
}
return offset2ptr(*pval, aux->ref_offset);
}
void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) {
CRYPTO_refcount_t *references = asn1_get_references(pval, it);
if (references != NULL) {
*references = 1;
}
}
int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) {
CRYPTO_refcount_t *references = asn1_get_references(pval, it);
if (references != NULL) {
return CRYPTO_refcount_dec_and_test_zero(references);
}
return 1;
}
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) {
const ASN1_AUX *aux;
if (!pval || !*pval) {
return NULL;
}
aux = it->funcs;
if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) {
return NULL;
}
return offset2ptr(*pval, aux->enc_offset);
}
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) {
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (enc) {
enc->enc = NULL;
enc->len = 0;
enc->alias_only = 0;
enc->alias_only_on_next_parse = 0;
enc->modified = 1;
}
}
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) {
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (enc) {
if (enc->enc && !enc->alias_only) {
OPENSSL_free(enc->enc);
}
enc->enc = NULL;
enc->len = 0;
enc->alias_only = 0;
enc->alias_only_on_next_parse = 0;
enc->modified = 1;
}
}
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
const ASN1_ITEM *it) {
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (!enc) {
return 1;
}
if (!enc->alias_only) {
OPENSSL_free(enc->enc);
}
enc->alias_only = enc->alias_only_on_next_parse;
enc->alias_only_on_next_parse = 0;
if (enc->alias_only) {
enc->enc = (uint8_t *) in;
} else {
enc->enc = OPENSSL_malloc(inlen);
if (!enc->enc) {
return 0;
}
OPENSSL_memcpy(enc->enc, in, inlen);
}
enc->len = inlen;
enc->modified = 0;
return 1;
}
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
const ASN1_ITEM *it) {
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (!enc || enc->modified) {
return 0;
}
if (out) {
OPENSSL_memcpy(*out, enc->enc, enc->len);
*out += enc->len;
}
if (len) {
*len = enc->len;
}
return 1;
}
/* Given an ASN1_TEMPLATE get a pointer to a field */
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
ASN1_VALUE **pvaltmp;
if (tt->flags & ASN1_TFLG_COMBINE) {
return pval;
}
pvaltmp = offset2ptr(*pval, tt->offset);
/* NOTE for BOOLEAN types the field is just a plain int so we can't return
* int **, so settle for (int *). */
return pvaltmp;
}
/* Handle ANY DEFINED BY template, find the selector, look up the relevant
* ASN1_TEMPLATE in the table and return it. */
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
int nullerr) {
const ASN1_ADB *adb;
const ASN1_ADB_TABLE *atbl;
long selector;
ASN1_VALUE **sfld;
int i;
if (!(tt->flags & ASN1_TFLG_ADB_MASK)) {
return tt;
}
/* Else ANY DEFINED BY ... get the table */
adb = ASN1_ADB_ptr(tt->item);
/* Get the selector field */
sfld = offset2ptr(*pval, adb->offset);
/* Check if NULL */
if (*sfld == NULL) {
if (!adb->null_tt) {
goto err;
}
return adb->null_tt;
}
/* Convert type to a long:
* NB: don't check for NID_undef here because it
* might be a legitimate value in the table */
if (tt->flags & ASN1_TFLG_ADB_OID) {
selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
} else {
selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
}
/* Try to find matching entry in table Maybe should check application types
* first to allow application override? Might also be useful to have a flag
* which indicates table is sorted and we can do a binary search. For now
* stick to a linear search. */
for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) {
if (atbl->value == selector) {
return &atbl->tt;
}
}
/* FIXME: need to search application table too */
/* No match, return default type */
if (!adb->default_tt) {
goto err;
}
return adb->default_tt;
err:
/* FIXME: should log the value or OID of unsupported type */
if (nullerr) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
}
return NULL;
}

View File

@ -1,206 +0,0 @@
/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
* project 2001.
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2008.
*/
/* ====================================================================
* Copyright (c) 2001 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#if !defined(_POSIX_C_SOURCE)
#define _POSIX_C_SOURCE 201410L /* for gmtime_r */
#endif
#include "asn1_locl.h"
#include <time.h>
#define SECS_PER_DAY (24 * 60 * 60)
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result) {
#if defined(OPENSSL_WINDOWS)
if (gmtime_s(result, time)) {
return NULL;
}
return result;
#else
return gmtime_r(time, result);
#endif
}
/* Convert date to and from julian day Uses Fliegel & Van Flandern algorithm */
static long date_to_julian(int y, int m, int d) {
return (1461 * (y + 4800 + (m - 14) / 12)) / 4 +
(367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 -
(3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075;
}
static void julian_to_date(long jd, int *y, int *m, int *d) {
long L = jd + 68569;
long n = (4 * L) / 146097;
long i, j;
L = L - (146097 * n + 3) / 4;
i = (4000 * (L + 1)) / 1461001;
L = L - (1461 * i) / 4 + 31;
j = (80 * L) / 2447;
*d = L - (2447 * j) / 80;
L = j / 11;
*m = j + 2 - (12 * L);
*y = 100 * (n - 49) + i + L;
}
/* Convert tm structure and offset into julian day and seconds */
static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
long *pday, int *psec) {
int offset_hms, offset_day;
long time_jd;
int time_year, time_month, time_day;
/* split offset into days and day seconds */
offset_day = offset_sec / SECS_PER_DAY;
/* Avoid sign issues with % operator */
offset_hms = offset_sec - (offset_day * SECS_PER_DAY);
offset_day += off_day;
/* Add current time seconds to offset */
offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
/* Adjust day seconds if overflow */
if (offset_hms >= SECS_PER_DAY) {
offset_day++;
offset_hms -= SECS_PER_DAY;
} else if (offset_hms < 0) {
offset_day--;
offset_hms += SECS_PER_DAY;
}
/* Convert date of time structure into a Julian day number. */
time_year = tm->tm_year + 1900;
time_month = tm->tm_mon + 1;
time_day = tm->tm_mday;
time_jd = date_to_julian(time_year, time_month, time_day);
/* Work out Julian day of new date */
time_jd += offset_day;
if (time_jd < 0) {
return 0;
}
*pday = time_jd;
*psec = offset_hms;
return 1;
}
int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) {
int time_sec, time_year, time_month, time_day;
long time_jd;
/* Convert time and offset into julian day and seconds */
if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec)) {
return 0;
}
/* Convert Julian day back to date */
julian_to_date(time_jd, &time_year, &time_month, &time_day);
if (time_year < 1900 || time_year > 9999) {
return 0;
}
/* Update tm structure */
tm->tm_year = time_year - 1900;
tm->tm_mon = time_month - 1;
tm->tm_mday = time_day;
tm->tm_hour = time_sec / 3600;
tm->tm_min = (time_sec / 60) % 60;
tm->tm_sec = time_sec % 60;
return 1;
}
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
const struct tm *to) {
int from_sec, to_sec, diff_sec;
long from_jd, to_jd, diff_day;
if (!julian_adj(from, 0, 0, &from_jd, &from_sec)) {
return 0;
}
if (!julian_adj(to, 0, 0, &to_jd, &to_sec)) {
return 0;
}
diff_day = to_jd - from_jd;
diff_sec = to_sec - from_sec;
/* Adjust differences so both positive or both negative */
if (diff_day > 0 && diff_sec < 0) {
diff_day--;
diff_sec += SECS_PER_DAY;
}
if (diff_day < 0 && diff_sec > 0) {
diff_day++;
diff_sec -= SECS_PER_DAY;
}
if (out_days) {
*out_days = (int)diff_day;
}
if (out_secs) {
*out_secs = diff_sec;
}
return 1;
}

View File

@ -1,466 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/base64.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <openssl/type_check.h>
#include "../internal.h"
// constant_time_lt_args_8 behaves like |constant_time_lt_8| but takes |uint8_t|
// arguments for a slightly simpler implementation.
static inline uint8_t constant_time_lt_args_8(uint8_t a, uint8_t b) {
crypto_word_t aw = a;
crypto_word_t bw = b;
// |crypto_word_t| is larger than |uint8_t|, so |aw| and |bw| have the same
// MSB. |aw| < |bw| iff MSB(|aw| - |bw|) is 1.
return constant_time_msb_w(aw - bw);
}
// constant_time_in_range_8 returns |CONSTTIME_TRUE_8| if |min| <= |a| <= |max|
// and |CONSTTIME_FALSE_8| otherwise.
static inline uint8_t constant_time_in_range_8(uint8_t a, uint8_t min,
uint8_t max) {
a -= min;
return constant_time_lt_args_8(a, max - min + 1);
}
// Encoding.
static uint8_t conv_bin2ascii(uint8_t a) {
// Since PEM is sometimes used to carry private keys, we encode base64 data
// itself in constant-time.
a &= 0x3f;
uint8_t ret = constant_time_select_8(constant_time_eq_8(a, 62), '+', '/');
ret =
constant_time_select_8(constant_time_lt_args_8(a, 62), a - 52 + '0', ret);
ret =
constant_time_select_8(constant_time_lt_args_8(a, 52), a - 26 + 'a', ret);
ret = constant_time_select_8(constant_time_lt_args_8(a, 26), a + 'A', ret);
return ret;
}
OPENSSL_COMPILE_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0,
data_length_must_be_multiple_of_base64_chunk_size);
int EVP_EncodedLength(size_t *out_len, size_t len) {
if (len + 2 < len) {
return 0;
}
len += 2;
len /= 3;
if (((len << 2) >> 2) != len) {
return 0;
}
len <<= 2;
if (len + 1 < len) {
return 0;
}
len++;
*out_len = len;
return 1;
}
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
}
void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
const uint8_t *in, size_t in_len) {
size_t total = 0;
*out_len = 0;
if (in_len == 0) {
return;
}
assert(ctx->data_used < sizeof(ctx->data));
if (sizeof(ctx->data) - ctx->data_used > in_len) {
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, in_len);
ctx->data_used += (unsigned)in_len;
return;
}
if (ctx->data_used != 0) {
const size_t todo = sizeof(ctx->data) - ctx->data_used;
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, todo);
in += todo;
in_len -= todo;
size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data));
ctx->data_used = 0;
out += encoded;
*(out++) = '\n';
*out = '\0';
total = encoded + 1;
}
while (in_len >= sizeof(ctx->data)) {
size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data));
in += sizeof(ctx->data);
in_len -= sizeof(ctx->data);
out += encoded;
*(out++) = '\n';
*out = '\0';
if (total + encoded + 1 < total) {
*out_len = 0;
return;
}
total += encoded + 1;
}
if (in_len != 0) {
OPENSSL_memcpy(ctx->data, in, in_len);
}
ctx->data_used = (unsigned)in_len;
if (total > INT_MAX) {
// We cannot signal an error, but we can at least avoid making *out_len
// negative.
total = 0;
}
*out_len = (int)total;
}
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
if (ctx->data_used == 0) {
*out_len = 0;
return;
}
size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used);
out[encoded++] = '\n';
out[encoded] = '\0';
ctx->data_used = 0;
// ctx->data_used is bounded by sizeof(ctx->data), so this does not
// overflow.
assert(encoded <= INT_MAX);
*out_len = (int)encoded;
}
size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
uint32_t l;
size_t remaining = src_len, ret = 0;
while (remaining) {
if (remaining >= 3) {
l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2];
*(dst++) = conv_bin2ascii(l >> 18L);
*(dst++) = conv_bin2ascii(l >> 12L);
*(dst++) = conv_bin2ascii(l >> 6L);
*(dst++) = conv_bin2ascii(l);
remaining -= 3;
} else {
l = ((uint32_t)src[0]) << 16L;
if (remaining == 2) {
l |= ((uint32_t)src[1] << 8L);
}
*(dst++) = conv_bin2ascii(l >> 18L);
*(dst++) = conv_bin2ascii(l >> 12L);
*(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L);
*(dst++) = '=';
remaining = 0;
}
ret += 4;
src += 3;
}
*dst = '\0';
return ret;
}
// Decoding.
int EVP_DecodedLength(size_t *out_len, size_t len) {
if (len % 4 != 0) {
return 0;
}
*out_len = (len / 4) * 3;
return 1;
}
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
}
static uint8_t base64_ascii_to_bin(uint8_t a) {
// Since PEM is sometimes used to carry private keys, we decode base64 data
// itself in constant-time.
const uint8_t is_upper = constant_time_in_range_8(a, 'A', 'Z');
const uint8_t is_lower = constant_time_in_range_8(a, 'a', 'z');
const uint8_t is_digit = constant_time_in_range_8(a, '0', '9');
const uint8_t is_plus = constant_time_eq_8(a, '+');
const uint8_t is_slash = constant_time_eq_8(a, '/');
const uint8_t is_equals = constant_time_eq_8(a, '=');
uint8_t ret = 0xff; // 0xff signals invalid.
ret = constant_time_select_8(is_upper, a - 'A', ret); // [0,26)
ret = constant_time_select_8(is_lower, a - 'a' + 26, ret); // [26,52)
ret = constant_time_select_8(is_digit, a - '0' + 52, ret); // [52,62)
ret = constant_time_select_8(is_plus, 62, ret);
ret = constant_time_select_8(is_slash, 63, ret);
// Padding maps to zero, to be further handled by the caller.
ret = constant_time_select_8(is_equals, 0, ret);
return ret;
}
// base64_decode_quad decodes a single “quad” (i.e. four characters) of base64
// data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the
// number of bytes written, which will be less than three if the quad ended
// with padding. It returns one on success or zero on error.
static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes,
const uint8_t *in) {
const uint8_t a = base64_ascii_to_bin(in[0]);
const uint8_t b = base64_ascii_to_bin(in[1]);
const uint8_t c = base64_ascii_to_bin(in[2]);
const uint8_t d = base64_ascii_to_bin(in[3]);
if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) {
return 0;
}
const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 |
((uint32_t)c) << 6 | (uint32_t)d;
const unsigned padding_pattern = (in[0] == '=') << 3 |
(in[1] == '=') << 2 |
(in[2] == '=') << 1 |
(in[3] == '=');
switch (padding_pattern) {
case 0:
// The common case of no padding.
*out_num_bytes = 3;
out[0] = v >> 16;
out[1] = v >> 8;
out[2] = v;
break;
case 1: // xxx=
*out_num_bytes = 2;
out[0] = v >> 16;
out[1] = v >> 8;
break;
case 3: // xx==
*out_num_bytes = 1;
out[0] = v >> 16;
break;
default:
return 0;
}
return 1;
}
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
const uint8_t *in, size_t in_len) {
*out_len = 0;
if (ctx->error_encountered) {
return -1;
}
size_t bytes_out = 0, i;
for (i = 0; i < in_len; i++) {
const char c = in[i];
switch (c) {
case ' ':
case '\t':
case '\r':
case '\n':
continue;
}
if (ctx->eof_seen) {
ctx->error_encountered = 1;
return -1;
}
ctx->data[ctx->data_used++] = c;
if (ctx->data_used == 4) {
size_t num_bytes_resulting;
if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) {
ctx->error_encountered = 1;
return -1;
}
ctx->data_used = 0;
bytes_out += num_bytes_resulting;
out += num_bytes_resulting;
if (num_bytes_resulting < 3) {
ctx->eof_seen = 1;
}
}
}
if (bytes_out > INT_MAX) {
ctx->error_encountered = 1;
*out_len = 0;
return -1;
}
*out_len = (int)bytes_out;
if (ctx->eof_seen) {
return 0;
}
return 1;
}
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
*out_len = 0;
if (ctx->error_encountered || ctx->data_used != 0) {
return -1;
}
return 1;
}
int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
const uint8_t *in, size_t in_len) {
*out_len = 0;
if (in_len % 4 != 0) {
return 0;
}
size_t max_len;
if (!EVP_DecodedLength(&max_len, in_len) ||
max_out < max_len) {
return 0;
}
size_t i, bytes_out = 0;
for (i = 0; i < in_len; i += 4) {
size_t num_bytes_resulting;
if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) {
return 0;
}
bytes_out += num_bytes_resulting;
out += num_bytes_resulting;
if (num_bytes_resulting != 3 && i != in_len - 4) {
return 0;
}
}
*out_len = bytes_out;
return 1;
}
int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
// Trim spaces and tabs from the beginning of the input.
while (src_len > 0) {
if (src[0] != ' ' && src[0] != '\t') {
break;
}
src++;
src_len--;
}
// Trim newlines, spaces and tabs from the end of the line.
while (src_len > 0) {
switch (src[src_len-1]) {
case ' ':
case '\t':
case '\r':
case '\n':
src_len--;
continue;
}
break;
}
size_t dst_len;
if (!EVP_DecodedLength(&dst_len, src_len) ||
dst_len > INT_MAX ||
!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
return -1;
}
// EVP_DecodeBlock does not take padding into account, so put the
// NULs back in... so the caller can strip them back out.
while (dst_len % 3 != 0) {
dst[dst_len++] = '\0';
}
assert(dst_len <= INT_MAX);
return (int)dst_len;
}

View File

@ -1,636 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/thread.h>
#include "../internal.h"
BIO *BIO_new(const BIO_METHOD *method) {
BIO *ret = OPENSSL_malloc(sizeof(BIO));
if (ret == NULL) {
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
return NULL;
}
OPENSSL_memset(ret, 0, sizeof(BIO));
ret->method = method;
ret->shutdown = 1;
ret->references = 1;
if (method->create != NULL && !method->create(ret)) {
OPENSSL_free(ret);
return NULL;
}
return ret;
}
int BIO_free(BIO *bio) {
BIO *next_bio;
for (; bio != NULL; bio = next_bio) {
if (!CRYPTO_refcount_dec_and_test_zero(&bio->references)) {
return 0;
}
next_bio = BIO_pop(bio);
if (bio->method != NULL && bio->method->destroy != NULL) {
bio->method->destroy(bio);
}
OPENSSL_free(bio);
}
return 1;
}
int BIO_up_ref(BIO *bio) {
CRYPTO_refcount_inc(&bio->references);
return 1;
}
void BIO_vfree(BIO *bio) {
BIO_free(bio);
}
void BIO_free_all(BIO *bio) {
BIO_free(bio);
}
int BIO_read(BIO *bio, void *buf, int len) {
if (bio == NULL || bio->method == NULL || bio->method->bread == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (!bio->init) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
return -2;
}
if (len <= 0) {
return 0;
}
int ret = bio->method->bread(bio, buf, len);
if (ret > 0) {
bio->num_read += ret;
}
return ret;
}
int BIO_gets(BIO *bio, char *buf, int len) {
if (bio == NULL || bio->method == NULL || bio->method->bgets == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (!bio->init) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
return -2;
}
if (len <= 0) {
return 0;
}
int ret = bio->method->bgets(bio, buf, len);
if (ret > 0) {
bio->num_read += ret;
}
return ret;
}
int BIO_write(BIO *bio, const void *in, int inl) {
if (bio == NULL || bio->method == NULL || bio->method->bwrite == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (!bio->init) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
return -2;
}
if (inl <= 0) {
return 0;
}
int ret = bio->method->bwrite(bio, in, inl);
if (ret > 0) {
bio->num_write += ret;
}
return ret;
}
int BIO_puts(BIO *bio, const char *in) {
return BIO_write(bio, in, strlen(in));
}
int BIO_flush(BIO *bio) {
return BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL);
}
long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
if (bio == NULL) {
return 0;
}
if (bio->method == NULL || bio->method->ctrl == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
return bio->method->ctrl(bio, cmd, larg, parg);
}
char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) {
char *p = NULL;
if (BIO_ctrl(b, cmd, larg, (void *)&p) <= 0) {
return NULL;
}
return p;
}
long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) {
int i = iarg;
return BIO_ctrl(b, cmd, larg, (void *)&i);
}
int BIO_reset(BIO *bio) {
return BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL);
}
int BIO_eof(BIO *bio) {
return BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL);
}
void BIO_set_flags(BIO *bio, int flags) {
bio->flags |= flags;
}
int BIO_test_flags(const BIO *bio, int flags) {
return bio->flags & flags;
}
int BIO_should_read(const BIO *bio) {
return BIO_test_flags(bio, BIO_FLAGS_READ);
}
int BIO_should_write(const BIO *bio) {
return BIO_test_flags(bio, BIO_FLAGS_WRITE);
}
int BIO_should_retry(const BIO *bio) {
return BIO_test_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
int BIO_should_io_special(const BIO *bio) {
return BIO_test_flags(bio, BIO_FLAGS_IO_SPECIAL);
}
int BIO_get_retry_reason(const BIO *bio) { return bio->retry_reason; }
void BIO_clear_flags(BIO *bio, int flags) {
bio->flags &= ~flags;
}
void BIO_set_retry_read(BIO *bio) {
bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY;
}
void BIO_set_retry_write(BIO *bio) {
bio->flags |= BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY;
}
static const int kRetryFlags = BIO_FLAGS_RWS | BIO_FLAGS_SHOULD_RETRY;
int BIO_get_retry_flags(BIO *bio) {
return bio->flags & kRetryFlags;
}
void BIO_clear_retry_flags(BIO *bio) {
bio->flags &= ~kRetryFlags;
bio->retry_reason = 0;
}
int BIO_method_type(const BIO *bio) { return bio->method->type; }
void BIO_copy_next_retry(BIO *bio) {
BIO_clear_retry_flags(bio);
BIO_set_flags(bio, BIO_get_retry_flags(bio->next_bio));
bio->retry_reason = bio->next_bio->retry_reason;
}
long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
if (bio == NULL) {
return 0;
}
if (bio->method == NULL || bio->method->callback_ctrl == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return 0;
}
return bio->method->callback_ctrl(bio, cmd, fp);
}
size_t BIO_pending(const BIO *bio) {
const long r = BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
assert(r >= 0);
if (r < 0) {
return 0;
}
return r;
}
size_t BIO_ctrl_pending(const BIO *bio) {
return BIO_pending(bio);
}
size_t BIO_wpending(const BIO *bio) {
const long r = BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
assert(r >= 0);
if (r < 0) {
return 0;
}
return r;
}
int BIO_set_close(BIO *bio, int close_flag) {
return BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, close_flag, NULL);
}
OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio) {
return bio->num_read;
}
OPENSSL_EXPORT size_t BIO_number_written(const BIO *bio) {
return bio->num_write;
}
BIO *BIO_push(BIO *bio, BIO *appended_bio) {
BIO *last_bio;
if (bio == NULL) {
return bio;
}
last_bio = bio;
while (last_bio->next_bio != NULL) {
last_bio = last_bio->next_bio;
}
last_bio->next_bio = appended_bio;
return bio;
}
BIO *BIO_pop(BIO *bio) {
BIO *ret;
if (bio == NULL) {
return NULL;
}
ret = bio->next_bio;
bio->next_bio = NULL;
return ret;
}
BIO *BIO_next(BIO *bio) {
if (!bio) {
return NULL;
}
return bio->next_bio;
}
BIO *BIO_find_type(BIO *bio, int type) {
int method_type, mask;
if (!bio) {
return NULL;
}
mask = type & 0xff;
do {
if (bio->method != NULL) {
method_type = bio->method->type;
if (!mask) {
if (method_type & type) {
return bio;
}
} else if (method_type == type) {
return bio;
}
}
bio = bio->next_bio;
} while (bio != NULL);
return NULL;
}
int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent) {
if (indent > max_indent) {
indent = max_indent;
}
while (indent--) {
if (BIO_puts(bio, " ") != 1) {
return 0;
}
}
return 1;
}
static int print_bio(const char *str, size_t len, void *bio) {
return BIO_write((BIO *)bio, str, len);
}
void ERR_print_errors(BIO *bio) {
ERR_print_errors_cb(print_bio, bio);
}
// bio_read_all reads everything from |bio| and prepends |prefix| to it. On
// success, |*out| is set to an allocated buffer (which should be freed with
// |OPENSSL_free|), |*out_len| is set to its length and one is returned. The
// buffer will contain |prefix| followed by the contents of |bio|. On failure,
// zero is returned.
//
// The function will fail if the size of the output would equal or exceed
// |max_len|.
static int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len,
const uint8_t *prefix, size_t prefix_len,
size_t max_len) {
static const size_t kChunkSize = 4096;
size_t len = prefix_len + kChunkSize;
if (len > max_len) {
len = max_len;
}
if (len < prefix_len) {
return 0;
}
*out = OPENSSL_malloc(len);
if (*out == NULL) {
return 0;
}
OPENSSL_memcpy(*out, prefix, prefix_len);
size_t done = prefix_len;
for (;;) {
if (done == len) {
OPENSSL_free(*out);
return 0;
}
const size_t todo = len - done;
assert(todo < INT_MAX);
const int n = BIO_read(bio, *out + done, todo);
if (n == 0) {
*out_len = done;
return 1;
} else if (n == -1) {
OPENSSL_free(*out);
return 0;
}
done += n;
if (len < max_len && len - done < kChunkSize / 2) {
len += kChunkSize;
if (len < kChunkSize || len > max_len) {
len = max_len;
}
uint8_t *new_buf = OPENSSL_realloc(*out, len);
if (new_buf == NULL) {
OPENSSL_free(*out);
return 0;
}
*out = new_buf;
}
}
}
int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
uint8_t header[6];
static const size_t kInitialHeaderLen = 2;
if (BIO_read(bio, header, kInitialHeaderLen) != (int) kInitialHeaderLen) {
return 0;
}
const uint8_t tag = header[0];
const uint8_t length_byte = header[1];
if ((tag & 0x1f) == 0x1f) {
// Long form tags are not supported.
return 0;
}
size_t len, header_len;
if ((length_byte & 0x80) == 0) {
// Short form length.
len = length_byte;
header_len = kInitialHeaderLen;
} else {
const size_t num_bytes = length_byte & 0x7f;
if ((tag & 0x20 /* constructed */) != 0 && num_bytes == 0) {
// indefinite length.
return bio_read_all(bio, out, out_len, header, kInitialHeaderLen,
max_len);
}
if (num_bytes == 0 || num_bytes > 4) {
return 0;
}
if (BIO_read(bio, header + kInitialHeaderLen, num_bytes) !=
(int)num_bytes) {
return 0;
}
header_len = kInitialHeaderLen + num_bytes;
uint32_t len32 = 0;
unsigned i;
for (i = 0; i < num_bytes; i++) {
len32 <<= 8;
len32 |= header[kInitialHeaderLen + i];
}
if (len32 < 128) {
// Length should have used short-form encoding.
return 0;
}
if ((len32 >> ((num_bytes-1)*8)) == 0) {
// Length should have been at least one byte shorter.
return 0;
}
len = len32;
}
if (len + header_len < len ||
len + header_len > max_len ||
len > INT_MAX) {
return 0;
}
len += header_len;
*out_len = len;
*out = OPENSSL_malloc(len);
if (*out == NULL) {
return 0;
}
OPENSSL_memcpy(*out, header, header_len);
if (BIO_read(bio, (*out) + header_len, len - header_len) !=
(int) (len - header_len)) {
OPENSSL_free(*out);
return 0;
}
return 1;
}
void BIO_set_retry_special(BIO *bio) {
bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL;
}
int BIO_set_write_buffer_size(BIO *bio, int buffer_size) { return 0; }
static struct CRYPTO_STATIC_MUTEX g_index_lock = CRYPTO_STATIC_MUTEX_INIT;
static int g_index = BIO_TYPE_START;
int BIO_get_new_index(void) {
CRYPTO_STATIC_MUTEX_lock_write(&g_index_lock);
// If |g_index| exceeds 255, it will collide with the flags bits.
int ret = g_index > 255 ? -1 : g_index++;
CRYPTO_STATIC_MUTEX_unlock_write(&g_index_lock);
return ret;
}
BIO_METHOD *BIO_meth_new(int type, const char *name) {
BIO_METHOD *method = OPENSSL_malloc(sizeof(BIO_METHOD));
if (method == NULL) {
return NULL;
}
OPENSSL_memset(method, 0, sizeof(BIO_METHOD));
method->type = type;
method->name = name;
return method;
}
void BIO_meth_free(BIO_METHOD *method) {
OPENSSL_free(method);
}
int BIO_meth_set_create(BIO_METHOD *method,
int (*create)(BIO *)) {
method->create = create;
return 1;
}
int BIO_meth_set_destroy(BIO_METHOD *method,
int (*destroy)(BIO *)) {
method->destroy = destroy;
return 1;
}
int BIO_meth_set_write(BIO_METHOD *method,
int (*write)(BIO *, const char *, int)) {
method->bwrite = write;
return 1;
}
int BIO_meth_set_read(BIO_METHOD *method,
int (*read)(BIO *, char *, int)) {
method->bread = read;
return 1;
}
int BIO_meth_set_gets(BIO_METHOD *method,
int (*gets)(BIO *, char *, int)) {
method->bgets = gets;
return 1;
}
int BIO_meth_set_ctrl(BIO_METHOD *method,
long (*ctrl)(BIO *, int, long, void *)) {
method->ctrl = ctrl;
return 1;
}
void BIO_set_data(BIO *bio, void *ptr) { bio->ptr = ptr; }
void *BIO_get_data(BIO *bio) { return bio->ptr; }
void BIO_set_init(BIO *bio, int init) { bio->init = init; }
int BIO_get_init(BIO *bio) { return bio->init; }
void BIO_set_shutdown(BIO *bio, int shutdown) { bio->shutdown = shutdown; }
int BIO_get_shutdown(BIO *bio) { return bio->shutdown; }
int BIO_meth_set_puts(BIO_METHOD *method, int (*puts)(BIO *, const char *)) {
// Ignore the parameter. We implement |BIO_puts| using |BIO_write|.
return 1;
}

View File

@ -1,330 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <limits.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
BIO *BIO_new_mem_buf(const void *buf, int len) {
BIO *ret;
BUF_MEM *b;
const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
if (!buf && len != 0) {
OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER);
return NULL;
}
ret = BIO_new(BIO_s_mem());
if (ret == NULL) {
return NULL;
}
b = (BUF_MEM *)ret->ptr;
// BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to.
b->data = (void *)buf;
b->length = size;
b->max = size;
ret->flags |= BIO_FLAGS_MEM_RDONLY;
// |num| is used to store the value that this BIO will return when it runs
// out of data. If it's negative then the retry flags will also be set. Since
// this is static data, retrying wont help
ret->num = 0;
return ret;
}
static int mem_new(BIO *bio) {
BUF_MEM *b;
b = BUF_MEM_new();
if (b == NULL) {
return 0;
}
// |shutdown| is used to store the close flag: whether the BIO has ownership
// of the BUF_MEM.
bio->shutdown = 1;
bio->init = 1;
bio->num = -1;
bio->ptr = (char *)b;
return 1;
}
static int mem_free(BIO *bio) {
BUF_MEM *b;
if (bio == NULL) {
return 0;
}
if (!bio->shutdown || !bio->init || bio->ptr == NULL) {
return 1;
}
b = (BUF_MEM *)bio->ptr;
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
b->data = NULL;
}
BUF_MEM_free(b);
bio->ptr = NULL;
return 1;
}
static int mem_read(BIO *bio, char *out, int outl) {
int ret;
BUF_MEM *b = (BUF_MEM*) bio->ptr;
BIO_clear_retry_flags(bio);
ret = outl;
if (b->length < INT_MAX && ret > (int)b->length) {
ret = b->length;
}
if (ret > 0) {
OPENSSL_memcpy(out, b->data, ret);
b->length -= ret;
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
b->data += ret;
} else {
OPENSSL_memmove(b->data, &b->data[ret], b->length);
}
} else if (b->length == 0) {
ret = bio->num;
if (ret != 0) {
BIO_set_retry_read(bio);
}
}
return ret;
}
static int mem_write(BIO *bio, const char *in, int inl) {
int ret = -1;
int blen;
BUF_MEM *b;
b = (BUF_MEM *)bio->ptr;
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
OPENSSL_PUT_ERROR(BIO, BIO_R_WRITE_TO_READ_ONLY_BIO);
goto err;
}
BIO_clear_retry_flags(bio);
blen = b->length;
if (INT_MAX - blen < inl) {
goto err;
}
if (BUF_MEM_grow_clean(b, blen + inl) != ((size_t) blen) + inl) {
goto err;
}
OPENSSL_memcpy(&b->data[blen], in, inl);
ret = inl;
err:
return ret;
}
static int mem_gets(BIO *bio, char *buf, int size) {
int i, j;
char *p;
BUF_MEM *b = (BUF_MEM *)bio->ptr;
BIO_clear_retry_flags(bio);
j = b->length;
if (size - 1 < j) {
j = size - 1;
}
if (j <= 0) {
if (size > 0) {
*buf = 0;
}
return 0;
}
p = b->data;
for (i = 0; i < j; i++) {
if (p[i] == '\n') {
i++;
break;
}
}
// i is now the max num of bytes to copy, either j or up to and including the
// first newline
i = mem_read(bio, buf, i);
if (i > 0) {
buf[i] = '\0';
}
return i;
}
static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
long ret = 1;
char **pptr;
BUF_MEM *b = (BUF_MEM *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
if (b->data != NULL) {
// For read only case reset to the start again
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
b->data -= b->max - b->length;
b->length = b->max;
} else {
OPENSSL_memset(b->data, 0, b->max);
b->length = 0;
}
}
break;
case BIO_CTRL_EOF:
ret = (long)(b->length == 0);
break;
case BIO_C_SET_BUF_MEM_EOF_RETURN:
bio->num = (int)num;
break;
case BIO_CTRL_INFO:
ret = (long)b->length;
if (ptr != NULL) {
pptr = (char **)ptr;
*pptr = (char *)&b->data[0];
}
break;
case BIO_C_SET_BUF_MEM:
mem_free(bio);
bio->shutdown = (int)num;
bio->ptr = ptr;
break;
case BIO_C_GET_BUF_MEM_PTR:
if (ptr != NULL) {
pptr = (char **)ptr;
*pptr = (char *)b;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = (long)bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_WPENDING:
ret = 0L;
break;
case BIO_CTRL_PENDING:
ret = (long)b->length;
break;
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
static const BIO_METHOD mem_method = {
BIO_TYPE_MEM, "memory buffer",
mem_write, mem_read,
NULL /* puts */, mem_gets,
mem_ctrl, mem_new,
mem_free, NULL /* callback_ctrl */,
};
const BIO_METHOD *BIO_s_mem(void) { return &mem_method; }
int BIO_mem_contents(const BIO *bio, const uint8_t **out_contents,
size_t *out_len) {
const BUF_MEM *b;
if (bio->method != &mem_method) {
return 0;
}
b = (BUF_MEM *)bio->ptr;
*out_contents = (uint8_t *)b->data;
*out_len = b->length;
return 1;
}
long BIO_get_mem_data(BIO *bio, char **contents) {
return BIO_ctrl(bio, BIO_CTRL_INFO, 0, (char *) contents);
}
int BIO_get_mem_ptr(BIO *bio, BUF_MEM **out) {
return BIO_ctrl(bio, BIO_C_GET_BUF_MEM_PTR, 0, (char *) out);
}
int BIO_set_mem_buf(BIO *bio, BUF_MEM *b, int take_ownership) {
return BIO_ctrl(bio, BIO_C_SET_BUF_MEM, take_ownership, (char *) b);
}
int BIO_set_mem_eof_return(BIO *bio, int eof_value) {
return BIO_ctrl(bio, BIO_C_SET_BUF_MEM_EOF_RETURN, eof_value, NULL);
}

View File

@ -1,542 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#if !defined(OPENSSL_WINDOWS)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#else
OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
#include <ws2tcpip.h>
OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "internal.h"
#include "../internal.h"
enum {
BIO_CONN_S_BEFORE,
BIO_CONN_S_BLOCKED_CONNECT,
BIO_CONN_S_OK,
};
typedef struct bio_connect_st {
int state;
char *param_hostname;
char *param_port;
int nbio;
unsigned short port;
struct sockaddr_storage them;
socklen_t them_length;
// the file descriptor is kept in bio->num in order to match the socket
// BIO.
// info_callback is called when the connection is initially made
// callback(BIO,state,ret); The callback should return 'ret', state is for
// compatibility with the SSL info_callback.
int (*info_callback)(const BIO *bio, int state, int ret);
} BIO_CONNECT;
#if !defined(OPENSSL_WINDOWS)
static int closesocket(int sock) {
return close(sock);
}
#endif
// split_host_and_port sets |*out_host| and |*out_port| to the host and port
// parsed from |name|. It returns one on success or zero on error. Even when
// successful, |*out_port| may be NULL on return if no port was specified.
static int split_host_and_port(char **out_host, char **out_port, const char *name) {
const char *host, *port = NULL;
size_t host_len = 0;
*out_host = NULL;
*out_port = NULL;
if (name[0] == '[') { // bracketed IPv6 address
const char *close = strchr(name, ']');
if (close == NULL) {
return 0;
}
host = name + 1;
host_len = close - host;
if (close[1] == ':') { // [IP]:port
port = close + 2;
} else if (close[1] != 0) {
return 0;
}
} else {
const char *colon = strchr(name, ':');
if (colon == NULL || strchr(colon + 1, ':') != NULL) { // IPv6 address
host = name;
host_len = strlen(name);
} else { // host:port
host = name;
host_len = colon - name;
port = colon + 1;
}
}
*out_host = BUF_strndup(host, host_len);
if (*out_host == NULL) {
return 0;
}
if (port == NULL) {
*out_port = NULL;
return 1;
}
*out_port = OPENSSL_strdup(port);
if (*out_port == NULL) {
OPENSSL_free(*out_host);
*out_host = NULL;
return 0;
}
return 1;
}
static int conn_state(BIO *bio, BIO_CONNECT *c) {
int ret = -1, i;
int (*cb)(const BIO *, int, int) = NULL;
if (c->info_callback != NULL) {
cb = c->info_callback;
}
for (;;) {
switch (c->state) {
case BIO_CONN_S_BEFORE:
// If there's a hostname and a port, assume that both are
// exactly what they say. If there is only a hostname, try
// (just once) to split it into a hostname and port.
if (c->param_hostname == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_HOSTNAME_SPECIFIED);
goto exit_loop;
}
if (c->param_port == NULL) {
char *host, *port;
if (!split_host_and_port(&host, &port, c->param_hostname) ||
port == NULL) {
OPENSSL_free(host);
OPENSSL_free(port);
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_PORT_SPECIFIED);
ERR_add_error_data(2, "host=", c->param_hostname);
goto exit_loop;
}
OPENSSL_free(c->param_port);
c->param_port = port;
OPENSSL_free(c->param_hostname);
c->param_hostname = host;
}
if (!bio_ip_and_port_to_socket_and_addr(
&bio->num, &c->them, &c->them_length, c->param_hostname,
c->param_port)) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
goto exit_loop;
}
if (c->nbio) {
if (!bio_socket_nbio(bio->num, 1)) {
OPENSSL_PUT_ERROR(BIO, BIO_R_ERROR_SETTING_NBIO);
ERR_add_error_data(4, "host=", c->param_hostname, ":",
c->param_port);
goto exit_loop;
}
}
i = 1;
ret = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
sizeof(i));
if (ret < 0) {
OPENSSL_PUT_SYSTEM_ERROR();
OPENSSL_PUT_ERROR(BIO, BIO_R_KEEPALIVE);
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
goto exit_loop;
}
BIO_clear_retry_flags(bio);
ret = connect(bio->num, (struct sockaddr*) &c->them, c->them_length);
if (ret < 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
c->state = BIO_CONN_S_BLOCKED_CONNECT;
bio->retry_reason = BIO_RR_CONNECT;
} else {
OPENSSL_PUT_SYSTEM_ERROR();
OPENSSL_PUT_ERROR(BIO, BIO_R_CONNECT_ERROR);
ERR_add_error_data(4, "host=", c->param_hostname, ":",
c->param_port);
}
goto exit_loop;
} else {
c->state = BIO_CONN_S_OK;
}
break;
case BIO_CONN_S_BLOCKED_CONNECT:
i = bio_sock_error(bio->num);
if (i) {
if (bio_fd_should_retry(ret)) {
BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
c->state = BIO_CONN_S_BLOCKED_CONNECT;
bio->retry_reason = BIO_RR_CONNECT;
ret = -1;
} else {
BIO_clear_retry_flags(bio);
OPENSSL_PUT_SYSTEM_ERROR();
OPENSSL_PUT_ERROR(BIO, BIO_R_NBIO_CONNECT_ERROR);
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
ret = 0;
}
goto exit_loop;
} else {
c->state = BIO_CONN_S_OK;
}
break;
case BIO_CONN_S_OK:
ret = 1;
goto exit_loop;
default:
assert(0);
goto exit_loop;
}
if (cb != NULL) {
ret = cb((BIO *)bio, c->state, ret);
if (ret == 0) {
goto end;
}
}
}
exit_loop:
if (cb != NULL) {
ret = cb((BIO *)bio, c->state, ret);
}
end:
return ret;
}
static BIO_CONNECT *BIO_CONNECT_new(void) {
BIO_CONNECT *ret = OPENSSL_malloc(sizeof(BIO_CONNECT));
if (ret == NULL) {
return NULL;
}
OPENSSL_memset(ret, 0, sizeof(BIO_CONNECT));
ret->state = BIO_CONN_S_BEFORE;
return ret;
}
static void BIO_CONNECT_free(BIO_CONNECT *c) {
if (c == NULL) {
return;
}
OPENSSL_free(c->param_hostname);
OPENSSL_free(c->param_port);
OPENSSL_free(c);
}
static int conn_new(BIO *bio) {
bio->init = 0;
bio->num = -1;
bio->flags = 0;
bio->ptr = (char *)BIO_CONNECT_new();
return bio->ptr != NULL;
}
static void conn_close_socket(BIO *bio) {
BIO_CONNECT *c = (BIO_CONNECT *) bio->ptr;
if (bio->num == -1) {
return;
}
// Only do a shutdown if things were established
if (c->state == BIO_CONN_S_OK) {
shutdown(bio->num, 2);
}
closesocket(bio->num);
bio->num = -1;
}
static int conn_free(BIO *bio) {
if (bio == NULL) {
return 0;
}
if (bio->shutdown) {
conn_close_socket(bio);
}
BIO_CONNECT_free((BIO_CONNECT*) bio->ptr);
return 1;
}
static int conn_read(BIO *bio, char *out, int out_len) {
int ret = 0;
BIO_CONNECT *data;
data = (BIO_CONNECT *)bio->ptr;
if (data->state != BIO_CONN_S_OK) {
ret = conn_state(bio, data);
if (ret <= 0) {
return ret;
}
}
bio_clear_socket_error();
ret = recv(bio->num, out, out_len, 0);
BIO_clear_retry_flags(bio);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_read(bio);
}
}
return ret;
}
static int conn_write(BIO *bio, const char *in, int in_len) {
int ret;
BIO_CONNECT *data;
data = (BIO_CONNECT *)bio->ptr;
if (data->state != BIO_CONN_S_OK) {
ret = conn_state(bio, data);
if (ret <= 0) {
return ret;
}
}
bio_clear_socket_error();
ret = send(bio->num, in, in_len, 0);
BIO_clear_retry_flags(bio);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_write(bio);
}
}
return ret;
}
static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
int *ip;
long ret = 1;
BIO_CONNECT *data;
data = (BIO_CONNECT *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
ret = 0;
data->state = BIO_CONN_S_BEFORE;
conn_close_socket(bio);
bio->flags = 0;
break;
case BIO_C_DO_STATE_MACHINE:
// use this one to start the connection
if (data->state != BIO_CONN_S_OK) {
ret = (long)conn_state(bio, data);
} else {
ret = 1;
}
break;
case BIO_C_SET_CONNECT:
if (ptr != NULL) {
bio->init = 1;
if (num == 0) {
OPENSSL_free(data->param_hostname);
data->param_hostname = BUF_strdup(ptr);
if (data->param_hostname == NULL) {
ret = 0;
}
} else if (num == 1) {
OPENSSL_free(data->param_port);
data->param_port = BUF_strdup(ptr);
if (data->param_port == NULL) {
ret = 0;
}
} else {
ret = 0;
}
}
break;
case BIO_C_SET_NBIO:
data->nbio = (int)num;
break;
case BIO_C_GET_FD:
if (bio->init) {
ip = (int *)ptr;
if (ip != NULL) {
*ip = bio->num;
}
ret = bio->num;
} else {
ret = -1;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_PENDING:
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_FLUSH:
break;
case BIO_CTRL_GET_CALLBACK: {
int (**fptr)(const BIO *bio, int state, int xret);
fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
*fptr = data->info_callback;
} break;
default:
ret = 0;
break;
}
return ret;
}
static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
long ret = 1;
BIO_CONNECT *data;
data = (BIO_CONNECT *)bio->ptr;
switch (cmd) {
case BIO_CTRL_SET_CALLBACK:
data->info_callback = (int (*)(const struct bio_st *, int, int))fp;
break;
default:
ret = 0;
break;
}
return ret;
}
BIO *BIO_new_connect(const char *hostname) {
BIO *ret;
ret = BIO_new(BIO_s_connect());
if (ret == NULL) {
return NULL;
}
if (!BIO_set_conn_hostname(ret, hostname)) {
BIO_free(ret);
return NULL;
}
return ret;
}
static const BIO_METHOD methods_connectp = {
BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read,
NULL /* puts */, NULL /* gets */, conn_ctrl, conn_new,
conn_free, conn_callback_ctrl,
};
const BIO_METHOD *BIO_s_connect(void) { return &methods_connectp; }
int BIO_set_conn_hostname(BIO *bio, const char *name) {
return BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, (void*) name);
}
int BIO_set_conn_port(BIO *bio, const char *port_str) {
return BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, (void*) port_str);
}
int BIO_set_conn_int_port(BIO *bio, const int *port) {
char buf[DECIMAL_SIZE(int) + 1];
BIO_snprintf(buf, sizeof(buf), "%d", *port);
return BIO_set_conn_port(bio, buf);
}
int BIO_set_nbio(BIO *bio, int on) {
return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL);
}
int BIO_do_connect(BIO *bio) {
return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL);
}

View File

@ -1,276 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <errno.h>
#include <string.h>
#if !defined(OPENSSL_WINDOWS)
#include <unistd.h>
#else
#include <io.h>
OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <windows.h>
OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "internal.h"
#include "../internal.h"
static int bio_fd_non_fatal_error(int err) {
if (
#ifdef EWOULDBLOCK
err == EWOULDBLOCK ||
#endif
#ifdef WSAEWOULDBLOCK
err == WSAEWOULDBLOCK ||
#endif
#ifdef ENOTCONN
err == ENOTCONN ||
#endif
#ifdef EINTR
err == EINTR ||
#endif
#ifdef EAGAIN
err == EAGAIN ||
#endif
#ifdef EPROTO
err == EPROTO ||
#endif
#ifdef EINPROGRESS
err == EINPROGRESS ||
#endif
#ifdef EALREADY
err == EALREADY ||
#endif
0) {
return 1;
}
return 0;
}
#if defined(OPENSSL_WINDOWS)
#define BORINGSSL_ERRNO (int)GetLastError()
#define BORINGSSL_CLOSE _close
#define BORINGSSL_LSEEK _lseek
#define BORINGSSL_READ _read
#define BORINGSSL_WRITE _write
#else
#define BORINGSSL_ERRNO errno
#define BORINGSSL_CLOSE close
#define BORINGSSL_LSEEK lseek
#define BORINGSSL_READ read
#define BORINGSSL_WRITE write
#endif
int bio_fd_should_retry(int i) {
if (i == -1) {
return bio_fd_non_fatal_error(BORINGSSL_ERRNO);
}
return 0;
}
BIO *BIO_new_fd(int fd, int close_flag) {
BIO *ret = BIO_new(BIO_s_fd());
if (ret == NULL) {
return NULL;
}
BIO_set_fd(ret, fd, close_flag);
return ret;
}
static int fd_new(BIO *bio) {
// num is used to store the file descriptor.
bio->num = -1;
return 1;
}
static int fd_free(BIO *bio) {
if (bio == NULL) {
return 0;
}
if (bio->shutdown) {
if (bio->init) {
BORINGSSL_CLOSE(bio->num);
}
bio->init = 0;
}
return 1;
}
static int fd_read(BIO *b, char *out, int outl) {
int ret = 0;
ret = BORINGSSL_READ(b->num, out, outl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_read(b);
}
}
return ret;
}
static int fd_write(BIO *b, const char *in, int inl) {
int ret = BORINGSSL_WRITE(b->num, in, inl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_write(b);
}
}
return ret;
}
static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) {
long ret = 1;
int *ip;
switch (cmd) {
case BIO_CTRL_RESET:
num = 0;
OPENSSL_FALLTHROUGH;
case BIO_C_FILE_SEEK:
ret = 0;
if (b->init) {
ret = (long)BORINGSSL_LSEEK(b->num, num, SEEK_SET);
}
break;
case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
ret = 0;
if (b->init) {
ret = (long)BORINGSSL_LSEEK(b->num, 0, SEEK_CUR);
}
break;
case BIO_C_SET_FD:
fd_free(b);
b->num = *((int *)ptr);
b->shutdown = (int)num;
b->init = 1;
break;
case BIO_C_GET_FD:
if (b->init) {
ip = (int *)ptr;
if (ip != NULL) {
*ip = b->num;
}
return b->num;
} else {
ret = -1;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = b->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
b->shutdown = (int)num;
break;
case BIO_CTRL_PENDING:
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
static int fd_gets(BIO *bp, char *buf, int size) {
char *ptr = buf;
char *end = buf + size - 1;
if (size <= 0) {
return 0;
}
while (ptr < end && fd_read(bp, ptr, 1) > 0 && ptr[0] != '\n') {
ptr++;
}
ptr[0] = '\0';
return ptr - buf;
}
static const BIO_METHOD methods_fdp = {
BIO_TYPE_FD, "file descriptor", fd_write, fd_read, NULL /* puts */,
fd_gets, fd_ctrl, fd_new, fd_free, NULL /* callback_ctrl */,
};
const BIO_METHOD *BIO_s_fd(void) { return &methods_fdp; }
int BIO_set_fd(BIO *bio, int fd, int close_flag) {
return BIO_int_ctrl(bio, BIO_C_SET_FD, close_flag, fd);
}
int BIO_get_fd(BIO *bio, int *out_fd) {
return BIO_ctrl(bio, BIO_C_GET_FD, 0, (char *) out_fd);
}

View File

@ -1,315 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#if defined(__linux) || defined(__sun) || defined(__hpux)
// Following definition aliases fopen to fopen64 on above mentioned
// platforms. This makes it possible to open and sequentially access
// files larger than 2GB from 32-bit application. It does not allow to
// traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
// 32-bit platform permits that, not with fseek/ftell. Not to mention
// that breaking 2GB limit for seeking would require surgery to *our*
// API. But sequential access suffices for practical cases when you
// can run into large files, such as fingerprinting, so we can let API
// alone. For reference, the list of 32-bit platforms which allow for
// sequential access of large files without extra "magic" comprise *BSD,
// Darwin, IRIX...
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#endif
#include <openssl/bio.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
#define BIO_FP_READ 0x02
#define BIO_FP_WRITE 0x04
#define BIO_FP_APPEND 0x08
BIO *BIO_new_file(const char *filename, const char *mode) {
BIO *ret;
FILE *file;
file = fopen(filename, mode);
if (file == NULL) {
OPENSSL_PUT_SYSTEM_ERROR();
ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
if (errno == ENOENT) {
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_SUCH_FILE);
} else {
OPENSSL_PUT_ERROR(BIO, BIO_R_SYS_LIB);
}
return NULL;
}
ret = BIO_new(BIO_s_file());
if (ret == NULL) {
fclose(file);
return NULL;
}
BIO_set_fp(ret, file, BIO_CLOSE);
return ret;
}
BIO *BIO_new_fp(FILE *stream, int close_flag) {
BIO *ret = BIO_new(BIO_s_file());
if (ret == NULL) {
return NULL;
}
BIO_set_fp(ret, stream, close_flag);
return ret;
}
static int file_new(BIO *bio) { return 1; }
static int file_free(BIO *bio) {
if (bio == NULL) {
return 0;
}
if (!bio->shutdown) {
return 1;
}
if (bio->init && bio->ptr != NULL) {
fclose(bio->ptr);
bio->ptr = NULL;
}
bio->init = 0;
return 1;
}
static int file_read(BIO *b, char *out, int outl) {
if (!b->init) {
return 0;
}
size_t ret = fread(out, 1, outl, (FILE *)b->ptr);
if (ret == 0 && ferror((FILE *)b->ptr)) {
OPENSSL_PUT_SYSTEM_ERROR();
OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB);
return -1;
}
// fread reads at most |outl| bytes, so |ret| fits in an int.
return (int)ret;
}
static int file_write(BIO *b, const char *in, int inl) {
int ret = 0;
if (!b->init) {
return 0;
}
ret = fwrite(in, inl, 1, (FILE *)b->ptr);
if (ret > 0) {
ret = inl;
}
return ret;
}
static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
long ret = 1;
FILE *fp = (FILE *)b->ptr;
FILE **fpp;
char p[4];
switch (cmd) {
case BIO_CTRL_RESET:
num = 0;
OPENSSL_FALLTHROUGH;
case BIO_C_FILE_SEEK:
ret = (long)fseek(fp, num, 0);
break;
case BIO_CTRL_EOF:
ret = (long)feof(fp);
break;
case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
ret = ftell(fp);
break;
case BIO_C_SET_FILE_PTR:
file_free(b);
b->shutdown = (int)num & BIO_CLOSE;
b->ptr = ptr;
b->init = 1;
break;
case BIO_C_SET_FILENAME:
file_free(b);
b->shutdown = (int)num & BIO_CLOSE;
if (num & BIO_FP_APPEND) {
if (num & BIO_FP_READ) {
BUF_strlcpy(p, "a+", sizeof(p));
} else {
BUF_strlcpy(p, "a", sizeof(p));
}
} else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) {
BUF_strlcpy(p, "r+", sizeof(p));
} else if (num & BIO_FP_WRITE) {
BUF_strlcpy(p, "w", sizeof(p));
} else if (num & BIO_FP_READ) {
BUF_strlcpy(p, "r", sizeof(p));
} else {
OPENSSL_PUT_ERROR(BIO, BIO_R_BAD_FOPEN_MODE);
ret = 0;
break;
}
fp = fopen(ptr, p);
if (fp == NULL) {
OPENSSL_PUT_SYSTEM_ERROR();
ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB);
ret = 0;
break;
}
b->ptr = fp;
b->init = 1;
break;
case BIO_C_GET_FILE_PTR:
// the ptr parameter is actually a FILE ** in this case.
if (ptr != NULL) {
fpp = (FILE **)ptr;
*fpp = (FILE *)b->ptr;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = (long)b->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
b->shutdown = (int)num;
break;
case BIO_CTRL_FLUSH:
ret = 0 == fflush((FILE *)b->ptr);
break;
case BIO_CTRL_WPENDING:
case BIO_CTRL_PENDING:
default:
ret = 0;
break;
}
return ret;
}
static int file_gets(BIO *bp, char *buf, int size) {
int ret = 0;
if (size == 0) {
return 0;
}
if (!fgets(buf, size, (FILE *)bp->ptr)) {
buf[0] = 0;
goto err;
}
ret = strlen(buf);
err:
return ret;
}
static const BIO_METHOD methods_filep = {
BIO_TYPE_FILE, "FILE pointer",
file_write, file_read,
NULL /* puts */, file_gets,
file_ctrl, file_new,
file_free, NULL /* callback_ctrl */,
};
const BIO_METHOD *BIO_s_file(void) { return &methods_filep; }
int BIO_get_fp(BIO *bio, FILE **out_file) {
return BIO_ctrl(bio, BIO_C_GET_FILE_PTR, 0, (char*) out_file);
}
int BIO_set_fp(BIO *bio, FILE *file, int close_flag) {
return BIO_ctrl(bio, BIO_C_SET_FILE_PTR, close_flag, (char *) file);
}
int BIO_read_filename(BIO *bio, const char *filename) {
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_READ,
(char *)filename);
}
int BIO_write_filename(BIO *bio, const char *filename) {
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_WRITE,
(char *)filename);
}
int BIO_append_filename(BIO *bio, const char *filename) {
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_APPEND,
(char *)filename);
}
int BIO_rw_filename(BIO *bio, const char *filename) {
return BIO_ctrl(bio, BIO_C_SET_FILENAME,
BIO_CLOSE | BIO_FP_READ | BIO_FP_WRITE, (char *)filename);
}

View File

@ -1,192 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <limits.h>
#include <string.h>
#include "../internal.h"
// hexdump_ctx contains the state of a hexdump.
struct hexdump_ctx {
BIO *bio;
char right_chars[18]; // the contents of the right-hand side, ASCII dump.
unsigned used; // number of bytes in the current line.
size_t n; // number of bytes total.
unsigned indent;
};
static void hexbyte(char *out, uint8_t b) {
static const char hextable[] = "0123456789abcdef";
out[0] = hextable[b>>4];
out[1] = hextable[b&0x0f];
}
static char to_char(uint8_t b) {
if (b < 32 || b > 126) {
return '.';
}
return b;
}
// hexdump_write adds |len| bytes of |data| to the current hex dump described by
// |ctx|.
static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
size_t len) {
char buf[10];
unsigned l;
// Output lines look like:
// 00000010 2e 2f 30 31 32 33 34 35 36 37 38 ... 3c 3d // |./0123456789:;<=|
// ^ offset ^ extra space ^ ASCII of line
for (size_t i = 0; i < len; i++) {
if (ctx->used == 0) {
// The beginning of a line.
BIO_indent(ctx->bio, ctx->indent, UINT_MAX);
hexbyte(&buf[0], ctx->n >> 24);
hexbyte(&buf[2], ctx->n >> 16);
hexbyte(&buf[4], ctx->n >> 8);
hexbyte(&buf[6], ctx->n);
buf[8] = buf[9] = ' ';
if (BIO_write(ctx->bio, buf, 10) < 0) {
return 0;
}
}
hexbyte(buf, data[i]);
buf[2] = ' ';
l = 3;
if (ctx->used == 7) {
// There's an additional space after the 8th byte.
buf[3] = ' ';
l = 4;
} else if (ctx->used == 15) {
// At the end of the line there's an extra space and the bar for the
// right column.
buf[3] = ' ';
buf[4] = '|';
l = 5;
}
if (BIO_write(ctx->bio, buf, l) < 0) {
return 0;
}
ctx->right_chars[ctx->used] = to_char(data[i]);
ctx->used++;
ctx->n++;
if (ctx->used == 16) {
ctx->right_chars[16] = '|';
ctx->right_chars[17] = '\n';
if (BIO_write(ctx->bio, ctx->right_chars, sizeof(ctx->right_chars)) < 0) {
return 0;
}
ctx->used = 0;
}
}
return 1;
}
// finish flushes any buffered data in |ctx|.
static int finish(struct hexdump_ctx *ctx) {
// See the comments in |hexdump| for the details of this format.
const unsigned n_bytes = ctx->used;
unsigned l;
char buf[5];
if (n_bytes == 0) {
return 1;
}
OPENSSL_memset(buf, ' ', 4);
buf[4] = '|';
for (; ctx->used < 16; ctx->used++) {
l = 3;
if (ctx->used == 7) {
l = 4;
} else if (ctx->used == 15) {
l = 5;
}
if (BIO_write(ctx->bio, buf, l) < 0) {
return 0;
}
}
ctx->right_chars[n_bytes] = '|';
ctx->right_chars[n_bytes + 1] = '\n';
if (BIO_write(ctx->bio, ctx->right_chars, n_bytes + 2) < 0) {
return 0;
}
return 1;
}
int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, unsigned indent) {
struct hexdump_ctx ctx;
OPENSSL_memset(&ctx, 0, sizeof(ctx));
ctx.bio = bio;
ctx.indent = indent;
if (!hexdump_write(&ctx, data, len) || !finish(&ctx)) {
return 0;
}
return 1;
}

View File

@ -1,111 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#ifndef OPENSSL_HEADER_BIO_INTERNAL_H
#define OPENSSL_HEADER_BIO_INTERNAL_H
#include <openssl/base.h>
#if !defined(OPENSSL_WINDOWS)
#if defined(OPENSSL_PNACL)
// newlib uses u_short in socket.h without defining it.
typedef unsigned short u_short;
#endif
#include <sys/types.h>
#include <sys/socket.h>
#else
OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
OPENSSL_MSVC_PRAGMA(warning(pop))
typedef int socklen_t;
#endif
#if defined(__cplusplus)
extern "C" {
#endif
// BIO_ip_and_port_to_socket_and_addr creates a socket and fills in |*out_addr|
// and |*out_addr_length| with the correct values for connecting to |hostname|
// on |port_str|. It returns one on success or zero on error.
int bio_ip_and_port_to_socket_and_addr(int *out_sock,
struct sockaddr_storage *out_addr,
socklen_t *out_addr_length,
const char *hostname,
const char *port_str);
// BIO_socket_nbio sets whether |sock| is non-blocking. It returns one on
// success and zero otherwise.
int bio_socket_nbio(int sock, int on);
// BIO_clear_socket_error clears the last system socket error.
//
// TODO(fork): remove all callers of this.
void bio_clear_socket_error(void);
// BIO_sock_error returns the last socket error on |sock|.
int bio_sock_error(int sock);
// BIO_fd_should_retry returns non-zero if |return_value| indicates an error
// and |errno| indicates that it's non-fatal.
int bio_fd_should_retry(int return_value);
#if defined(__cplusplus)
} // extern C
#endif
#endif // OPENSSL_HEADER_BIO_INTERNAL_H

View File

@ -1,489 +0,0 @@
/* ====================================================================
* Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <openssl/bio.h>
#include <assert.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
struct bio_bio_st {
BIO *peer; // NULL if buf == NULL.
// If peer != NULL, then peer->ptr is also a bio_bio_st,
// and its "peer" member points back to us.
// peer != NULL iff init != 0 in the BIO.
// This is for what we write (i.e. reading uses peer's struct):
int closed; // valid iff peer != NULL
size_t len; // valid iff buf != NULL; 0 if peer == NULL
size_t offset; // valid iff buf != NULL; 0 if len == 0
size_t size;
uint8_t *buf; // "size" elements (if != NULL)
size_t request; // valid iff peer != NULL; 0 if len != 0,
// otherwise set by peer to number of bytes
// it (unsuccessfully) tried to read,
// never more than buffer space (size-len) warrants.
};
static int bio_new(BIO *bio) {
struct bio_bio_st *b;
b = OPENSSL_malloc(sizeof *b);
if (b == NULL) {
return 0;
}
OPENSSL_memset(b, 0, sizeof(struct bio_bio_st));
b->size = 17 * 1024; // enough for one TLS record (just a default)
bio->ptr = b;
return 1;
}
static void bio_destroy_pair(BIO *bio) {
struct bio_bio_st *b = bio->ptr;
BIO *peer_bio;
struct bio_bio_st *peer_b;
if (b == NULL) {
return;
}
peer_bio = b->peer;
if (peer_bio == NULL) {
return;
}
peer_b = peer_bio->ptr;
assert(peer_b != NULL);
assert(peer_b->peer == bio);
peer_b->peer = NULL;
peer_bio->init = 0;
assert(peer_b->buf != NULL);
peer_b->len = 0;
peer_b->offset = 0;
b->peer = NULL;
bio->init = 0;
assert(b->buf != NULL);
b->len = 0;
b->offset = 0;
}
static int bio_free(BIO *bio) {
struct bio_bio_st *b;
if (bio == NULL) {
return 0;
}
b = bio->ptr;
assert(b != NULL);
if (b->peer) {
bio_destroy_pair(bio);
}
OPENSSL_free(b->buf);
OPENSSL_free(b);
return 1;
}
static int bio_read(BIO *bio, char *buf, int size_) {
size_t size = size_;
size_t rest;
struct bio_bio_st *b, *peer_b;
BIO_clear_retry_flags(bio);
if (!bio->init) {
return 0;
}
b = bio->ptr;
assert(b != NULL);
assert(b->peer != NULL);
peer_b = b->peer->ptr;
assert(peer_b != NULL);
assert(peer_b->buf != NULL);
peer_b->request = 0; // will be set in "retry_read" situation
if (buf == NULL || size == 0) {
return 0;
}
if (peer_b->len == 0) {
if (peer_b->closed) {
return 0; // writer has closed, and no data is left
} else {
BIO_set_retry_read(bio); // buffer is empty
if (size <= peer_b->size) {
peer_b->request = size;
} else {
// don't ask for more than the peer can
// deliver in one write
peer_b->request = peer_b->size;
}
return -1;
}
}
// we can read
if (peer_b->len < size) {
size = peer_b->len;
}
// now read "size" bytes
rest = size;
assert(rest > 0);
// one or two iterations
do {
size_t chunk;
assert(rest <= peer_b->len);
if (peer_b->offset + rest <= peer_b->size) {
chunk = rest;
} else {
// wrap around ring buffer
chunk = peer_b->size - peer_b->offset;
}
assert(peer_b->offset + chunk <= peer_b->size);
OPENSSL_memcpy(buf, peer_b->buf + peer_b->offset, chunk);
peer_b->len -= chunk;
if (peer_b->len) {
peer_b->offset += chunk;
assert(peer_b->offset <= peer_b->size);
if (peer_b->offset == peer_b->size) {
peer_b->offset = 0;
}
buf += chunk;
} else {
// buffer now empty, no need to advance "buf"
assert(chunk == rest);
peer_b->offset = 0;
}
rest -= chunk;
} while (rest);
return size;
}
static int bio_write(BIO *bio, const char *buf, int num_) {
size_t num = num_;
size_t rest;
struct bio_bio_st *b;
BIO_clear_retry_flags(bio);
if (!bio->init || buf == NULL || num == 0) {
return 0;
}
b = bio->ptr;
assert(b != NULL);
assert(b->peer != NULL);
assert(b->buf != NULL);
b->request = 0;
if (b->closed) {
// we already closed
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
return -1;
}
assert(b->len <= b->size);
if (b->len == b->size) {
BIO_set_retry_write(bio); // buffer is full
return -1;
}
// we can write
if (num > b->size - b->len) {
num = b->size - b->len;
}
// now write "num" bytes
rest = num;
assert(rest > 0);
// one or two iterations
do {
size_t write_offset;
size_t chunk;
assert(b->len + rest <= b->size);
write_offset = b->offset + b->len;
if (write_offset >= b->size) {
write_offset -= b->size;
}
// b->buf[write_offset] is the first byte we can write to.
if (write_offset + rest <= b->size) {
chunk = rest;
} else {
// wrap around ring buffer
chunk = b->size - write_offset;
}
OPENSSL_memcpy(b->buf + write_offset, buf, chunk);
b->len += chunk;
assert(b->len <= b->size);
rest -= chunk;
buf += chunk;
} while (rest);
return num;
}
static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
size_t writebuf2_len) {
struct bio_bio_st *b1, *b2;
assert(bio1 != NULL);
assert(bio2 != NULL);
b1 = bio1->ptr;
b2 = bio2->ptr;
if (b1->peer != NULL || b2->peer != NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_IN_USE);
return 0;
}
if (b1->buf == NULL) {
if (writebuf1_len) {
b1->size = writebuf1_len;
}
b1->buf = OPENSSL_malloc(b1->size);
if (b1->buf == NULL) {
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
b1->len = 0;
b1->offset = 0;
}
if (b2->buf == NULL) {
if (writebuf2_len) {
b2->size = writebuf2_len;
}
b2->buf = OPENSSL_malloc(b2->size);
if (b2->buf == NULL) {
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
b2->len = 0;
b2->offset = 0;
}
b1->peer = bio2;
b1->closed = 0;
b1->request = 0;
b2->peer = bio1;
b2->closed = 0;
b2->request = 0;
bio1->init = 1;
bio2->init = 1;
return 1;
}
static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
long ret;
struct bio_bio_st *b = bio->ptr;
assert(b != NULL);
switch (cmd) {
// specific CTRL codes
case BIO_C_GET_WRITE_BUF_SIZE:
ret = (long)b->size;
break;
case BIO_C_GET_WRITE_GUARANTEE:
// How many bytes can the caller feed to the next write
// without having to keep any?
if (b->peer == NULL || b->closed) {
ret = 0;
} else {
ret = (long)b->size - b->len;
}
break;
case BIO_C_GET_READ_REQUEST:
// If the peer unsuccessfully tried to read, how many bytes
// were requested? (As with BIO_CTRL_PENDING, that number
// can usually be treated as boolean.)
ret = (long)b->request;
break;
case BIO_C_RESET_READ_REQUEST:
// Reset request. (Can be useful after read attempts
// at the other side that are meant to be non-blocking,
// e.g. when probing SSL_read to see if any data is
// available.)
b->request = 0;
ret = 1;
break;
case BIO_C_SHUTDOWN_WR:
// similar to shutdown(..., SHUT_WR)
b->closed = 1;
ret = 1;
break;
// standard CTRL codes follow
case BIO_CTRL_GET_CLOSE:
ret = bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
ret = 1;
break;
case BIO_CTRL_PENDING:
if (b->peer != NULL) {
struct bio_bio_st *peer_b = b->peer->ptr;
ret = (long)peer_b->len;
} else {
ret = 0;
}
break;
case BIO_CTRL_WPENDING:
ret = 0;
if (b->buf != NULL) {
ret = (long)b->len;
}
break;
case BIO_CTRL_FLUSH:
ret = 1;
break;
case BIO_CTRL_EOF: {
BIO *other_bio = ptr;
if (other_bio) {
struct bio_bio_st *other_b = other_bio->ptr;
assert(other_b != NULL);
ret = other_b->len == 0 && other_b->closed;
} else {
ret = 1;
}
} break;
default:
ret = 0;
}
return ret;
}
static const BIO_METHOD methods_biop = {
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read, NULL /* puts */,
NULL /* gets */, bio_ctrl, bio_new, bio_free, NULL /* callback_ctrl */,
};
static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1_len,
BIO** bio2_p, size_t writebuf2_len) {
BIO *bio1 = BIO_new(bio_s_bio());
BIO *bio2 = BIO_new(bio_s_bio());
if (bio1 == NULL || bio2 == NULL ||
!bio_make_pair(bio1, bio2, writebuf1_len, writebuf2_len)) {
BIO_free(bio1);
BIO_free(bio2);
*bio1_p = NULL;
*bio2_p = NULL;
return 0;
}
*bio1_p = bio1;
*bio2_p = bio2;
return 1;
}
size_t BIO_ctrl_get_read_request(BIO *bio) {
return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
}
size_t BIO_ctrl_get_write_guarantee(BIO *bio) {
return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
}
int BIO_shutdown_wr(BIO *bio) {
return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL);
}

View File

@ -1,115 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int BIO_printf(BIO *bio, const char *format, ...) {
va_list args;
char buf[256], *out, out_malloced = 0;
int out_len, ret;
va_start(args, format);
out_len = vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
#if defined(OPENSSL_WINDOWS)
// On Windows, vsnprintf returns -1 rather than the requested length on
// truncation
if (out_len < 0) {
va_start(args, format);
out_len = _vscprintf(format, args);
va_end(args);
assert(out_len >= (int)sizeof(buf));
}
#endif
if (out_len < 0) {
return -1;
}
if ((size_t) out_len >= sizeof(buf)) {
const int requested_len = out_len;
// The output was truncated. Note that vsnprintf's return value
// does not include a trailing NUL, but the buffer must be sized
// for it.
out = OPENSSL_malloc(requested_len + 1);
out_malloced = 1;
if (out == NULL) {
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
return -1;
}
va_start(args, format);
out_len = vsnprintf(out, requested_len + 1, format, args);
va_end(args);
assert(out_len == requested_len);
} else {
out = buf;
}
ret = BIO_write(bio, out, out_len);
if (out_malloced) {
OPENSSL_free(out);
}
return ret;
}

View File

@ -1,202 +0,0 @@
/* crypto/bio/bss_sock.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <fcntl.h>
#include <string.h>
#if !defined(OPENSSL_WINDOWS)
#include <unistd.h>
#else
OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
OPENSSL_MSVC_PRAGMA(warning(pop))
OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
#endif
#include "internal.h"
#if !defined(OPENSSL_WINDOWS)
static int closesocket(int sock) {
return close(sock);
}
#endif
static int sock_new(BIO *bio) {
bio->init = 0;
bio->num = 0;
bio->ptr = NULL;
bio->flags = 0;
return 1;
}
static int sock_free(BIO *bio) {
if (bio == NULL) {
return 0;
}
if (bio->shutdown) {
if (bio->init) {
closesocket(bio->num);
}
bio->init = 0;
bio->flags = 0;
}
return 1;
}
static int sock_read(BIO *b, char *out, int outl) {
int ret = 0;
if (out == NULL) {
return 0;
}
bio_clear_socket_error();
#if defined(OPENSSL_WINDOWS)
ret = recv(b->num, out, outl, 0);
#else
ret = read(b->num, out, outl);
#endif
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_read(b);
}
}
return ret;
}
static int sock_write(BIO *b, const char *in, int inl) {
int ret;
bio_clear_socket_error();
#if defined(OPENSSL_WINDOWS)
ret = send(b->num, in, inl, 0);
#else
ret = write(b->num, in, inl);
#endif
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_write(b);
}
}
return ret;
}
static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
long ret = 1;
int *ip;
switch (cmd) {
case BIO_C_SET_FD:
sock_free(b);
b->num = *((int *)ptr);
b->shutdown = (int)num;
b->init = 1;
break;
case BIO_C_GET_FD:
if (b->init) {
ip = (int *)ptr;
if (ip != NULL) {
*ip = b->num;
}
ret = b->num;
} else {
ret = -1;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = b->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
b->shutdown = (int)num;
break;
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
static const BIO_METHOD methods_sockp = {
BIO_TYPE_SOCKET, "socket",
sock_write, sock_read,
NULL /* puts */, NULL /* gets, */,
sock_ctrl, sock_new,
sock_free, NULL /* callback_ctrl */,
};
const BIO_METHOD *BIO_s_socket(void) { return &methods_sockp; }
BIO *BIO_new_socket(int fd, int close_flag) {
BIO *ret;
ret = BIO_new(BIO_s_socket());
if (ret == NULL) {
return NULL;
}
BIO_set_fd(ret, fd, close_flag);
return ret;
}

View File

@ -1,114 +0,0 @@
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#include <openssl/bio.h>
#include <openssl/err.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#if !defined(OPENSSL_WINDOWS)
#include <netdb.h>
#include <unistd.h>
#else
OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <winsock2.h>
#include <ws2tcpip.h>
OPENSSL_MSVC_PRAGMA(warning(pop))
#endif
#include "internal.h"
#include "../internal.h"
int bio_ip_and_port_to_socket_and_addr(int *out_sock,
struct sockaddr_storage *out_addr,
socklen_t *out_addr_length,
const char *hostname,
const char *port_str) {
struct addrinfo hint, *result, *cur;
int ret;
*out_sock = -1;
OPENSSL_memset(&hint, 0, sizeof(hint));
hint.ai_family = AF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;
ret = getaddrinfo(hostname, port_str, &hint, &result);
if (ret != 0) {
OPENSSL_PUT_ERROR(SYS, 0);
ERR_add_error_data(1, gai_strerror(ret));
return 0;
}
ret = 0;
for (cur = result; cur; cur = cur->ai_next) {
if ((size_t) cur->ai_addrlen > sizeof(struct sockaddr_storage)) {
continue;
}
OPENSSL_memset(out_addr, 0, sizeof(struct sockaddr_storage));
OPENSSL_memcpy(out_addr, cur->ai_addr, cur->ai_addrlen);
*out_addr_length = cur->ai_addrlen;
*out_sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
if (*out_sock < 0) {
OPENSSL_PUT_SYSTEM_ERROR();
goto out;
}
ret = 1;
break;
}
out:
freeaddrinfo(result);
return ret;
}
int bio_socket_nbio(int sock, int on) {
#if defined(OPENSSL_WINDOWS)
u_long arg = on;
return 0 == ioctlsocket(sock, FIONBIO, &arg);
#else
int flags = fcntl(sock, F_GETFL, 0);
if (flags < 0) {
return 0;
}
if (!on) {
flags &= ~O_NONBLOCK;
} else {
flags |= O_NONBLOCK;
}
return fcntl(sock, F_SETFL, flags) == 0;
#endif
}
void bio_clear_socket_error(void) {}
int bio_sock_error(int sock) {
int error;
socklen_t error_size = sizeof(error);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&error, &error_size) < 0) {
return 1;
}
return error;
}

View File

@ -1,64 +0,0 @@
/* Copyright (c) 2015, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
CBS child;
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
CBS_len(&child) == 0) {
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
return 0;
}
if (CBS_data(&child)[0] & 0x80) {
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
return 0;
}
// INTEGERs must be minimal.
if (CBS_data(&child)[0] == 0x00 &&
CBS_len(&child) > 1 &&
!(CBS_data(&child)[1] & 0x80)) {
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
return 0;
}
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
}
int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
// Negative numbers are unsupported.
if (BN_is_negative(bn)) {
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
return 0;
}
CBB child;
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER) ||
// The number must be padded with a leading zero if the high bit would
// otherwise be set or if |bn| is zero.
(BN_num_bits(bn) % 8 == 0 && !CBB_add_u8(&child, 0x00)) ||
!BN_bn2cbb_padded(&child, BN_num_bytes(bn), bn) ||
!CBB_flush(cbb)) {
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
return 0;
}
return 1;
}

View File

@ -1,466 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bn.h>
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <openssl/bio.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../fipsmodule/bn/internal.h"
int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
uint8_t *ptr;
return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
}
static const char hextable[] = "0123456789abcdef";
char *BN_bn2hex(const BIGNUM *bn) {
int width = bn_minimal_width(bn);
char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ +
width * BN_BYTES * 2 + 1 /* trailing NUL */);
if (buf == NULL) {
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
char *p = buf;
if (bn->neg) {
*(p++) = '-';
}
if (BN_is_zero(bn)) {
*(p++) = '0';
}
int z = 0;
for (int i = width - 1; i >= 0; i--) {
for (int j = BN_BITS2 - 8; j >= 0; j -= 8) {
// strip leading zeros
int v = ((int)(bn->d[i] >> (long)j)) & 0xff;
if (z || v != 0) {
*(p++) = hextable[v >> 4];
*(p++) = hextable[v & 0x0f];
z = 1;
}
}
}
*p = '\0';
return buf;
}
// decode_hex decodes |in_len| bytes of hex data from |in| and updates |bn|.
static int decode_hex(BIGNUM *bn, const char *in, int in_len) {
if (in_len > INT_MAX/4) {
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
return 0;
}
// |in_len| is the number of hex digits.
if (!bn_expand(bn, in_len * 4)) {
return 0;
}
int i = 0;
while (in_len > 0) {
// Decode one |BN_ULONG| at a time.
int todo = BN_BYTES * 2;
if (todo > in_len) {
todo = in_len;
}
BN_ULONG word = 0;
int j;
for (j = todo; j > 0; j--) {
char c = in[in_len - j];
BN_ULONG hex;
if (c >= '0' && c <= '9') {
hex = c - '0';
} else if (c >= 'a' && c <= 'f') {
hex = c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
hex = c - 'A' + 10;
} else {
hex = 0;
// This shouldn't happen. The caller checks |isxdigit|.
assert(0);
}
word = (word << 4) | hex;
}
bn->d[i++] = word;
in_len -= todo;
}
assert(i <= bn->dmax);
bn->width = i;
return 1;
}
// decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|.
static int decode_dec(BIGNUM *bn, const char *in, int in_len) {
int i, j;
BN_ULONG l = 0;
// Decode |BN_DEC_NUM| digits at a time.
j = BN_DEC_NUM - (in_len % BN_DEC_NUM);
if (j == BN_DEC_NUM) {
j = 0;
}
l = 0;
for (i = 0; i < in_len; i++) {
l *= 10;
l += in[i] - '0';
if (++j == BN_DEC_NUM) {
if (!BN_mul_word(bn, BN_DEC_CONV) ||
!BN_add_word(bn, l)) {
return 0;
}
l = 0;
j = 0;
}
}
return 1;
}
typedef int (*decode_func) (BIGNUM *bn, const char *in, int in_len);
typedef int (*char_test_func) (int c);
static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) {
BIGNUM *ret = NULL;
int neg = 0, i;
int num;
if (in == NULL || *in == 0) {
return 0;
}
if (*in == '-') {
neg = 1;
in++;
}
for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {}
num = i + neg;
if (outp == NULL) {
return num;
}
// in is the start of the hex digits, and it is 'i' long
if (*outp == NULL) {
ret = BN_new();
if (ret == NULL) {
return 0;
}
} else {
ret = *outp;
BN_zero(ret);
}
if (!decode(ret, in, i)) {
goto err;
}
bn_set_minimal_width(ret);
if (!BN_is_zero(ret)) {
ret->neg = neg;
}
*outp = ret;
return num;
err:
if (*outp == NULL) {
BN_free(ret);
}
return 0;
}
int BN_hex2bn(BIGNUM **outp, const char *in) {
return bn_x2bn(outp, in, decode_hex, isxdigit);
}
char *BN_bn2dec(const BIGNUM *a) {
// It is easier to print strings little-endian, so we assemble it in reverse
// and fix at the end.
BIGNUM *copy = NULL;
CBB cbb;
if (!CBB_init(&cbb, 16) ||
!CBB_add_u8(&cbb, 0 /* trailing NUL */)) {
goto cbb_err;
}
if (BN_is_zero(a)) {
if (!CBB_add_u8(&cbb, '0')) {
goto cbb_err;
}
} else {
copy = BN_dup(a);
if (copy == NULL) {
goto err;
}
while (!BN_is_zero(copy)) {
BN_ULONG word = BN_div_word(copy, BN_DEC_CONV);
if (word == (BN_ULONG)-1) {
goto err;
}
const int add_leading_zeros = !BN_is_zero(copy);
for (int i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) {
if (!CBB_add_u8(&cbb, '0' + word % 10)) {
goto cbb_err;
}
word /= 10;
}
assert(word == 0);
}
}
if (BN_is_negative(a) &&
!CBB_add_u8(&cbb, '-')) {
goto cbb_err;
}
uint8_t *data;
size_t len;
if (!CBB_finish(&cbb, &data, &len)) {
goto cbb_err;
}
// Reverse the buffer.
for (size_t i = 0; i < len/2; i++) {
uint8_t tmp = data[i];
data[i] = data[len - 1 - i];
data[len - 1 - i] = tmp;
}
BN_free(copy);
return (char *)data;
cbb_err:
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
err:
BN_free(copy);
CBB_cleanup(&cbb);
return NULL;
}
int BN_dec2bn(BIGNUM **outp, const char *in) {
return bn_x2bn(outp, in, decode_dec, isdigit);
}
int BN_asc2bn(BIGNUM **outp, const char *in) {
const char *const orig_in = in;
if (*in == '-') {
in++;
}
if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) {
if (!BN_hex2bn(outp, in+2)) {
return 0;
}
} else {
if (!BN_dec2bn(outp, in)) {
return 0;
}
}
if (*orig_in == '-' && !BN_is_zero(*outp)) {
(*outp)->neg = 1;
}
return 1;
}
int BN_print(BIO *bp, const BIGNUM *a) {
int i, j, v, z = 0;
int ret = 0;
if (a->neg && BIO_write(bp, "-", 1) != 1) {
goto end;
}
if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) {
goto end;
}
for (i = bn_minimal_width(a) - 1; i >= 0; i--) {
for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
// strip leading zeros
v = ((int)(a->d[i] >> (long)j)) & 0x0f;
if (z || v != 0) {
if (BIO_write(bp, &hextable[v], 1) != 1) {
goto end;
}
z = 1;
}
}
}
ret = 1;
end:
return ret;
}
int BN_print_fp(FILE *fp, const BIGNUM *a) {
BIO *b;
int ret;
b = BIO_new(BIO_s_file());
if (b == NULL) {
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = BN_print(b, a);
BIO_free(b);
return ret;
}
size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
const size_t bits = BN_num_bits(in);
const size_t bytes = (bits + 7) / 8;
// If the number of bits is a multiple of 8, i.e. if the MSB is set,
// prefix with a zero byte.
int extend = 0;
if (bytes != 0 && (bits & 0x07) == 0) {
extend = 1;
}
const size_t len = bytes + extend;
if (len < bytes ||
4 + len < len ||
(len & 0xffffffff) != len) {
// If we cannot represent the number then we emit zero as the interface
// doesn't allow an error to be signalled.
if (out) {
OPENSSL_memset(out, 0, 4);
}
return 4;
}
if (out == NULL) {
return 4 + len;
}
out[0] = len >> 24;
out[1] = len >> 16;
out[2] = len >> 8;
out[3] = len;
if (extend) {
out[4] = 0;
}
BN_bn2bin(in, out + 4 + extend);
if (in->neg && len > 0) {
out[4] |= 0x80;
}
return len + 4;
}
BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
if (len < 4) {
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
return NULL;
}
const size_t in_len = ((size_t)in[0] << 24) |
((size_t)in[1] << 16) |
((size_t)in[2] << 8) |
((size_t)in[3]);
if (in_len != len - 4) {
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
return NULL;
}
int out_is_alloced = 0;
if (out == NULL) {
out = BN_new();
if (out == NULL) {
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
return NULL;
}
out_is_alloced = 1;
}
if (in_len == 0) {
BN_zero(out);
return out;
}
in += 4;
if (BN_bin2bn(in, in_len, out) == NULL) {
if (out_is_alloced) {
BN_free(out);
}
return NULL;
}
out->neg = ((*in) & 0x80) != 0;
if (out->neg) {
BN_clear_bit(out, BN_num_bits(out) - 1);
}
return out;
}

View File

@ -1,231 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/buf.h>
#include <string.h>
#include <openssl/mem.h>
#include <openssl/err.h>
#include "../internal.h"
BUF_MEM *BUF_MEM_new(void) {
BUF_MEM *ret;
ret = OPENSSL_malloc(sizeof(BUF_MEM));
if (ret == NULL) {
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
OPENSSL_memset(ret, 0, sizeof(BUF_MEM));
return ret;
}
void BUF_MEM_free(BUF_MEM *buf) {
if (buf == NULL) {
return;
}
OPENSSL_free(buf->data);
OPENSSL_free(buf);
}
int BUF_MEM_reserve(BUF_MEM *buf, size_t cap) {
if (buf->max >= cap) {
return 1;
}
size_t n = cap + 3;
if (n < cap) {
// overflow
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return 0;
}
n = n / 3;
size_t alloc_size = n * 4;
if (alloc_size / 4 != n) {
// overflow
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return 0;
}
char *new_buf = OPENSSL_realloc(buf->data, alloc_size);
if (new_buf == NULL) {
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return 0;
}
buf->data = new_buf;
buf->max = alloc_size;
return 1;
}
size_t BUF_MEM_grow(BUF_MEM *buf, size_t len) {
if (!BUF_MEM_reserve(buf, len)) {
return 0;
}
if (buf->length < len) {
OPENSSL_memset(&buf->data[buf->length], 0, len - buf->length);
}
buf->length = len;
return len;
}
size_t BUF_MEM_grow_clean(BUF_MEM *buf, size_t len) {
return BUF_MEM_grow(buf, len);
}
int BUF_MEM_append(BUF_MEM *buf, const void *in, size_t len) {
size_t new_len = buf->length + len;
if (new_len < len) {
OPENSSL_PUT_ERROR(BUF, ERR_R_OVERFLOW);
return 0;
}
if (!BUF_MEM_reserve(buf, new_len)) {
return 0;
}
OPENSSL_memcpy(buf->data + buf->length, in, len);
buf->length = new_len;
return 1;
}
char *BUF_strdup(const char *str) {
if (str == NULL) {
return NULL;
}
return BUF_strndup(str, strlen(str));
}
size_t BUF_strnlen(const char *str, size_t max_len) {
size_t i;
for (i = 0; i < max_len; i++) {
if (str[i] == 0) {
break;
}
}
return i;
}
char *BUF_strndup(const char *str, size_t size) {
char *ret;
size_t alloc_size;
if (str == NULL) {
return NULL;
}
size = BUF_strnlen(str, size);
alloc_size = size + 1;
if (alloc_size < size) {
// overflow
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret = OPENSSL_malloc(alloc_size);
if (ret == NULL) {
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
OPENSSL_memcpy(ret, str, size);
ret[size] = '\0';
return ret;
}
size_t BUF_strlcpy(char *dst, const char *src, size_t dst_size) {
size_t l = 0;
for (; dst_size > 1 && *src; dst_size--) {
*dst++ = *src++;
l++;
}
if (dst_size) {
*dst = 0;
}
return l + strlen(src);
}
size_t BUF_strlcat(char *dst, const char *src, size_t dst_size) {
size_t l = 0;
for (; dst_size > 0 && *dst; dst_size--, dst++) {
l++;
}
return l + BUF_strlcpy(dst, src, dst_size);
}
void *BUF_memdup(const void *data, size_t size) {
if (size == 0) {
return NULL;
}
void *ret = OPENSSL_malloc(size);
if (ret == NULL) {
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
OPENSSL_memcpy(ret, data, size);
return ret;
}

View File

@ -1,52 +0,0 @@
/* Copyright (c) 2016, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/bytestring.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <openssl/mem.h>
#include "internal.h"
#include "../internal.h"
int CBB_finish_i2d(CBB *cbb, uint8_t **outp) {
assert(cbb->base->can_resize);
uint8_t *der;
size_t der_len;
if (!CBB_finish(cbb, &der, &der_len)) {
CBB_cleanup(cbb);
return -1;
}
if (der_len > INT_MAX) {
OPENSSL_free(der);
return -1;
}
if (outp != NULL) {
if (*outp == NULL) {
*outp = der;
der = NULL;
} else {
OPENSSL_memcpy(*outp, der, der_len);
*outp += der_len;
}
}
OPENSSL_free(der);
return (int)der_len;
}

View File

@ -1,261 +0,0 @@
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/bytestring.h>
#include <assert.h>
#include <string.h>
#include "internal.h"
#include "../internal.h"
// kMaxDepth is a just a sanity limit. The code should be such that the length
// of the input being processes always decreases. None the less, a very large
// input could otherwise cause the stack to overflow.
static const unsigned kMaxDepth = 2048;
// is_string_type returns one if |tag| is a string type and zero otherwise. It
// ignores the constructed bit.
static int is_string_type(unsigned tag) {
switch (tag & ~CBS_ASN1_CONSTRUCTED) {
case CBS_ASN1_BITSTRING:
case CBS_ASN1_OCTETSTRING:
case CBS_ASN1_UTF8STRING:
case CBS_ASN1_NUMERICSTRING:
case CBS_ASN1_PRINTABLESTRING:
case CBS_ASN1_T61STRING:
case CBS_ASN1_VIDEOTEXSTRING:
case CBS_ASN1_IA5STRING:
case CBS_ASN1_GRAPHICSTRING:
case CBS_ASN1_VISIBLESTRING:
case CBS_ASN1_GENERALSTRING:
case CBS_ASN1_UNIVERSALSTRING:
case CBS_ASN1_BMPSTRING:
return 1;
default:
return 0;
}
}
// cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
// depending on whether an indefinite length element or constructed string was
// found. The value of |orig_in| is not changed. It returns one on success (i.e.
// |*ber_found| was set) and zero on error.
static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
CBS in;
if (depth > kMaxDepth) {
return 0;
}
CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
*ber_found = 0;
while (CBS_len(&in) > 0) {
CBS contents;
unsigned tag;
size_t header_len;
if (!CBS_get_any_ber_asn1_element(&in, &contents, &tag, &header_len)) {
return 0;
}
if (CBS_len(&contents) == header_len &&
header_len > 0 &&
CBS_data(&contents)[header_len-1] == 0x80) {
// Found an indefinite-length element.
*ber_found = 1;
return 1;
}
if (tag & CBS_ASN1_CONSTRUCTED) {
if (is_string_type(tag)) {
// Constructed strings are only legal in BER and require conversion.
*ber_found = 1;
return 1;
}
if (!CBS_skip(&contents, header_len) ||
!cbs_find_ber(&contents, ber_found, depth + 1)) {
return 0;
}
}
}
return 1;
}
// is_eoc returns true if |header_len| and |contents|, as returned by
// |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value.
static char is_eoc(size_t header_len, CBS *contents) {
return header_len == 2 && CBS_len(contents) == 2 &&
OPENSSL_memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
}
// cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
// |string_tag| is non-zero, then all elements must match |string_tag| up to the
// constructed bit and primitive element bodies are written to |out| without
// element headers. This is used when concatenating the fragments of a
// constructed string. If |looking_for_eoc| is set then any EOC elements found
// will cause the function to return after consuming it. It returns one on
// success and zero on error.
static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
char looking_for_eoc, unsigned depth) {
assert(!(string_tag & CBS_ASN1_CONSTRUCTED));
if (depth > kMaxDepth) {
return 0;
}
while (CBS_len(in) > 0) {
CBS contents;
unsigned tag, child_string_tag = string_tag;
size_t header_len;
CBB *out_contents, out_contents_storage;
if (!CBS_get_any_ber_asn1_element(in, &contents, &tag, &header_len)) {
return 0;
}
if (is_eoc(header_len, &contents)) {
return looking_for_eoc;
}
if (string_tag != 0) {
// This is part of a constructed string. All elements must match
// |string_tag| up to the constructed bit and get appended to |out|
// without a child element.
if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) {
return 0;
}
out_contents = out;
} else {
unsigned out_tag = tag;
if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) {
// If a constructed string, clear the constructed bit and inform
// children to concatenate bodies.
out_tag &= ~CBS_ASN1_CONSTRUCTED;
child_string_tag = out_tag;
}
if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
return 0;
}
out_contents = &out_contents_storage;
}
if (CBS_len(&contents) == header_len && header_len > 0 &&
CBS_data(&contents)[header_len - 1] == 0x80) {
// This is an indefinite length element.
if (!cbs_convert_ber(in, out_contents, child_string_tag,
1 /* looking for eoc */, depth + 1) ||
!CBB_flush(out)) {
return 0;
}
continue;
}
if (!CBS_skip(&contents, header_len)) {
return 0;
}
if (tag & CBS_ASN1_CONSTRUCTED) {
// Recurse into children.
if (!cbs_convert_ber(&contents, out_contents, child_string_tag,
0 /* not looking for eoc */, depth + 1)) {
return 0;
}
} else {
// Copy primitive contents as-is.
if (!CBB_add_bytes(out_contents, CBS_data(&contents),
CBS_len(&contents))) {
return 0;
}
}
if (!CBB_flush(out)) {
return 0;
}
}
return looking_for_eoc == 0;
}
int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) {
CBB cbb;
// First, do a quick walk to find any indefinite-length elements. Most of the
// time we hope that there aren't any and thus we can quickly return.
char conversion_needed;
if (!cbs_find_ber(in, &conversion_needed, 0)) {
return 0;
}
if (!conversion_needed) {
*out = NULL;
*out_len = 0;
return 1;
}
if (!CBB_init(&cbb, CBS_len(in)) ||
!cbs_convert_ber(in, &cbb, 0, 0, 0) ||
!CBB_finish(&cbb, out, out_len)) {
CBB_cleanup(&cbb);
return 0;
}
return 1;
}
int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage,
unsigned outer_tag, unsigned inner_tag) {
assert(!(outer_tag & CBS_ASN1_CONSTRUCTED));
assert(!(inner_tag & CBS_ASN1_CONSTRUCTED));
assert(is_string_type(inner_tag));
if (CBS_peek_asn1_tag(in, outer_tag)) {
// Normal implicitly-tagged string.
*out_storage = NULL;
return CBS_get_asn1(in, out, outer_tag);
}
// Otherwise, try to parse an implicitly-tagged constructed string.
// |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
// of nesting.
CBB result;
CBS child;
if (!CBB_init(&result, CBS_len(in)) ||
!CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) {
goto err;
}
while (CBS_len(&child) > 0) {
CBS chunk;
if (!CBS_get_asn1(&child, &chunk, inner_tag) ||
!CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) {
goto err;
}
}
uint8_t *data;
size_t len;
if (!CBB_finish(&result, &data, &len)) {
goto err;
}
CBS_init(out, data, len);
*out_storage = data;
return 1;
err:
CBB_cleanup(&result);
return 0;
}

View File

@ -1,668 +0,0 @@
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/bytestring.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/mem.h>
#include "../internal.h"
void CBB_zero(CBB *cbb) {
OPENSSL_memset(cbb, 0, sizeof(CBB));
}
static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
// This assumes that |cbb| has already been zeroed.
struct cbb_buffer_st *base;
base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
if (base == NULL) {
return 0;
}
base->buf = buf;
base->len = 0;
base->cap = cap;
base->can_resize = 1;
base->error = 0;
cbb->base = base;
cbb->is_top_level = 1;
return 1;
}
int CBB_init(CBB *cbb, size_t initial_capacity) {
CBB_zero(cbb);
uint8_t *buf = OPENSSL_malloc(initial_capacity);
if (initial_capacity > 0 && buf == NULL) {
return 0;
}
if (!cbb_init(cbb, buf, initial_capacity)) {
OPENSSL_free(buf);
return 0;
}
return 1;
}
int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
CBB_zero(cbb);
if (!cbb_init(cbb, buf, len)) {
return 0;
}
cbb->base->can_resize = 0;
return 1;
}
void CBB_cleanup(CBB *cbb) {
if (cbb->base) {
// Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They
// are implicitly discarded when the parent is flushed or cleaned up.
assert(cbb->is_top_level);
if (cbb->base->can_resize) {
OPENSSL_free(cbb->base->buf);
}
OPENSSL_free(cbb->base);
}
cbb->base = NULL;
}
static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
size_t len) {
size_t newlen;
if (base == NULL) {
return 0;
}
newlen = base->len + len;
if (newlen < base->len) {
// Overflow
goto err;
}
if (newlen > base->cap) {
size_t newcap = base->cap * 2;
uint8_t *newbuf;
if (!base->can_resize) {
goto err;
}
if (newcap < base->cap || newcap < newlen) {
newcap = newlen;
}
newbuf = OPENSSL_realloc(base->buf, newcap);
if (newbuf == NULL) {
goto err;
}
base->buf = newbuf;
base->cap = newcap;
}
if (out) {
*out = base->buf + base->len;
}
return 1;
err:
base->error = 1;
return 0;
}
static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
size_t len) {
if (!cbb_buffer_reserve(base, out, len)) {
return 0;
}
// This will not overflow or |cbb_buffer_reserve| would have failed.
base->len += len;
return 1;
}
static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
size_t len_len) {
if (len_len == 0) {
return 1;
}
uint8_t *buf;
if (!cbb_buffer_add(base, &buf, len_len)) {
return 0;
}
for (size_t i = len_len - 1; i < len_len; i--) {
buf[i] = v;
v >>= 8;
}
if (v != 0) {
base->error = 1;
return 0;
}
return 1;
}
int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
if (!cbb->is_top_level) {
return 0;
}
if (!CBB_flush(cbb)) {
return 0;
}
if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
// |out_data| and |out_len| can only be NULL if the CBB is fixed.
return 0;
}
if (out_data != NULL) {
*out_data = cbb->base->buf;
}
if (out_len != NULL) {
*out_len = cbb->base->len;
}
cbb->base->buf = NULL;
CBB_cleanup(cbb);
return 1;
}
// CBB_flush recurses and then writes out any pending length prefix. The
// current length of the underlying base is taken to be the length of the
// length-prefixed data.
int CBB_flush(CBB *cbb) {
size_t child_start, i, len;
// If |cbb->base| has hit an error, the buffer is in an undefined state, so
// fail all following calls. In particular, |cbb->child| may point to invalid
// memory.
if (cbb->base == NULL || cbb->base->error) {
return 0;
}
if (cbb->child == NULL || cbb->child->pending_len_len == 0) {
return 1;
}
child_start = cbb->child->offset + cbb->child->pending_len_len;
if (!CBB_flush(cbb->child) ||
child_start < cbb->child->offset ||
cbb->base->len < child_start) {
goto err;
}
len = cbb->base->len - child_start;
if (cbb->child->pending_is_asn1) {
// For ASN.1 we assume that we'll only need a single byte for the length.
// If that turned out to be incorrect, we have to move the contents along
// in order to make space.
uint8_t len_len;
uint8_t initial_length_byte;
assert (cbb->child->pending_len_len == 1);
if (len > 0xfffffffe) {
// Too large.
goto err;
} else if (len > 0xffffff) {
len_len = 5;
initial_length_byte = 0x80 | 4;
} else if (len > 0xffff) {
len_len = 4;
initial_length_byte = 0x80 | 3;
} else if (len > 0xff) {
len_len = 3;
initial_length_byte = 0x80 | 2;
} else if (len > 0x7f) {
len_len = 2;
initial_length_byte = 0x80 | 1;
} else {
len_len = 1;
initial_length_byte = (uint8_t)len;
len = 0;
}
if (len_len != 1) {
// We need to move the contents along in order to make space.
size_t extra_bytes = len_len - 1;
if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
goto err;
}
OPENSSL_memmove(cbb->base->buf + child_start + extra_bytes,
cbb->base->buf + child_start, len);
}
cbb->base->buf[cbb->child->offset++] = initial_length_byte;
cbb->child->pending_len_len = len_len - 1;
}
for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len;
i--) {
cbb->base->buf[cbb->child->offset + i] = (uint8_t)len;
len >>= 8;
}
if (len != 0) {
goto err;
}
cbb->child->base = NULL;
cbb->child = NULL;
return 1;
err:
cbb->base->error = 1;
return 0;
}
const uint8_t *CBB_data(const CBB *cbb) {
assert(cbb->child == NULL);
return cbb->base->buf + cbb->offset + cbb->pending_len_len;
}
size_t CBB_len(const CBB *cbb) {
assert(cbb->child == NULL);
assert(cbb->offset + cbb->pending_len_len <= cbb->base->len);
return cbb->base->len - cbb->offset - cbb->pending_len_len;
}
static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
uint8_t len_len) {
uint8_t *prefix_bytes;
if (!CBB_flush(cbb)) {
return 0;
}
size_t offset = cbb->base->len;
if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
return 0;
}
OPENSSL_memset(prefix_bytes, 0, len_len);
OPENSSL_memset(out_contents, 0, sizeof(CBB));
out_contents->base = cbb->base;
cbb->child = out_contents;
cbb->child->offset = offset;
cbb->child->pending_len_len = len_len;
cbb->child->pending_is_asn1 = 0;
return 1;
}
int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
return cbb_add_length_prefixed(cbb, out_contents, 1);
}
int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
return cbb_add_length_prefixed(cbb, out_contents, 2);
}
int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
return cbb_add_length_prefixed(cbb, out_contents, 3);
}
// add_base128_integer encodes |v| as a big-endian base-128 integer where the
// high bit of each byte indicates where there is more data. This is the
// encoding used in DER for both high tag number form and OID components.
static int add_base128_integer(CBB *cbb, uint64_t v) {
unsigned len_len = 0;
uint64_t copy = v;
while (copy > 0) {
len_len++;
copy >>= 7;
}
if (len_len == 0) {
len_len = 1; // Zero is encoded with one byte.
}
for (unsigned i = len_len - 1; i < len_len; i--) {
uint8_t byte = (v >> (7 * i)) & 0x7f;
if (i != 0) {
// The high bit denotes whether there is more data.
byte |= 0x80;
}
if (!CBB_add_u8(cbb, byte)) {
return 0;
}
}
return 1;
}
int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) {
if (!CBB_flush(cbb)) {
return 0;
}
// Split the tag into leading bits and tag number.
uint8_t tag_bits = (tag >> CBS_ASN1_TAG_SHIFT) & 0xe0;
unsigned tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK;
if (tag_number >= 0x1f) {
// Set all the bits in the tag number to signal high tag number form.
if (!CBB_add_u8(cbb, tag_bits | 0x1f) ||
!add_base128_integer(cbb, tag_number)) {
return 0;
}
} else if (!CBB_add_u8(cbb, tag_bits | tag_number)) {
return 0;
}
size_t offset = cbb->base->len;
if (!CBB_add_u8(cbb, 0)) {
return 0;
}
OPENSSL_memset(out_contents, 0, sizeof(CBB));
out_contents->base = cbb->base;
cbb->child = out_contents;
cbb->child->offset = offset;
cbb->child->pending_len_len = 1;
cbb->child->pending_is_asn1 = 1;
return 1;
}
int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
uint8_t *dest;
if (!CBB_flush(cbb) ||
!cbb_buffer_add(cbb->base, &dest, len)) {
return 0;
}
OPENSSL_memcpy(dest, data, len);
return 1;
}
int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
if (!CBB_flush(cbb) ||
!cbb_buffer_add(cbb->base, out_data, len)) {
return 0;
}
return 1;
}
int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) {
if (!CBB_flush(cbb) ||
!cbb_buffer_reserve(cbb->base, out_data, len)) {
return 0;
}
return 1;
}
int CBB_did_write(CBB *cbb, size_t len) {
size_t newlen = cbb->base->len + len;
if (cbb->child != NULL ||
newlen < cbb->base->len ||
newlen > cbb->base->cap) {
return 0;
}
cbb->base->len = newlen;
return 1;
}
int CBB_add_u8(CBB *cbb, uint8_t value) {
if (!CBB_flush(cbb)) {
return 0;
}
return cbb_buffer_add_u(cbb->base, value, 1);
}
int CBB_add_u16(CBB *cbb, uint16_t value) {
if (!CBB_flush(cbb)) {
return 0;
}
return cbb_buffer_add_u(cbb->base, value, 2);
}
int CBB_add_u24(CBB *cbb, uint32_t value) {
if (!CBB_flush(cbb)) {
return 0;
}
return cbb_buffer_add_u(cbb->base, value, 3);
}
int CBB_add_u32(CBB *cbb, uint32_t value) {
if (!CBB_flush(cbb)) {
return 0;
}
return cbb_buffer_add_u(cbb->base, value, 4);
}
void CBB_discard_child(CBB *cbb) {
if (cbb->child == NULL) {
return;
}
cbb->base->len = cbb->child->offset;
cbb->child->base = NULL;
cbb->child = NULL;
}
int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
CBB child;
int started = 0;
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
return 0;
}
for (size_t i = 0; i < 8; i++) {
uint8_t byte = (value >> 8*(7-i)) & 0xff;
if (!started) {
if (byte == 0) {
// Don't encode leading zeros.
continue;
}
// If the high bit is set, add a padding byte to make it
// unsigned.
if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
return 0;
}
started = 1;
}
if (!CBB_add_u8(&child, byte)) {
return 0;
}
}
// 0 is encoded as a single 0, not the empty string.
if (!started && !CBB_add_u8(&child, 0)) {
return 0;
}
return CBB_flush(cbb);
}
int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, size_t data_len) {
CBB child;
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child, data, data_len) ||
!CBB_flush(cbb)) {
return 0;
}
return 1;
}
int CBB_add_asn1_bool(CBB *cbb, int value) {
CBB child;
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_BOOLEAN) ||
!CBB_add_u8(&child, value != 0 ? 0xff : 0) ||
!CBB_flush(cbb)) {
return 0;
}
return 1;
}
// parse_dotted_decimal parses one decimal component from |cbs|, where |cbs| is
// an OID literal, e.g., "1.2.840.113554.4.1.72585". It consumes both the
// component and the dot, so |cbs| may be passed into the function again for the
// next value.
static int parse_dotted_decimal(CBS *cbs, uint64_t *out) {
*out = 0;
int seen_digit = 0;
for (;;) {
// Valid terminators for a component are the end of the string or a
// non-terminal dot. If the string ends with a dot, this is not a valid OID
// string.
uint8_t u;
if (!CBS_get_u8(cbs, &u) ||
(u == '.' && CBS_len(cbs) > 0)) {
break;
}
if (u < '0' || u > '9' ||
// Forbid stray leading zeros.
(seen_digit && *out == 0) ||
// Check for overflow.
*out > UINT64_MAX / 10 ||
*out * 10 > UINT64_MAX - (u - '0')) {
return 0;
}
*out = *out * 10 + (u - '0');
seen_digit = 1;
}
// The empty string is not a legal OID component.
return seen_digit;
}
int CBB_add_asn1_oid_from_text(CBB *cbb, const char *text, size_t len) {
if (!CBB_flush(cbb)) {
return 0;
}
CBS cbs;
CBS_init(&cbs, (const uint8_t *)text, len);
// OIDs must have at least two components.
uint64_t a, b;
if (!parse_dotted_decimal(&cbs, &a) ||
!parse_dotted_decimal(&cbs, &b)) {
return 0;
}
// The first component is encoded as 40 * |a| + |b|. This assumes that |a| is
// 0, 1, or 2 and that, when it is 0 or 1, |b| is at most 39.
if (a > 2 ||
(a < 2 && b > 39) ||
b > UINT64_MAX - 80 ||
!add_base128_integer(cbb, 40u * a + b)) {
return 0;
}
// The remaining components are encoded unmodified.
while (CBS_len(&cbs) > 0) {
if (!parse_dotted_decimal(&cbs, &a) ||
!add_base128_integer(cbb, a)) {
return 0;
}
}
return 1;
}
static int compare_set_of_element(const void *a_ptr, const void *b_ptr) {
// See X.690, section 11.6 for the ordering. They are sorted in ascending
// order by their DER encoding.
const CBS *a = a_ptr, *b = b_ptr;
size_t a_len = CBS_len(a), b_len = CBS_len(b);
size_t min_len = a_len < b_len ? a_len : b_len;
int ret = OPENSSL_memcmp(CBS_data(a), CBS_data(b), min_len);
if (ret != 0) {
return ret;
}
if (a_len == b_len) {
return 0;
}
// If one is a prefix of the other, the shorter one sorts first. (This is not
// actually reachable. No DER encoding is a prefix of another DER encoding.)
return a_len < b_len ? -1 : 1;
}
int CBB_flush_asn1_set_of(CBB *cbb) {
if (!CBB_flush(cbb)) {
return 0;
}
CBS cbs;
size_t num_children = 0;
CBS_init(&cbs, CBB_data(cbb), CBB_len(cbb));
while (CBS_len(&cbs) != 0) {
if (!CBS_get_any_asn1_element(&cbs, NULL, NULL, NULL)) {
return 0;
}
num_children++;
}
if (num_children < 2) {
return 1; // Nothing to do. This is the common case for X.509.
}
if (num_children > ((size_t)-1) / sizeof(CBS)) {
return 0; // Overflow.
}
// Parse out the children and sort. We alias them into a copy of so they
// remain valid as we rewrite |cbb|.
int ret = 0;
size_t buf_len = CBB_len(cbb);
uint8_t *buf = BUF_memdup(CBB_data(cbb), buf_len);
CBS *children = OPENSSL_malloc(num_children * sizeof(CBS));
if (buf == NULL || children == NULL) {
goto err;
}
CBS_init(&cbs, buf, buf_len);
for (size_t i = 0; i < num_children; i++) {
if (!CBS_get_any_asn1_element(&cbs, &children[i], NULL, NULL)) {
goto err;
}
}
qsort(children, num_children, sizeof(CBS), compare_set_of_element);
// Rewind |cbb| and write the contents back in the new order.
cbb->base->len = cbb->offset + cbb->pending_len_len;
for (size_t i = 0; i < num_children; i++) {
if (!CBB_add_bytes(cbb, CBS_data(&children[i]), CBS_len(&children[i]))) {
goto err;
}
}
assert(CBB_len(cbb) == buf_len);
ret = 1;
err:
OPENSSL_free(buf);
OPENSSL_free(children);
return ret;
}

View File

@ -1,618 +0,0 @@
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#if !defined(__STDC_FORMAT_MACROS)
#define __STDC_FORMAT_MACROS
#endif
#include <openssl/buf.h>
#include <openssl/mem.h>
#include <openssl/bytestring.h>
#include <assert.h>
#include <inttypes.h>
#include <string.h>
#include "internal.h"
#include "../internal.h"
void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
cbs->data = data;
cbs->len = len;
}
static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
if (cbs->len < n) {
return 0;
}
*p = cbs->data;
cbs->data += n;
cbs->len -= n;
return 1;
}
int CBS_skip(CBS *cbs, size_t len) {
const uint8_t *dummy;
return cbs_get(cbs, &dummy, len);
}
const uint8_t *CBS_data(const CBS *cbs) {
return cbs->data;
}
size_t CBS_len(const CBS *cbs) {
return cbs->len;
}
int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
OPENSSL_free(*out_ptr);
*out_ptr = NULL;
*out_len = 0;
if (cbs->len == 0) {
return 1;
}
*out_ptr = BUF_memdup(cbs->data, cbs->len);
if (*out_ptr == NULL) {
return 0;
}
*out_len = cbs->len;
return 1;
}
int CBS_strdup(const CBS *cbs, char **out_ptr) {
if (*out_ptr != NULL) {
OPENSSL_free(*out_ptr);
}
*out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
return (*out_ptr != NULL);
}
int CBS_contains_zero_byte(const CBS *cbs) {
return OPENSSL_memchr(cbs->data, 0, cbs->len) != NULL;
}
int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
if (len != cbs->len) {
return 0;
}
return CRYPTO_memcmp(cbs->data, data, len) == 0;
}
static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
uint32_t result = 0;
const uint8_t *data;
if (!cbs_get(cbs, &data, len)) {
return 0;
}
for (size_t i = 0; i < len; i++) {
result <<= 8;
result |= data[i];
}
*out = result;
return 1;
}
int CBS_get_u8(CBS *cbs, uint8_t *out) {
const uint8_t *v;
if (!cbs_get(cbs, &v, 1)) {
return 0;
}
*out = *v;
return 1;
}
int CBS_get_u16(CBS *cbs, uint16_t *out) {
uint32_t v;
if (!cbs_get_u(cbs, &v, 2)) {
return 0;
}
*out = v;
return 1;
}
int CBS_get_u24(CBS *cbs, uint32_t *out) {
return cbs_get_u(cbs, out, 3);
}
int CBS_get_u32(CBS *cbs, uint32_t *out) {
return cbs_get_u(cbs, out, 4);
}
int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
if (cbs->len == 0) {
return 0;
}
*out = cbs->data[cbs->len - 1];
cbs->len--;
return 1;
}
int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
const uint8_t *v;
if (!cbs_get(cbs, &v, len)) {
return 0;
}
CBS_init(out, v, len);
return 1;
}
int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) {
const uint8_t *v;
if (!cbs_get(cbs, &v, len)) {
return 0;
}
OPENSSL_memcpy(out, v, len);
return 1;
}
static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
uint32_t len;
if (!cbs_get_u(cbs, &len, len_len)) {
return 0;
}
return CBS_get_bytes(cbs, out, len);
}
int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
return cbs_get_length_prefixed(cbs, out, 1);
}
int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
return cbs_get_length_prefixed(cbs, out, 2);
}
int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
return cbs_get_length_prefixed(cbs, out, 3);
}
// parse_base128_integer reads a big-endian base-128 integer from |cbs| and sets
// |*out| to the result. This is the encoding used in DER for both high tag
// number form and OID components.
static int parse_base128_integer(CBS *cbs, uint64_t *out) {
uint64_t v = 0;
uint8_t b;
do {
if (!CBS_get_u8(cbs, &b)) {
return 0;
}
if ((v >> (64 - 7)) != 0) {
// The value is too large.
return 0;
}
if (v == 0 && b == 0x80) {
// The value must be minimally encoded.
return 0;
}
v = (v << 7) | (b & 0x7f);
// Values end at an octet with the high bit cleared.
} while (b & 0x80);
*out = v;
return 1;
}
static int parse_asn1_tag(CBS *cbs, unsigned *out) {
uint8_t tag_byte;
if (!CBS_get_u8(cbs, &tag_byte)) {
return 0;
}
// ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
// number no greater than 30.
//
// If the number portion is 31 (0x1f, the largest value that fits in the
// allotted bits), then the tag is more than one byte long and the
// continuation bytes contain the tag number. This parser only supports tag
// numbers less than 31 (and thus single-byte tags).
unsigned tag = ((unsigned)tag_byte & 0xe0) << CBS_ASN1_TAG_SHIFT;
unsigned tag_number = tag_byte & 0x1f;
if (tag_number == 0x1f) {
uint64_t v;
if (!parse_base128_integer(cbs, &v) ||
// Check the tag number is within our supported bounds.
v > CBS_ASN1_TAG_NUMBER_MASK ||
// Small tag numbers should have used low tag number form.
v < 0x1f) {
return 0;
}
tag_number = (unsigned)v;
}
tag |= tag_number;
*out = tag;
return 1;
}
static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
size_t *out_header_len, int ber_ok) {
CBS header = *cbs;
CBS throwaway;
if (out == NULL) {
out = &throwaway;
}
unsigned tag;
if (!parse_asn1_tag(&header, &tag)) {
return 0;
}
if (out_tag != NULL) {
*out_tag = tag;
}
uint8_t length_byte;
if (!CBS_get_u8(&header, &length_byte)) {
return 0;
}
size_t header_len = CBS_len(cbs) - CBS_len(&header);
size_t len;
// The format for the length encoding is specified in ITU-T X.690 section
// 8.1.3.
if ((length_byte & 0x80) == 0) {
// Short form length.
len = ((size_t) length_byte) + header_len;
if (out_header_len != NULL) {
*out_header_len = header_len;
}
} else {
// The high bit indicate that this is the long form, while the next 7 bits
// encode the number of subsequent octets used to encode the length (ITU-T
// X.690 clause 8.1.3.5.b).
const size_t num_bytes = length_byte & 0x7f;
uint32_t len32;
if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
// indefinite length
if (out_header_len != NULL) {
*out_header_len = header_len;
}
return CBS_get_bytes(cbs, out, header_len);
}
// ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
// used as the first byte of the length. If this parser encounters that
// value, num_bytes will be parsed as 127, which will fail the check below.
if (num_bytes == 0 || num_bytes > 4) {
return 0;
}
if (!cbs_get_u(&header, &len32, num_bytes)) {
return 0;
}
// ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
// with the minimum number of octets.
if (len32 < 128) {
// Length should have used short-form encoding.
return 0;
}
if ((len32 >> ((num_bytes-1)*8)) == 0) {
// Length should have been at least one byte shorter.
return 0;
}
len = len32;
if (len + header_len + num_bytes < len) {
// Overflow.
return 0;
}
len += header_len + num_bytes;
if (out_header_len != NULL) {
*out_header_len = header_len + num_bytes;
}
}
return CBS_get_bytes(cbs, out, len);
}
int CBS_get_any_asn1(CBS *cbs, CBS *out, unsigned *out_tag) {
size_t header_len;
if (!CBS_get_any_asn1_element(cbs, out, out_tag, &header_len)) {
return 0;
}
if (!CBS_skip(out, header_len)) {
assert(0);
return 0;
}
return 1;
}
int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
size_t *out_header_len) {
return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
0 /* DER only */);
}
int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
size_t *out_header_len) {
return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
1 /* BER allowed */);
}
static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value,
int skip_header) {
size_t header_len;
unsigned tag;
CBS throwaway;
if (out == NULL) {
out = &throwaway;
}
if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
tag != tag_value) {
return 0;
}
if (skip_header && !CBS_skip(out, header_len)) {
assert(0);
return 0;
}
return 1;
}
int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
}
int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
}
int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
if (CBS_len(cbs) < 1) {
return 0;
}
CBS copy = *cbs;
unsigned actual_tag;
return parse_asn1_tag(&copy, &actual_tag) && tag_value == actual_tag;
}
int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
CBS bytes;
if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
return 0;
}
*out = 0;
const uint8_t *data = CBS_data(&bytes);
size_t len = CBS_len(&bytes);
if (len == 0) {
// An INTEGER is encoded with at least one octet.
return 0;
}
if ((data[0] & 0x80) != 0) {
// Negative number.
return 0;
}
if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) {
// Extra leading zeros.
return 0;
}
for (size_t i = 0; i < len; i++) {
if ((*out >> 56) != 0) {
// Too large to represent as a uint64_t.
return 0;
}
*out <<= 8;
*out |= data[i];
}
return 1;
}
int CBS_get_asn1_bool(CBS *cbs, int *out) {
CBS bytes;
if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_BOOLEAN) ||
CBS_len(&bytes) != 1) {
return 0;
}
const uint8_t value = *CBS_data(&bytes);
if (value != 0 && value != 0xff) {
return 0;
}
*out = !!value;
return 1;
}
int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
int present = 0;
if (CBS_peek_asn1_tag(cbs, tag)) {
if (!CBS_get_asn1(cbs, out, tag)) {
return 0;
}
present = 1;
}
if (out_present != NULL) {
*out_present = present;
}
return 1;
}
int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
unsigned tag) {
CBS child;
int present;
if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
return 0;
}
if (present) {
assert(out);
if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
CBS_len(&child) != 0) {
return 0;
}
} else {
CBS_init(out, NULL, 0);
}
if (out_present) {
*out_present = present;
}
return 1;
}
int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag,
uint64_t default_value) {
CBS child;
int present;
if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
return 0;
}
if (present) {
if (!CBS_get_asn1_uint64(&child, out) ||
CBS_len(&child) != 0) {
return 0;
}
} else {
*out = default_value;
}
return 1;
}
int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
int default_value) {
CBS child, child2;
int present;
if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
return 0;
}
if (present) {
uint8_t boolean;
if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
CBS_len(&child2) != 1 ||
CBS_len(&child) != 0) {
return 0;
}
boolean = CBS_data(&child2)[0];
if (boolean == 0) {
*out = 0;
} else if (boolean == 0xff) {
*out = 1;
} else {
return 0;
}
} else {
*out = default_value;
}
return 1;
}
int CBS_is_valid_asn1_bitstring(const CBS *cbs) {
CBS in = *cbs;
uint8_t num_unused_bits;
if (!CBS_get_u8(&in, &num_unused_bits) ||
num_unused_bits > 7) {
return 0;
}
if (num_unused_bits == 0) {
return 1;
}
// All num_unused_bits bits must exist and be zeros.
uint8_t last;
if (!CBS_get_last_u8(&in, &last) ||
(last & ((1 << num_unused_bits) - 1)) != 0) {
return 0;
}
return 1;
}
int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) {
if (!CBS_is_valid_asn1_bitstring(cbs)) {
return 0;
}
const unsigned byte_num = (bit >> 3) + 1;
const unsigned bit_num = 7 - (bit & 7);
// Unused bits are zero, and this function does not distinguish between
// missing and unset bits. Thus it is sufficient to do a byte-level length
// check.
return byte_num < CBS_len(cbs) &&
(CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0;
}
static int add_decimal(CBB *out, uint64_t v) {
char buf[DECIMAL_SIZE(uint64_t) + 1];
BIO_snprintf(buf, sizeof(buf), "%" PRIu64, v);
return CBB_add_bytes(out, (const uint8_t *)buf, strlen(buf));
}
char *CBS_asn1_oid_to_text(const CBS *cbs) {
CBB cbb;
if (!CBB_init(&cbb, 32)) {
goto err;
}
CBS copy = *cbs;
// The first component is 40 * value1 + value2, where value1 is 0, 1, or 2.
uint64_t v;
if (!parse_base128_integer(&copy, &v)) {
goto err;
}
if (v >= 80) {
if (!CBB_add_bytes(&cbb, (const uint8_t *)"2.", 2) ||
!add_decimal(&cbb, v - 80)) {
goto err;
}
} else if (!add_decimal(&cbb, v / 40) ||
!CBB_add_u8(&cbb, '.') ||
!add_decimal(&cbb, v % 40)) {
goto err;
}
while (CBS_len(&copy) != 0) {
if (!parse_base128_integer(&copy, &v) ||
!CBB_add_u8(&cbb, '.') ||
!add_decimal(&cbb, v)) {
goto err;
}
}
uint8_t *txt;
size_t txt_len;
if (!CBB_add_u8(&cbb, '\0') ||
!CBB_finish(&cbb, &txt, &txt_len)) {
goto err;
}
return (char *)txt;
err:
CBB_cleanup(&cbb);
return NULL;
}

View File

@ -1,75 +0,0 @@
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#ifndef OPENSSL_HEADER_BYTESTRING_INTERNAL_H
#define OPENSSL_HEADER_BYTESTRING_INTERNAL_H
#include <openssl/base.h>
#if defined(__cplusplus)
extern "C" {
#endif
// CBS_asn1_ber_to_der reads a BER element from |in|. If it finds
// indefinite-length elements or constructed strings then it converts the BER
// data to DER and sets |*out| and |*out_length| to describe a malloced buffer
// containing the DER data. Additionally, |*in| will be advanced over the BER
// element.
//
// If it doesn't find any indefinite-length elements or constructed strings then
// it sets |*out| to NULL and |*in| is unmodified.
//
// This function should successfully process any valid BER input, however it
// will not convert all of BER's deviations from DER. BER is ambiguous between
// implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed
// strings. Implicitly-tagged strings must be parsed with
// |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller
// must also account for BER variations in the contents of a primitive.
//
// It returns one on success and zero otherwise.
OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
// CBS_get_asn1_implicit_string parses a BER string of primitive type
// |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the
// contents. If concatenation was needed, it sets |*out_storage| to a buffer
// which the caller must release with |OPENSSL_free|. Otherwise, it sets
// |*out_storage| to NULL.
//
// This function does not parse all of BER. It requires the string be
// definite-length. Constructed strings are allowed, but all children of the
// outermost element must be primitive. The caller should use
// |CBS_asn1_ber_to_der| before running this function.
//
// It returns one on success and zero otherwise.
OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out,
uint8_t **out_storage,
unsigned outer_tag,
unsigned inner_tag);
// CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized
// with |CBB_init|. If |outp| is not NULL then the result is written to |*outp|
// and |*outp| is advanced just past the output. It returns the number of bytes
// in the result, whether written or not, or a negative value on error. On
// error, it calls |CBB_cleanup| on |cbb|.
//
// This function may be used to help implement legacy i2d ASN.1 functions.
int CBB_finish_i2d(CBB *cbb, uint8_t **outp);
#if defined(__cplusplus)
} // extern C
#endif
#endif // OPENSSL_HEADER_BYTESTRING_INTERNAL_H

View File

@ -1,167 +0,0 @@
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
// Adapted from the public domain, estream code by D. Bernstein.
#include <openssl/chacha.h>
#include <assert.h>
#include <string.h>
#include <openssl/cpu.h>
#include "../internal.h"
#define U8TO32_LITTLE(p) \
(((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
#if !defined(OPENSSL_NO_ASM) && \
(defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
// ChaCha20_ctr32 is defined in asm/chacha-*.pl.
void ChaCha20_ctr32(uint8_t *out, const uint8_t *in, size_t in_len,
const uint32_t key[8], const uint32_t counter[4]);
void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
const uint8_t key[32], const uint8_t nonce[12],
uint32_t counter) {
assert(!buffers_alias(out, in_len, in, in_len) || in == out);
uint32_t counter_nonce[4]; counter_nonce[0] = counter;
counter_nonce[1] = U8TO32_LITTLE(nonce + 0);
counter_nonce[2] = U8TO32_LITTLE(nonce + 4);
counter_nonce[3] = U8TO32_LITTLE(nonce + 8);
const uint32_t *key_ptr = (const uint32_t *)key;
#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
// The assembly expects the key to be four-byte aligned.
uint32_t key_u32[8];
if ((((uintptr_t)key) & 3) != 0) {
key_u32[0] = U8TO32_LITTLE(key + 0);
key_u32[1] = U8TO32_LITTLE(key + 4);
key_u32[2] = U8TO32_LITTLE(key + 8);
key_u32[3] = U8TO32_LITTLE(key + 12);
key_u32[4] = U8TO32_LITTLE(key + 16);
key_u32[5] = U8TO32_LITTLE(key + 20);
key_u32[6] = U8TO32_LITTLE(key + 24);
key_u32[7] = U8TO32_LITTLE(key + 28);
key_ptr = key_u32;
}
#endif
ChaCha20_ctr32(out, in, in_len, key_ptr, counter_nonce);
}
#else
// sigma contains the ChaCha constants, which happen to be an ASCII string.
static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
'2', '-', 'b', 'y', 't', 'e', ' ', 'k' };
#define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
#define U32TO8_LITTLE(p, v) \
{ \
(p)[0] = (v >> 0) & 0xff; \
(p)[1] = (v >> 8) & 0xff; \
(p)[2] = (v >> 16) & 0xff; \
(p)[3] = (v >> 24) & 0xff; \
}
// QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round.
#define QUARTERROUND(a, b, c, d) \
x[a] += x[b]; x[d] = ROTATE(x[d] ^ x[a], 16); \
x[c] += x[d]; x[b] = ROTATE(x[b] ^ x[c], 12); \
x[a] += x[b]; x[d] = ROTATE(x[d] ^ x[a], 8); \
x[c] += x[d]; x[b] = ROTATE(x[b] ^ x[c], 7);
// chacha_core performs 20 rounds of ChaCha on the input words in
// |input| and writes the 64 output bytes to |output|.
static void chacha_core(uint8_t output[64], const uint32_t input[16]) {
uint32_t x[16];
int i;
OPENSSL_memcpy(x, input, sizeof(uint32_t) * 16);
for (i = 20; i > 0; i -= 2) {
QUARTERROUND(0, 4, 8, 12)
QUARTERROUND(1, 5, 9, 13)
QUARTERROUND(2, 6, 10, 14)
QUARTERROUND(3, 7, 11, 15)
QUARTERROUND(0, 5, 10, 15)
QUARTERROUND(1, 6, 11, 12)
QUARTERROUND(2, 7, 8, 13)
QUARTERROUND(3, 4, 9, 14)
}
for (i = 0; i < 16; ++i) {
x[i] += input[i];
}
for (i = 0; i < 16; ++i) {
U32TO8_LITTLE(output + 4 * i, x[i]);
}
}
void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
const uint8_t key[32], const uint8_t nonce[12],
uint32_t counter) {
assert(!buffers_alias(out, in_len, in, in_len) || in == out);
uint32_t input[16];
uint8_t buf[64];
size_t todo, i;
input[0] = U8TO32_LITTLE(sigma + 0);
input[1] = U8TO32_LITTLE(sigma + 4);
input[2] = U8TO32_LITTLE(sigma + 8);
input[3] = U8TO32_LITTLE(sigma + 12);
input[4] = U8TO32_LITTLE(key + 0);
input[5] = U8TO32_LITTLE(key + 4);
input[6] = U8TO32_LITTLE(key + 8);
input[7] = U8TO32_LITTLE(key + 12);
input[8] = U8TO32_LITTLE(key + 16);
input[9] = U8TO32_LITTLE(key + 20);
input[10] = U8TO32_LITTLE(key + 24);
input[11] = U8TO32_LITTLE(key + 28);
input[12] = counter;
input[13] = U8TO32_LITTLE(nonce + 0);
input[14] = U8TO32_LITTLE(nonce + 4);
input[15] = U8TO32_LITTLE(nonce + 8);
while (in_len > 0) {
todo = sizeof(buf);
if (in_len < todo) {
todo = in_len;
}
chacha_core(buf, input);
for (i = 0; i < todo; i++) {
out[i] = in[i] ^ buf[i];
}
out += todo;
in += todo;
in_len -= todo;
input[12]++;
}
}
#endif

View File

@ -1,114 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/cipher.h>
#include <assert.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/nid.h>
#include "internal.h"
#include "../internal.h"
const EVP_CIPHER *EVP_get_cipherbynid(int nid) {
switch (nid) {
case NID_rc2_cbc:
return EVP_rc2_cbc();
case NID_rc2_40_cbc:
return EVP_rc2_40_cbc();
case NID_des_ede3_cbc:
return EVP_des_ede3_cbc();
case NID_des_ede_cbc:
return EVP_des_cbc();
case NID_aes_128_cbc:
return EVP_aes_128_cbc();
case NID_aes_192_cbc:
return EVP_aes_192_cbc();
case NID_aes_256_cbc:
return EVP_aes_256_cbc();
default:
return NULL;
}
}
const EVP_CIPHER *EVP_get_cipherbyname(const char *name) {
if (OPENSSL_strcasecmp(name, "rc4") == 0) {
return EVP_rc4();
} else if (OPENSSL_strcasecmp(name, "des-cbc") == 0) {
return EVP_des_cbc();
} else if (OPENSSL_strcasecmp(name, "des-ede3-cbc") == 0 ||
OPENSSL_strcasecmp(name, "3des") == 0) {
return EVP_des_ede3_cbc();
} else if (OPENSSL_strcasecmp(name, "aes-128-cbc") == 0) {
return EVP_aes_128_cbc();
} else if (OPENSSL_strcasecmp(name, "aes-256-cbc") == 0) {
return EVP_aes_256_cbc();
} else if (OPENSSL_strcasecmp(name, "aes-128-ctr") == 0) {
return EVP_aes_128_ctr();
} else if (OPENSSL_strcasecmp(name, "aes-256-ctr") == 0) {
return EVP_aes_256_ctr();
} else if (OPENSSL_strcasecmp(name, "aes-128-ecb") == 0) {
return EVP_aes_128_ecb();
} else if (OPENSSL_strcasecmp(name, "aes-256-ecb") == 0) {
return EVP_aes_256_ecb();
}
return NULL;
}

View File

@ -1,152 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/cipher.h>
#include <assert.h>
#include <openssl/digest.h>
#include <openssl/mem.h>
#define PKCS5_SALT_LEN 8
int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
const uint8_t *salt, const uint8_t *data, size_t data_len,
unsigned count, uint8_t *key, uint8_t *iv) {
EVP_MD_CTX c;
uint8_t md_buf[EVP_MAX_MD_SIZE];
unsigned niv, nkey, addmd = 0;
unsigned mds = 0, i;
int rv = 0;
nkey = type->key_len;
niv = type->iv_len;
assert(nkey <= EVP_MAX_KEY_LENGTH);
assert(niv <= EVP_MAX_IV_LENGTH);
if (data == NULL) {
return nkey;
}
EVP_MD_CTX_init(&c);
for (;;) {
if (!EVP_DigestInit_ex(&c, md, NULL)) {
return 0;
}
if (addmd++) {
if (!EVP_DigestUpdate(&c, md_buf, mds)) {
goto err;
}
}
if (!EVP_DigestUpdate(&c, data, data_len)) {
goto err;
}
if (salt != NULL) {
if (!EVP_DigestUpdate(&c, salt, PKCS5_SALT_LEN)) {
goto err;
}
}
if (!EVP_DigestFinal_ex(&c, md_buf, &mds)) {
goto err;
}
for (i = 1; i < count; i++) {
if (!EVP_DigestInit_ex(&c, md, NULL) ||
!EVP_DigestUpdate(&c, md_buf, mds) ||
!EVP_DigestFinal_ex(&c, md_buf, &mds)) {
goto err;
}
}
i = 0;
if (nkey) {
for (;;) {
if (nkey == 0 || i == mds) {
break;
}
if (key != NULL) {
*(key++) = md_buf[i];
}
nkey--;
i++;
}
}
if (niv && i != mds) {
for (;;) {
if (niv == 0 || i == mds) {
break;
}
if (iv != NULL) {
*(iv++) = md_buf[i];
}
niv--;
i++;
}
}
if (nkey == 0 && niv == 0) {
break;
}
}
rv = type->key_len;
err:
EVP_MD_CTX_cleanup(&c);
OPENSSL_cleanse(md_buf, EVP_MAX_MD_SIZE);
return rv;
}

View File

@ -1,203 +0,0 @@
/* Copyright (c) 2018, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/aead.h>
#include <assert.h>
#include <openssl/cipher.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../fipsmodule/cipher/internal.h"
#define EVP_AEAD_AES_CCM_MAX_TAG_LEN 16
struct aead_aes_ccm_ctx {
union {
double align;
AES_KEY ks;
} ks;
CCM128_CONTEXT ccm;
};
static int aead_aes_ccm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len, unsigned M,
unsigned L) {
assert(M == EVP_AEAD_max_overhead(ctx->aead));
assert(M == EVP_AEAD_max_tag_len(ctx->aead));
assert(15 - L == EVP_AEAD_nonce_length(ctx->aead));
if (key_len != EVP_AEAD_key_length(ctx->aead)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
return 0; // EVP_AEAD_CTX_init should catch this.
}
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
tag_len = M;
}
if (tag_len != M) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
return 0;
}
struct aead_aes_ccm_ctx *ccm_ctx =
OPENSSL_malloc(sizeof(struct aead_aes_ccm_ctx));
if (ccm_ctx == NULL) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
return 0;
}
block128_f block;
ctr128_f ctr = aes_ctr_set_key(&ccm_ctx->ks.ks, NULL, &block, key, key_len);
ctx->tag_len = tag_len;
if (!CRYPTO_ccm128_init(&ccm_ctx->ccm, &ccm_ctx->ks.ks, block, ctr, M, L)) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_INTERNAL_ERROR);
OPENSSL_free(ccm_ctx);
return 0;
}
ctx->aead_state = ccm_ctx;
return 1;
}
static void aead_aes_ccm_cleanup(EVP_AEAD_CTX *ctx) {
OPENSSL_free(ctx->aead_state);
}
static int aead_aes_ccm_seal_scatter(
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_aes_ccm_ctx *ccm_ctx = ctx->aead_state;
if (in_len > CRYPTO_ccm128_max_input(&ccm_ctx->ccm)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (max_out_tag_len < ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
return 0;
}
if (!CRYPTO_ccm128_encrypt(&ccm_ctx->ccm, &ccm_ctx->ks.ks, out, out_tag,
ctx->tag_len, nonce, nonce_len, in, in_len, ad,
ad_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
*out_tag_len = ctx->tag_len;
return 1;
}
static int aead_aes_ccm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *in_tag, size_t in_tag_len,
const uint8_t *ad, size_t ad_len) {
const struct aead_aes_ccm_ctx *ccm_ctx = ctx->aead_state;
if (in_len > CRYPTO_ccm128_max_input(&ccm_ctx->ccm)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
return 0;
}
if (in_tag_len != ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
uint8_t tag[EVP_AEAD_AES_CCM_MAX_TAG_LEN];
assert(ctx->tag_len <= EVP_AEAD_AES_CCM_MAX_TAG_LEN);
if (!CRYPTO_ccm128_decrypt(&ccm_ctx->ccm, &ccm_ctx->ks.ks, out, tag,
ctx->tag_len, nonce, nonce_len, in, in_len, ad,
ad_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (CRYPTO_memcmp(tag, in_tag, ctx->tag_len) != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
return 1;
}
static int aead_aes_ccm_bluetooth_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
return aead_aes_ccm_init(ctx, key, key_len, tag_len, 4, 2);
}
static const EVP_AEAD aead_aes_128_ccm_bluetooth = {
16, // key length (AES-128)
13, // nonce length
4, // overhead
4, // max tag length
0, // seal_scatter_supports_extra_in
aead_aes_ccm_bluetooth_init,
NULL /* init_with_direction */,
aead_aes_ccm_cleanup,
NULL /* open */,
aead_aes_ccm_seal_scatter,
aead_aes_ccm_open_gather,
NULL /* get_iv */,
NULL /* tag_len */,
};
const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth(void) {
return &aead_aes_128_ccm_bluetooth;
}
static int aead_aes_ccm_bluetooth_8_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
return aead_aes_ccm_init(ctx, key, key_len, tag_len, 8, 2);
}
static const EVP_AEAD aead_aes_128_ccm_bluetooth_8 = {
16, // key length (AES-128)
13, // nonce length
8, // overhead
8, // max tag length
0, // seal_scatter_supports_extra_in
aead_aes_ccm_bluetooth_8_init,
NULL /* init_with_direction */,
aead_aes_ccm_cleanup,
NULL /* open */,
aead_aes_ccm_seal_scatter,
aead_aes_ccm_open_gather,
NULL /* get_iv */,
NULL /* tag_len */,
};
const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth_8(void) {
return &aead_aes_128_ccm_bluetooth_8;
}

View File

@ -1,281 +0,0 @@
/* Copyright (c) 2017, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/aead.h>
#include <openssl/cipher.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#include "../fipsmodule/cipher/internal.h"
#define EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN SHA256_DIGEST_LENGTH
#define EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN 12
struct aead_aes_ctr_hmac_sha256_ctx {
union {
double align;
AES_KEY ks;
} ks;
ctr128_f ctr;
block128_f block;
SHA256_CTX inner_init_state;
SHA256_CTX outer_init_state;
};
static void hmac_init(SHA256_CTX *out_inner, SHA256_CTX *out_outer,
const uint8_t hmac_key[32]) {
static const size_t hmac_key_len = 32;
uint8_t block[SHA256_CBLOCK];
OPENSSL_memcpy(block, hmac_key, hmac_key_len);
OPENSSL_memset(block + hmac_key_len, 0x36, sizeof(block) - hmac_key_len);
unsigned i;
for (i = 0; i < hmac_key_len; i++) {
block[i] ^= 0x36;
}
SHA256_Init(out_inner);
SHA256_Update(out_inner, block, sizeof(block));
OPENSSL_memset(block + hmac_key_len, 0x5c, sizeof(block) - hmac_key_len);
for (i = 0; i < hmac_key_len; i++) {
block[i] ^= (0x36 ^ 0x5c);
}
SHA256_Init(out_outer);
SHA256_Update(out_outer, block, sizeof(block));
}
static int aead_aes_ctr_hmac_sha256_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx;
static const size_t hmac_key_len = 32;
if (key_len < hmac_key_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
return 0; // EVP_AEAD_CTX_init should catch this.
}
const size_t aes_key_len = key_len - hmac_key_len;
if (aes_key_len != 16 && aes_key_len != 32) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
return 0; // EVP_AEAD_CTX_init should catch this.
}
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
tag_len = EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN;
}
if (tag_len > EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
return 0;
}
aes_ctx = OPENSSL_malloc(sizeof(struct aead_aes_ctr_hmac_sha256_ctx));
if (aes_ctx == NULL) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
return 0;
}
aes_ctx->ctr =
aes_ctr_set_key(&aes_ctx->ks.ks, NULL, &aes_ctx->block, key, aes_key_len);
ctx->tag_len = tag_len;
hmac_init(&aes_ctx->inner_init_state, &aes_ctx->outer_init_state,
key + aes_key_len);
ctx->aead_state = aes_ctx;
return 1;
}
static void aead_aes_ctr_hmac_sha256_cleanup(EVP_AEAD_CTX *ctx) {
OPENSSL_free(ctx->aead_state);
}
static void hmac_update_uint64(SHA256_CTX *sha256, uint64_t value) {
unsigned i;
uint8_t bytes[8];
for (i = 0; i < sizeof(bytes); i++) {
bytes[i] = value & 0xff;
value >>= 8;
}
SHA256_Update(sha256, bytes, sizeof(bytes));
}
static void hmac_calculate(uint8_t out[SHA256_DIGEST_LENGTH],
const SHA256_CTX *inner_init_state,
const SHA256_CTX *outer_init_state,
const uint8_t *ad, size_t ad_len,
const uint8_t *nonce, const uint8_t *ciphertext,
size_t ciphertext_len) {
SHA256_CTX sha256;
OPENSSL_memcpy(&sha256, inner_init_state, sizeof(sha256));
hmac_update_uint64(&sha256, ad_len);
hmac_update_uint64(&sha256, ciphertext_len);
SHA256_Update(&sha256, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN);
SHA256_Update(&sha256, ad, ad_len);
// Pad with zeros to the end of the SHA-256 block.
const unsigned num_padding =
(SHA256_CBLOCK - ((sizeof(uint64_t)*2 +
EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN + ad_len) %
SHA256_CBLOCK)) %
SHA256_CBLOCK;
uint8_t padding[SHA256_CBLOCK];
OPENSSL_memset(padding, 0, num_padding);
SHA256_Update(&sha256, padding, num_padding);
SHA256_Update(&sha256, ciphertext, ciphertext_len);
uint8_t inner_digest[SHA256_DIGEST_LENGTH];
SHA256_Final(inner_digest, &sha256);
OPENSSL_memcpy(&sha256, outer_init_state, sizeof(sha256));
SHA256_Update(&sha256, inner_digest, sizeof(inner_digest));
SHA256_Final(out, &sha256);
}
static void aead_aes_ctr_hmac_sha256_crypt(
const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx, uint8_t *out,
const uint8_t *in, size_t len, const uint8_t *nonce) {
// Since the AEAD operation is one-shot, keeping a buffer of unused keystream
// bytes is pointless. However, |CRYPTO_ctr128_encrypt| requires it.
uint8_t partial_block_buffer[AES_BLOCK_SIZE];
unsigned partial_block_offset = 0;
OPENSSL_memset(partial_block_buffer, 0, sizeof(partial_block_buffer));
uint8_t counter[AES_BLOCK_SIZE];
OPENSSL_memcpy(counter, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN);
OPENSSL_memset(counter + EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN, 0, 4);
if (aes_ctx->ctr) {
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &aes_ctx->ks.ks, counter,
partial_block_buffer, &partial_block_offset,
aes_ctx->ctr);
} else {
CRYPTO_ctr128_encrypt(in, out, len, &aes_ctx->ks.ks, counter,
partial_block_buffer, &partial_block_offset,
aes_ctx->block);
}
}
static int aead_aes_ctr_hmac_sha256_seal_scatter(
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state;
const uint64_t in_len_64 = in_len;
if (in_len_64 >= (UINT64_C(1) << 32) * AES_BLOCK_SIZE) {
// This input is so large it would overflow the 32-bit block counter.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (max_out_tag_len < ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
aead_aes_ctr_hmac_sha256_crypt(aes_ctx, out, in, in_len, nonce);
uint8_t hmac_result[SHA256_DIGEST_LENGTH];
hmac_calculate(hmac_result, &aes_ctx->inner_init_state,
&aes_ctx->outer_init_state, ad, ad_len, nonce, out, in_len);
OPENSSL_memcpy(out_tag, hmac_result, ctx->tag_len);
*out_tag_len = ctx->tag_len;
return 1;
}
static int aead_aes_ctr_hmac_sha256_open_gather(
const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *in_tag,
size_t in_tag_len, const uint8_t *ad, size_t ad_len) {
const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state;
if (in_tag_len != ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
if (nonce_len != EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
uint8_t hmac_result[SHA256_DIGEST_LENGTH];
hmac_calculate(hmac_result, &aes_ctx->inner_init_state,
&aes_ctx->outer_init_state, ad, ad_len, nonce, in,
in_len);
if (CRYPTO_memcmp(hmac_result, in_tag, ctx->tag_len) != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
aead_aes_ctr_hmac_sha256_crypt(aes_ctx, out, in, in_len, nonce);
return 1;
}
static const EVP_AEAD aead_aes_128_ctr_hmac_sha256 = {
16 /* AES key */ + 32 /* HMAC key */,
12, // nonce length
EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, // overhead
EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, // max tag length
0, // seal_scatter_supports_extra_in
aead_aes_ctr_hmac_sha256_init,
NULL /* init_with_direction */,
aead_aes_ctr_hmac_sha256_cleanup,
NULL /* open */,
aead_aes_ctr_hmac_sha256_seal_scatter,
aead_aes_ctr_hmac_sha256_open_gather,
NULL /* get_iv */,
NULL /* tag_len */,
};
static const EVP_AEAD aead_aes_256_ctr_hmac_sha256 = {
32 /* AES key */ + 32 /* HMAC key */,
12, // nonce length
EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, // overhead
EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, // max tag length
0, // seal_scatter_supports_extra_in
aead_aes_ctr_hmac_sha256_init,
NULL /* init_with_direction */,
aead_aes_ctr_hmac_sha256_cleanup,
NULL /* open */,
aead_aes_ctr_hmac_sha256_seal_scatter,
aead_aes_ctr_hmac_sha256_open_gather,
NULL /* get_iv */,
NULL /* tag_len */,
};
const EVP_AEAD *EVP_aead_aes_128_ctr_hmac_sha256(void) {
return &aead_aes_128_ctr_hmac_sha256;
}
const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void) {
return &aead_aes_256_ctr_hmac_sha256;
}

View File

@ -1,867 +0,0 @@
/* Copyright (c) 2017, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/aead.h>
#include <assert.h>
#include <openssl/cipher.h>
#include <openssl/cpu.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "../fipsmodule/cipher/internal.h"
#define EVP_AEAD_AES_GCM_SIV_NONCE_LEN 12
#define EVP_AEAD_AES_GCM_SIV_TAG_LEN 16
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)
// Optimised AES-GCM-SIV
struct aead_aes_gcm_siv_asm_ctx {
alignas(16) uint8_t key[16*15];
int is_128_bit;
// ptr contains the original pointer from |OPENSSL_malloc|, which may only be
// 8-byte aligned. When freeing this structure, actually call |OPENSSL_free|
// on this pointer.
void *ptr;
};
// aes128gcmsiv_aes_ks writes an AES-128 key schedule for |key| to
// |out_expanded_key|.
extern void aes128gcmsiv_aes_ks(
const uint8_t key[16], uint8_t out_expanded_key[16*15]);
// aes128gcmsiv_aes_ks writes an AES-128 key schedule for |key| to
// |out_expanded_key|.
extern void aes256gcmsiv_aes_ks(
const uint8_t key[16], uint8_t out_expanded_key[16*15]);
static int aead_aes_gcm_siv_asm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
const size_t key_bits = key_len * 8;
if (key_bits != 128 && key_bits != 256) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
return 0; // EVP_AEAD_CTX_init should catch this.
}
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
}
if (tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
return 0;
}
char *ptr = OPENSSL_malloc(sizeof(struct aead_aes_gcm_siv_asm_ctx) + 8);
if (ptr == NULL) {
return 0;
}
assert((((uintptr_t)ptr) & 7) == 0);
// gcm_siv_ctx needs to be 16-byte aligned in a cross-platform way.
struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx =
(struct aead_aes_gcm_siv_asm_ctx *)(ptr + (((uintptr_t)ptr) & 8));
assert((((uintptr_t)gcm_siv_ctx) & 15) == 0);
gcm_siv_ctx->ptr = ptr;
if (key_bits == 128) {
aes128gcmsiv_aes_ks(key, &gcm_siv_ctx->key[0]);
gcm_siv_ctx->is_128_bit = 1;
} else {
aes256gcmsiv_aes_ks(key, &gcm_siv_ctx->key[0]);
gcm_siv_ctx->is_128_bit = 0;
}
ctx->aead_state = gcm_siv_ctx;
ctx->tag_len = tag_len;
return 1;
}
static void aead_aes_gcm_siv_asm_cleanup(EVP_AEAD_CTX *ctx) {
const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = ctx->aead_state;
OPENSSL_free(gcm_siv_ctx->ptr);
}
// aesgcmsiv_polyval_horner updates the POLYVAL value in |in_out_poly| to
// include a number (|in_blocks|) of 16-byte blocks of data from |in|, given
// the POLYVAL key in |key|.
extern void aesgcmsiv_polyval_horner(const uint8_t in_out_poly[16],
const uint8_t key[16], const uint8_t *in,
size_t in_blocks);
// aesgcmsiv_htable_init writes powers 1..8 of |auth_key| to |out_htable|.
extern void aesgcmsiv_htable_init(uint8_t out_htable[16 * 8],
const uint8_t auth_key[16]);
// aesgcmsiv_htable6_init writes powers 1..6 of |auth_key| to |out_htable|.
extern void aesgcmsiv_htable6_init(uint8_t out_htable[16 * 6],
const uint8_t auth_key[16]);
// aesgcmsiv_htable_polyval updates the POLYVAL value in |in_out_poly| to
// include |in_len| bytes of data from |in|. (Where |in_len| must be a multiple
// of 16.) It uses the precomputed powers of the key given in |htable|.
extern void aesgcmsiv_htable_polyval(const uint8_t htable[16 * 8],
const uint8_t *in, size_t in_len,
uint8_t in_out_poly[16]);
// aes128gcmsiv_dec decrypts |in_len| & ~15 bytes from |out| and writes them to
// |in|. (The full value of |in_len| is still used to find the authentication
// tag appended to the ciphertext, however, so must not be pre-masked.)
//
// |in| and |out| may be equal, but must not otherwise overlap.
//
// While decrypting, it updates the POLYVAL value found at the beginning of
// |in_out_calculated_tag_and_scratch| and writes the updated value back before
// return. During executation, it may use the whole of this space for other
// purposes. In order to decrypt and update the POLYVAL value, it uses the
// expanded key from |key| and the table of powers in |htable|.
extern void aes128gcmsiv_dec(const uint8_t *in, uint8_t *out,
uint8_t in_out_calculated_tag_and_scratch[16 * 8],
const uint8_t htable[16 * 6],
const struct aead_aes_gcm_siv_asm_ctx *key,
size_t in_len);
// aes256gcmsiv_dec acts like |aes128gcmsiv_dec|, but for AES-256.
extern void aes256gcmsiv_dec(const uint8_t *in, uint8_t *out,
uint8_t in_out_calculated_tag_and_scratch[16 * 8],
const uint8_t htable[16 * 6],
const struct aead_aes_gcm_siv_asm_ctx *key,
size_t in_len);
// aes128gcmsiv_kdf performs the AES-GCM-SIV KDF given the expanded key from
// |key_schedule| and the nonce in |nonce|. Note that, while only 12 bytes of
// the nonce are used, 16 bytes are read and so the value must be
// right-padded.
extern void aes128gcmsiv_kdf(const uint8_t nonce[16],
uint64_t out_key_material[8],
const uint8_t *key_schedule);
// aes256gcmsiv_kdf acts like |aes128gcmsiv_kdf|, but for AES-256.
extern void aes256gcmsiv_kdf(const uint8_t nonce[16],
uint64_t out_key_material[12],
const uint8_t *key_schedule);
// aes128gcmsiv_aes_ks_enc_x1 performs a key expansion of the AES-128 key in
// |key|, writes the expanded key to |out_expanded_key| and encrypts a single
// block from |in| to |out|.
extern void aes128gcmsiv_aes_ks_enc_x1(const uint8_t in[16], uint8_t out[16],
uint8_t out_expanded_key[16 * 15],
const uint64_t key[2]);
// aes256gcmsiv_aes_ks_enc_x1 acts like |aes128gcmsiv_aes_ks_enc_x1|, but for
// AES-256.
extern void aes256gcmsiv_aes_ks_enc_x1(const uint8_t in[16], uint8_t out[16],
uint8_t out_expanded_key[16 * 15],
const uint64_t key[4]);
// aes128gcmsiv_ecb_enc_block encrypts a single block from |in| to |out| using
// the expanded key in |expanded_key|.
extern void aes128gcmsiv_ecb_enc_block(
const uint8_t in[16], uint8_t out[16],
const struct aead_aes_gcm_siv_asm_ctx *expanded_key);
// aes256gcmsiv_ecb_enc_block acts like |aes128gcmsiv_ecb_enc_block|, but for
// AES-256.
extern void aes256gcmsiv_ecb_enc_block(
const uint8_t in[16], uint8_t out[16],
const struct aead_aes_gcm_siv_asm_ctx *expanded_key);
// aes128gcmsiv_enc_msg_x4 encrypts |in_len| bytes from |in| to |out| using the
// expanded key from |key|. (The value of |in_len| must be a multiple of 16.)
// The |in| and |out| buffers may be equal but must not otherwise overlap. The
// initial counter is constructed from the given |tag| as required by
// AES-GCM-SIV.
extern void aes128gcmsiv_enc_msg_x4(const uint8_t *in, uint8_t *out,
const uint8_t *tag,
const struct aead_aes_gcm_siv_asm_ctx *key,
size_t in_len);
// aes256gcmsiv_enc_msg_x4 acts like |aes128gcmsiv_enc_msg_x4|, but for
// AES-256.
extern void aes256gcmsiv_enc_msg_x4(const uint8_t *in, uint8_t *out,
const uint8_t *tag,
const struct aead_aes_gcm_siv_asm_ctx *key,
size_t in_len);
// aes128gcmsiv_enc_msg_x8 acts like |aes128gcmsiv_enc_msg_x4|, but is
// optimised for longer messages.
extern void aes128gcmsiv_enc_msg_x8(const uint8_t *in, uint8_t *out,
const uint8_t *tag,
const struct aead_aes_gcm_siv_asm_ctx *key,
size_t in_len);
// aes256gcmsiv_enc_msg_x8 acts like |aes256gcmsiv_enc_msg_x4|, but is
// optimised for longer messages.
extern void aes256gcmsiv_enc_msg_x8(const uint8_t *in, uint8_t *out,
const uint8_t *tag,
const struct aead_aes_gcm_siv_asm_ctx *key,
size_t in_len);
// gcm_siv_asm_polyval evaluates POLYVAL at |auth_key| on the given plaintext
// and AD. The result is written to |out_tag|.
static void gcm_siv_asm_polyval(uint8_t out_tag[16], const uint8_t *in,
size_t in_len, const uint8_t *ad, size_t ad_len,
const uint8_t auth_key[16],
const uint8_t nonce[12]) {
OPENSSL_memset(out_tag, 0, 16);
const size_t ad_blocks = ad_len / 16;
const size_t in_blocks = in_len / 16;
int htable_init = 0;
alignas(16) uint8_t htable[16*8];
if (ad_blocks > 8 || in_blocks > 8) {
htable_init = 1;
aesgcmsiv_htable_init(htable, auth_key);
}
if (htable_init) {
aesgcmsiv_htable_polyval(htable, ad, ad_len & ~15, out_tag);
} else {
aesgcmsiv_polyval_horner(out_tag, auth_key, ad, ad_blocks);
}
uint8_t scratch[16];
if (ad_len & 15) {
OPENSSL_memset(scratch, 0, sizeof(scratch));
OPENSSL_memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
aesgcmsiv_polyval_horner(out_tag, auth_key, scratch, 1);
}
if (htable_init) {
aesgcmsiv_htable_polyval(htable, in, in_len & ~15, out_tag);
} else {
aesgcmsiv_polyval_horner(out_tag, auth_key, in, in_blocks);
}
if (in_len & 15) {
OPENSSL_memset(scratch, 0, sizeof(scratch));
OPENSSL_memcpy(scratch, &in[in_len & ~15], in_len & 15);
aesgcmsiv_polyval_horner(out_tag, auth_key, scratch, 1);
}
union {
uint8_t c[16];
struct {
uint64_t ad;
uint64_t in;
} bitlens;
} length_block;
length_block.bitlens.ad = ad_len * 8;
length_block.bitlens.in = in_len * 8;
aesgcmsiv_polyval_horner(out_tag, auth_key, length_block.c, 1);
for (size_t i = 0; i < 12; i++) {
out_tag[i] ^= nonce[i];
}
out_tag[15] &= 0x7f;
}
// aead_aes_gcm_siv_asm_crypt_last_block handles the encryption/decryption
// (same thing in CTR mode) of the final block of a plaintext/ciphertext. It
// writes |in_len| & 15 bytes to |out| + |in_len|, based on an initial counter
// derived from |tag|.
static void aead_aes_gcm_siv_asm_crypt_last_block(
int is_128_bit, uint8_t *out, const uint8_t *in, size_t in_len,
const uint8_t tag[16],
const struct aead_aes_gcm_siv_asm_ctx *enc_key_expanded) {
alignas(16) union {
uint8_t c[16];
uint32_t u32[4];
} counter;
OPENSSL_memcpy(&counter, tag, sizeof(counter));
counter.c[15] |= 0x80;
counter.u32[0] += in_len / 16;
if (is_128_bit) {
aes128gcmsiv_ecb_enc_block(&counter.c[0], &counter.c[0], enc_key_expanded);
} else {
aes256gcmsiv_ecb_enc_block(&counter.c[0], &counter.c[0], enc_key_expanded);
}
const size_t last_bytes_offset = in_len & ~15;
const size_t last_bytes_len = in_len & 15;
uint8_t *last_bytes_out = &out[last_bytes_offset];
const uint8_t *last_bytes_in = &in[last_bytes_offset];
for (size_t i = 0; i < last_bytes_len; i++) {
last_bytes_out[i] = last_bytes_in[i] ^ counter.c[i];
}
}
// aead_aes_gcm_siv_kdf calculates the record encryption and authentication
// keys given the |nonce|.
static void aead_aes_gcm_siv_kdf(
int is_128_bit, const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx,
uint64_t out_record_auth_key[2], uint64_t out_record_enc_key[4],
const uint8_t nonce[12]) {
alignas(16) uint8_t padded_nonce[16];
OPENSSL_memcpy(padded_nonce, nonce, 12);
alignas(16) uint64_t key_material[12];
if (is_128_bit) {
aes128gcmsiv_kdf(padded_nonce, key_material, &gcm_siv_ctx->key[0]);
out_record_enc_key[0] = key_material[4];
out_record_enc_key[1] = key_material[6];
} else {
aes256gcmsiv_kdf(padded_nonce, key_material, &gcm_siv_ctx->key[0]);
out_record_enc_key[0] = key_material[4];
out_record_enc_key[1] = key_material[6];
out_record_enc_key[2] = key_material[8];
out_record_enc_key[3] = key_material[10];
}
out_record_auth_key[0] = key_material[0];
out_record_auth_key[1] = key_material[2];
}
static int aead_aes_gcm_siv_asm_seal_scatter(
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = ctx->aead_state;
const uint64_t in_len_64 = in_len;
const uint64_t ad_len_64 = ad_len;
if (in_len_64 > (UINT64_C(1) << 36) ||
ad_len_64 >= (UINT64_C(1) << 61)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (max_out_tag_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
alignas(16) uint64_t record_auth_key[2];
alignas(16) uint64_t record_enc_key[4];
aead_aes_gcm_siv_kdf(gcm_siv_ctx->is_128_bit, gcm_siv_ctx, record_auth_key,
record_enc_key, nonce);
alignas(16) uint8_t tag[16] = {0};
gcm_siv_asm_polyval(tag, in, in_len, ad, ad_len,
(const uint8_t *)record_auth_key, nonce);
struct aead_aes_gcm_siv_asm_ctx enc_key_expanded;
if (gcm_siv_ctx->is_128_bit) {
aes128gcmsiv_aes_ks_enc_x1(tag, tag, &enc_key_expanded.key[0],
record_enc_key);
if (in_len < 128) {
aes128gcmsiv_enc_msg_x4(in, out, tag, &enc_key_expanded, in_len & ~15);
} else {
aes128gcmsiv_enc_msg_x8(in, out, tag, &enc_key_expanded, in_len & ~15);
}
} else {
aes256gcmsiv_aes_ks_enc_x1(tag, tag, &enc_key_expanded.key[0],
record_enc_key);
if (in_len < 128) {
aes256gcmsiv_enc_msg_x4(in, out, tag, &enc_key_expanded, in_len & ~15);
} else {
aes256gcmsiv_enc_msg_x8(in, out, tag, &enc_key_expanded, in_len & ~15);
}
}
if (in_len & 15) {
aead_aes_gcm_siv_asm_crypt_last_block(gcm_siv_ctx->is_128_bit, out, in,
in_len, tag, &enc_key_expanded);
}
OPENSSL_memcpy(out_tag, tag, sizeof(tag));
*out_tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
return 1;
}
// TODO(martinkr): Add aead_aes_gcm_siv_asm_open_gather. N.B. aes128gcmsiv_dec
// expects ciphertext and tag in a contiguous buffer.
static int aead_aes_gcm_siv_asm_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
const uint64_t ad_len_64 = ad_len;
if (ad_len_64 >= (UINT64_C(1) << 61)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
const uint64_t in_len_64 = in_len;
if (in_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN ||
in_len_64 > (UINT64_C(1) << 36) + AES_BLOCK_SIZE) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = ctx->aead_state;
const size_t plaintext_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
const uint8_t *const given_tag = in + plaintext_len;
if (max_out_len < plaintext_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
alignas(16) uint64_t record_auth_key[2];
alignas(16) uint64_t record_enc_key[4];
aead_aes_gcm_siv_kdf(gcm_siv_ctx->is_128_bit, gcm_siv_ctx, record_auth_key,
record_enc_key, nonce);
struct aead_aes_gcm_siv_asm_ctx expanded_key;
if (gcm_siv_ctx->is_128_bit) {
aes128gcmsiv_aes_ks((const uint8_t *) record_enc_key, &expanded_key.key[0]);
} else {
aes256gcmsiv_aes_ks((const uint8_t *) record_enc_key, &expanded_key.key[0]);
}
// calculated_tag is 16*8 bytes, rather than 16 bytes, because
// aes[128|256]gcmsiv_dec uses the extra as scratch space.
alignas(16) uint8_t calculated_tag[16 * 8] = {0};
OPENSSL_memset(calculated_tag, 0, EVP_AEAD_AES_GCM_SIV_TAG_LEN);
const size_t ad_blocks = ad_len / 16;
aesgcmsiv_polyval_horner(calculated_tag, (const uint8_t *)record_auth_key, ad,
ad_blocks);
uint8_t scratch[16];
if (ad_len & 15) {
OPENSSL_memset(scratch, 0, sizeof(scratch));
OPENSSL_memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
aesgcmsiv_polyval_horner(calculated_tag, (const uint8_t *)record_auth_key,
scratch, 1);
}
alignas(16) uint8_t htable[16 * 6];
aesgcmsiv_htable6_init(htable, (const uint8_t *)record_auth_key);
if (gcm_siv_ctx->is_128_bit) {
aes128gcmsiv_dec(in, out, calculated_tag, htable, &expanded_key,
plaintext_len);
} else {
aes256gcmsiv_dec(in, out, calculated_tag, htable, &expanded_key,
plaintext_len);
}
if (plaintext_len & 15) {
aead_aes_gcm_siv_asm_crypt_last_block(gcm_siv_ctx->is_128_bit, out, in,
plaintext_len, given_tag,
&expanded_key);
OPENSSL_memset(scratch, 0, sizeof(scratch));
OPENSSL_memcpy(scratch, out + (plaintext_len & ~15), plaintext_len & 15);
aesgcmsiv_polyval_horner(calculated_tag, (const uint8_t *)record_auth_key,
scratch, 1);
}
union {
uint8_t c[16];
struct {
uint64_t ad;
uint64_t in;
} bitlens;
} length_block;
length_block.bitlens.ad = ad_len * 8;
length_block.bitlens.in = plaintext_len * 8;
aesgcmsiv_polyval_horner(calculated_tag, (const uint8_t *)record_auth_key,
length_block.c, 1);
for (size_t i = 0; i < 12; i++) {
calculated_tag[i] ^= nonce[i];
}
calculated_tag[15] &= 0x7f;
if (gcm_siv_ctx->is_128_bit) {
aes128gcmsiv_ecb_enc_block(calculated_tag, calculated_tag, &expanded_key);
} else {
aes256gcmsiv_ecb_enc_block(calculated_tag, calculated_tag, &expanded_key);
}
if (CRYPTO_memcmp(calculated_tag, given_tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN) !=
0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
*out_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
return 1;
}
static const EVP_AEAD aead_aes_128_gcm_siv_asm = {
16, // key length
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, // nonce length
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // overhead
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // max tag length
0, // seal_scatter_supports_extra_in
aead_aes_gcm_siv_asm_init,
NULL /* init_with_direction */,
aead_aes_gcm_siv_asm_cleanup,
aead_aes_gcm_siv_asm_open,
aead_aes_gcm_siv_asm_seal_scatter,
NULL /* open_gather */,
NULL /* get_iv */,
NULL /* tag_len */,
};
static const EVP_AEAD aead_aes_256_gcm_siv_asm = {
32, // key length
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, // nonce length
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // overhead
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // max tag length
0, // seal_scatter_supports_extra_in
aead_aes_gcm_siv_asm_init,
NULL /* init_with_direction */,
aead_aes_gcm_siv_asm_cleanup,
aead_aes_gcm_siv_asm_open,
aead_aes_gcm_siv_asm_seal_scatter,
NULL /* open_gather */,
NULL /* get_iv */,
NULL /* tag_len */,
};
#endif // X86_64 && !NO_ASM
struct aead_aes_gcm_siv_ctx {
union {
double align;
AES_KEY ks;
} ks;
block128_f kgk_block;
unsigned is_256:1;
};
static int aead_aes_gcm_siv_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
const size_t key_bits = key_len * 8;
if (key_bits != 128 && key_bits != 256) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
return 0; // EVP_AEAD_CTX_init should catch this.
}
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
}
if (tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
return 0;
}
struct aead_aes_gcm_siv_ctx *gcm_siv_ctx =
OPENSSL_malloc(sizeof(struct aead_aes_gcm_siv_ctx));
if (gcm_siv_ctx == NULL) {
return 0;
}
OPENSSL_memset(gcm_siv_ctx, 0, sizeof(struct aead_aes_gcm_siv_ctx));
aes_ctr_set_key(&gcm_siv_ctx->ks.ks, NULL, &gcm_siv_ctx->kgk_block, key,
key_len);
gcm_siv_ctx->is_256 = (key_len == 32);
ctx->aead_state = gcm_siv_ctx;
ctx->tag_len = tag_len;
return 1;
}
static void aead_aes_gcm_siv_cleanup(EVP_AEAD_CTX *ctx) {
OPENSSL_free(ctx->aead_state);
}
// gcm_siv_crypt encrypts (or decrypts—it's the same thing) |in_len| bytes from
// |in| to |out|, using the block function |enc_block| with |key| in counter
// mode, starting at |initial_counter|. This differs from the traditional
// counter mode code in that the counter is handled little-endian, only the
// first four bytes are used and the GCM-SIV tweak to the final byte is
// applied. The |in| and |out| pointers may be equal but otherwise must not
// alias.
static void gcm_siv_crypt(uint8_t *out, const uint8_t *in, size_t in_len,
const uint8_t initial_counter[AES_BLOCK_SIZE],
block128_f enc_block, const AES_KEY *key) {
union {
uint32_t w[4];
uint8_t c[16];
} counter;
OPENSSL_memcpy(counter.c, initial_counter, AES_BLOCK_SIZE);
counter.c[15] |= 0x80;
for (size_t done = 0; done < in_len;) {
uint8_t keystream[AES_BLOCK_SIZE];
enc_block(counter.c, keystream, key);
counter.w[0]++;
size_t todo = AES_BLOCK_SIZE;
if (in_len - done < todo) {
todo = in_len - done;
}
for (size_t i = 0; i < todo; i++) {
out[done + i] = keystream[i] ^ in[done + i];
}
done += todo;
}
}
// gcm_siv_polyval evaluates POLYVAL at |auth_key| on the given plaintext and
// AD. The result is written to |out_tag|.
static void gcm_siv_polyval(
uint8_t out_tag[16], const uint8_t *in, size_t in_len, const uint8_t *ad,
size_t ad_len, const uint8_t auth_key[16],
const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
struct polyval_ctx polyval_ctx;
CRYPTO_POLYVAL_init(&polyval_ctx, auth_key);
CRYPTO_POLYVAL_update_blocks(&polyval_ctx, ad, ad_len & ~15);
uint8_t scratch[16];
if (ad_len & 15) {
OPENSSL_memset(scratch, 0, sizeof(scratch));
OPENSSL_memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
}
CRYPTO_POLYVAL_update_blocks(&polyval_ctx, in, in_len & ~15);
if (in_len & 15) {
OPENSSL_memset(scratch, 0, sizeof(scratch));
OPENSSL_memcpy(scratch, &in[in_len & ~15], in_len & 15);
CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
}
union {
uint8_t c[16];
struct {
uint64_t ad;
uint64_t in;
} bitlens;
} length_block;
length_block.bitlens.ad = ad_len * 8;
length_block.bitlens.in = in_len * 8;
CRYPTO_POLYVAL_update_blocks(&polyval_ctx, length_block.c,
sizeof(length_block));
CRYPTO_POLYVAL_finish(&polyval_ctx, out_tag);
for (size_t i = 0; i < EVP_AEAD_AES_GCM_SIV_NONCE_LEN; i++) {
out_tag[i] ^= nonce[i];
}
out_tag[15] &= 0x7f;
}
// gcm_siv_record_keys contains the keys used for a specific GCM-SIV record.
struct gcm_siv_record_keys {
uint8_t auth_key[16];
union {
double align;
AES_KEY ks;
} enc_key;
block128_f enc_block;
};
// gcm_siv_keys calculates the keys for a specific GCM-SIV record with the
// given nonce and writes them to |*out_keys|.
static void gcm_siv_keys(
const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx,
struct gcm_siv_record_keys *out_keys,
const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
const AES_KEY *const key = &gcm_siv_ctx->ks.ks;
uint8_t key_material[(128 /* POLYVAL key */ + 256 /* max AES key */) / 8];
const size_t blocks_needed = gcm_siv_ctx->is_256 ? 6 : 4;
uint8_t counter[AES_BLOCK_SIZE];
OPENSSL_memset(counter, 0, AES_BLOCK_SIZE - EVP_AEAD_AES_GCM_SIV_NONCE_LEN);
OPENSSL_memcpy(counter + AES_BLOCK_SIZE - EVP_AEAD_AES_GCM_SIV_NONCE_LEN,
nonce, EVP_AEAD_AES_GCM_SIV_NONCE_LEN);
for (size_t i = 0; i < blocks_needed; i++) {
counter[0] = i;
uint8_t ciphertext[AES_BLOCK_SIZE];
gcm_siv_ctx->kgk_block(counter, ciphertext, key);
OPENSSL_memcpy(&key_material[i * 8], ciphertext, 8);
}
OPENSSL_memcpy(out_keys->auth_key, key_material, 16);
aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16);
}
static int aead_aes_gcm_siv_seal_scatter(
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
const uint64_t in_len_64 = in_len;
const uint64_t ad_len_64 = ad_len;
if (in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN < in_len ||
in_len_64 > (UINT64_C(1) << 36) ||
ad_len_64 >= (UINT64_C(1) << 61)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (max_out_tag_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
struct gcm_siv_record_keys keys;
gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
uint8_t tag[16];
gcm_siv_polyval(tag, in, in_len, ad, ad_len, keys.auth_key, nonce);
keys.enc_block(tag, tag, &keys.enc_key.ks);
gcm_siv_crypt(out, in, in_len, tag, keys.enc_block, &keys.enc_key.ks);
OPENSSL_memcpy(out_tag, tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN);
*out_tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
return 1;
}
static int aead_aes_gcm_siv_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *in_tag,
size_t in_tag_len, const uint8_t *ad,
size_t ad_len) {
const uint64_t ad_len_64 = ad_len;
if (ad_len_64 >= (UINT64_C(1) << 61)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
const uint64_t in_len_64 = in_len;
if (in_tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN ||
in_len_64 > (UINT64_C(1) << 36) + AES_BLOCK_SIZE) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
struct gcm_siv_record_keys keys;
gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
gcm_siv_crypt(out, in, in_len, in_tag, keys.enc_block, &keys.enc_key.ks);
uint8_t expected_tag[EVP_AEAD_AES_GCM_SIV_TAG_LEN];
gcm_siv_polyval(expected_tag, out, in_len, ad, ad_len, keys.auth_key, nonce);
keys.enc_block(expected_tag, expected_tag, &keys.enc_key.ks);
if (CRYPTO_memcmp(expected_tag, in_tag, sizeof(expected_tag)) != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
return 1;
}
static const EVP_AEAD aead_aes_128_gcm_siv = {
16, // key length
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, // nonce length
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // overhead
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // max tag length
0, // seal_scatter_supports_extra_in
aead_aes_gcm_siv_init,
NULL /* init_with_direction */,
aead_aes_gcm_siv_cleanup,
NULL /* open */,
aead_aes_gcm_siv_seal_scatter,
aead_aes_gcm_siv_open_gather,
NULL /* get_iv */,
NULL /* tag_len */,
};
static const EVP_AEAD aead_aes_256_gcm_siv = {
32, // key length
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, // nonce length
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // overhead
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // max tag length
0, // seal_scatter_supports_extra_in
aead_aes_gcm_siv_init,
NULL /* init_with_direction */,
aead_aes_gcm_siv_cleanup,
NULL /* open */,
aead_aes_gcm_siv_seal_scatter,
aead_aes_gcm_siv_open_gather,
NULL /* get_iv */,
NULL /* tag_len */,
};
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)
static char avx_aesni_capable(void) {
const uint32_t ecx = OPENSSL_ia32cap_P[1];
return (ecx & (1 << (57 - 32))) != 0 /* AESNI */ &&
(ecx & (1 << 28)) != 0 /* AVX */;
}
const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void) {
if (avx_aesni_capable()) {
return &aead_aes_128_gcm_siv_asm;
}
return &aead_aes_128_gcm_siv;
}
const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void) {
if (avx_aesni_capable()) {
return &aead_aes_256_gcm_siv_asm;
}
return &aead_aes_256_gcm_siv;
}
#else
const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void) {
return &aead_aes_128_gcm_siv;
}
const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void) {
return &aead_aes_256_gcm_siv;
}
#endif // X86_64 && !NO_ASM

View File

@ -1,326 +0,0 @@
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/aead.h>
#include <string.h>
#include <openssl/chacha.h>
#include <openssl/cipher.h>
#include <openssl/cpu.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/poly1305.h>
#include <openssl/type_check.h>
#include "../fipsmodule/cipher/internal.h"
#include "../internal.h"
#define POLY1305_TAG_LEN 16
struct aead_chacha20_poly1305_ctx {
uint8_t key[32];
};
// For convenience (the x86_64 calling convention allows only six parameters in
// registers), the final parameter for the assembly functions is both an input
// and output parameter.
union open_data {
struct {
alignas(16) uint8_t key[32];
uint32_t counter;
uint8_t nonce[12];
} in;
struct {
uint8_t tag[POLY1305_TAG_LEN];
} out;
};
union seal_data {
struct {
alignas(16) uint8_t key[32];
uint32_t counter;
uint8_t nonce[12];
const uint8_t *extra_ciphertext;
size_t extra_ciphertext_len;
} in;
struct {
uint8_t tag[POLY1305_TAG_LEN];
} out;
};
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
!defined(OPENSSL_WINDOWS)
static int asm_capable(void) {
const int sse41_capable = (OPENSSL_ia32cap_P[1] & (1 << 19)) != 0;
return sse41_capable;
}
OPENSSL_COMPILE_ASSERT(sizeof(union open_data) == 48, wrong_open_data_size);
OPENSSL_COMPILE_ASSERT(sizeof(union seal_data) == 48 + 8 + 8,
wrong_seal_data_size);
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It decrypts
// |plaintext_len| bytes from |ciphertext| and writes them to |out_plaintext|.
// Additional input parameters are passed in |aead_data->in|. On exit, it will
// write calculated tag value to |aead_data->out.tag|, which the caller must
// check.
extern void chacha20_poly1305_open(uint8_t *out_plaintext,
const uint8_t *ciphertext,
size_t plaintext_len, const uint8_t *ad,
size_t ad_len, union open_data *aead_data);
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It encrypts
// |plaintext_len| bytes from |plaintext| and writes them to |out_ciphertext|.
// Additional input parameters are passed in |aead_data->in|. The calculated tag
// value is over the computed ciphertext concatenated with |extra_ciphertext|
// and written to |aead_data->out.tag|.
extern void chacha20_poly1305_seal(uint8_t *out_ciphertext,
const uint8_t *plaintext,
size_t plaintext_len, const uint8_t *ad,
size_t ad_len, union seal_data *aead_data);
#else
static int asm_capable(void) { return 0; }
static void chacha20_poly1305_open(uint8_t *out_plaintext,
const uint8_t *ciphertext,
size_t plaintext_len, const uint8_t *ad,
size_t ad_len, union open_data *aead_data) {}
static void chacha20_poly1305_seal(uint8_t *out_ciphertext,
const uint8_t *plaintext,
size_t plaintext_len, const uint8_t *ad,
size_t ad_len, union seal_data *aead_data) {}
#endif
static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
struct aead_chacha20_poly1305_ctx *c20_ctx;
if (tag_len == 0) {
tag_len = POLY1305_TAG_LEN;
}
if (tag_len > POLY1305_TAG_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (key_len != sizeof(c20_ctx->key)) {
return 0; // internal error - EVP_AEAD_CTX_init should catch this.
}
c20_ctx = OPENSSL_malloc(sizeof(struct aead_chacha20_poly1305_ctx));
if (c20_ctx == NULL) {
return 0;
}
OPENSSL_memcpy(c20_ctx->key, key, key_len);
ctx->aead_state = c20_ctx;
ctx->tag_len = tag_len;
return 1;
}
static void aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) {
OPENSSL_free(ctx->aead_state);
}
static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) {
uint8_t length_bytes[8];
for (unsigned i = 0; i < sizeof(length_bytes); i++) {
length_bytes[i] = data_len;
data_len >>= 8;
}
CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
}
// calc_tag fills |tag| with the authentication tag for the given inputs.
static void calc_tag(uint8_t tag[POLY1305_TAG_LEN],
const struct aead_chacha20_poly1305_ctx *c20_ctx,
const uint8_t nonce[12], const uint8_t *ad, size_t ad_len,
const uint8_t *ciphertext, size_t ciphertext_len,
const uint8_t *ciphertext_extra,
size_t ciphertext_extra_len) {
alignas(16) uint8_t poly1305_key[32];
OPENSSL_memset(poly1305_key, 0, sizeof(poly1305_key));
CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
c20_ctx->key, nonce, 0);
static const uint8_t padding[16] = { 0 }; // Padding is all zeros.
poly1305_state ctx;
CRYPTO_poly1305_init(&ctx, poly1305_key);
CRYPTO_poly1305_update(&ctx, ad, ad_len);
if (ad_len % 16 != 0) {
CRYPTO_poly1305_update(&ctx, padding, sizeof(padding) - (ad_len % 16));
}
CRYPTO_poly1305_update(&ctx, ciphertext, ciphertext_len);
CRYPTO_poly1305_update(&ctx, ciphertext_extra, ciphertext_extra_len);
const size_t ciphertext_total = ciphertext_len + ciphertext_extra_len;
if (ciphertext_total % 16 != 0) {
CRYPTO_poly1305_update(&ctx, padding,
sizeof(padding) - (ciphertext_total % 16));
}
poly1305_update_length(&ctx, ad_len);
poly1305_update_length(&ctx, ciphertext_total);
CRYPTO_poly1305_finish(&ctx, tag);
}
static int aead_chacha20_poly1305_seal_scatter(
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
if (extra_in_len + ctx->tag_len < ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (max_out_tag_len < ctx->tag_len + extra_in_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != 12) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
// |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
// individual operations that work on more than 256GB at a time.
// |in_len_64| is needed because, on 32-bit platforms, size_t is only
// 32-bits and this produces a warning because it's always false.
// Casting to uint64_t inside the conditional is not sufficient to stop
// the warning.
const uint64_t in_len_64 = in_len;
if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (max_out_tag_len < ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
// The the extra input is given, it is expected to be very short and so is
// encrypted byte-by-byte first.
if (extra_in_len) {
static const size_t kChaChaBlockSize = 64;
uint32_t block_counter = 1 + (in_len / kChaChaBlockSize);
size_t offset = in_len % kChaChaBlockSize;
uint8_t block[64 /* kChaChaBlockSize */];
for (size_t done = 0; done < extra_in_len; block_counter++) {
memset(block, 0, sizeof(block));
CRYPTO_chacha_20(block, block, sizeof(block), c20_ctx->key, nonce,
block_counter);
for (size_t i = offset; i < sizeof(block) && done < extra_in_len;
i++, done++) {
out_tag[done] = extra_in[done] ^ block[i];
}
offset = 0;
}
}
union seal_data data;
if (asm_capable()) {
OPENSSL_memcpy(data.in.key, c20_ctx->key, 32);
data.in.counter = 0;
OPENSSL_memcpy(data.in.nonce, nonce, 12);
data.in.extra_ciphertext = out_tag;
data.in.extra_ciphertext_len = extra_in_len;
chacha20_poly1305_seal(out, in, in_len, ad, ad_len, &data);
} else {
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
calc_tag(data.out.tag, c20_ctx, nonce, ad, ad_len, out, in_len, out_tag,
extra_in_len);
}
OPENSSL_memcpy(out_tag + extra_in_len, data.out.tag, ctx->tag_len);
*out_tag_len = extra_in_len + ctx->tag_len;
return 1;
}
static int aead_chacha20_poly1305_open_gather(
const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *in_tag,
size_t in_tag_len, const uint8_t *ad, size_t ad_len) {
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
if (nonce_len != 12) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
return 0;
}
if (in_tag_len != ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
// |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
// individual operations that work on more than 256GB at a time.
// |in_len_64| is needed because, on 32-bit platforms, size_t is only
// 32-bits and this produces a warning because it's always false.
// Casting to uint64_t inside the conditional is not sufficient to stop
// the warning.
const uint64_t in_len_64 = in_len;
if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
union open_data data;
if (asm_capable()) {
OPENSSL_memcpy(data.in.key, c20_ctx->key, 32);
data.in.counter = 0;
OPENSSL_memcpy(data.in.nonce, nonce, 12);
chacha20_poly1305_open(out, in, in_len, ad, ad_len, &data);
} else {
calc_tag(data.out.tag, c20_ctx, nonce, ad, ad_len, in, in_len, NULL, 0);
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
}
if (CRYPTO_memcmp(data.out.tag, in_tag, ctx->tag_len) != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
return 1;
}
static const EVP_AEAD aead_chacha20_poly1305 = {
32, // key len
12, // nonce len
POLY1305_TAG_LEN, // overhead
POLY1305_TAG_LEN, // max tag length
1, // seal_scatter_supports_extra_in
aead_chacha20_poly1305_init,
NULL, // init_with_direction
aead_chacha20_poly1305_cleanup,
NULL /* open */,
aead_chacha20_poly1305_seal_scatter,
aead_chacha20_poly1305_open_gather,
NULL, // get_iv
NULL, // tag_len
};
const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
return &aead_chacha20_poly1305;
}

View File

@ -1,85 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/cipher.h>
#include <string.h>
#include <openssl/nid.h>
#include "../internal.h"
static int null_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
const uint8_t *iv, int enc) {
return 1;
}
static int null_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
const uint8_t *in, size_t in_len) {
if (in != out) {
OPENSSL_memcpy(out, in, in_len);
}
return 1;
}
static const EVP_CIPHER n_cipher = {
NID_undef, 1 /* block size */, 0 /* key_len */, 0 /* iv_len */,
0 /* ctx_size */, 0 /* flags */, NULL /* app_data */, null_init_key,
null_cipher, NULL /* cleanup */, NULL /* ctrl */,
};
const EVP_CIPHER *EVP_enc_null(void) { return &n_cipher; }

View File

@ -1,462 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/cipher.h>
#include <openssl/nid.h>
#include "../internal.h"
#define c2l(c, l) \
do { \
(l) = ((uint32_t)(*((c)++))); \
(l) |= ((uint32_t)(*((c)++))) << 8L; \
(l) |= ((uint32_t)(*((c)++))) << 16L; \
(l) |= ((uint32_t)(*((c)++))) << 24L; \
} while (0)
#define c2ln(c, l1, l2, n) \
do { \
(c) += (n); \
(l1) = (l2) = 0; \
switch (n) { \
case 8: \
(l2) = ((uint32_t)(*(--(c)))) << 24L; \
OPENSSL_FALLTHROUGH; \
case 7: \
(l2) |= ((uint32_t)(*(--(c)))) << 16L; \
OPENSSL_FALLTHROUGH; \
case 6: \
(l2) |= ((uint32_t)(*(--(c)))) << 8L; \
OPENSSL_FALLTHROUGH; \
case 5: \
(l2) |= ((uint32_t)(*(--(c)))); \
OPENSSL_FALLTHROUGH; \
case 4: \
(l1) = ((uint32_t)(*(--(c)))) << 24L; \
OPENSSL_FALLTHROUGH; \
case 3: \
(l1) |= ((uint32_t)(*(--(c)))) << 16L; \
OPENSSL_FALLTHROUGH; \
case 2: \
(l1) |= ((uint32_t)(*(--(c)))) << 8L; \
OPENSSL_FALLTHROUGH; \
case 1: \
(l1) |= ((uint32_t)(*(--(c)))); \
} \
} while (0)
#define l2c(l, c) \
do { \
*((c)++) = (uint8_t)(((l)) & 0xff); \
*((c)++) = (uint8_t)(((l) >> 8L) & 0xff); \
*((c)++) = (uint8_t)(((l) >> 16L) & 0xff); \
*((c)++) = (uint8_t)(((l) >> 24L) & 0xff); \
} while (0)
#define l2cn(l1, l2, c, n) \
do { \
(c) += (n); \
switch (n) { \
case 8: \
*(--(c)) = (uint8_t)(((l2) >> 24L) & 0xff); \
OPENSSL_FALLTHROUGH; \
case 7: \
*(--(c)) = (uint8_t)(((l2) >> 16L) & 0xff); \
OPENSSL_FALLTHROUGH; \
case 6: \
*(--(c)) = (uint8_t)(((l2) >> 8L) & 0xff); \
OPENSSL_FALLTHROUGH; \
case 5: \
*(--(c)) = (uint8_t)(((l2)) & 0xff); \
OPENSSL_FALLTHROUGH; \
case 4: \
*(--(c)) = (uint8_t)(((l1) >> 24L) & 0xff); \
OPENSSL_FALLTHROUGH; \
case 3: \
*(--(c)) = (uint8_t)(((l1) >> 16L) & 0xff); \
OPENSSL_FALLTHROUGH; \
case 2: \
*(--(c)) = (uint8_t)(((l1) >> 8L) & 0xff); \
OPENSSL_FALLTHROUGH; \
case 1: \
*(--(c)) = (uint8_t)(((l1)) & 0xff); \
} \
} while (0)
typedef struct rc2_key_st { uint16_t data[64]; } RC2_KEY;
static void RC2_encrypt(uint32_t *d, RC2_KEY *key) {
int i, n;
uint16_t *p0, *p1;
uint16_t x0, x1, x2, x3, t;
uint32_t l;
l = d[0];
x0 = (uint16_t)l & 0xffff;
x1 = (uint16_t)(l >> 16L);
l = d[1];
x2 = (uint16_t)l & 0xffff;
x3 = (uint16_t)(l >> 16L);
n = 3;
i = 5;
p0 = p1 = &key->data[0];
for (;;) {
t = (x0 + (x1 & ~x3) + (x2 & x3) + *(p0++)) & 0xffff;
x0 = (t << 1) | (t >> 15);
t = (x1 + (x2 & ~x0) + (x3 & x0) + *(p0++)) & 0xffff;
x1 = (t << 2) | (t >> 14);
t = (x2 + (x3 & ~x1) + (x0 & x1) + *(p0++)) & 0xffff;
x2 = (t << 3) | (t >> 13);
t = (x3 + (x0 & ~x2) + (x1 & x2) + *(p0++)) & 0xffff;
x3 = (t << 5) | (t >> 11);
if (--i == 0) {
if (--n == 0) {
break;
}
i = (n == 2) ? 6 : 5;
x0 += p1[x3 & 0x3f];
x1 += p1[x0 & 0x3f];
x2 += p1[x1 & 0x3f];
x3 += p1[x2 & 0x3f];
}
}
d[0] = (uint32_t)(x0 & 0xffff) | ((uint32_t)(x1 & 0xffff) << 16L);
d[1] = (uint32_t)(x2 & 0xffff) | ((uint32_t)(x3 & 0xffff) << 16L);
}
static void RC2_decrypt(uint32_t *d, RC2_KEY *key) {
int i, n;
uint16_t *p0, *p1;
uint16_t x0, x1, x2, x3, t;
uint32_t l;
l = d[0];
x0 = (uint16_t)l & 0xffff;
x1 = (uint16_t)(l >> 16L);
l = d[1];
x2 = (uint16_t)l & 0xffff;
x3 = (uint16_t)(l >> 16L);
n = 3;
i = 5;
p0 = &key->data[63];
p1 = &key->data[0];
for (;;) {
t = ((x3 << 11) | (x3 >> 5)) & 0xffff;
x3 = (t - (x0 & ~x2) - (x1 & x2) - *(p0--)) & 0xffff;
t = ((x2 << 13) | (x2 >> 3)) & 0xffff;
x2 = (t - (x3 & ~x1) - (x0 & x1) - *(p0--)) & 0xffff;
t = ((x1 << 14) | (x1 >> 2)) & 0xffff;
x1 = (t - (x2 & ~x0) - (x3 & x0) - *(p0--)) & 0xffff;
t = ((x0 << 15) | (x0 >> 1)) & 0xffff;
x0 = (t - (x1 & ~x3) - (x2 & x3) - *(p0--)) & 0xffff;
if (--i == 0) {
if (--n == 0) {
break;
}
i = (n == 2) ? 6 : 5;
x3 = (x3 - p1[x2 & 0x3f]) & 0xffff;
x2 = (x2 - p1[x1 & 0x3f]) & 0xffff;
x1 = (x1 - p1[x0 & 0x3f]) & 0xffff;
x0 = (x0 - p1[x3 & 0x3f]) & 0xffff;
}
}
d[0] = (uint32_t)(x0 & 0xffff) | ((uint32_t)(x1 & 0xffff) << 16L);
d[1] = (uint32_t)(x2 & 0xffff) | ((uint32_t)(x3 & 0xffff) << 16L);
}
static void RC2_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
RC2_KEY *ks, uint8_t *iv, int encrypt) {
uint32_t tin0, tin1;
uint32_t tout0, tout1, xor0, xor1;
long l = length;
uint32_t tin[2];
if (encrypt) {
c2l(iv, tout0);
c2l(iv, tout1);
iv -= 8;
for (l -= 8; l >= 0; l -= 8) {
c2l(in, tin0);
c2l(in, tin1);
tin0 ^= tout0;
tin1 ^= tout1;
tin[0] = tin0;
tin[1] = tin1;
RC2_encrypt(tin, ks);
tout0 = tin[0];
l2c(tout0, out);
tout1 = tin[1];
l2c(tout1, out);
}
if (l != -8) {
c2ln(in, tin0, tin1, l + 8);
tin0 ^= tout0;
tin1 ^= tout1;
tin[0] = tin0;
tin[1] = tin1;
RC2_encrypt(tin, ks);
tout0 = tin[0];
l2c(tout0, out);
tout1 = tin[1];
l2c(tout1, out);
}
l2c(tout0, iv);
l2c(tout1, iv);
} else {
c2l(iv, xor0);
c2l(iv, xor1);
iv -= 8;
for (l -= 8; l >= 0; l -= 8) {
c2l(in, tin0);
tin[0] = tin0;
c2l(in, tin1);
tin[1] = tin1;
RC2_decrypt(tin, ks);
tout0 = tin[0] ^ xor0;
tout1 = tin[1] ^ xor1;
l2c(tout0, out);
l2c(tout1, out);
xor0 = tin0;
xor1 = tin1;
}
if (l != -8) {
c2l(in, tin0);
tin[0] = tin0;
c2l(in, tin1);
tin[1] = tin1;
RC2_decrypt(tin, ks);
tout0 = tin[0] ^ xor0;
tout1 = tin[1] ^ xor1;
l2cn(tout0, tout1, out, l + 8);
xor0 = tin0;
xor1 = tin1;
}
l2c(xor0, iv);
l2c(xor1, iv);
}
tin[0] = tin[1] = 0;
}
static const uint8_t key_table[256] = {
0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79,
0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,
0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5,
0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22,
0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,
0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f,
0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b,
0xbc, 0x94, 0x43, 0x03, 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,
0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x08, 0xe8, 0xea, 0xde,
0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e,
0x04, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,
0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85,
0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10,
0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,
0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0x0d, 0x38, 0x34, 0x1b,
0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68,
0xfe, 0x7f, 0xc1, 0xad,
};
static void RC2_set_key(RC2_KEY *key, int len, const uint8_t *data, int bits) {
int i, j;
uint8_t *k;
uint16_t *ki;
unsigned int c, d;
k = (uint8_t *)&key->data[0];
*k = 0; // for if there is a zero length key
if (len > 128) {
len = 128;
}
if (bits <= 0) {
bits = 1024;
}
if (bits > 1024) {
bits = 1024;
}
for (i = 0; i < len; i++) {
k[i] = data[i];
}
// expand table
d = k[len - 1];
j = 0;
for (i = len; i < 128; i++, j++) {
d = key_table[(k[j] + d) & 0xff];
k[i] = d;
}
// hmm.... key reduction to 'bits' bits
j = (bits + 7) >> 3;
i = 128 - j;
c = (0xff >> (-bits & 0x07));
d = key_table[k[i] & c];
k[i] = d;
while (i--) {
d = key_table[k[i + j] ^ d];
k[i] = d;
}
// copy from bytes into uint16_t's
ki = &(key->data[63]);
for (i = 127; i >= 0; i -= 2) {
*(ki--) = ((k[i] << 8) | k[i - 1]) & 0xffff;
}
}
typedef struct {
int key_bits; // effective key bits
RC2_KEY ks; // key schedule
} EVP_RC2_KEY;
static int rc2_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
const uint8_t *iv, int enc) {
EVP_RC2_KEY *rc2_key = (EVP_RC2_KEY *)ctx->cipher_data;
RC2_set_key(&rc2_key->ks, EVP_CIPHER_CTX_key_length(ctx), key,
rc2_key->key_bits);
return 1;
}
static int rc2_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
size_t inl) {
EVP_RC2_KEY *key = (EVP_RC2_KEY *)ctx->cipher_data;
static const size_t kChunkSize = 0x10000;
while (inl >= kChunkSize) {
RC2_cbc_encrypt(in, out, kChunkSize, &key->ks, ctx->iv, ctx->encrypt);
inl -= kChunkSize;
in += kChunkSize;
out += kChunkSize;
}
if (inl) {
RC2_cbc_encrypt(in, out, inl, &key->ks, ctx->iv, ctx->encrypt);
}
return 1;
}
static int rc2_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) {
EVP_RC2_KEY *key = (EVP_RC2_KEY *)ctx->cipher_data;
switch (type) {
case EVP_CTRL_INIT:
key->key_bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
return 1;
case EVP_CTRL_SET_RC2_KEY_BITS:
// Should be overridden by later call to |EVP_CTRL_INIT|, but
// people call it, so it may as well work.
key->key_bits = arg;
return 1;
default:
return -1;
}
}
static const EVP_CIPHER rc2_40_cbc = {
NID_rc2_40_cbc,
8 /* block size */,
5 /* 40 bit */,
8 /* iv len */,
sizeof(EVP_RC2_KEY),
EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
NULL /* app_data */,
rc2_init_key,
rc2_cbc_cipher,
NULL,
rc2_ctrl,
};
const EVP_CIPHER *EVP_rc2_40_cbc(void) {
return &rc2_40_cbc;
}
static const EVP_CIPHER rc2_cbc = {
NID_rc2_cbc,
8 /* block size */,
16 /* 128 bit */,
8 /* iv len */,
sizeof(EVP_RC2_KEY),
EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
NULL /* app_data */,
rc2_init_key,
rc2_cbc_cipher,
NULL,
rc2_ctrl,
};
const EVP_CIPHER *EVP_rc2_cbc(void) {
return &rc2_cbc;
}

View File

@ -1,87 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <assert.h>
#include <string.h>
#include <openssl/cipher.h>
#include <openssl/nid.h>
#include <openssl/rc4.h>
static int rc4_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
const uint8_t *iv, int enc) {
RC4_KEY *rc4key = (RC4_KEY *)ctx->cipher_data;
RC4_set_key(rc4key, EVP_CIPHER_CTX_key_length(ctx), key);
return 1;
}
static int rc4_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
size_t in_len) {
RC4_KEY *rc4key = (RC4_KEY *)ctx->cipher_data;
RC4(rc4key, in_len, in, out);
return 1;
}
static const EVP_CIPHER rc4 = {
NID_rc4, 1 /* block_size */, 16 /* key_size */,
0 /* iv_len */, sizeof(RC4_KEY), EVP_CIPH_VARIABLE_LENGTH,
NULL /* app_data */, rc4_init_key, rc4_cipher,
NULL /* cleanup */, NULL /* ctrl */, };
const EVP_CIPHER *EVP_rc4(void) { return &rc4; }

View File

@ -1,460 +0,0 @@
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <openssl/aead.h>
#include <openssl/cipher.h>
#include <openssl/err.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/mem.h>
#include <openssl/sha.h>
#include "internal.h"
#include "../internal.h"
#include "../fipsmodule/cipher/internal.h"
typedef struct {
EVP_CIPHER_CTX cipher_ctx;
EVP_MD_CTX md_ctx;
} AEAD_SSL3_CTX;
static int ssl3_mac(AEAD_SSL3_CTX *ssl3_ctx, uint8_t *out, unsigned *out_len,
const uint8_t *ad, size_t ad_len, const uint8_t *in,
size_t in_len) {
size_t md_size = EVP_MD_CTX_size(&ssl3_ctx->md_ctx);
size_t pad_len = (md_size == 20) ? 40 : 48;
// To allow for CBC mode which changes cipher length, |ad| doesn't include the
// length for legacy ciphers.
uint8_t ad_extra[2];
ad_extra[0] = (uint8_t)(in_len >> 8);
ad_extra[1] = (uint8_t)(in_len & 0xff);
EVP_MD_CTX md_ctx;
EVP_MD_CTX_init(&md_ctx);
uint8_t pad[48];
uint8_t tmp[EVP_MAX_MD_SIZE];
OPENSSL_memset(pad, 0x36, pad_len);
if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) ||
!EVP_DigestUpdate(&md_ctx, pad, pad_len) ||
!EVP_DigestUpdate(&md_ctx, ad, ad_len) ||
!EVP_DigestUpdate(&md_ctx, ad_extra, sizeof(ad_extra)) ||
!EVP_DigestUpdate(&md_ctx, in, in_len) ||
!EVP_DigestFinal_ex(&md_ctx, tmp, NULL)) {
EVP_MD_CTX_cleanup(&md_ctx);
return 0;
}
OPENSSL_memset(pad, 0x5c, pad_len);
if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) ||
!EVP_DigestUpdate(&md_ctx, pad, pad_len) ||
!EVP_DigestUpdate(&md_ctx, tmp, md_size) ||
!EVP_DigestFinal_ex(&md_ctx, out, out_len)) {
EVP_MD_CTX_cleanup(&md_ctx);
return 0;
}
EVP_MD_CTX_cleanup(&md_ctx);
return 1;
}
static void aead_ssl3_cleanup(EVP_AEAD_CTX *ctx) {
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
EVP_CIPHER_CTX_cleanup(&ssl3_ctx->cipher_ctx);
EVP_MD_CTX_cleanup(&ssl3_ctx->md_ctx);
OPENSSL_free(ssl3_ctx);
ctx->aead_state = NULL;
}
static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
size_t tag_len, enum evp_aead_direction_t dir,
const EVP_CIPHER *cipher, const EVP_MD *md) {
if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH &&
tag_len != EVP_MD_size(md)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE);
return 0;
}
if (key_len != EVP_AEAD_key_length(ctx->aead)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
return 0;
}
size_t mac_key_len = EVP_MD_size(md);
size_t enc_key_len = EVP_CIPHER_key_length(cipher);
assert(mac_key_len + enc_key_len + EVP_CIPHER_iv_length(cipher) == key_len);
AEAD_SSL3_CTX *ssl3_ctx = OPENSSL_malloc(sizeof(AEAD_SSL3_CTX));
if (ssl3_ctx == NULL) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
return 0;
}
EVP_CIPHER_CTX_init(&ssl3_ctx->cipher_ctx);
EVP_MD_CTX_init(&ssl3_ctx->md_ctx);
ctx->aead_state = ssl3_ctx;
if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len],
&key[mac_key_len + enc_key_len],
dir == evp_aead_seal) ||
!EVP_DigestInit_ex(&ssl3_ctx->md_ctx, md, NULL) ||
!EVP_DigestUpdate(&ssl3_ctx->md_ctx, key, mac_key_len)) {
aead_ssl3_cleanup(ctx);
ctx->aead_state = NULL;
return 0;
}
EVP_CIPHER_CTX_set_padding(&ssl3_ctx->cipher_ctx, 0);
return 1;
}
static size_t aead_ssl3_tag_len(const EVP_AEAD_CTX *ctx, const size_t in_len,
const size_t extra_in_len) {
assert(extra_in_len == 0);
const AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX*)ctx->aead_state;
const size_t digest_len = EVP_MD_CTX_size(&ssl3_ctx->md_ctx);
if (EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE) {
// The NULL cipher.
return digest_len;
}
const size_t block_size = EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx);
// An overflow of |in_len + digest_len| doesn't affect the result mod
// |block_size|, provided that |block_size| is a smaller power of two.
assert(block_size != 0 && (block_size & (block_size - 1)) == 0);
const size_t pad_len = block_size - ((in_len + digest_len) % block_size);
return digest_len + pad_len;
}
static int aead_ssl3_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out,
uint8_t *out_tag, size_t *out_tag_len,
const size_t max_out_tag_len,
const uint8_t *nonce, const size_t nonce_len,
const uint8_t *in, const size_t in_len,
const uint8_t *extra_in,
const size_t extra_in_len, const uint8_t *ad,
const size_t ad_len) {
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
if (!ssl3_ctx->cipher_ctx.encrypt) {
// Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
return 0;
}
if (in_len > INT_MAX) {
// EVP_CIPHER takes int as input.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (max_out_tag_len < aead_ssl3_tag_len(ctx, in_len, extra_in_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_IV_TOO_LARGE);
return 0;
}
if (ad_len != 11 - 2 /* length bytes */) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE);
return 0;
}
// Compute the MAC. This must be first in case the operation is being done
// in-place.
uint8_t mac[EVP_MAX_MD_SIZE];
unsigned mac_len;
if (!ssl3_mac(ssl3_ctx, mac, &mac_len, ad, ad_len, in, in_len)) {
return 0;
}
// Encrypt the input.
int len;
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in,
(int)in_len)) {
return 0;
}
const size_t block_size = EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx);
// Feed the MAC into the cipher in two steps. First complete the final partial
// block from encrypting the input and split the result between |out| and
// |out_tag|. Then encrypt the remainder.
size_t early_mac_len = (block_size - (in_len % block_size)) % block_size;
if (early_mac_len != 0) {
assert(len + block_size - early_mac_len == in_len);
uint8_t buf[EVP_MAX_BLOCK_LENGTH];
int buf_len;
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, buf, &buf_len, mac,
(int)early_mac_len)) {
return 0;
}
assert(buf_len == (int)block_size);
OPENSSL_memcpy(out + len, buf, block_size - early_mac_len);
OPENSSL_memcpy(out_tag, buf + block_size - early_mac_len, early_mac_len);
}
size_t tag_len = early_mac_len;
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out_tag + tag_len, &len,
mac + tag_len, mac_len - tag_len)) {
return 0;
}
tag_len += len;
if (block_size > 1) {
assert(block_size <= 256);
assert(EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE);
// Compute padding and feed that into the cipher.
uint8_t padding[256];
size_t padding_len = block_size - ((in_len + mac_len) % block_size);
OPENSSL_memset(padding, 0, padding_len - 1);
padding[padding_len - 1] = padding_len - 1;
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out_tag + tag_len, &len, padding,
(int)padding_len)) {
return 0;
}
tag_len += len;
}
if (!EVP_EncryptFinal_ex(&ssl3_ctx->cipher_ctx, out_tag + tag_len, &len)) {
return 0;
}
tag_len += len;
assert(tag_len == aead_ssl3_tag_len(ctx, in_len, extra_in_len));
*out_tag_len = tag_len;
return 1;
}
static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
if (ssl3_ctx->cipher_ctx.encrypt) {
// Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
return 0;
}
size_t mac_len = EVP_MD_CTX_size(&ssl3_ctx->md_ctx);
if (in_len < mac_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
if (max_out_len < in_len) {
// This requires that the caller provide space for the MAC, even though it
// will always be removed on return.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (ad_len != 11 - 2 /* length bytes */) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE);
return 0;
}
if (in_len > INT_MAX) {
// EVP_CIPHER takes int as input.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
// Decrypt to get the plaintext + MAC + padding.
size_t total = 0;
int len;
if (!EVP_DecryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in, (int)in_len)) {
return 0;
}
total += len;
if (!EVP_DecryptFinal_ex(&ssl3_ctx->cipher_ctx, out + total, &len)) {
return 0;
}
total += len;
assert(total == in_len);
// Remove CBC padding and MAC. This would normally be timing-sensitive, but
// SSLv3 CBC ciphers are already broken. Support will be removed eventually.
// https://www.openssl.org/~bodo/ssl-poodle.pdf
size_t data_len;
if (EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
unsigned padding_length = out[total - 1];
if (total < padding_length + 1 + mac_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
// The padding must be minimal.
if (padding_length + 1 > EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
data_len = total - padding_length - 1 - mac_len;
} else {
data_len = total - mac_len;
}
// Compute the MAC and compare against the one in the record.
uint8_t mac[EVP_MAX_MD_SIZE];
if (!ssl3_mac(ssl3_ctx, mac, NULL, ad, ad_len, out, data_len)) {
return 0;
}
if (CRYPTO_memcmp(&out[data_len], mac, mac_len) != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
*out_len = data_len;
return 1;
}
static int aead_ssl3_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
size_t *out_iv_len) {
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
const size_t iv_len = EVP_CIPHER_CTX_iv_length(&ssl3_ctx->cipher_ctx);
if (iv_len <= 1) {
return 0;
}
*out_iv = ssl3_ctx->cipher_ctx.iv;
*out_iv_len = iv_len;
return 1;
}
static int aead_aes_128_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha1());
}
static int aead_aes_256_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha1());
}
static int aead_des_ede3_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
EVP_sha1());
}
static int aead_null_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_enc_null(),
EVP_sha1());
}
static const EVP_AEAD aead_aes_128_cbc_sha1_ssl3 = {
SHA_DIGEST_LENGTH + 16 + 16, // key len (SHA1 + AES128 + IV)
0, // nonce len
16 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_aes_128_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_open,
aead_ssl3_seal_scatter,
NULL, // open_gather
aead_ssl3_get_iv,
aead_ssl3_tag_len,
};
static const EVP_AEAD aead_aes_256_cbc_sha1_ssl3 = {
SHA_DIGEST_LENGTH + 32 + 16, // key len (SHA1 + AES256 + IV)
0, // nonce len
16 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_aes_256_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_open,
aead_ssl3_seal_scatter,
NULL, // open_gather
aead_ssl3_get_iv,
aead_ssl3_tag_len,
};
static const EVP_AEAD aead_des_ede3_cbc_sha1_ssl3 = {
SHA_DIGEST_LENGTH + 24 + 8, // key len (SHA1 + 3DES + IV)
0, // nonce len
8 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_des_ede3_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_open,
aead_ssl3_seal_scatter,
NULL, // open_gather
aead_ssl3_get_iv,
aead_ssl3_tag_len,
};
static const EVP_AEAD aead_null_sha1_ssl3 = {
SHA_DIGEST_LENGTH, // key len
0, // nonce len
SHA_DIGEST_LENGTH, // overhead (SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_null_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_open,
aead_ssl3_seal_scatter,
NULL, // open_gather
NULL, // get_iv
aead_ssl3_tag_len,
};
const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void) {
return &aead_aes_128_cbc_sha1_ssl3;
}
const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void) {
return &aead_aes_256_cbc_sha1_ssl3;
}
const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void) {
return &aead_des_ede3_cbc_sha1_ssl3;
}
const EVP_AEAD *EVP_aead_null_sha1_ssl3(void) { return &aead_null_sha1_ssl3; }

View File

@ -1,680 +0,0 @@
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <openssl/aead.h>
#include <openssl/cipher.h>
#include <openssl/err.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/mem.h>
#include <openssl/sha.h>
#include <openssl/type_check.h>
#include "../fipsmodule/cipher/internal.h"
#include "../internal.h"
#include "internal.h"
typedef struct {
EVP_CIPHER_CTX cipher_ctx;
HMAC_CTX hmac_ctx;
// mac_key is the portion of the key used for the MAC. It is retained
// separately for the constant-time CBC code.
uint8_t mac_key[EVP_MAX_MD_SIZE];
uint8_t mac_key_len;
// implicit_iv is one iff this is a pre-TLS-1.1 CBC cipher without an explicit
// IV.
char implicit_iv;
} AEAD_TLS_CTX;
OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE < 256, mac_key_len_fits_in_uint8_t);
static void aead_tls_cleanup(EVP_AEAD_CTX *ctx) {
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
EVP_CIPHER_CTX_cleanup(&tls_ctx->cipher_ctx);
HMAC_CTX_cleanup(&tls_ctx->hmac_ctx);
OPENSSL_free(tls_ctx);
ctx->aead_state = NULL;
}
static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
size_t tag_len, enum evp_aead_direction_t dir,
const EVP_CIPHER *cipher, const EVP_MD *md,
char implicit_iv) {
if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH &&
tag_len != EVP_MD_size(md)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE);
return 0;
}
if (key_len != EVP_AEAD_key_length(ctx->aead)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
return 0;
}
size_t mac_key_len = EVP_MD_size(md);
size_t enc_key_len = EVP_CIPHER_key_length(cipher);
assert(mac_key_len + enc_key_len +
(implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0) == key_len);
AEAD_TLS_CTX *tls_ctx = OPENSSL_malloc(sizeof(AEAD_TLS_CTX));
if (tls_ctx == NULL) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
return 0;
}
EVP_CIPHER_CTX_init(&tls_ctx->cipher_ctx);
HMAC_CTX_init(&tls_ctx->hmac_ctx);
assert(mac_key_len <= EVP_MAX_MD_SIZE);
OPENSSL_memcpy(tls_ctx->mac_key, key, mac_key_len);
tls_ctx->mac_key_len = (uint8_t)mac_key_len;
tls_ctx->implicit_iv = implicit_iv;
ctx->aead_state = tls_ctx;
if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len],
implicit_iv ? &key[mac_key_len + enc_key_len] : NULL,
dir == evp_aead_seal) ||
!HMAC_Init_ex(&tls_ctx->hmac_ctx, key, mac_key_len, md, NULL)) {
aead_tls_cleanup(ctx);
ctx->aead_state = NULL;
return 0;
}
EVP_CIPHER_CTX_set_padding(&tls_ctx->cipher_ctx, 0);
return 1;
}
static size_t aead_tls_tag_len(const EVP_AEAD_CTX *ctx, const size_t in_len,
const size_t extra_in_len) {
assert(extra_in_len == 0);
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
const size_t hmac_len = HMAC_size(&tls_ctx->hmac_ctx);
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE) {
// The NULL cipher.
return hmac_len;
}
const size_t block_size = EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx);
// An overflow of |in_len + hmac_len| doesn't affect the result mod
// |block_size|, provided that |block_size| is a smaller power of two.
assert(block_size != 0 && (block_size & (block_size - 1)) == 0);
const size_t pad_len = block_size - (in_len + hmac_len) % block_size;
return hmac_len + pad_len;
}
static int aead_tls_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out,
uint8_t *out_tag, size_t *out_tag_len,
const size_t max_out_tag_len,
const uint8_t *nonce, const size_t nonce_len,
const uint8_t *in, const size_t in_len,
const uint8_t *extra_in,
const size_t extra_in_len, const uint8_t *ad,
const size_t ad_len) {
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
if (!tls_ctx->cipher_ctx.encrypt) {
// Unlike a normal AEAD, a TLS AEAD may only be used in one direction.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
return 0;
}
if (in_len > INT_MAX) {
// EVP_CIPHER takes int as input.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (max_out_tag_len < aead_tls_tag_len(ctx, in_len, extra_in_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
return 0;
}
if (ad_len != 13 - 2 /* length bytes */) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE);
return 0;
}
// To allow for CBC mode which changes cipher length, |ad| doesn't include the
// length for legacy ciphers.
uint8_t ad_extra[2];
ad_extra[0] = (uint8_t)(in_len >> 8);
ad_extra[1] = (uint8_t)(in_len & 0xff);
// Compute the MAC. This must be first in case the operation is being done
// in-place.
uint8_t mac[EVP_MAX_MD_SIZE];
unsigned mac_len;
if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) ||
!HMAC_Update(&tls_ctx->hmac_ctx, ad, ad_len) ||
!HMAC_Update(&tls_ctx->hmac_ctx, ad_extra, sizeof(ad_extra)) ||
!HMAC_Update(&tls_ctx->hmac_ctx, in, in_len) ||
!HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len)) {
return 0;
}
// Configure the explicit IV.
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
!tls_ctx->implicit_iv &&
!EVP_EncryptInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, NULL, nonce)) {
return 0;
}
// Encrypt the input.
int len;
if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out, &len, in, (int)in_len)) {
return 0;
}
unsigned block_size = EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx);
// Feed the MAC into the cipher in two steps. First complete the final partial
// block from encrypting the input and split the result between |out| and
// |out_tag|. Then feed the rest.
const size_t early_mac_len = (block_size - (in_len % block_size)) % block_size;
if (early_mac_len != 0) {
assert(len + block_size - early_mac_len == in_len);
uint8_t buf[EVP_MAX_BLOCK_LENGTH];
int buf_len;
if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, buf, &buf_len, mac,
(int)early_mac_len)) {
return 0;
}
assert(buf_len == (int)block_size);
OPENSSL_memcpy(out + len, buf, block_size - early_mac_len);
OPENSSL_memcpy(out_tag, buf + block_size - early_mac_len, early_mac_len);
}
size_t tag_len = early_mac_len;
if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out_tag + tag_len, &len,
mac + tag_len, mac_len - tag_len)) {
return 0;
}
tag_len += len;
if (block_size > 1) {
assert(block_size <= 256);
assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE);
// Compute padding and feed that into the cipher.
uint8_t padding[256];
unsigned padding_len = block_size - ((in_len + mac_len) % block_size);
OPENSSL_memset(padding, padding_len - 1, padding_len);
if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out_tag + tag_len, &len,
padding, (int)padding_len)) {
return 0;
}
tag_len += len;
}
if (!EVP_EncryptFinal_ex(&tls_ctx->cipher_ctx, out_tag + tag_len, &len)) {
return 0;
}
assert(len == 0); // Padding is explicit.
assert(tag_len == aead_tls_tag_len(ctx, in_len, extra_in_len));
*out_tag_len = tag_len;
return 1;
}
static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
size_t max_out_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
if (tls_ctx->cipher_ctx.encrypt) {
// Unlike a normal AEAD, a TLS AEAD may only be used in one direction.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
return 0;
}
if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
if (max_out_len < in_len) {
// This requires that the caller provide space for the MAC, even though it
// will always be removed on return.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
return 0;
}
if (ad_len != 13 - 2 /* length bytes */) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE);
return 0;
}
if (in_len > INT_MAX) {
// EVP_CIPHER takes int as input.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
// Configure the explicit IV.
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
!tls_ctx->implicit_iv &&
!EVP_DecryptInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, NULL, nonce)) {
return 0;
}
// Decrypt to get the plaintext + MAC + padding.
size_t total = 0;
int len;
if (!EVP_DecryptUpdate(&tls_ctx->cipher_ctx, out, &len, in, (int)in_len)) {
return 0;
}
total += len;
if (!EVP_DecryptFinal_ex(&tls_ctx->cipher_ctx, out + total, &len)) {
return 0;
}
total += len;
assert(total == in_len);
// Remove CBC padding. Code from here on is timing-sensitive with respect to
// |padding_ok| and |data_plus_mac_len| for CBC ciphers.
size_t data_plus_mac_len;
crypto_word_t padding_ok;
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
if (!EVP_tls_cbc_remove_padding(
&padding_ok, &data_plus_mac_len, out, total,
EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx),
HMAC_size(&tls_ctx->hmac_ctx))) {
// Publicly invalid. This can be rejected in non-constant time.
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
} else {
padding_ok = CONSTTIME_TRUE_W;
data_plus_mac_len = total;
// |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has
// already been checked against the MAC size at the top of the function.
assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx));
}
size_t data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
// At this point, if the padding is valid, the first |data_plus_mac_len| bytes
// after |out| are the plaintext and MAC. Otherwise, |data_plus_mac_len| is
// still large enough to extract a MAC, but it will be irrelevant.
// To allow for CBC mode which changes cipher length, |ad| doesn't include the
// length for legacy ciphers.
uint8_t ad_fixed[13];
OPENSSL_memcpy(ad_fixed, ad, 11);
ad_fixed[11] = (uint8_t)(data_len >> 8);
ad_fixed[12] = (uint8_t)(data_len & 0xff);
ad_len += 2;
// Compute the MAC and extract the one in the record.
uint8_t mac[EVP_MAX_MD_SIZE];
size_t mac_len;
uint8_t record_mac_tmp[EVP_MAX_MD_SIZE];
uint8_t *record_mac;
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
EVP_tls_cbc_record_digest_supported(tls_ctx->hmac_ctx.md)) {
if (!EVP_tls_cbc_digest_record(tls_ctx->hmac_ctx.md, mac, &mac_len,
ad_fixed, out, data_plus_mac_len, total,
tls_ctx->mac_key, tls_ctx->mac_key_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx));
record_mac = record_mac_tmp;
EVP_tls_cbc_copy_mac(record_mac, mac_len, out, data_plus_mac_len, total);
} else {
// We should support the constant-time path for all CBC-mode ciphers
// implemented.
assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE);
unsigned mac_len_u;
if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) ||
!HMAC_Update(&tls_ctx->hmac_ctx, ad_fixed, ad_len) ||
!HMAC_Update(&tls_ctx->hmac_ctx, out, data_len) ||
!HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len_u)) {
return 0;
}
mac_len = mac_len_u;
assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx));
record_mac = &out[data_len];
}
// Perform the MAC check and the padding check in constant-time. It should be
// safe to simply perform the padding check first, but it would not be under a
// different choice of MAC location on padding failure. See
// EVP_tls_cbc_remove_padding.
crypto_word_t good =
constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len), 0);
good &= padding_ok;
if (!good) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
// End of timing-sensitive code.
*out_len = data_len;
return 1;
}
static int aead_aes_128_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha1(), 0);
}
static int aead_aes_128_cbc_sha1_tls_implicit_iv_init(
EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha1(), 1);
}
static int aead_aes_128_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha256(), 0);
}
static int aead_aes_256_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha1(), 0);
}
static int aead_aes_256_cbc_sha1_tls_implicit_iv_init(
EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha1(), 1);
}
static int aead_aes_256_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha256(), 0);
}
static int aead_aes_256_cbc_sha384_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha384(), 0);
}
static int aead_des_ede3_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
EVP_sha1(), 0);
}
static int aead_des_ede3_cbc_sha1_tls_implicit_iv_init(
EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
EVP_sha1(), 1);
}
static int aead_tls_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
size_t *out_iv_len) {
const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state;
const size_t iv_len = EVP_CIPHER_CTX_iv_length(&tls_ctx->cipher_ctx);
if (iv_len <= 1) {
return 0;
}
*out_iv = tls_ctx->cipher_ctx.iv;
*out_iv_len = iv_len;
return 1;
}
static int aead_null_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_enc_null(),
EVP_sha1(), 1 /* implicit iv */);
}
static const EVP_AEAD aead_aes_128_cbc_sha1_tls = {
SHA_DIGEST_LENGTH + 16, // key len (SHA1 + AES128)
16, // nonce len (IV)
16 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_aes_128_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
NULL, // get_iv
aead_tls_tag_len,
};
static const EVP_AEAD aead_aes_128_cbc_sha1_tls_implicit_iv = {
SHA_DIGEST_LENGTH + 16 + 16, // key len (SHA1 + AES128 + IV)
0, // nonce len
16 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_aes_128_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
aead_tls_get_iv, // get_iv
aead_tls_tag_len,
};
static const EVP_AEAD aead_aes_128_cbc_sha256_tls = {
SHA256_DIGEST_LENGTH + 16, // key len (SHA256 + AES128)
16, // nonce len (IV)
16 + SHA256_DIGEST_LENGTH, // overhead (padding + SHA256)
SHA256_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_aes_128_cbc_sha256_tls_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
NULL, // get_iv
aead_tls_tag_len,
};
static const EVP_AEAD aead_aes_256_cbc_sha1_tls = {
SHA_DIGEST_LENGTH + 32, // key len (SHA1 + AES256)
16, // nonce len (IV)
16 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_aes_256_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
NULL, // get_iv
aead_tls_tag_len,
};
static const EVP_AEAD aead_aes_256_cbc_sha1_tls_implicit_iv = {
SHA_DIGEST_LENGTH + 32 + 16, // key len (SHA1 + AES256 + IV)
0, // nonce len
16 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_aes_256_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
aead_tls_get_iv, // get_iv
aead_tls_tag_len,
};
static const EVP_AEAD aead_aes_256_cbc_sha256_tls = {
SHA256_DIGEST_LENGTH + 32, // key len (SHA256 + AES256)
16, // nonce len (IV)
16 + SHA256_DIGEST_LENGTH, // overhead (padding + SHA256)
SHA256_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_aes_256_cbc_sha256_tls_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
NULL, // get_iv
aead_tls_tag_len,
};
static const EVP_AEAD aead_aes_256_cbc_sha384_tls = {
SHA384_DIGEST_LENGTH + 32, // key len (SHA384 + AES256)
16, // nonce len (IV)
16 + SHA384_DIGEST_LENGTH, // overhead (padding + SHA384)
SHA384_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_aes_256_cbc_sha384_tls_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
NULL, // get_iv
aead_tls_tag_len,
};
static const EVP_AEAD aead_des_ede3_cbc_sha1_tls = {
SHA_DIGEST_LENGTH + 24, // key len (SHA1 + 3DES)
8, // nonce len (IV)
8 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_des_ede3_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
NULL, // get_iv
aead_tls_tag_len,
};
static const EVP_AEAD aead_des_ede3_cbc_sha1_tls_implicit_iv = {
SHA_DIGEST_LENGTH + 24 + 8, // key len (SHA1 + 3DES + IV)
0, // nonce len
8 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_des_ede3_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
aead_tls_get_iv, // get_iv
aead_tls_tag_len,
};
static const EVP_AEAD aead_null_sha1_tls = {
SHA_DIGEST_LENGTH, // key len
0, // nonce len
SHA_DIGEST_LENGTH, // overhead (SHA1)
SHA_DIGEST_LENGTH, // max tag length
0, // seal_scatter_supports_extra_in
NULL, // init
aead_null_sha1_tls_init,
aead_tls_cleanup,
aead_tls_open,
aead_tls_seal_scatter,
NULL, // open_gather
NULL, // get_iv
aead_tls_tag_len,
};
const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void) {
return &aead_aes_128_cbc_sha1_tls;
}
const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void) {
return &aead_aes_128_cbc_sha1_tls_implicit_iv;
}
const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void) {
return &aead_aes_128_cbc_sha256_tls;
}
const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void) {
return &aead_aes_256_cbc_sha1_tls;
}
const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void) {
return &aead_aes_256_cbc_sha1_tls_implicit_iv;
}
const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void) {
return &aead_aes_256_cbc_sha256_tls;
}
const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void) {
return &aead_aes_256_cbc_sha384_tls;
}
const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void) {
return &aead_des_ede3_cbc_sha1_tls;
}
const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void) {
return &aead_des_ede3_cbc_sha1_tls_implicit_iv;
}
const EVP_AEAD *EVP_aead_null_sha1_tls(void) { return &aead_null_sha1_tls; }

View File

@ -1,128 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#ifndef OPENSSL_HEADER_CIPHER_EXTRA_INTERNAL_H
#define OPENSSL_HEADER_CIPHER_EXTRA_INTERNAL_H
#include <openssl/base.h>
#include "../internal.h"
#if defined(__cplusplus)
extern "C" {
#endif
// EVP_tls_cbc_get_padding determines the padding from the decrypted, TLS, CBC
// record in |in|. This decrypted record should not include any "decrypted"
// explicit IV. If the record is publicly invalid, it returns zero. Otherwise,
// it returns one and sets |*out_padding_ok| to all ones (0xfff..f) if the
// padding is valid and zero otherwise. It then sets |*out_len| to the length
// with the padding removed or |in_len| if invalid.
//
// If the function returns one, it runs in time independent of the contents of
// |in|. It is also guaranteed that |*out_len| >= |mac_size|, satisfying
// |EVP_tls_cbc_copy_mac|'s precondition.
int EVP_tls_cbc_remove_padding(crypto_word_t *out_padding_ok, size_t *out_len,
const uint8_t *in, size_t in_len,
size_t block_size, size_t mac_size);
// EVP_tls_cbc_copy_mac copies |md_size| bytes from the end of the first
// |in_len| bytes of |in| to |out| in constant time (independent of the concrete
// value of |in_len|, which may vary within a 256-byte window). |in| must point
// to a buffer of |orig_len| bytes.
//
// On entry:
// orig_len >= in_len >= md_size
// md_size <= EVP_MAX_MD_SIZE
void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
size_t in_len, size_t orig_len);
// EVP_tls_cbc_record_digest_supported returns 1 iff |md| is a hash function
// which EVP_tls_cbc_digest_record supports.
int EVP_tls_cbc_record_digest_supported(const EVP_MD *md);
// EVP_tls_cbc_digest_record computes the MAC of a decrypted, padded TLS
// record.
//
// md: the hash function used in the HMAC.
// EVP_tls_cbc_record_digest_supported must return true for this hash.
// md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written.
// md_out_size: the number of output bytes is written here.
// header: the 13-byte, TLS record header.
// data: the record data itself
// data_plus_mac_size: the secret, reported length of the data and MAC
// once the padding has been removed.
// data_plus_mac_plus_padding_size: the public length of the whole
// record, including padding.
//
// On entry: by virtue of having been through one of the remove_padding
// functions, above, we know that data_plus_mac_size is large enough to contain
// a padding byte and MAC. (If the padding was invalid, it might contain the
// padding too. )
int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
size_t *md_out_size, const uint8_t header[13],
const uint8_t *data, size_t data_plus_mac_size,
size_t data_plus_mac_plus_padding_size,
const uint8_t *mac_secret,
unsigned mac_secret_length);
#if defined(__cplusplus)
} // extern C
#endif
#endif // OPENSSL_HEADER_CIPHER_EXTRA_INTERNAL_H

View File

@ -1,482 +0,0 @@
/* ====================================================================
* Copyright (c) 2012 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <assert.h>
#include <string.h>
#include <openssl/digest.h>
#include <openssl/nid.h>
#include <openssl/sha.h>
#include "../internal.h"
#include "internal.h"
#include "../fipsmodule/cipher/internal.h"
// MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's length
// field. (SHA-384/512 have 128-bit length.)
#define MAX_HASH_BIT_COUNT_BYTES 16
// MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support.
// Currently SHA-384/512 has a 128-byte block size and that's the largest
// supported by TLS.)
#define MAX_HASH_BLOCK_SIZE 128
int EVP_tls_cbc_remove_padding(crypto_word_t *out_padding_ok, size_t *out_len,
const uint8_t *in, size_t in_len,
size_t block_size, size_t mac_size) {
const size_t overhead = 1 /* padding length byte */ + mac_size;
// These lengths are all public so we can test them in non-constant time.
if (overhead > in_len) {
return 0;
}
size_t padding_length = in[in_len - 1];
crypto_word_t good = constant_time_ge_w(in_len, overhead + padding_length);
// The padding consists of a length byte at the end of the record and
// then that many bytes of padding, all with the same value as the
// length byte. Thus, with the length byte included, there are i+1
// bytes of padding.
//
// We can't check just |padding_length+1| bytes because that leaks
// decrypted information. Therefore we always have to check the maximum
// amount of padding possible. (Again, the length of the record is
// public information so we can use it.)
size_t to_check = 256; // maximum amount of padding, inc length byte.
if (to_check > in_len) {
to_check = in_len;
}
for (size_t i = 0; i < to_check; i++) {
uint8_t mask = constant_time_ge_8(padding_length, i);
uint8_t b = in[in_len - 1 - i];
// The final |padding_length+1| bytes should all have the value
// |padding_length|. Therefore the XOR should be zero.
good &= ~(mask & (padding_length ^ b));
}
// If any of the final |padding_length+1| bytes had the wrong value,
// one or more of the lower eight bits of |good| will be cleared.
good = constant_time_eq_w(0xff, good & 0xff);
// Always treat |padding_length| as zero on error. If, assuming block size of
// 16, a padding of [<15 arbitrary bytes> 15] treated |padding_length| as 16
// and returned -1, distinguishing good MAC and bad padding from bad MAC and
// bad padding would give POODLE's padding oracle.
padding_length = good & (padding_length + 1);
*out_len = in_len - padding_length;
*out_padding_ok = good;
return 1;
}
void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
size_t in_len, size_t orig_len) {
uint8_t rotated_mac1[EVP_MAX_MD_SIZE], rotated_mac2[EVP_MAX_MD_SIZE];
uint8_t *rotated_mac = rotated_mac1;
uint8_t *rotated_mac_tmp = rotated_mac2;
// mac_end is the index of |in| just after the end of the MAC.
size_t mac_end = in_len;
size_t mac_start = mac_end - md_size;
assert(orig_len >= in_len);
assert(in_len >= md_size);
assert(md_size <= EVP_MAX_MD_SIZE);
// scan_start contains the number of bytes that we can ignore because
// the MAC's position can only vary by 255 bytes.
size_t scan_start = 0;
// This information is public so it's safe to branch based on it.
if (orig_len > md_size + 255 + 1) {
scan_start = orig_len - (md_size + 255 + 1);
}
size_t rotate_offset = 0;
uint8_t mac_started = 0;
OPENSSL_memset(rotated_mac, 0, md_size);
for (size_t i = scan_start, j = 0; i < orig_len; i++, j++) {
if (j >= md_size) {
j -= md_size;
}
crypto_word_t is_mac_start = constant_time_eq_w(i, mac_start);
mac_started |= is_mac_start;
uint8_t mac_ended = constant_time_ge_8(i, mac_end);
rotated_mac[j] |= in[i] & mac_started & ~mac_ended;
// Save the offset that |mac_start| is mapped to.
rotate_offset |= j & is_mac_start;
}
// Now rotate the MAC. We rotate in log(md_size) steps, one for each bit
// position.
for (size_t offset = 1; offset < md_size; offset <<= 1, rotate_offset >>= 1) {
// Rotate by |offset| iff the corresponding bit is set in
// |rotate_offset|, placing the result in |rotated_mac_tmp|.
const uint8_t skip_rotate = (rotate_offset & 1) - 1;
for (size_t i = 0, j = offset; i < md_size; i++, j++) {
if (j >= md_size) {
j -= md_size;
}
rotated_mac_tmp[i] =
constant_time_select_8(skip_rotate, rotated_mac[i], rotated_mac[j]);
}
// Swap pointers so |rotated_mac| contains the (possibly) rotated value.
// Note the number of iterations and thus the identity of these pointers is
// public information.
uint8_t *tmp = rotated_mac;
rotated_mac = rotated_mac_tmp;
rotated_mac_tmp = tmp;
}
OPENSSL_memcpy(out, rotated_mac, md_size);
}
// u32toBE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
// big-endian order. The value of p is advanced by four.
#define u32toBE(n, p) \
do { \
*((p)++) = (uint8_t)((n) >> 24); \
*((p)++) = (uint8_t)((n) >> 16); \
*((p)++) = (uint8_t)((n) >> 8); \
*((p)++) = (uint8_t)((n)); \
} while (0)
// u64toBE serialises an unsigned, 64-bit number (n) as eight bytes at (p) in
// big-endian order. The value of p is advanced by eight.
#define u64toBE(n, p) \
do { \
*((p)++) = (uint8_t)((n) >> 56); \
*((p)++) = (uint8_t)((n) >> 48); \
*((p)++) = (uint8_t)((n) >> 40); \
*((p)++) = (uint8_t)((n) >> 32); \
*((p)++) = (uint8_t)((n) >> 24); \
*((p)++) = (uint8_t)((n) >> 16); \
*((p)++) = (uint8_t)((n) >> 8); \
*((p)++) = (uint8_t)((n)); \
} while (0)
typedef union {
SHA_CTX sha1;
SHA256_CTX sha256;
SHA512_CTX sha512;
} HASH_CTX;
static void tls1_sha1_transform(HASH_CTX *ctx, const uint8_t *block) {
SHA1_Transform(&ctx->sha1, block);
}
static void tls1_sha256_transform(HASH_CTX *ctx, const uint8_t *block) {
SHA256_Transform(&ctx->sha256, block);
}
static void tls1_sha512_transform(HASH_CTX *ctx, const uint8_t *block) {
SHA512_Transform(&ctx->sha512, block);
}
// These functions serialize the state of a hash and thus perform the standard
// "final" operation without adding the padding and length that such a function
// typically does.
static void tls1_sha1_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
SHA_CTX *sha1 = &ctx->sha1;
u32toBE(sha1->h[0], md_out);
u32toBE(sha1->h[1], md_out);
u32toBE(sha1->h[2], md_out);
u32toBE(sha1->h[3], md_out);
u32toBE(sha1->h[4], md_out);
}
static void tls1_sha256_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
SHA256_CTX *sha256 = &ctx->sha256;
for (unsigned i = 0; i < 8; i++) {
u32toBE(sha256->h[i], md_out);
}
}
static void tls1_sha512_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
SHA512_CTX *sha512 = &ctx->sha512;
for (unsigned i = 0; i < 8; i++) {
u64toBE(sha512->h[i], md_out);
}
}
int EVP_tls_cbc_record_digest_supported(const EVP_MD *md) {
switch (EVP_MD_type(md)) {
case NID_sha1:
case NID_sha256:
case NID_sha384:
return 1;
default:
return 0;
}
}
int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
size_t *md_out_size, const uint8_t header[13],
const uint8_t *data, size_t data_plus_mac_size,
size_t data_plus_mac_plus_padding_size,
const uint8_t *mac_secret,
unsigned mac_secret_length) {
HASH_CTX md_state;
void (*md_final_raw)(HASH_CTX *ctx, uint8_t *md_out);
void (*md_transform)(HASH_CTX *ctx, const uint8_t *block);
unsigned md_size, md_block_size = 64;
// md_length_size is the number of bytes in the length field that terminates
// the hash.
unsigned md_length_size = 8;
// Bound the acceptable input so we can forget about many possible overflows
// later in this function. This is redundant with the record size limits in
// TLS.
if (data_plus_mac_plus_padding_size >= 1024 * 1024) {
assert(0);
return 0;
}
switch (EVP_MD_type(md)) {
case NID_sha1:
SHA1_Init(&md_state.sha1);
md_final_raw = tls1_sha1_final_raw;
md_transform = tls1_sha1_transform;
md_size = SHA_DIGEST_LENGTH;
break;
case NID_sha256:
SHA256_Init(&md_state.sha256);
md_final_raw = tls1_sha256_final_raw;
md_transform = tls1_sha256_transform;
md_size = SHA256_DIGEST_LENGTH;
break;
case NID_sha384:
SHA384_Init(&md_state.sha512);
md_final_raw = tls1_sha512_final_raw;
md_transform = tls1_sha512_transform;
md_size = SHA384_DIGEST_LENGTH;
md_block_size = 128;
md_length_size = 16;
break;
default:
// EVP_tls_cbc_record_digest_supported should have been called first to
// check that the hash function is supported.
assert(0);
*md_out_size = 0;
return 0;
}
assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
assert(md_size <= EVP_MAX_MD_SIZE);
static const size_t kHeaderLength = 13;
// kVarianceBlocks is the number of blocks of the hash that we have to
// calculate in constant time because they could be altered by the
// padding value.
//
// TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
// required to be minimal. Therefore we say that the final six blocks
// can vary based on the padding.
static const size_t kVarianceBlocks = 6;
// From now on we're dealing with the MAC, which conceptually has 13
// bytes of `header' before the start of the data.
size_t len = data_plus_mac_plus_padding_size + kHeaderLength;
// max_mac_bytes contains the maximum bytes of bytes in the MAC, including
// |header|, assuming that there's no padding.
size_t max_mac_bytes = len - md_size - 1;
// num_blocks is the maximum number of hash blocks.
size_t num_blocks =
(max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
// In order to calculate the MAC in constant time we have to handle
// the final blocks specially because the padding value could cause the
// end to appear somewhere in the final |kVarianceBlocks| blocks and we
// can't leak where. However, |num_starting_blocks| worth of data can
// be hashed right away because no padding value can affect whether
// they are plaintext.
size_t num_starting_blocks = 0;
// k is the starting byte offset into the conceptual header||data where
// we start processing.
size_t k = 0;
// mac_end_offset is the index just past the end of the data to be
// MACed.
size_t mac_end_offset = data_plus_mac_size + kHeaderLength - md_size;
// c is the index of the 0x80 byte in the final hash block that
// contains application data.
size_t c = mac_end_offset % md_block_size;
// index_a is the hash block number that contains the 0x80 terminating
// value.
size_t index_a = mac_end_offset / md_block_size;
// index_b is the hash block number that contains the 64-bit hash
// length, in bits.
size_t index_b = (mac_end_offset + md_length_size) / md_block_size;
if (num_blocks > kVarianceBlocks) {
num_starting_blocks = num_blocks - kVarianceBlocks;
k = md_block_size * num_starting_blocks;
}
// bits is the hash-length in bits. It includes the additional hash
// block for the masked HMAC key.
size_t bits = 8 * mac_end_offset; // at most 18 bits to represent
// Compute the initial HMAC block.
bits += 8 * md_block_size;
// hmac_pad is the masked HMAC key.
uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
OPENSSL_memset(hmac_pad, 0, md_block_size);
assert(mac_secret_length <= sizeof(hmac_pad));
OPENSSL_memcpy(hmac_pad, mac_secret, mac_secret_length);
for (size_t i = 0; i < md_block_size; i++) {
hmac_pad[i] ^= 0x36;
}
md_transform(&md_state, hmac_pad);
// The length check means |bits| fits in four bytes.
uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
OPENSSL_memset(length_bytes, 0, md_length_size - 4);
length_bytes[md_length_size - 4] = (uint8_t)(bits >> 24);
length_bytes[md_length_size - 3] = (uint8_t)(bits >> 16);
length_bytes[md_length_size - 2] = (uint8_t)(bits >> 8);
length_bytes[md_length_size - 1] = (uint8_t)bits;
if (k > 0) {
// k is a multiple of md_block_size.
uint8_t first_block[MAX_HASH_BLOCK_SIZE];
OPENSSL_memcpy(first_block, header, 13);
OPENSSL_memcpy(first_block + 13, data, md_block_size - 13);
md_transform(&md_state, first_block);
for (size_t i = 1; i < k / md_block_size; i++) {
md_transform(&md_state, data + md_block_size * i - 13);
}
}
uint8_t mac_out[EVP_MAX_MD_SIZE];
OPENSSL_memset(mac_out, 0, sizeof(mac_out));
// We now process the final hash blocks. For each block, we construct
// it in constant time. If the |i==index_a| then we'll include the 0x80
// bytes and zero pad etc. For each block we selectively copy it, in
// constant time, to |mac_out|.
for (size_t i = num_starting_blocks;
i <= num_starting_blocks + kVarianceBlocks; i++) {
uint8_t block[MAX_HASH_BLOCK_SIZE];
uint8_t is_block_a = constant_time_eq_8(i, index_a);
uint8_t is_block_b = constant_time_eq_8(i, index_b);
for (size_t j = 0; j < md_block_size; j++) {
uint8_t b = 0;
if (k < kHeaderLength) {
b = header[k];
} else if (k < data_plus_mac_plus_padding_size + kHeaderLength) {
b = data[k - kHeaderLength];
}
k++;
uint8_t is_past_c = is_block_a & constant_time_ge_8(j, c);
uint8_t is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
// If this is the block containing the end of the
// application data, and we are at the offset for the
// 0x80 value, then overwrite b with 0x80.
b = constant_time_select_8(is_past_c, 0x80, b);
// If this the the block containing the end of the
// application data and we're past the 0x80 value then
// just write zero.
b = b & ~is_past_cp1;
// If this is index_b (the final block), but not
// index_a (the end of the data), then the 64-bit
// length didn't fit into index_a and we're having to
// add an extra block of zeros.
b &= ~is_block_b | is_block_a;
// The final bytes of one of the blocks contains the
// length.
if (j >= md_block_size - md_length_size) {
// If this is index_b, write a length byte.
b = constant_time_select_8(
is_block_b, length_bytes[j - (md_block_size - md_length_size)], b);
}
block[j] = b;
}
md_transform(&md_state, block);
md_final_raw(&md_state, block);
// If this is index_b, copy the hash value to |mac_out|.
for (size_t j = 0; j < md_size; j++) {
mac_out[j] |= block[j] & is_block_b;
}
}
EVP_MD_CTX md_ctx;
EVP_MD_CTX_init(&md_ctx);
if (!EVP_DigestInit_ex(&md_ctx, md, NULL /* engine */)) {
EVP_MD_CTX_cleanup(&md_ctx);
return 0;
}
// Complete the HMAC in the standard manner.
for (size_t i = 0; i < md_block_size; i++) {
hmac_pad[i] ^= 0x6a;
}
EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
EVP_DigestUpdate(&md_ctx, mac_out, md_size);
unsigned md_out_size_u;
EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
*md_out_size = md_out_size_u;
EVP_MD_CTX_cleanup(&md_ctx);
return 1;
}

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