refs #4904 Remove old apps code
This commit is contained in:
parent
5267f60023
commit
e841a88215
|
@ -1,3 +0,0 @@
|
|||
BaseLibrary
|
||||
Verdnaturaventas/VerdnaturaventasTests
|
||||
Verdnaturaventas/VerdnaturaventasuiTests
|
|
@ -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 */;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:BaseLibrary.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -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>
|
Binary file not shown.
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {}
|
||||
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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))!
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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";
|
|
@ -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";
|
|
@ -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";
|
|
@ -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";
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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.
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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];
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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(©, &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(©, &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(©) != 0) {
|
||||
if (!parse_base128_integer(©, &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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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; }
|
|
@ -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;
|
||||
}
|
|
@ -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; }
|
|
@ -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; }
|
|
@ -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; }
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue