forked from qt-creator/qt-creator
Merge "Merge remote-tracking branch 'origin/4.8' into master"
This commit is contained in:
@@ -37,7 +37,8 @@
|
||||
\title Connecting Android Devices
|
||||
|
||||
You can connect Android devices to the development PC to run, debug,
|
||||
and analyze applications built for them from \QC.
|
||||
and analyze applications built for them from \QC. Devices with Android
|
||||
version 4.1 (API level 16) or later are supported.
|
||||
|
||||
If you have a tool chain for building applications for Android devices
|
||||
installed on the development PC, you can add it to \QC. You can then add a
|
||||
@@ -59,7 +60,10 @@
|
||||
\list
|
||||
|
||||
\li \l{http://www.oracle.com/technetwork/java/javase/downloads/index.html}
|
||||
{Java SE Development Kit (JDK)} version 6, or later
|
||||
{Java SE Development Kit (JDK)} version 6, or later.
|
||||
You can also use \l{http://openjdk.java.net/}{OpenJDK} on Linux.
|
||||
|
||||
\note Android SDK Tools have issues with JDK versions later than 8.
|
||||
|
||||
\li \l{http://www.gradle.org}{Gradle} for building application packages
|
||||
for Android devices (APK). Gradle is delivered with Qt 5.9, and
|
||||
@@ -71,7 +75,7 @@
|
||||
|
||||
\li A tool chain for building applications for Android devices provided
|
||||
by the \l{http://developer.android.com/tools/sdk/ndk/index.html}
|
||||
{Android NDK} from Google.
|
||||
{Android NDK} from Google. The recommended version is 10e.
|
||||
|
||||
\li \l{http://developer.android.com/sdk/index.html}{Android SDK Tools}
|
||||
|
||||
@@ -106,9 +110,12 @@
|
||||
\section1 Setting Up the Development Environment
|
||||
|
||||
You must download and install the latest Android NDK and SDK, and then
|
||||
update or install the tools and packages needed for development. The SDK
|
||||
tool used to update and install the other SDK tools and packages depends on
|
||||
the Android SDK Tools version that you have installed:
|
||||
update or install the tools and packages needed for development. However,
|
||||
if your Qt version is earlier than v5.9, use the SDK tools package v25.2.5
|
||||
or earlier.
|
||||
|
||||
The SDK tool used to update and install the other SDK tools and packages
|
||||
depends on the Android SDK Tools version that you have installed:
|
||||
|
||||
\list
|
||||
|
||||
@@ -135,6 +142,10 @@
|
||||
|
||||
In addition, you must install Qt for Android as part of Qt 5.2, or later.
|
||||
|
||||
\note You can build a 64-bit version of Qt for Android yourself. However,
|
||||
for such a Qt version, the minimum required Android version on devices
|
||||
is 5.0 (API level 21).
|
||||
|
||||
For more information, see \l{Qt for Android}.
|
||||
|
||||
\section2 Specifying Android Device Settings
|
||||
@@ -287,22 +298,11 @@
|
||||
|
||||
\section1 Debugging on Android Devices
|
||||
|
||||
Android devices support debugging multi-thread applications in version
|
||||
2.2.1 and later. If you use AVD, select Android 2.3, or later. For more
|
||||
information, see the Android documentation.
|
||||
|
||||
In addition, debugging is supported at android-10 API level, or higher. In
|
||||
the run settings for the project, in the \uicontrol {Android build SDK} field,
|
||||
select android-10, or higher. For more information about Android API levels,
|
||||
see \l{http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels}
|
||||
{What is API Level?}.
|
||||
|
||||
\note Select a \l{glossary-build-config}{debug build configuration} to build
|
||||
Select a \l{glossary-build-config}{debug build configuration} to build
|
||||
the application for debugging.
|
||||
|
||||
\note \QC cannot debug applications on Android devices if Android Studio is
|
||||
running. If the following message is displayed in the \uicontrol Output
|
||||
pane, close Android Studio and try again: \e {Ignoring second debugger -
|
||||
accepting and dropping.}
|
||||
|
||||
*/
|
||||
|
@@ -60,7 +60,7 @@
|
||||
first-letter case-sensitivity, select \uicontrol Full or
|
||||
\uicontrol {First Letter} in the \uicontrol {Case-sensitivity} field.
|
||||
|
||||
\section2 Summary of Available Types
|
||||
\section1 Summary of Available Types
|
||||
|
||||
The following table lists available types for code completion and icon used
|
||||
for each.
|
||||
@@ -132,7 +132,7 @@
|
||||
\endif
|
||||
\endtable
|
||||
|
||||
\section2 Completing Code Snippets
|
||||
\section1 Completing Code Snippets
|
||||
|
||||
Code snippets can consist of multiple variables that you specify values for.
|
||||
Select an item in the list and press \key Tab or \key Enter to complete the
|
||||
@@ -189,7 +189,7 @@
|
||||
|
||||
\endlist
|
||||
|
||||
\section3 Adding and Editing Snippets
|
||||
\section2 Adding and Editing Snippets
|
||||
|
||||
Select a snippet in the list to edit it in the snippet editor. To add a new
|
||||
snippet, select \uicontrol Add. Specify a trigger and, if the trigger is
|
||||
@@ -268,7 +268,7 @@
|
||||
To discard the changes you made to a built-in snippet, select
|
||||
\uicontrol {Revert Built-in}.
|
||||
|
||||
\section3 Removing Snippets
|
||||
\section2 Removing Snippets
|
||||
|
||||
Several similar built-in snippets might be provided for different use cases.
|
||||
To make the list of suggestions shorter when you write code, remove the
|
||||
@@ -279,7 +279,7 @@
|
||||
\uicontrol Remove. To restore the removed snippets, select
|
||||
\uicontrol {Restore Removed Built-ins}.
|
||||
|
||||
\section3 Resetting Snippets
|
||||
\section2 Resetting Snippets
|
||||
|
||||
To remove all added snippets and to restore all removed snippets, select
|
||||
\uicontrol {Reset All}.
|
||||
|
@@ -56,8 +56,9 @@
|
||||
This is totally transparent to users. As Qt is composed of libraries
|
||||
referencing each other, Qt 4 applications are only supported on
|
||||
Android version 1.6, or later, and Qt 5 applications on version
|
||||
2.3.3, or later. You must install a Qt version targeting Android and
|
||||
the Android SDK and NDK to develop for Android devices.
|
||||
4.1 (API level 16), or later. You must install a Qt version
|
||||
targeting Android and the Android SDK and NDK to develop for
|
||||
Android devices.
|
||||
|
||||
\if defined(qtcreator)
|
||||
\li \l{Connecting Bare Metal Devices}
|
||||
|
@@ -4,16 +4,16 @@ import qbs.FileInfo
|
||||
import "qtc.js" as HelperFunctions
|
||||
|
||||
Module {
|
||||
property string qtcreator_display_version: '4.8.0-beta1'
|
||||
property string qtcreator_display_version: '4.8.0-beta2'
|
||||
property string ide_version_major: '4'
|
||||
property string ide_version_minor: '7'
|
||||
property string ide_version_release: '82'
|
||||
property string ide_version_release: '83'
|
||||
property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.'
|
||||
+ ide_version_release
|
||||
|
||||
property string ide_compat_version_major: '4'
|
||||
property string ide_compat_version_minor: '7'
|
||||
property string ide_compat_version_release: '82'
|
||||
property string ide_compat_version_release: '83'
|
||||
property string qtcreator_compat_version: ide_compat_version_major + '.'
|
||||
+ ide_compat_version_minor + '.' + ide_compat_version_release
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
!isEmpty(QTCREATOR_PRI_INCLUDED):error("qtcreator.pri already included")
|
||||
QTCREATOR_PRI_INCLUDED = 1
|
||||
|
||||
QTCREATOR_VERSION = 4.7.82
|
||||
QTCREATOR_COMPAT_VERSION = 4.7.82
|
||||
QTCREATOR_VERSION = 4.7.83
|
||||
QTCREATOR_COMPAT_VERSION = 4.7.83
|
||||
VERSION = $$QTCREATOR_VERSION
|
||||
QTCREATOR_DISPLAY_VERSION = 4.8.0-beta1
|
||||
QTCREATOR_DISPLAY_VERSION = 4.8.0-beta2
|
||||
QTCREATOR_COPYRIGHT_YEAR = 2018
|
||||
BINARY_ARTIFACTS_BRANCH = master
|
||||
|
||||
|
@@ -2795,7 +2795,7 @@ def qdump__qfloat16(d, value):
|
||||
elif exp == 0b11111:
|
||||
res = ('-inf' if sign else 'inf') if fraction == 0 else 'nan'
|
||||
else:
|
||||
res = (-1)**sign * (1 + fraction / 2**10) * 2**(exp - 15)
|
||||
res = (-1)**sign * (1 + 1. * fraction / 2**10) * 2**(exp - 15)
|
||||
d.putValue(res)
|
||||
d.putNumChild(1)
|
||||
d.putPlainChildren(value)
|
||||
|
@@ -25,7 +25,9 @@
|
||||
<style name="Function"/>
|
||||
<style name="Keyword" foreground="#45c6d6" italic="true"/>
|
||||
<style name="PrimitiveType" foreground="#d69aa7"/>
|
||||
<style name="Punctuation"/>
|
||||
<style name="Operator" foreground="#d6bb9a"/>
|
||||
<style name="Overloaded Operator"/>
|
||||
<style name="Preprocessor" foreground="#ff6aad"/>
|
||||
<style name="Label" foreground="#d6c540"/>
|
||||
<style name="Comment" foreground="#a8abb0" italic="true"/>
|
||||
|
@@ -25,7 +25,9 @@
|
||||
<style name="Number" foreground="#ff55ff"/>
|
||||
<style name="Occurrences" background="#363636"/>
|
||||
<style name="Occurrences.Rename" foreground="#ffaaaa" background="#553636"/>
|
||||
<style name="Punctuation"/>
|
||||
<style name="Operator" foreground="#aaaaaa"/>
|
||||
<style name="Overloaded Operator"/>
|
||||
<style name="Parentheses" foreground="#ff5555" background="#333333"/>
|
||||
<style name="ParenthesesMismatch" background="#800080"/>
|
||||
<style name="AutoComplete" foreground="#a0a0ff" background="#333333"/>
|
||||
|
@@ -25,7 +25,9 @@
|
||||
<style name="Function" background="#ffffff"/>
|
||||
<style name="Keyword" foreground="#808000"/>
|
||||
<style name="PrimitiveType" foreground="#808000"/>
|
||||
<style name="Punctuation"/>
|
||||
<style name="Operator"/>
|
||||
<style name="Overloaded Operator" background="#ffffff"/>
|
||||
<style name="Preprocessor" foreground="#000080"/>
|
||||
<style name="Label" foreground="#800000"/>
|
||||
<style name="Comment" foreground="#008000"/>
|
||||
|
@@ -22,7 +22,9 @@
|
||||
<style name="Link" foreground="#0000ff"/>
|
||||
<style name="Local"/>
|
||||
<style name="Number" foreground="#3f3f3f"/>
|
||||
<style name="Punctuation"/>
|
||||
<style name="Operator"/>
|
||||
<style name="Overloaded Operator"/>
|
||||
<style name="Parentheses" background="#e3e3e3" bold="true"/>
|
||||
<style name="ParenthesesMismatch" background="#808080"/>
|
||||
<style name="AutoComplete" foreground="#303030" background="#d0d0d0"/>
|
||||
|
@@ -31,7 +31,9 @@
|
||||
<style name="Occurrences" foreground="#000000" background="#616161"/>
|
||||
<style name="Occurrences.Rename" foreground="#000000" background="#ff6464"/>
|
||||
<style name="Occurrences.Unused" foreground="#808000"/>
|
||||
<style name="Punctuation"/>
|
||||
<style name="Operator" foreground="#cfbfad"/>
|
||||
<style name="Overloaded Operator"/>
|
||||
<style name="Parentheses" foreground="#ffff00" background="#4e4e8f"/>
|
||||
<style name="ParenthesesMismatch" background="#404040"/>
|
||||
<style name="AutoComplete" foreground="#ffff00" background="#4e4e8f"/>
|
||||
|
@@ -15,6 +15,7 @@
|
||||
<style name="Local" foreground="#000000"/>
|
||||
<style name="Number" foreground="#0000ff"/>
|
||||
<style name="Operator" foreground="#000000"/>
|
||||
<style name="Overloaded Operator" foreground="#000000"/>
|
||||
<style name="Parentheses" foreground="#ff0000" background="#c3e1ff"/>
|
||||
<style name="ParenthesesMismatch" background="#ff00ff"/>
|
||||
<style name="AutoComplete" foreground="#ff0000" background="#c3e1ff"/>
|
||||
|
@@ -31,7 +31,9 @@
|
||||
<style name="Function"/>
|
||||
<style name="Keyword" foreground="#78d7ec" italic="true"/>
|
||||
<style name="PrimitiveType" foreground="#ff8080"/>
|
||||
<style name="Punctuation"/>
|
||||
<style name="Operator" foreground="#a6e22e"/>
|
||||
<style name="Overloaded Operator"/>
|
||||
<style name="Preprocessor" foreground="#f92672"/>
|
||||
<style name="Label" foreground="#ffff55"/>
|
||||
<style name="Comment" foreground="#75715e" italic="true"/>
|
||||
|
@@ -31,7 +31,9 @@
|
||||
<style name="Function" foreground="#839496"/>
|
||||
<style name="Keyword" foreground="#709d06"/>
|
||||
<style name="PrimitiveType" foreground="#808000"/>
|
||||
<style name="Punctuation"/>
|
||||
<style name="Operator" foreground="#839496"/>
|
||||
<style name="Overloaded Operator" foreground="#839496"/>
|
||||
<style name="Preprocessor" foreground="#cb4b16"/>
|
||||
<style name="Label" foreground="#268bd2" bold="true"/>
|
||||
<style name="Comment" foreground="#586e75" italic="true"/>
|
||||
|
@@ -31,7 +31,9 @@
|
||||
<style name="Function" foreground="#657b83"/>
|
||||
<style name="Keyword" foreground="#709d06"/>
|
||||
<style name="PrimitiveType" foreground="#808000"/>
|
||||
<style name="Punctuation"/>
|
||||
<style name="Operator" foreground="#657b83"/>
|
||||
<style name="Overloaded Operator" foreground="#657b83"/>
|
||||
<style name="Preprocessor" foreground="#cb4b16"/>
|
||||
<style name="Label" foreground="#268bd2" bold="true"/>
|
||||
<style name="Comment" foreground="#93a1a1" italic="true"/>
|
||||
|
@@ -1757,6 +1757,10 @@ Install an SDK of at least API version %1.</source>
|
||||
<source>Alt+Shift+T,Alt+A</source>
|
||||
<translation>Alt+Shift+T,Alt+A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ctrl+Meta+T, Ctrl+Meta+A</source>
|
||||
<translation>Ctrl+Meta+T, Ctrl+Meta+A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Run Selected Tests</source>
|
||||
<translation>&Запустить выбранные</translation>
|
||||
@@ -1769,6 +1773,10 @@ Install an SDK of at least API version %1.</source>
|
||||
<source>Alt+Shift+T,Alt+R</source>
|
||||
<translation>Alt+Shift+T,Alt+R</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ctrl+Meta+T, Ctrl+Meta+R</source>
|
||||
<translation>Ctrl+Meta+T, Ctrl+Meta+R</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Run Tests for Current &File</source>
|
||||
<translation>Запустить тесты для текущего &файла</translation>
|
||||
@@ -1781,6 +1789,10 @@ Install an SDK of at least API version %1.</source>
|
||||
<source>Alt+Shift+T,Alt+F</source>
|
||||
<translation>Alt+Shift+T,Alt+F</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ctrl+Meta+T, Ctrl+Meta+F</source>
|
||||
<translation>Ctrl+Meta+T, Ctrl+Meta+F</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Re&scan Tests</source>
|
||||
<translation>&Пересканировать</translation>
|
||||
@@ -1789,6 +1801,10 @@ Install an SDK of at least API version %1.</source>
|
||||
<source>Alt+Shift+T,Alt+S</source>
|
||||
<translation>Alt+Shift+T,Alt+S</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ctrl+Meta+T, Ctrl+Meta+S</source>
|
||||
<translation>Ctrl+Meta+T, Ctrl+Meta+S</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Run Test Under Cursor</source>
|
||||
<translation>&Запустить тест под курсором</translation>
|
||||
@@ -11195,7 +11211,7 @@ Flags: %3</source>
|
||||
<name>CppTools::TidyChecksTreeModel</name>
|
||||
<message>
|
||||
<source>Web Page</source>
|
||||
<translation>Вэб-страница</translation>
|
||||
<translation>Веб-страница</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@@ -13312,7 +13328,7 @@ Affected are breakpoints %1</source>
|
||||
</message>
|
||||
<message>
|
||||
<source>Start Debugging Without Deployment</source>
|
||||
<translation>Начать отладку с установкой</translation>
|
||||
<translation>Начать отладку без установки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Start and Debug External Application...</source>
|
||||
@@ -26820,6 +26836,10 @@ to project "%2".</source>
|
||||
<source>Alt+Shift+L</source>
|
||||
<translation>Alt+Shift+L</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Meta+Shift+L</source>
|
||||
<translation>Meta+Shift+L</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide Empty Directories</source>
|
||||
<translation>Скрывать пустые каталоги</translation>
|
||||
@@ -36383,7 +36403,7 @@ For more details, see /etc/sysctl.d/10-ptrace.conf
|
||||
</message>
|
||||
<message>
|
||||
<source>Classes for displaying and editing Web content</source>
|
||||
<translation>Классы для отображения и правки вэб-страниц</translation>
|
||||
<translation>Классы для отображения и правки веб-страниц</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WebKit1 and QWidget-based classes from Qt 4 (Qt 5)</source>
|
||||
@@ -45318,6 +45338,10 @@ should a repository require SSH-authentication (see documentation on SSH and the
|
||||
<source>No executable to deploy found in %1.</source>
|
||||
<translation>В %1 не обнаружен исполняемый файл для установки.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot find windeployqt.exe in "%1".</source>
|
||||
<translation>Не удалось найти windeployqt.exe в «%1».</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot parse manifest file %1.</source>
|
||||
<translation>Не удалось разобрать файл манифеста %1.</translation>
|
||||
|
138
src/libs/3rdparty/botan/configure.py
vendored
138
src/libs/3rdparty/botan/configure.py
vendored
@@ -276,7 +276,7 @@ class BuildPaths(object): # pylint: disable=too-many-instance-attributes
|
||||
else:
|
||||
raise InternalError("Unknown src info type '%s'" % (typ))
|
||||
|
||||
def process_command_line(args): # pylint: disable=too-many-locals
|
||||
def process_command_line(args): # pylint: disable=too-many-locals,too-many-statements
|
||||
"""
|
||||
Handle command line options
|
||||
Do not use logging in this method as command line options need to be
|
||||
@@ -469,6 +469,9 @@ def process_command_line(args): # pylint: disable=too-many-locals
|
||||
build_group.add_option('--with-debug-asserts', action='store_true', default=False,
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
|
||||
build_group.add_option('--ack-vc2013-deprecated', action='store_true', default=False,
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
|
||||
docs_group = optparse.OptionGroup(parser, 'Documentation Options')
|
||||
|
||||
docs_group.add_option('--with-documentation', action='store_true',
|
||||
@@ -520,7 +523,7 @@ def process_command_line(args): # pylint: disable=too-many-locals
|
||||
help='minimize build')
|
||||
|
||||
# Should be derived from info.txt but this runs too early
|
||||
third_party = ['bearssl', 'boost', 'bzip2', 'lzma', 'openssl', 'sqlite3', 'zlib', 'tpm']
|
||||
third_party = ['bearssl', 'boost', 'bzip2', 'lzma', 'openssl', 'commoncrypto', 'sqlite3', 'zlib', 'tpm']
|
||||
|
||||
for mod in third_party:
|
||||
mods_group.add_option('--with-%s' % (mod),
|
||||
@@ -754,6 +757,7 @@ class ModuleInfo(InfoObject):
|
||||
"""
|
||||
|
||||
def __init__(self, infofile):
|
||||
# pylint: disable=too-many-statements
|
||||
super(ModuleInfo, self).__init__(infofile)
|
||||
lex = lex_me_harder(
|
||||
infofile,
|
||||
@@ -850,7 +854,7 @@ class ModuleInfo(InfoObject):
|
||||
for key, value in defines.items():
|
||||
if not re.match('^[0-9A-Za-z_]{3,30}$', key):
|
||||
raise InternalError('Module defines key has invalid format: "%s"' % key)
|
||||
if not re.match('^[0-9]{8}$', value):
|
||||
if not re.match('^20[0-9]{6}$', value):
|
||||
raise InternalError('Module defines value has invalid format: "%s"' % value)
|
||||
|
||||
def cross_check(self, arch_info, cc_info, all_os_features):
|
||||
@@ -959,7 +963,7 @@ class ModuleInfo(InfoObject):
|
||||
def dependencies(self, osinfo):
|
||||
# base is an implicit dep for all submodules
|
||||
deps = ['base']
|
||||
if self.parent_module != None:
|
||||
if self.parent_module is not None:
|
||||
deps.append(self.parent_module)
|
||||
|
||||
for req in self.requires:
|
||||
@@ -1173,22 +1177,22 @@ class CompilerInfo(InfoObject): # pylint: disable=too-many-instance-attributes
|
||||
return self.visibility_attribute
|
||||
return ''
|
||||
|
||||
def mach_abi_link_flags(self, options, with_debug_info=None):
|
||||
def mach_abi_link_flags(self, options, debug_mode=None):
|
||||
#pylint: disable=too-many-branches
|
||||
|
||||
"""
|
||||
Return the machine specific ABI flags
|
||||
"""
|
||||
|
||||
if with_debug_info is None:
|
||||
with_debug_info = options.with_debug_info
|
||||
if debug_mode is None:
|
||||
debug_mode = options.debug_mode
|
||||
|
||||
def mach_abi_groups():
|
||||
|
||||
yield 'all'
|
||||
|
||||
if options.msvc_runtime is None:
|
||||
if with_debug_info:
|
||||
if debug_mode:
|
||||
yield 'rt-debug'
|
||||
else:
|
||||
yield 'rt'
|
||||
@@ -1205,7 +1209,7 @@ class CompilerInfo(InfoObject): # pylint: disable=too-many-instance-attributes
|
||||
for what in mach_abi_groups():
|
||||
if what in self.mach_abi_linking:
|
||||
flag = self.mach_abi_linking.get(what)
|
||||
if flag != None and flag != '' and flag not in abi_link:
|
||||
if flag is not None and flag != '' and flag not in abi_link:
|
||||
abi_link.add(flag)
|
||||
|
||||
if options.msvc_runtime:
|
||||
@@ -1418,7 +1422,7 @@ class OsInfo(InfoObject): # pylint: disable=too-many-instance-attributes
|
||||
return False
|
||||
|
||||
def building_shared_supported(self):
|
||||
return self.soname_pattern_base != None
|
||||
return self.soname_pattern_base is not None
|
||||
|
||||
def enabled_features(self, options):
|
||||
feats = []
|
||||
@@ -1466,7 +1470,7 @@ def guess_processor(archinfo):
|
||||
for info_part in system_cpu_info():
|
||||
if info_part:
|
||||
match = canon_processor(archinfo, info_part)
|
||||
if match != None:
|
||||
if match is not None:
|
||||
logging.debug("Matched '%s' to processor '%s'" % (info_part, match))
|
||||
return match, info_part
|
||||
else:
|
||||
@@ -1727,13 +1731,13 @@ def create_template_vars(source_paths, build_paths, options, modules, cc, arch,
|
||||
"""
|
||||
Figure out what external libraries/frameworks are needed based on selected modules
|
||||
"""
|
||||
if not (module_member_name == 'libs' or module_member_name == 'frameworks'):
|
||||
if module_member_name not in ['libs', 'frameworks']:
|
||||
raise InternalError("Invalid argument")
|
||||
|
||||
libs = set()
|
||||
for module in modules:
|
||||
for (osname, module_link_to) in getattr(module, module_member_name).items():
|
||||
if osname == 'all' or osname == osinfo.basename:
|
||||
if osname in ['all', osinfo.basename]:
|
||||
libs |= set(module_link_to)
|
||||
else:
|
||||
match = re.match('^all!(.*)', osname)
|
||||
@@ -1787,7 +1791,7 @@ def create_template_vars(source_paths, build_paths, options, modules, cc, arch,
|
||||
return osinfo.ar_command
|
||||
|
||||
def choose_endian(arch_info, options):
|
||||
if options.with_endian != None:
|
||||
if options.with_endian is not None:
|
||||
return options.with_endian
|
||||
|
||||
if options.cpu.endswith('eb') or options.cpu.endswith('be'):
|
||||
@@ -1795,6 +1799,7 @@ def create_template_vars(source_paths, build_paths, options, modules, cc, arch,
|
||||
elif options.cpu.endswith('el') or options.cpu.endswith('le'):
|
||||
return 'little'
|
||||
|
||||
if arch_info.endian:
|
||||
logging.info('Defaulting to assuming %s endian', arch_info.endian)
|
||||
return arch_info.endian
|
||||
|
||||
@@ -1863,6 +1868,7 @@ def create_template_vars(source_paths, build_paths, options, modules, cc, arch,
|
||||
'with_rst2man': options.with_rst2man,
|
||||
'sphinx_config_dir': source_paths.sphinx_config_dir,
|
||||
'with_doxygen': options.with_doxygen,
|
||||
'maintainer_mode': options.maintainer_mode,
|
||||
|
||||
'out_dir': build_dir,
|
||||
'build_dir': build_paths.build_dir,
|
||||
@@ -1968,6 +1974,7 @@ def create_template_vars(source_paths, build_paths, options, modules, cc, arch,
|
||||
'with_openmp': options.with_openmp,
|
||||
'with_debug_asserts': options.with_debug_asserts,
|
||||
'test_mode': options.test_mode,
|
||||
'optimize_for_size': options.optimize_for_size,
|
||||
|
||||
'mod_list': sorted([m.basename for m in modules])
|
||||
}
|
||||
@@ -1980,15 +1987,15 @@ def create_template_vars(source_paths, build_paths, options, modules, cc, arch,
|
||||
variables['static_suffix'])
|
||||
|
||||
if options.build_shared_lib:
|
||||
if osinfo.soname_pattern_base != None:
|
||||
if osinfo.soname_pattern_base is not None:
|
||||
variables['soname_base'] = osinfo.soname_pattern_base.format(**variables)
|
||||
variables['shared_lib_name'] = variables['soname_base']
|
||||
|
||||
if osinfo.soname_pattern_abi != None:
|
||||
if osinfo.soname_pattern_abi is not None:
|
||||
variables['soname_abi'] = osinfo.soname_pattern_abi.format(**variables)
|
||||
variables['shared_lib_name'] = variables['soname_abi']
|
||||
|
||||
if osinfo.soname_pattern_patch != None:
|
||||
if osinfo.soname_pattern_patch is not None:
|
||||
variables['soname_patch'] = osinfo.soname_pattern_patch.format(**variables)
|
||||
|
||||
variables['lib_link_cmd'] = variables['lib_link_cmd'].format(**variables)
|
||||
@@ -2035,15 +2042,15 @@ class ModulesChooser(object):
|
||||
self._modules, self._options.enabled_modules, self._options.disabled_modules)
|
||||
|
||||
def _check_usable(self, module, modname):
|
||||
if not module.compatible_os(self._osinfo, self._options):
|
||||
if not module.compatible_cpu(self._archinfo, self._options):
|
||||
self._not_using_because['incompatible CPU'].add(modname)
|
||||
return False
|
||||
elif not module.compatible_os(self._osinfo, self._options):
|
||||
self._not_using_because['incompatible OS'].add(modname)
|
||||
return False
|
||||
elif not module.compatible_compiler(self._ccinfo, self._cc_min_version, self._archinfo.basename):
|
||||
self._not_using_because['incompatible compiler'].add(modname)
|
||||
return False
|
||||
elif not module.compatible_cpu(self._archinfo, self._options):
|
||||
self._not_using_because['incompatible CPU'].add(modname)
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
@@ -2265,11 +2272,13 @@ def choose_link_method(options):
|
||||
# Symbolic link support on Windows was introduced in Windows 6.0 (Vista) and Python 3.2
|
||||
# Furthermore the SeCreateSymbolicLinkPrivilege is required in order to successfully create symlinks
|
||||
# So only try to use symlinks on Windows if explicitly requested
|
||||
if req == 'symlink' and options.os == 'windows':
|
||||
|
||||
if options.os in ['windows', 'mingw', 'cygwin']:
|
||||
if req == 'symlink':
|
||||
yield 'symlink'
|
||||
# otherwise keep old conservative behavior
|
||||
if 'symlink' in os.__dict__ and options.os != 'windows':
|
||||
elif 'symlink' in os.__dict__:
|
||||
yield 'symlink'
|
||||
|
||||
if 'link' in os.__dict__:
|
||||
yield 'hardlink'
|
||||
yield 'copy'
|
||||
@@ -2352,16 +2361,10 @@ class AmalgamationHeader(object):
|
||||
self.included_already = set()
|
||||
self.all_std_includes = set()
|
||||
|
||||
encoding_kwords = {}
|
||||
if sys.version_info[0] == 3:
|
||||
encoding_kwords['encoding'] = 'utf8'
|
||||
|
||||
self.file_contents = {}
|
||||
for filepath in sorted(input_filepaths):
|
||||
try:
|
||||
with open(filepath, **encoding_kwords) as f:
|
||||
raw_content = f.readlines()
|
||||
contents = AmalgamationGenerator.strip_header_goop(filepath, raw_content)
|
||||
contents = AmalgamationGenerator.read_header(filepath)
|
||||
self.file_contents[os.path.basename(filepath)] = contents
|
||||
except IOError as e:
|
||||
logging.error('Error processing file %s for amalgamation: %s' % (filepath, e))
|
||||
@@ -2438,6 +2441,15 @@ class AmalgamationGenerator(object):
|
||||
|
||||
_header_guard_pattern = re.compile('^#define BOTAN_.*_H_$')
|
||||
|
||||
@staticmethod
|
||||
def read_header(filepath):
|
||||
encoding_kwords = {}
|
||||
if sys.version_info[0] == 3:
|
||||
encoding_kwords['encoding'] = 'utf8'
|
||||
with open(filepath, **encoding_kwords) as f:
|
||||
raw_content = f.readlines()
|
||||
return AmalgamationGenerator.strip_header_goop(filepath, raw_content)
|
||||
|
||||
@staticmethod
|
||||
def strip_header_goop(header_name, header_lines):
|
||||
lines = copy.copy(header_lines) # defensive copy
|
||||
@@ -2505,16 +2517,32 @@ class AmalgamationGenerator(object):
|
||||
logging.info('Writing amalgamation header to %s' % (header_name))
|
||||
pub_header_amalag.write_to_file(header_name, "BOTAN_AMALGAMATION_H_")
|
||||
|
||||
internal_headers = AmalgamationHeader(self._build_paths.internal_headers)
|
||||
isa_headers = {}
|
||||
internal_headers = []
|
||||
|
||||
def known_isa_header(hdr):
|
||||
if hdr == 'simd_avx2.h':
|
||||
return 'avx2'
|
||||
return None
|
||||
|
||||
for hdr in self._build_paths.internal_headers:
|
||||
isa = known_isa_header(os.path.basename(hdr))
|
||||
if isa:
|
||||
isa_headers[isa] = ''.join(AmalgamationGenerator.read_header(hdr))
|
||||
else:
|
||||
internal_headers.append(hdr)
|
||||
|
||||
internal_headers = AmalgamationHeader(internal_headers)
|
||||
header_int_name = '%s_internal.h' % (AmalgamationGenerator.filename_prefix)
|
||||
logging.info('Writing amalgamation header to %s' % (header_int_name))
|
||||
internal_headers.write_to_file(header_int_name, "BOTAN_AMALGAMATION_INTERNAL_H_")
|
||||
|
||||
header_files = [header_name, header_int_name]
|
||||
included_in_headers = pub_header_amalag.all_std_includes | internal_headers.all_std_includes
|
||||
return header_files, included_in_headers
|
||||
return header_files, included_in_headers, isa_headers
|
||||
|
||||
def _generate_sources(self, amalgamation_headers, included_in_headers): #pylint: disable=too-many-locals,too-many-branches
|
||||
def _generate_sources(self, amalgamation_headers, included_in_headers, isa_headers):
|
||||
#pylint: disable=too-many-locals,too-many-branches
|
||||
encoding_kwords = {}
|
||||
if sys.version_info[0] == 3:
|
||||
encoding_kwords['encoding'] = 'utf8'
|
||||
@@ -2533,6 +2561,14 @@ class AmalgamationGenerator(object):
|
||||
logging.info('Writing amalgamation source to %s' % (filepath))
|
||||
amalgamation_files[target] = open(filepath, 'w', **encoding_kwords)
|
||||
|
||||
def gcc_isa(isa):
|
||||
if isa == 'sse41':
|
||||
return 'sse4.1'
|
||||
elif isa == 'sse42':
|
||||
return 'ssse4.2'
|
||||
else:
|
||||
return isa
|
||||
|
||||
for target, f in amalgamation_files.items():
|
||||
AmalgamationHeader.write_banner(f)
|
||||
f.write('\n')
|
||||
@@ -2542,13 +2578,11 @@ class AmalgamationGenerator(object):
|
||||
|
||||
for isa in self._isas_for_target(target):
|
||||
|
||||
if isa == 'sse41':
|
||||
isa = 'sse4.1'
|
||||
elif isa == 'sse42':
|
||||
isa = 'ssse4.2'
|
||||
if isa in isa_headers:
|
||||
f.write(isa_headers[isa])
|
||||
|
||||
f.write('#if defined(__GNUG__) && !defined(__clang__)\n')
|
||||
f.write('#pragma GCC target ("%s")\n' % (isa))
|
||||
f.write('#pragma GCC target ("%s")\n' % (gcc_isa(isa)))
|
||||
f.write('#endif\n')
|
||||
|
||||
# target to include header map
|
||||
@@ -2580,8 +2614,8 @@ class AmalgamationGenerator(object):
|
||||
return set(amalgamation_sources.values())
|
||||
|
||||
def generate(self):
|
||||
amalgamation_headers, included_in_headers = self._generate_headers()
|
||||
amalgamation_sources = self._generate_sources(amalgamation_headers, included_in_headers)
|
||||
amalgamation_headers, included_in_headers, isa_headers = self._generate_headers()
|
||||
amalgamation_sources = self._generate_sources(amalgamation_headers, included_in_headers, isa_headers)
|
||||
return (sorted(amalgamation_sources), sorted(amalgamation_headers))
|
||||
|
||||
|
||||
@@ -2712,7 +2746,7 @@ def set_defaults_for_unset_options(options, info_arch, info_cc): # pylint: disab
|
||||
return 'gcc'
|
||||
return None
|
||||
|
||||
if options.compiler is None and options.compiler_binary != None:
|
||||
if options.compiler is None and options.compiler_binary is not None:
|
||||
options.compiler = deduce_compiler_type_from_cc_bin(options.compiler_binary)
|
||||
|
||||
if options.compiler is None:
|
||||
@@ -2836,7 +2870,7 @@ def validate_options(options, info_os, info_cc, available_module_policies):
|
||||
if options.os != options.cpu:
|
||||
raise UserError('LLVM target requires both CPU and OS be set to llvm')
|
||||
|
||||
if options.build_fuzzers != None:
|
||||
if options.build_fuzzers is not None:
|
||||
if options.build_fuzzers not in ['libfuzzer', 'afl', 'klee', 'test']:
|
||||
raise UserError('Bad value to --build-fuzzers')
|
||||
|
||||
@@ -2932,7 +2966,10 @@ def calculate_cc_min_version(options, ccinfo, source_paths):
|
||||
|
||||
if ccinfo.basename == 'msvc':
|
||||
if major_version == 18:
|
||||
logging.warning('MSVC 2013 support is deprecated and will be removed in a future release')
|
||||
logging.warning('MSVC 2013 support is deprecated, and will be removed in Jan 2019')
|
||||
if not options.ack_vc2013_deprecated:
|
||||
logging.error('Acknowledge this deprecation by adding flag --ack-vc2013-deprecated')
|
||||
|
||||
return cc_version
|
||||
|
||||
def check_compiler_arch(options, ccinfo, archinfo, source_paths):
|
||||
@@ -2941,7 +2978,10 @@ def check_compiler_arch(options, ccinfo, archinfo, source_paths):
|
||||
abi_flags = ccinfo.mach_abi_link_flags(options).split(' ')
|
||||
cc_output = run_compiler_preproc(options, ccinfo, detect_version_source, 'UNKNOWN', abi_flags).lower()
|
||||
|
||||
if cc_output in ['', 'unknown']:
|
||||
if cc_output == '':
|
||||
cc_output = run_compiler_preproc(options, ccinfo, detect_version_source, 'UNKNOWN').lower()
|
||||
|
||||
if cc_output == 'unknown':
|
||||
logging.warning('Unable to detect target architecture via compiler macro checks')
|
||||
return None
|
||||
|
||||
@@ -2954,7 +2994,7 @@ def check_compiler_arch(options, ccinfo, archinfo, source_paths):
|
||||
return cc_output
|
||||
|
||||
def do_io_for_build(cc, arch, osinfo, using_mods, build_paths, source_paths, template_vars, options):
|
||||
# pylint: disable=too-many-locals,too-many-branches
|
||||
# pylint: disable=too-many-locals,too-many-branches,too-many-statements
|
||||
|
||||
try:
|
||||
robust_rmtree(build_paths.build_dir)
|
||||
@@ -3165,10 +3205,8 @@ if __name__ == '__main__':
|
||||
logging.error("""%s
|
||||
An internal error occurred.
|
||||
|
||||
Don't panic, this is probably not your fault!
|
||||
|
||||
Please report the entire output at https://github.com/randombit/botan or email
|
||||
to the mailing list https://lists.randombit.net/mailman/listinfo/botan-devel
|
||||
Don't panic, this is probably not your fault! Please open an issue
|
||||
with the entire output at https://github.com/randombit/botan
|
||||
|
||||
You'll meet friendly people happy to help!""" % traceback.format_exc())
|
||||
|
||||
|
134
src/libs/3rdparty/botan/readme.rst
vendored
134
src/libs/3rdparty/botan/readme.rst
vendored
@@ -1,50 +1,36 @@
|
||||
Botan: Crypto and TLS for C++11
|
||||
Botan: Crypto and TLS for Modern C++
|
||||
========================================
|
||||
|
||||
Botan (Japanese for peony) is a cryptography library written in C++11
|
||||
and released under the permissive `Simplified BSD
|
||||
<https://botan.randombit.net/license.txt>`_ license.
|
||||
Botan (Japanese for peony flower) is a C++ cryptography library released under the
|
||||
permissive `Simplified BSD <https://botan.randombit.net/license.txt>`_ license.
|
||||
|
||||
Botan's goal is to be the best option for cryptography in C++ by offering the
|
||||
tools necessary to implement a range of practical systems, such as TLS/DTLS,
|
||||
tools necessary to implement a range of practical systems, such as TLS protocol,
|
||||
X.509 certificates, modern AEAD ciphers, PKCS#11 and TPM hardware support,
|
||||
password hashing, and post quantum crypto schemes. Botan also has a C89 API
|
||||
specifically designed to be easy to call from other languages. A Python binding
|
||||
using ctypes is included, and several other `language bindings
|
||||
password hashing, and post quantum crypto schemes.
|
||||
See the `documentation <https://botan.randombit.net/manual>`_ for more information.
|
||||
|
||||
A Python binding is included, and several other `language bindings
|
||||
<https://github.com/randombit/botan/wiki/Language-Bindings>`_ are available.
|
||||
Find the full feature list below.
|
||||
|
||||
Development is coordinated on `GitHub <https://github.com/randombit/botan>`_
|
||||
and contributions are welcome (read `doc/contributing.rst` for more info).
|
||||
|
||||
If you need help with a problem, please open an `issue on GitHub
|
||||
<https://github.com/randombit/botan/issues>`_ or email the
|
||||
`botan-devel mailing list
|
||||
<https://lists.randombit.net/mailman/listinfo/botan-devel/>`_.
|
||||
|
||||
New releases are announced on the
|
||||
`botan-announce mailing list
|
||||
and contributions are welcome. If you need help, please open an issue on
|
||||
`GitHub <https://github.com/randombit/botan/issues>`_ or email the
|
||||
`botan-devel mailing list <https://lists.randombit.net/mailman/listinfo/botan-devel/>`_.
|
||||
New releases are announced on the `botan-announce mailing list
|
||||
<https://lists.randombit.net/mailman/listinfo/botan-announce/>`_.
|
||||
If you think you have found a security issue, see the `security page
|
||||
<https://botan.randombit.net/security.html>`_ for contact information.
|
||||
|
||||
If you think you have found a security bug in Botan please contact
|
||||
Jack Lloyd by emailing jack@randombit.net. His PGP public key with
|
||||
fingerprint 4E60C73551AF2188DF0A5A6278E9804357123B60 can can be found
|
||||
in ``doc/pgpkey.txt`` in the distribution,
|
||||
https://keybase.io/jacklloyd, and some public PGP key servers.
|
||||
|
||||
.. highlight:: none
|
||||
|
||||
For all the details on building the library, read the
|
||||
`users manual <https://botan.randombit.net/manual>`_, but basically::
|
||||
|
||||
$ ./configure.py
|
||||
$ make
|
||||
$ ./botan-test
|
||||
...
|
||||
$ make install
|
||||
|
||||
Botan can also be built into a single-file amalgamation for easy inclusion into
|
||||
external build systems, see the manual for details.
|
||||
The latest release is
|
||||
`2.8.0 <https://botan.randombit.net/releases/Botan-2.8.0.tgz>`_
|
||||
`(sig) <https://botan.randombit.net/releases/Botan-2.8.0.tgz.asc>`_,
|
||||
released on 2018-10-01.
|
||||
All releases are signed with a `PGP key <https://botan.randombit.net/pgpkey.txt>`_.
|
||||
See the `release notes <https://botan.randombit.net/news.html>`_ for
|
||||
what is new. Botan is also available through most
|
||||
`distributions <https://github.com/randombit/botan/wiki/Distros>`_
|
||||
such as Fedora, Debian, Arch and Homebrew.
|
||||
|
||||
.. image:: https://travis-ci.org/randombit/botan.svg?branch=master
|
||||
:target: https://travis-ci.org/randombit/botan
|
||||
@@ -66,55 +52,10 @@ external build systems, see the manual for details.
|
||||
:target: https://scan.coverity.com/projects/624
|
||||
:alt: Coverity results
|
||||
|
||||
.. image:: https://sonarcloud.io/api/project_badges/measure?project=botan&metric=ncloc
|
||||
:target: https://sonarcloud.io/dashboard/index/botan
|
||||
:alt: Sonarcloud analysis
|
||||
|
||||
.. image:: https://bestpractices.coreinfrastructure.org/projects/531/badge
|
||||
:target: https://bestpractices.coreinfrastructure.org/projects/531
|
||||
:alt: CII Best Practices statement
|
||||
|
||||
Release Downloads
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See the `release notes <https://botan.randombit.net/news.html>`_ and
|
||||
`security advisories <https://botan.randombit.net/security.html>`_
|
||||
|
||||
All releases are signed with a
|
||||
`PGP key <https://botan.randombit.net/pgpkey.txt>`_::
|
||||
|
||||
pub 2048R/EFBADFBC 2004-10-30
|
||||
Key fingerprint = 621D AF64 11E1 851C 4CF9 A2E1 6211 EBF1 EFBA DFBC
|
||||
uid Botan Distribution Key
|
||||
|
||||
Some `distributions <https://github.com/randombit/botan/wiki/Distros>`_
|
||||
such as Arch, Fedora and Debian include packages for Botan. However
|
||||
these are often out of date; using the latest source release is recommended.
|
||||
|
||||
Current Stable Release
|
||||
----------------------------------------
|
||||
|
||||
Version 2 requires a C++11 compiler; GCC 4.8 and later, Clang 3.8 and later, and
|
||||
MSVC 2015/2017 are regularly tested. New releases of Botan 2 are made on a
|
||||
quarterly basis.
|
||||
|
||||
The latest 2.x release is
|
||||
`2.7.0 <https://botan.randombit.net/releases/Botan-2.7.0.tgz>`_
|
||||
`(sig) <https://botan.randombit.net/releases/Botan-2.7.0.tgz.asc>`_
|
||||
released on 2018-07-02
|
||||
|
||||
Old Release
|
||||
----------------------------------------
|
||||
|
||||
The 1.10 branch is the last version of the library written in C++98. It is no
|
||||
longer supported except for critical security updates (with all support ending
|
||||
in December 2018), and the developers do not recommend its use anymore.
|
||||
|
||||
The latest 1.10 release is
|
||||
`1.10.17 <https://botan.randombit.net/releases/Botan-1.10.17.tgz>`_
|
||||
`(sig) <https://botan.randombit.net/releases/Botan-1.10.17.tgz.asc>`_
|
||||
released on 2017-10-02
|
||||
|
||||
Find Enclosed
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -123,8 +64,8 @@ Transport Layer Security (TLS) Protocol
|
||||
|
||||
* TLS v1.0, v1.1, and v1.2. The broken SSLv3 protocol is no longer supported.
|
||||
* DTLS v1.0 and v1.2 are adaptations of TLS to datagram operation.
|
||||
* Extensions include session tickets, SNI, ALPN, OCSP staple requests (client
|
||||
side only right now), encrypt-then-mac CBC, and extended master secret.
|
||||
* Supported extensions include session tickets, SNI, ALPN, OCSP stapling,
|
||||
encrypt-then-mac CBC, and extended master secret.
|
||||
* Supports authentication using preshared keys (PSK) or passwords (SRP)
|
||||
* Supports record encryption with ChaCha20Poly1305, AES/OCB, AES/GCM, AES/CCM,
|
||||
Camellia/GCM as well as legacy CBC ciphersuites.
|
||||
@@ -144,7 +85,7 @@ Public Key Cryptography
|
||||
|
||||
* RSA signatures and encryption
|
||||
* DH and ECDH key agreement
|
||||
* Signature schemes ECDSA, DSA, Ed25519, ECGDSA, ECKCDSA, SM2, and GOST 34.10-2001
|
||||
* Signature schemes ECDSA, DSA, Ed25519, ECGDSA, ECKCDSA, SM2, GOST 34.10-2001
|
||||
* Post-quantum signature scheme XMSS
|
||||
* Post-quantum key agreement schemes McEliece and NewHope
|
||||
* ElGamal encryption
|
||||
@@ -153,17 +94,15 @@ Public Key Cryptography
|
||||
Ciphers, hashes, MACs, and checksums
|
||||
----------------------------------------
|
||||
|
||||
* Authenticated cipher modes EAX, OCB, GCM, SIV, CCM, and ChaCha20Poly1305
|
||||
* Cipher modes CTR, CBC, XTS, CFB, and OFB
|
||||
* Block ciphers AES, ARIA, Blowfish, Camellia, CAST-128, CAST-256,
|
||||
DES/3DES, GOST 28147, IDEA, KASUMI, Lion, MISTY1, Noekeon, SEED,
|
||||
Serpent, SHACAL2, SM4, Threefish-512, Twofish, XTEA
|
||||
* Stream ciphers ChaCha20, Salsa20/XSalsa20, SHAKE-128, and RC4
|
||||
* Hash functions SHA-1, SHA-2, SHA-3, RIPEMD-160, Skein-512,
|
||||
BLAKE2b, SM3, Tiger, Whirlpool, GOST 34.11, MD5, MD4
|
||||
* Hash function combiners Parallel and Comb4P
|
||||
* Authentication codes HMAC, CMAC, Poly1305, SipHash, GMAC, CBC-MAC, X9.19 DES-MAC
|
||||
* Non-cryptographic checksums Adler32, CRC24, and CRC32
|
||||
* Authenticated cipher modes EAX, OCB, GCM, SIV, CCM, (X)ChaCha20Poly1305
|
||||
* Cipher modes CTR, CBC, XTS, CFB, OFB
|
||||
* Block ciphers AES, ARIA, Blowfish, Camellia, CAST-128, DES/3DES, GOST 28147,
|
||||
IDEA, Lion, Noekeon, SEED, Serpent, SHACAL2, SM4, Threefish-512, Twofish, XTEA
|
||||
* Stream ciphers (X)ChaCha20, (X)Salsa20, SHAKE-128, RC4
|
||||
* Hash functions SHA-1, SHA-2, SHA-3, MD4, MD5, RIPEMD-160, BLAKE2b,
|
||||
Skein-512, SM3, Tiger, Whirlpool, GOST 34.11
|
||||
* Authentication codes HMAC, CMAC, Poly1305, SipHash, GMAC, X9.19 DES-MAC
|
||||
* Non-cryptographic checksums Adler32, CRC24, CRC32
|
||||
|
||||
Other Useful Things
|
||||
----------------------------------------
|
||||
@@ -173,8 +112,7 @@ Other Useful Things
|
||||
* Simple compression API wrapping zlib, bzip2, and lzma libraries
|
||||
* RNG wrappers for system RNG and hardware RNGs
|
||||
* HMAC_DRBG and entropy collection system for userspace RNGs
|
||||
* Password based key derivation functions PBKDF2 and Scrypt
|
||||
* Password hashing function bcrypt and passhash9 (custom PBKDF scheme)
|
||||
* Password hashing schemes PBKDF2, Scrypt, bcrypt
|
||||
* SRP-6a password authenticated key exchange
|
||||
* Key derivation functions including HKDF, KDF2, SP 800-108, SP 800-56A, SP 800-56C
|
||||
* HOTP and TOTP algorithms
|
||||
|
@@ -12,4 +12,8 @@ armv8-a
|
||||
<isa_extensions>
|
||||
neon
|
||||
armv8crypto
|
||||
armv8sm3
|
||||
armv8sm4
|
||||
armv8sha3
|
||||
armv8sha512
|
||||
</isa_extensions>
|
||||
|
@@ -6,6 +6,7 @@ wordsize 64
|
||||
<aliases>
|
||||
powerpc64
|
||||
ppc64le
|
||||
ppc64el
|
||||
</aliases>
|
||||
|
||||
<isa_extensions>
|
||||
|
@@ -1 +1,2 @@
|
||||
family riscv
|
||||
endian little
|
||||
|
@@ -1,2 +1,3 @@
|
||||
family sparc
|
||||
wordsize 64
|
||||
endian big
|
||||
|
@@ -12,6 +12,7 @@ x86pc # for QNX
|
||||
bepc # for Haiku
|
||||
|
||||
i686
|
||||
i586
|
||||
i386
|
||||
</aliases>
|
||||
|
||||
|
@@ -74,7 +74,10 @@ WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = YES
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
|
||||
%{if maintainer_mode}
|
||||
WARN_AS_ERROR = YES
|
||||
%{endif}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
@@ -154,14 +157,17 @@ PREDEFINED = BOTAN_HAS_AES_ARMV8 \
|
||||
BOTAN_HAS_AES_POWER8 \
|
||||
BOTAN_HAS_AES_SSSE3 \
|
||||
BOTAN_HAS_CHACHA_SSE2 \
|
||||
BOTAN_HAS_CHACHA_AVX2 \
|
||||
BOTAN_HAS_IDEA_SSE2 \
|
||||
BOTAN_HAS_NOEKEON_SIMD \
|
||||
BOTAN_HAS_SERPENT_SIMD \
|
||||
BOTAN_HAS_SERPENT_AVX2 \
|
||||
BOTAN_HAS_SHA1_SSE2 \
|
||||
BOTAN_HAS_SHA2_32_X86 \
|
||||
BOTAN_HAS_SHA2_32_X86_BMI2 \
|
||||
BOTAN_HAS_SHACAL2_SIMD \
|
||||
BOTAN_HAS_SHACAL2_X86 \
|
||||
BOTAN_HAS_SM4_ARMV8 \
|
||||
BOTAN_HAS_THREEFISH_512_AVX2 \
|
||||
BOTAN_DEPRECATED(msg)= \
|
||||
BOTAN_PUBLIC_API(maj,min)=
|
||||
|
10
src/libs/3rdparty/botan/src/build-data/buildh.in
vendored
10
src/libs/3rdparty/botan/src/build-data/buildh.in
vendored
@@ -87,6 +87,10 @@
|
||||
#define BOTAN_ENABLE_DEBUG_ASSERTS
|
||||
%{endif}
|
||||
|
||||
%{if optimize_for_size}
|
||||
#define BOTAN_OPTIMIZE_FOR_SIZE
|
||||
%{endif}
|
||||
|
||||
/*
|
||||
* Module availability definitions
|
||||
*/
|
||||
@@ -166,8 +170,8 @@
|
||||
* broken system RNG.
|
||||
*/
|
||||
#define BOTAN_ENTROPY_DEFAULT_SOURCES \
|
||||
{ "rdseed", "rdrand", "darwin_secrandom", "getentropy", \
|
||||
"dev_random", "system_rng", "proc_walk", "system_stats" }
|
||||
{ "rdseed", "rdrand", "getentropy", "dev_random", \
|
||||
"system_rng", "proc_walk", "system_stats" }
|
||||
|
||||
/* Multiplier on a block cipher's native parallelism */
|
||||
#define BOTAN_BLOCK_CIPHER_PAR_MULT 4
|
||||
@@ -176,7 +180,7 @@
|
||||
* These control the RNG used by the system RNG interface
|
||||
*/
|
||||
#define BOTAN_SYSTEM_RNG_DEVICE "/dev/urandom"
|
||||
#define BOTAN_SYSTEM_RNG_POLL_DEVICES { "/dev/urandom", "/dev/random", "/dev/srandom" }
|
||||
#define BOTAN_SYSTEM_RNG_POLL_DEVICES { "/dev/urandom", "/dev/random" }
|
||||
|
||||
/*
|
||||
* This directory will be monitored by ProcWalking_EntropySource and
|
||||
|
@@ -18,7 +18,7 @@ default -> address,undefined
|
||||
|
||||
address -> "-fsanitize=address"
|
||||
undefined -> "-fsanitize=undefined -fno-sanitize-recover=undefined"
|
||||
coverage -> "-fsanitize-coverage=edge,indirect-calls,8bit-counters"
|
||||
coverage -> "-fsanitize-coverage=edge,indirect-calls,trace-pc-guard,trace-cmp,trace-gep"
|
||||
memory -> "-fsanitize=memory"
|
||||
</sanitizers>
|
||||
|
||||
|
@@ -65,6 +65,10 @@ altivec -> "-maltivec"
|
||||
ppccrypto -> "-mcrypto"
|
||||
|
||||
arm64:armv8crypto -> ""
|
||||
arm64:armv8sm3 -> "-march=armv8.2-a+sm4"
|
||||
arm64:armv8sm4 -> "-march=armv8.2-a+sm4"
|
||||
arm64:armv8sha512 -> "-march=armv8.2-a+sha3"
|
||||
arm64:armv8sha3 -> "-march=armv8.2-a+sha3"
|
||||
|
||||
# For Aarch32 -mfpu=neon is required
|
||||
# For Aarch64 NEON is enabled by default
|
||||
|
@@ -23,7 +23,7 @@ debug_info_flags "/Zi /FS"
|
||||
|
||||
preproc_flags "/nologo /EP"
|
||||
|
||||
lang_flags "/EHs /GR"
|
||||
lang_flags "/EHs /GR /D_ENABLE_EXTENDED_ALIGNED_STORAGE"
|
||||
warning_flags "/W4 /wd4250 /wd4251 /wd4275"
|
||||
|
||||
visibility_build_flags "/DBOTAN_DLL=__declspec(dllexport)"
|
||||
@@ -38,7 +38,7 @@ sse2 -> ""
|
||||
ssse3 -> ""
|
||||
sse41 -> ""
|
||||
sse42 -> ""
|
||||
x86_64:avx2 -> ""
|
||||
x86_64:avx2 -> "/arch:AVX"
|
||||
bmi2 -> ""
|
||||
aesni -> ""
|
||||
clmul -> ""
|
||||
|
@@ -5,8 +5,8 @@ binary_name CC
|
||||
optimization_flags "-xO2"
|
||||
|
||||
shared_flags "-KPIC"
|
||||
warning_flags "+w -erroff=truncwarn,wnoretvalue"
|
||||
lang_flags "-std=c++11 +p -features=extensions -D__FUNCTION__=__func__"
|
||||
warning_flags "+w -erroff=truncwarn,wnoretvalue,wlessrestrictedthrow"
|
||||
lang_flags "-std=c++11 +p -features=extensions"
|
||||
|
||||
ar_command CC
|
||||
ar_options "-xar -o"
|
||||
@@ -19,7 +19,7 @@ default -> "$(CXX) -G -h{soname_abi}"
|
||||
# Needed on some Linux distros
|
||||
linux -> "-library=stlport4"
|
||||
|
||||
sparc64 -> "-xarch=v9"
|
||||
sparc64 -> "-m64 -xarch=sparc"
|
||||
x86_64 -> "-m64"
|
||||
</mach_abi_linking>
|
||||
|
||||
|
@@ -57,6 +57,14 @@
|
||||
#elif defined(__s390__)
|
||||
S390
|
||||
|
||||
#elif defined(__riscv)
|
||||
|
||||
#if defined(__LP64__)
|
||||
RISCV64
|
||||
#else
|
||||
RISCV32
|
||||
#endif
|
||||
|
||||
#else
|
||||
UNKNOWN
|
||||
|
||||
|
@@ -54,7 +54,7 @@ distclean:
|
||||
$(PYTHON_EXE) $(SCRIPTS_DIR)/cleanup.py --build-dir="%{build_dir}" --distclean
|
||||
|
||||
install: libs cli docs
|
||||
$(PYTHON_EXE) $(SCRIPTS_DIR)/install.py --prefix=%{prefix} --build-dir="%{build_dir}" --bindir=%{bindir} --libdir=%{libdir} --docdir=%{docdir} --includedir=%{includedir}
|
||||
$(PYTHON_EXE) $(SCRIPTS_DIR)/install.py --prefix="%{prefix}" --build-dir="%{build_dir}" --bindir=%{bindir} --libdir=%{libdir} --docdir=%{docdir} --includedir=%{includedir}
|
||||
|
||||
# Object Files
|
||||
LIBOBJS = %{join lib_objs}
|
||||
|
25
src/libs/3rdparty/botan/src/build-data/oids.txt
vendored
25
src/libs/3rdparty/botan/src/build-data/oids.txt
vendored
@@ -21,6 +21,7 @@
|
||||
1.3.132.1.12 = ECDH
|
||||
|
||||
1.2.156.10197.1.301.1 = SM2_Sig
|
||||
1.2.156.10197.1.301.1 = SM2
|
||||
1.2.156.10197.1.301.2 = SM2_Kex
|
||||
1.2.156.10197.1.301.3 = SM2_Enc
|
||||
|
||||
@@ -40,7 +41,6 @@
|
||||
# Cipher modes
|
||||
1.3.14.3.2.7 = DES/CBC
|
||||
1.2.840.113549.3.7 = TripleDES/CBC
|
||||
1.2.840.113549.3.2 = RC2/CBC
|
||||
1.2.840.113533.7.66.10 = CAST-128/CBC
|
||||
2.16.840.1.101.3.4.1.2 = AES-128/CBC
|
||||
2.16.840.1.101.3.4.1.22 = AES-192/CBC
|
||||
@@ -80,6 +80,21 @@
|
||||
1.3.6.1.4.1.25258.3.2.3 = AES-256/OCB
|
||||
1.3.6.1.4.1.25258.3.2.4 = Serpent/OCB
|
||||
1.3.6.1.4.1.25258.3.2.5 = Twofish/OCB
|
||||
1.3.6.1.4.1.25258.3.2.6 = Camellia-128/OCB
|
||||
1.3.6.1.4.1.25258.3.2.7 = Camellia-192/OCB
|
||||
1.3.6.1.4.1.25258.3.2.8 = Camellia-256/OCB
|
||||
|
||||
1.2.156.10197.1.104.100 = SM4/OCB
|
||||
|
||||
1.3.6.1.4.1.25258.3.4.1 = AES-128/SIV
|
||||
1.3.6.1.4.1.25258.3.4.2 = AES-192/SIV
|
||||
1.3.6.1.4.1.25258.3.4.3 = AES-256/SIV
|
||||
1.3.6.1.4.1.25258.3.4.4 = Serpent/SIV
|
||||
1.3.6.1.4.1.25258.3.4.5 = Twofish/SIV
|
||||
1.3.6.1.4.1.25258.3.4.6 = Camellia-128/SIV
|
||||
1.3.6.1.4.1.25258.3.4.7 = Camellia-192/SIV
|
||||
1.3.6.1.4.1.25258.3.4.8 = Camellia-256/SIV
|
||||
1.3.6.1.4.1.25258.3.4.9 = SM4/SIV
|
||||
|
||||
[hash]
|
||||
# Hash functions
|
||||
@@ -115,11 +130,11 @@
|
||||
1.2.840.113549.2.9 = HMAC(SHA-256)
|
||||
1.2.840.113549.2.10 = HMAC(SHA-384)
|
||||
1.2.840.113549.2.11 = HMAC(SHA-512)
|
||||
1.2.840.113549.2.13 = HMAC(SHA-512-256)
|
||||
|
||||
[keywrap]
|
||||
# Keywrap algorithms
|
||||
1.2.840.113549.1.9.16.3.6 = KeyWrap.TripleDES
|
||||
1.2.840.113549.1.9.16.3.7 = KeyWrap.RC2
|
||||
1.2.840.113533.7.66.15 = KeyWrap.CAST-128
|
||||
2.16.840.1.101.3.4.1.5 = KeyWrap.AES-128
|
||||
2.16.840.1.101.3.4.1.25 = KeyWrap.AES-192
|
||||
@@ -140,6 +155,8 @@
|
||||
1.2.840.113549.1.1.14 = RSA/EMSA3(SHA-224)
|
||||
1.2.840.113549.1.1.16 = RSA/EMSA3(SHA-512-256)
|
||||
1.3.36.3.3.1.2 = RSA/EMSA3(RIPEMD-160)
|
||||
|
||||
1.2.156.10197.1.501 = SM2_Sig/SM3
|
||||
1.2.156.10197.1.504 = RSA/EMSA3(SM3)
|
||||
|
||||
1.2.840.10040.4.3 = DSA/EMSA1(SHA-160)
|
||||
@@ -208,6 +225,7 @@
|
||||
|
||||
[pbe]
|
||||
1.2.840.113549.1.5.12 = PKCS5.PBKDF2
|
||||
1.2.840.113549.1.5.13 = PBES2
|
||||
1.2.840.113549.1.5.13 = PBE-PKCS5v20
|
||||
|
||||
1.3.6.1.4.1.11591.4.11 = Scrypt
|
||||
@@ -258,6 +276,9 @@
|
||||
1.3.6.1.5.5.7.48.2 = PKIX.CertificateAuthorityIssuers
|
||||
|
||||
1.3.6.1.4.1.311.20.2.2 = Microsoft SmartcardLogon
|
||||
1.3.6.1.4.1.311.20.2.3 = Microsoft UPN
|
||||
|
||||
2.16.840.1.113730.1.13 = Certificate Comment
|
||||
|
||||
# ECC param sets
|
||||
[ecc_param]
|
||||
|
@@ -14,8 +14,8 @@ posix1
|
||||
posix_mlock
|
||||
arc4random
|
||||
dev_random
|
||||
security_framework
|
||||
|
||||
commoncrypto
|
||||
sockets
|
||||
threads
|
||||
filesystem
|
||||
|
@@ -10,6 +10,7 @@ posix1
|
||||
posix_mlock
|
||||
arc4random
|
||||
|
||||
commoncrypto
|
||||
sockets
|
||||
threads
|
||||
filesystem
|
||||
|
@@ -10,6 +10,9 @@ proc_fs
|
||||
clock_gettime
|
||||
getauxval
|
||||
|
||||
# not enabled by default as only available in newer kernel/glibc
|
||||
#getrandom
|
||||
|
||||
sockets
|
||||
threads
|
||||
filesystem
|
||||
|
@@ -1,10 +1,10 @@
|
||||
|
||||
release_major = 2
|
||||
release_minor = 7
|
||||
release_minor = 8
|
||||
release_patch = 0
|
||||
release_so_abi_rev = 7
|
||||
release_so_abi_rev = 8
|
||||
|
||||
# These are set by the distribution script
|
||||
release_vc_rev = 'git:5874000d42c338ec95a7ff24cdc0c64e70f967b5'
|
||||
release_datestamp = 20180702
|
||||
release_vc_rev = 'git:a792728e8941b62761052f5e0d288ba13a016c77'
|
||||
release_datestamp = 20181001
|
||||
release_type = 'release'
|
||||
|
@@ -174,7 +174,7 @@ void ASN1_Formatter::decode(std::ostream& output,
|
||||
data.decode(number, ENUMERATED, class_tag);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> rep = BigInt::encode(number, BigInt::Binary);
|
||||
std::vector<uint8_t> rep = BigInt::encode(number);
|
||||
if(rep.empty()) // if zero
|
||||
rep.resize(1);
|
||||
|
||||
|
@@ -262,6 +262,12 @@ std::chrono::system_clock::time_point X509_Time::to_std_timepoint() const
|
||||
return calendar_point(m_year, m_month, m_day, m_hour, m_minute, m_second).to_std_timepoint();
|
||||
}
|
||||
|
||||
uint64_t X509_Time::time_since_epoch() const
|
||||
{
|
||||
auto tp = this->to_std_timepoint();
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two X509_Times for in various ways
|
||||
*/
|
||||
|
@@ -49,6 +49,9 @@ class BOTAN_PUBLIC_API(2,0) X509_Time final : public ASN1_Object
|
||||
/// Returns a STL timepoint object
|
||||
std::chrono::system_clock::time_point to_std_timepoint() const;
|
||||
|
||||
/// Return time since epoch
|
||||
uint64_t time_since_epoch() const;
|
||||
|
||||
private:
|
||||
void set_to(const std::string& t_spec, ASN1_Tag);
|
||||
bool passes_sanity_check() const;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* OID maps
|
||||
*
|
||||
* This file was automatically generated by ./src/scripts/oids.py on 2018-07-01
|
||||
* This file was automatically generated by ./src/scripts/oids.py on 2018-08-23
|
||||
*
|
||||
* All manual edits to this file will be lost. Edit the script
|
||||
* then regenerate this source file.
|
||||
@@ -21,13 +21,15 @@ std::unordered_map<std::string, std::string> OIDS::load_oid2str_map()
|
||||
{ "0.3.4401.5.3.1.9.46", "Camellia-256/GCM" },
|
||||
{ "0.3.4401.5.3.1.9.6", "Camellia-128/GCM" },
|
||||
{ "1.0.14888.3.0.5", "ECKCDSA" },
|
||||
{ "1.2.156.10197.1.104.100", "SM4/OCB" },
|
||||
{ "1.2.156.10197.1.104.2", "SM4/CBC" },
|
||||
{ "1.2.156.10197.1.104.8", "SM4/GCM" },
|
||||
{ "1.2.156.10197.1.301", "sm2p256v1" },
|
||||
{ "1.2.156.10197.1.301.1", "SM2_Sig" },
|
||||
{ "1.2.156.10197.1.301.1", "SM2" },
|
||||
{ "1.2.156.10197.1.301.2", "SM2_Kex" },
|
||||
{ "1.2.156.10197.1.301.3", "SM2_Enc" },
|
||||
{ "1.2.156.10197.1.401", "SM3" },
|
||||
{ "1.2.156.10197.1.501", "SM2_Sig/SM3" },
|
||||
{ "1.2.156.10197.1.504", "RSA/EMSA3(SM3)" },
|
||||
{ "1.2.250.1.223.101.256.1", "frp256v1" },
|
||||
{ "1.2.392.200011.61.1.1.1.2", "Camellia-128/CBC" },
|
||||
@@ -78,7 +80,6 @@ std::unordered_map<std::string, std::string> OIDS::load_oid2str_map()
|
||||
{ "1.2.840.113549.1.9.14", "PKCS9.ExtensionRequest" },
|
||||
{ "1.2.840.113549.1.9.16.3.18", "ChaCha20Poly1305" },
|
||||
{ "1.2.840.113549.1.9.16.3.6", "KeyWrap.TripleDES" },
|
||||
{ "1.2.840.113549.1.9.16.3.7", "KeyWrap.RC2" },
|
||||
{ "1.2.840.113549.1.9.16.3.8", "Compression.Zlib" },
|
||||
{ "1.2.840.113549.1.9.2", "PKCS9.UnstructuredName" },
|
||||
{ "1.2.840.113549.1.9.3", "PKCS9.ContentType" },
|
||||
@@ -86,11 +87,11 @@ std::unordered_map<std::string, std::string> OIDS::load_oid2str_map()
|
||||
{ "1.2.840.113549.1.9.7", "PKCS9.ChallengePassword" },
|
||||
{ "1.2.840.113549.2.10", "HMAC(SHA-384)" },
|
||||
{ "1.2.840.113549.2.11", "HMAC(SHA-512)" },
|
||||
{ "1.2.840.113549.2.13", "HMAC(SHA-512-256)" },
|
||||
{ "1.2.840.113549.2.5", "MD5" },
|
||||
{ "1.2.840.113549.2.7", "HMAC(SHA-160)" },
|
||||
{ "1.2.840.113549.2.8", "HMAC(SHA-224)" },
|
||||
{ "1.2.840.113549.2.9", "HMAC(SHA-256)" },
|
||||
{ "1.2.840.113549.3.2", "RC2/CBC" },
|
||||
{ "1.2.840.113549.3.7", "TripleDES/CBC" },
|
||||
{ "1.3.101.110", "Curve25519" },
|
||||
{ "1.3.101.112", "Ed25519" },
|
||||
@@ -137,10 +138,23 @@ std::unordered_map<std::string, std::string> OIDS::load_oid2str_map()
|
||||
{ "1.3.6.1.4.1.25258.3.2.3", "AES-256/OCB" },
|
||||
{ "1.3.6.1.4.1.25258.3.2.4", "Serpent/OCB" },
|
||||
{ "1.3.6.1.4.1.25258.3.2.5", "Twofish/OCB" },
|
||||
{ "1.3.6.1.4.1.25258.3.2.6", "Camellia-128/OCB" },
|
||||
{ "1.3.6.1.4.1.25258.3.2.7", "Camellia-192/OCB" },
|
||||
{ "1.3.6.1.4.1.25258.3.2.8", "Camellia-256/OCB" },
|
||||
{ "1.3.6.1.4.1.25258.3.3", "Twofish/CBC" },
|
||||
{ "1.3.6.1.4.1.25258.3.4.1", "AES-128/SIV" },
|
||||
{ "1.3.6.1.4.1.25258.3.4.2", "AES-192/SIV" },
|
||||
{ "1.3.6.1.4.1.25258.3.4.3", "AES-256/SIV" },
|
||||
{ "1.3.6.1.4.1.25258.3.4.4", "Serpent/SIV" },
|
||||
{ "1.3.6.1.4.1.25258.3.4.5", "Twofish/SIV" },
|
||||
{ "1.3.6.1.4.1.25258.3.4.6", "Camellia-128/SIV" },
|
||||
{ "1.3.6.1.4.1.25258.3.4.7", "Camellia-192/SIV" },
|
||||
{ "1.3.6.1.4.1.25258.3.4.8", "Camellia-256/SIV" },
|
||||
{ "1.3.6.1.4.1.25258.3.4.9", "SM4/SIV" },
|
||||
{ "1.3.6.1.4.1.3029.1.2.1", "ElGamal" },
|
||||
{ "1.3.6.1.4.1.3029.1.5.1", "OpenPGP.Curve25519" },
|
||||
{ "1.3.6.1.4.1.311.20.2.2", "Microsoft SmartcardLogon" },
|
||||
{ "1.3.6.1.4.1.311.20.2.3", "Microsoft UPN" },
|
||||
{ "1.3.6.1.4.1.8301.3.1.2.9.0.38", "secp521r1" },
|
||||
{ "1.3.6.1.5.5.7.1.1", "PKIX.AuthorityInformationAccess" },
|
||||
{ "1.3.6.1.5.5.7.3.1", "PKIX.ServerAuth" },
|
||||
@@ -195,6 +209,7 @@ std::unordered_map<std::string, std::string> OIDS::load_oid2str_map()
|
||||
{ "2.16.840.1.101.3.4.3.7", "DSA/EMSA1(SHA-3(384))" },
|
||||
{ "2.16.840.1.101.3.4.3.8", "DSA/EMSA1(SHA-3(512))" },
|
||||
{ "2.16.840.1.101.3.4.3.9", "ECDSA/EMSA1(SHA-3(224))" },
|
||||
{ "2.16.840.1.113730.1.13", "Certificate Comment" },
|
||||
{ "2.5.29.14", "X509v3.SubjectKeyIdentifier" },
|
||||
{ "2.5.29.15", "X509v3.KeyUsage" },
|
||||
{ "2.5.29.17", "X509v3.SubjectAlternativeName" },
|
||||
@@ -237,21 +252,31 @@ std::unordered_map<std::string, OID> OIDS::load_str2oid_map()
|
||||
{ "AES-128/CCM", OID({2,16,840,1,101,3,4,1,7}) },
|
||||
{ "AES-128/GCM", OID({2,16,840,1,101,3,4,1,6}) },
|
||||
{ "AES-128/OCB", OID({1,3,6,1,4,1,25258,3,2,1}) },
|
||||
{ "AES-128/SIV", OID({1,3,6,1,4,1,25258,3,4,1}) },
|
||||
{ "AES-192/CBC", OID({2,16,840,1,101,3,4,1,22}) },
|
||||
{ "AES-192/CCM", OID({2,16,840,1,101,3,4,1,27}) },
|
||||
{ "AES-192/GCM", OID({2,16,840,1,101,3,4,1,26}) },
|
||||
{ "AES-192/OCB", OID({1,3,6,1,4,1,25258,3,2,2}) },
|
||||
{ "AES-192/SIV", OID({1,3,6,1,4,1,25258,3,4,2}) },
|
||||
{ "AES-256/CBC", OID({2,16,840,1,101,3,4,1,42}) },
|
||||
{ "AES-256/CCM", OID({2,16,840,1,101,3,4,1,47}) },
|
||||
{ "AES-256/GCM", OID({2,16,840,1,101,3,4,1,46}) },
|
||||
{ "AES-256/OCB", OID({1,3,6,1,4,1,25258,3,2,3}) },
|
||||
{ "AES-256/SIV", OID({1,3,6,1,4,1,25258,3,4,3}) },
|
||||
{ "CAST-128/CBC", OID({1,2,840,113533,7,66,10}) },
|
||||
{ "Camellia-128/CBC", OID({1,2,392,200011,61,1,1,1,2}) },
|
||||
{ "Camellia-128/GCM", OID({0,3,4401,5,3,1,9,6}) },
|
||||
{ "Camellia-128/OCB", OID({1,3,6,1,4,1,25258,3,2,6}) },
|
||||
{ "Camellia-128/SIV", OID({1,3,6,1,4,1,25258,3,4,6}) },
|
||||
{ "Camellia-192/CBC", OID({1,2,392,200011,61,1,1,1,3}) },
|
||||
{ "Camellia-192/GCM", OID({0,3,4401,5,3,1,9,26}) },
|
||||
{ "Camellia-192/OCB", OID({1,3,6,1,4,1,25258,3,2,7}) },
|
||||
{ "Camellia-192/SIV", OID({1,3,6,1,4,1,25258,3,4,7}) },
|
||||
{ "Camellia-256/CBC", OID({1,2,392,200011,61,1,1,1,4}) },
|
||||
{ "Camellia-256/GCM", OID({0,3,4401,5,3,1,9,46}) },
|
||||
{ "Camellia-256/OCB", OID({1,3,6,1,4,1,25258,3,2,8}) },
|
||||
{ "Camellia-256/SIV", OID({1,3,6,1,4,1,25258,3,4,8}) },
|
||||
{ "Certificate Comment", OID({2,16,840,1,113730,1,13}) },
|
||||
{ "ChaCha20Poly1305", OID({1,2,840,113549,1,9,16,3,18}) },
|
||||
{ "Compression.Zlib", OID({1,2,840,113549,1,9,16,3,8}) },
|
||||
{ "Curve25519", OID({1,3,101,110}) },
|
||||
@@ -299,19 +324,21 @@ std::unordered_map<std::string, OID> OIDS::load_str2oid_map()
|
||||
{ "HMAC(SHA-256)", OID({1,2,840,113549,2,9}) },
|
||||
{ "HMAC(SHA-384)", OID({1,2,840,113549,2,10}) },
|
||||
{ "HMAC(SHA-512)", OID({1,2,840,113549,2,11}) },
|
||||
{ "HMAC(SHA-512-256)", OID({1,2,840,113549,2,13}) },
|
||||
{ "KeyWrap.AES-128", OID({2,16,840,1,101,3,4,1,5}) },
|
||||
{ "KeyWrap.AES-192", OID({2,16,840,1,101,3,4,1,25}) },
|
||||
{ "KeyWrap.AES-256", OID({2,16,840,1,101,3,4,1,45}) },
|
||||
{ "KeyWrap.CAST-128", OID({1,2,840,113533,7,66,15}) },
|
||||
{ "KeyWrap.RC2", OID({1,2,840,113549,1,9,16,3,7}) },
|
||||
{ "KeyWrap.TripleDES", OID({1,2,840,113549,1,9,16,3,6}) },
|
||||
{ "MD5", OID({1,2,840,113549,2,5}) },
|
||||
{ "MGF1", OID({1,2,840,113549,1,1,8}) },
|
||||
{ "McEliece", OID({1,3,6,1,4,1,25258,1,3}) },
|
||||
{ "Microsoft SmartcardLogon", OID({1,3,6,1,4,1,311,20,2,2}) },
|
||||
{ "Microsoft UPN", OID({1,3,6,1,4,1,311,20,2,3}) },
|
||||
{ "OpenPGP.Curve25519", OID({1,3,6,1,4,1,3029,1,5,1}) },
|
||||
{ "OpenPGP.Ed25519", OID({1,3,6,1,4,1,11591,15,1}) },
|
||||
{ "PBE-PKCS5v20", OID({1,2,840,113549,1,5,13}) },
|
||||
{ "PBES2", OID({1,2,840,113549,1,5,13}) },
|
||||
{ "PKCS5.PBKDF2", OID({1,2,840,113549,1,5,12}) },
|
||||
{ "PKCS9.ChallengePassword", OID({1,2,840,113549,1,9,7}) },
|
||||
{ "PKCS9.ContentType", OID({1,2,840,113549,1,9,3}) },
|
||||
@@ -333,7 +360,6 @@ std::unordered_map<std::string, OID> OIDS::load_str2oid_map()
|
||||
{ "PKIX.ServerAuth", OID({1,3,6,1,5,5,7,3,1}) },
|
||||
{ "PKIX.TimeStamping", OID({1,3,6,1,5,5,7,3,8}) },
|
||||
{ "PKIX.XMPPAddr", OID({1,3,6,1,5,5,7,8,5}) },
|
||||
{ "RC2/CBC", OID({1,2,840,113549,3,2}) },
|
||||
{ "RIPEMD-160", OID({1,3,36,3,2,1}) },
|
||||
{ "RSA", OID({1,2,840,113549,1,1,1}) },
|
||||
{ "RSA/EMSA3(MD5)", OID({1,2,840,113549,1,1,4}) },
|
||||
@@ -364,16 +390,21 @@ std::unordered_map<std::string, OID> OIDS::load_str2oid_map()
|
||||
{ "SHA-512-256", OID({2,16,840,1,101,3,4,2,6}) },
|
||||
{ "SHAKE-128", OID({2,16,840,1,101,3,4,2,11}) },
|
||||
{ "SHAKE-256", OID({2,16,840,1,101,3,4,2,12}) },
|
||||
{ "SM2", OID({1,2,156,10197,1,301,1}) },
|
||||
{ "SM2_Enc", OID({1,2,156,10197,1,301,3}) },
|
||||
{ "SM2_Kex", OID({1,2,156,10197,1,301,2}) },
|
||||
{ "SM2_Sig", OID({1,2,156,10197,1,301,1}) },
|
||||
{ "SM2_Sig/SM3", OID({1,2,156,10197,1,501}) },
|
||||
{ "SM3", OID({1,2,156,10197,1,401}) },
|
||||
{ "SM4/CBC", OID({1,2,156,10197,1,104,2}) },
|
||||
{ "SM4/GCM", OID({1,2,156,10197,1,104,8}) },
|
||||
{ "SM4/OCB", OID({1,2,156,10197,1,104,100}) },
|
||||
{ "SM4/SIV", OID({1,3,6,1,4,1,25258,3,4,9}) },
|
||||
{ "Scrypt", OID({1,3,6,1,4,1,11591,4,11}) },
|
||||
{ "Serpent/CBC", OID({1,3,6,1,4,1,25258,3,1}) },
|
||||
{ "Serpent/GCM", OID({1,3,6,1,4,1,25258,3,101}) },
|
||||
{ "Serpent/OCB", OID({1,3,6,1,4,1,25258,3,2,4}) },
|
||||
{ "Serpent/SIV", OID({1,3,6,1,4,1,25258,3,4,4}) },
|
||||
{ "Streebog-256", OID({1,2,643,7,1,1,2,2}) },
|
||||
{ "Streebog-512", OID({1,2,643,7,1,1,2,3}) },
|
||||
{ "Threefish-512/CBC", OID({1,3,6,1,4,1,25258,3,2}) },
|
||||
@@ -382,6 +413,7 @@ std::unordered_map<std::string, OID> OIDS::load_str2oid_map()
|
||||
{ "Twofish/CBC", OID({1,3,6,1,4,1,25258,3,3}) },
|
||||
{ "Twofish/GCM", OID({1,3,6,1,4,1,25258,3,102}) },
|
||||
{ "Twofish/OCB", OID({1,3,6,1,4,1,25258,3,2,5}) },
|
||||
{ "Twofish/SIV", OID({1,3,6,1,4,1,25258,3,4,5}) },
|
||||
{ "X509v3.AnyPolicy", OID({2,5,29,32,0}) },
|
||||
{ "X509v3.AuthorityKeyIdentifier", OID({2,5,29,35}) },
|
||||
{ "X509v3.BasicConstraints", OID({2,5,29,19}) },
|
||||
|
@@ -14,7 +14,7 @@ namespace OIDS {
|
||||
|
||||
namespace {
|
||||
|
||||
class OID_Map
|
||||
class OID_Map final
|
||||
{
|
||||
public:
|
||||
void add_oid(const OID& oid, const std::string& str)
|
||||
|
@@ -88,7 +88,7 @@ operator!=(const secure_allocator<T>&, const secure_allocator<U>&)
|
||||
template<typename T> using secure_vector = std::vector<T, secure_allocator<T>>;
|
||||
template<typename T> using secure_deque = std::deque<T, secure_allocator<T>>;
|
||||
|
||||
// For better compatability with 1.10 API
|
||||
// For better compatibility with 1.10 API
|
||||
template<typename T> using SecureVector = secure_vector<T>;
|
||||
|
||||
template<typename T>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* AES
|
||||
* (C) 1999-2010,2015,2017 Jack Lloyd
|
||||
* (C) 1999-2010,2015,2017,2018 Jack Lloyd
|
||||
*
|
||||
* Based on the public domain reference implementation by Paulo Baretto
|
||||
*
|
||||
@@ -18,14 +18,14 @@
|
||||
* countermeasures are used which may be helpful in some situations:
|
||||
*
|
||||
* - Only a single 256-word T-table is used, with rotations applied.
|
||||
* Most implementations use 4 T-tables which leaks much more
|
||||
* information via cache usage.
|
||||
* Most implementations use 4 (or sometimes 5) T-tables, which leaks
|
||||
* much more information via cache usage.
|
||||
*
|
||||
* - The TE and TD tables are computed at runtime to avoid flush+reload
|
||||
* attacks using clflush. As different processes will not share the
|
||||
* same underlying table data, an attacker can't manipulate another
|
||||
* processes cache lines via their shared reference to the library
|
||||
* read only segment.
|
||||
* read only segment. (However, prime+probe attacks are still possible.)
|
||||
*
|
||||
* - Each cache line of the lookup tables is accessed at the beginning
|
||||
* of each call to encrypt or decrypt. (See the Z variable below)
|
||||
@@ -188,7 +188,6 @@ void aes_encrypt_n(const uint8_t in[], uint8_t out[],
|
||||
BOTAN_ASSERT(EK.size() && ME.size() == 16, "Key was set");
|
||||
|
||||
const size_t cache_line_size = CPUID::cache_line_size();
|
||||
|
||||
const uint32_t* TE = AES_TE();
|
||||
|
||||
// Hit every cache line of TE
|
||||
@@ -269,6 +268,10 @@ void aes_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks,
|
||||
{
|
||||
Z |= TD[i];
|
||||
}
|
||||
for(size_t i = 0; i < 256; i += cache_line_size)
|
||||
{
|
||||
Z |= SD[i];
|
||||
}
|
||||
Z &= TD[99]; // this is zero, which hopefully the compiler cannot deduce
|
||||
|
||||
for(size_t i = 0; i != blocks; ++i)
|
||||
@@ -339,8 +342,24 @@ void aes_key_schedule(const uint8_t key[], size_t length,
|
||||
// Can't happen, but make static analyzers happy
|
||||
BOTAN_ARG_CHECK(X == 4 || X == 6 || X == 8, "Invalid AES key size");
|
||||
|
||||
const uint32_t* TD = AES_TD();
|
||||
|
||||
// Prefetch TD and SE which are used later on in this function
|
||||
volatile uint32_t Z = 0;
|
||||
const size_t cache_line_size = CPUID::cache_line_size();
|
||||
|
||||
for(size_t i = 0; i < 256; i += cache_line_size / sizeof(uint32_t))
|
||||
{
|
||||
Z |= TD[i];
|
||||
}
|
||||
for(size_t i = 0; i < 256; i += cache_line_size)
|
||||
{
|
||||
Z |= SE[i];
|
||||
}
|
||||
Z &= TD[99]; // this is zero, which hopefully the compiler cannot deduce
|
||||
|
||||
for(size_t i = 0; i != X; ++i)
|
||||
XEK[i] = load_be<uint32_t>(key, i);
|
||||
XEK[i] = Z ^ load_be<uint32_t>(key, i);
|
||||
|
||||
for(size_t i = X; i < 4*(rounds+1); i += X)
|
||||
{
|
||||
@@ -367,8 +386,8 @@ void aes_key_schedule(const uint8_t key[], size_t length,
|
||||
|
||||
for(size_t i = 4; i != length + 24; ++i)
|
||||
{
|
||||
XDK[i] = SE_word(XDK[i]);
|
||||
XDK[i] = AES_T(AES_TD(), 0, XDK[i], XDK[i], XDK[i], XDK[i]);
|
||||
XDK[i] = Z ^ SE_word(XDK[i]);
|
||||
XDK[i] = AES_T(TD, 0, XDK[i], XDK[i], XDK[i], XDK[i]);
|
||||
}
|
||||
|
||||
ME.resize(16);
|
||||
|
@@ -2,6 +2,4 @@
|
||||
AES_NI -> 20131128
|
||||
</defines>
|
||||
|
||||
load_on auto
|
||||
|
||||
need_isa aesni
|
||||
|
@@ -2,8 +2,6 @@
|
||||
AES_SSSE3 -> 20131128
|
||||
</defines>
|
||||
|
||||
load_on auto
|
||||
|
||||
need_isa ssse3
|
||||
|
||||
# Intel C++ can't deal with syntax for defining constants :(
|
||||
|
@@ -98,12 +98,27 @@
|
||||
#include <botan/internal/openssl.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_COMMONCRYPTO)
|
||||
#include <botan/internal/commoncrypto.h>
|
||||
#endif
|
||||
|
||||
namespace Botan {
|
||||
|
||||
std::unique_ptr<BlockCipher>
|
||||
BlockCipher::create(const std::string& algo,
|
||||
const std::string& provider)
|
||||
{
|
||||
#if defined(BOTAN_HAS_COMMONCRYPTO)
|
||||
if(provider.empty() || provider == "commoncrypto")
|
||||
{
|
||||
if(auto bc = make_commoncrypto_block_cipher(algo))
|
||||
return bc;
|
||||
|
||||
if(!provider.empty())
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_OPENSSL)
|
||||
if(provider.empty() || provider == "openssl")
|
||||
{
|
||||
@@ -115,7 +130,6 @@ BlockCipher::create(const std::string& algo,
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: CommonCrypto
|
||||
// TODO: CryptoAPI
|
||||
// TODO: /dev/crypto
|
||||
|
||||
@@ -343,7 +357,7 @@ BlockCipher::create_or_throw(const std::string& algo,
|
||||
|
||||
std::vector<std::string> BlockCipher::providers(const std::string& algo)
|
||||
{
|
||||
return probe_providers_of<BlockCipher>(algo, { "base", "openssl" });
|
||||
return probe_providers_of<BlockCipher>(algo, { "base", "openssl", "commoncrypto" });
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -197,36 +197,52 @@ class BOTAN_PUBLIC_API(2,0) BlockCipher : public SymmetricAlgorithm
|
||||
virtual ~BlockCipher() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tweakable block ciphers allow setting a tweak which is a non-keyed
|
||||
* value which affects the encryption/decryption operation.
|
||||
*/
|
||||
class BOTAN_PUBLIC_API(2,8) Tweakable_Block_Cipher : public BlockCipher
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Set the tweak value. This must be called after setting a key. The value
|
||||
* persists until either set_tweak, set_key, or clear is called.
|
||||
* Different algorithms support different tweak length(s). If called with
|
||||
* an unsupported length, Invalid_Argument will be thrown.
|
||||
*/
|
||||
virtual void set_tweak(const uint8_t tweak[], size_t len) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a block cipher with a single fixed block size
|
||||
*/
|
||||
template<size_t BS, size_t KMIN, size_t KMAX = 0, size_t KMOD = 1>
|
||||
class Block_Cipher_Fixed_Params : public BlockCipher
|
||||
template<size_t BS, size_t KMIN, size_t KMAX = 0, size_t KMOD = 1, typename BaseClass = BlockCipher>
|
||||
class Block_Cipher_Fixed_Params : public BaseClass
|
||||
{
|
||||
public:
|
||||
enum { BLOCK_SIZE = BS };
|
||||
size_t block_size() const override { return BS; }
|
||||
size_t block_size() const final override { return BS; }
|
||||
|
||||
// override to take advantage of compile time constant block size
|
||||
void encrypt_n_xex(uint8_t data[],
|
||||
const uint8_t mask[],
|
||||
size_t blocks) const override
|
||||
size_t blocks) const final override
|
||||
{
|
||||
xor_buf(data, mask, blocks * BS);
|
||||
encrypt_n(data, data, blocks);
|
||||
this->encrypt_n(data, data, blocks);
|
||||
xor_buf(data, mask, blocks * BS);
|
||||
}
|
||||
|
||||
void decrypt_n_xex(uint8_t data[],
|
||||
const uint8_t mask[],
|
||||
size_t blocks) const override
|
||||
size_t blocks) const final override
|
||||
{
|
||||
xor_buf(data, mask, blocks * BS);
|
||||
decrypt_n(data, data, blocks);
|
||||
this->decrypt_n(data, data, blocks);
|
||||
xor_buf(data, mask, blocks * BS);
|
||||
}
|
||||
|
||||
Key_Length_Specification key_spec() const override
|
||||
Key_Length_Specification key_spec() const final override
|
||||
{
|
||||
return Key_Length_Specification(KMIN, KMAX, KMOD);
|
||||
}
|
||||
|
@@ -6,109 +6,129 @@
|
||||
*/
|
||||
|
||||
#include <botan/base64.h>
|
||||
#include <botan/internal/codec_base.h>
|
||||
#include <botan/exceptn.h>
|
||||
#include <botan/mem_ops.h>
|
||||
#include <botan/internal/rounding.h>
|
||||
|
||||
namespace Botan {
|
||||
|
||||
namespace {
|
||||
|
||||
static const uint8_t BIN_TO_BASE64[64] = {
|
||||
class Base64 final
|
||||
{
|
||||
public:
|
||||
static inline size_t encoding_bytes_in() BOTAN_NOEXCEPT
|
||||
{
|
||||
return m_encoding_bytes_in;
|
||||
}
|
||||
static inline size_t encoding_bytes_out() BOTAN_NOEXCEPT
|
||||
{
|
||||
return m_encoding_bytes_out;
|
||||
}
|
||||
|
||||
static inline size_t decoding_bytes_in() BOTAN_NOEXCEPT
|
||||
{
|
||||
return m_encoding_bytes_out;
|
||||
}
|
||||
static inline size_t decoding_bytes_out() BOTAN_NOEXCEPT
|
||||
{
|
||||
return m_encoding_bytes_in;
|
||||
}
|
||||
|
||||
static inline size_t bits_consumed() BOTAN_NOEXCEPT
|
||||
{
|
||||
return m_encoding_bits;
|
||||
}
|
||||
static inline size_t remaining_bits_before_padding() BOTAN_NOEXCEPT
|
||||
{
|
||||
return m_remaining_bits_before_padding;
|
||||
}
|
||||
|
||||
static inline size_t encode_max_output(size_t input_length)
|
||||
{
|
||||
return (round_up(input_length, m_encoding_bytes_in) / m_encoding_bytes_in) * m_encoding_bytes_out;
|
||||
}
|
||||
static inline size_t decode_max_output(size_t input_length)
|
||||
{
|
||||
return (round_up(input_length, m_encoding_bytes_out) * m_encoding_bytes_in) / m_encoding_bytes_out;
|
||||
}
|
||||
|
||||
static void encode(char out[8], const uint8_t in[5]) BOTAN_NOEXCEPT
|
||||
{
|
||||
out[0] = Base64::m_bin_to_base64[(in[0] & 0xFC) >> 2];
|
||||
out[1] = Base64::m_bin_to_base64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
|
||||
out[2] = Base64::m_bin_to_base64[((in[1] & 0x0F) << 2) | (in[2] >> 6)];
|
||||
out[3] = Base64::m_bin_to_base64[in[2] & 0x3F];
|
||||
}
|
||||
|
||||
static inline uint8_t lookup_binary_value(char input) BOTAN_NOEXCEPT
|
||||
{
|
||||
return Base64::m_base64_to_bin[static_cast<uint8_t>(input)];
|
||||
}
|
||||
|
||||
static inline bool check_bad_char(uint8_t bin, char input, bool ignore_ws)
|
||||
{
|
||||
if(bin <= 0x3F)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws)))
|
||||
{
|
||||
std::string bad_char(1, input);
|
||||
if(bad_char == "\t")
|
||||
{ bad_char = "\\t"; }
|
||||
else if(bad_char == "\n")
|
||||
{ bad_char = "\\n"; }
|
||||
else if(bad_char == "\r")
|
||||
{ bad_char = "\\r"; }
|
||||
|
||||
throw Invalid_Argument(
|
||||
std::string("base64_decode: invalid base64 character '") +
|
||||
bad_char + "'");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void decode(uint8_t* out_ptr, const uint8_t decode_buf[4])
|
||||
{
|
||||
out_ptr[0] = (decode_buf[0] << 2) | (decode_buf[1] >> 4);
|
||||
out_ptr[1] = (decode_buf[1] << 4) | (decode_buf[2] >> 2);
|
||||
out_ptr[2] = (decode_buf[2] << 6) | decode_buf[3];
|
||||
}
|
||||
|
||||
static inline size_t bytes_to_remove(size_t final_truncate)
|
||||
{
|
||||
return final_truncate;
|
||||
}
|
||||
|
||||
private:
|
||||
static const size_t m_encoding_bits = 6;
|
||||
static const size_t m_remaining_bits_before_padding = 8;
|
||||
|
||||
|
||||
static const size_t m_encoding_bytes_in = 3;
|
||||
static const size_t m_encoding_bytes_out = 4;
|
||||
|
||||
|
||||
static const uint8_t m_bin_to_base64[64];
|
||||
static const uint8_t m_base64_to_bin[256];
|
||||
};
|
||||
|
||||
const uint8_t Base64::m_bin_to_base64[64] =
|
||||
{
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
};
|
||||
|
||||
void do_base64_encode(char out[4], const uint8_t in[3])
|
||||
/*
|
||||
* base64 Decoder Lookup Table
|
||||
* Warning: assumes ASCII encodings
|
||||
*/
|
||||
const uint8_t Base64::m_base64_to_bin[256] =
|
||||
{
|
||||
out[0] = BIN_TO_BASE64[(in[0] & 0xFC) >> 2];
|
||||
out[1] = BIN_TO_BASE64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
|
||||
out[2] = BIN_TO_BASE64[((in[1] & 0x0F) << 2) | (in[2] >> 6)];
|
||||
out[3] = BIN_TO_BASE64[in[2] & 0x3F];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t base64_encode(char out[],
|
||||
const uint8_t in[],
|
||||
size_t input_length,
|
||||
size_t& input_consumed,
|
||||
bool final_inputs)
|
||||
{
|
||||
input_consumed = 0;
|
||||
|
||||
size_t input_remaining = input_length;
|
||||
size_t output_produced = 0;
|
||||
|
||||
while(input_remaining >= 3)
|
||||
{
|
||||
do_base64_encode(out + output_produced, in + input_consumed);
|
||||
|
||||
input_consumed += 3;
|
||||
output_produced += 4;
|
||||
input_remaining -= 3;
|
||||
}
|
||||
|
||||
if(final_inputs && input_remaining)
|
||||
{
|
||||
uint8_t remainder[3] = { 0 };
|
||||
for(size_t i = 0; i != input_remaining; ++i)
|
||||
remainder[i] = in[input_consumed + i];
|
||||
|
||||
do_base64_encode(out + output_produced, remainder);
|
||||
|
||||
size_t empty_bits = 8 * (3 - input_remaining);
|
||||
size_t index = output_produced + 4 - 1;
|
||||
while(empty_bits >= 8)
|
||||
{
|
||||
out[index--] = '=';
|
||||
empty_bits -= 6;
|
||||
}
|
||||
|
||||
input_consumed += input_remaining;
|
||||
output_produced += 4;
|
||||
}
|
||||
|
||||
return output_produced;
|
||||
}
|
||||
|
||||
std::string base64_encode(const uint8_t input[],
|
||||
size_t input_length)
|
||||
{
|
||||
const size_t output_length = base64_encode_max_output(input_length);
|
||||
std::string output(output_length, 0);
|
||||
|
||||
size_t consumed = 0;
|
||||
size_t produced = 0;
|
||||
|
||||
if (output_length > 0)
|
||||
{
|
||||
produced = base64_encode(&output.front(),
|
||||
input, input_length,
|
||||
consumed, true);
|
||||
}
|
||||
|
||||
BOTAN_ASSERT_EQUAL(consumed, input_length, "Consumed the entire input");
|
||||
BOTAN_ASSERT_EQUAL(produced, output.size(), "Produced expected size");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
size_t base64_decode(uint8_t output[],
|
||||
const char input[],
|
||||
size_t input_length,
|
||||
size_t& input_consumed,
|
||||
bool final_inputs,
|
||||
bool ignore_ws)
|
||||
{
|
||||
/*
|
||||
* Base64 Decoder Lookup Table
|
||||
* Warning: assumes ASCII encodings
|
||||
*/
|
||||
static const uint8_t BASE64_TO_BIN[256] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
|
||||
0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
@@ -134,74 +154,49 @@ size_t base64_decode(uint8_t output[],
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
}
|
||||
|
||||
uint8_t* out_ptr = output;
|
||||
uint8_t decode_buf[4];
|
||||
size_t decode_buf_pos = 0;
|
||||
size_t final_truncate = 0;
|
||||
|
||||
clear_mem(output, input_length * 3 / 4);
|
||||
|
||||
for(size_t i = 0; i != input_length; ++i)
|
||||
size_t base64_encode(char out[],
|
||||
const uint8_t in[],
|
||||
size_t input_length,
|
||||
size_t& input_consumed,
|
||||
bool final_inputs)
|
||||
{
|
||||
const uint8_t bin = BASE64_TO_BIN[static_cast<uint8_t>(input[i])];
|
||||
|
||||
if(bin <= 0x3F)
|
||||
{
|
||||
decode_buf[decode_buf_pos] = bin;
|
||||
decode_buf_pos += 1;
|
||||
}
|
||||
else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws)))
|
||||
{
|
||||
std::string bad_char(1, input[i]);
|
||||
if(bad_char == "\t")
|
||||
bad_char = "\\t";
|
||||
else if(bad_char == "\n")
|
||||
bad_char = "\\n";
|
||||
else if(bad_char == "\r")
|
||||
bad_char = "\\r";
|
||||
|
||||
throw Invalid_Argument(
|
||||
std::string("base64_decode: invalid base64 character '") +
|
||||
bad_char + "'");
|
||||
return base_encode(Base64(), out, in, input_length, input_consumed, final_inputs);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're at the end of the input, pad with 0s and truncate
|
||||
*/
|
||||
if(final_inputs && (i == input_length - 1))
|
||||
std::string base64_encode(const uint8_t input[],
|
||||
size_t input_length)
|
||||
{
|
||||
if(decode_buf_pos)
|
||||
const size_t output_length = Base64::encode_max_output(input_length);
|
||||
std::string output(output_length, 0);
|
||||
|
||||
size_t consumed = 0;
|
||||
size_t produced = 0;
|
||||
|
||||
if(output_length > 0)
|
||||
{
|
||||
for(size_t j = decode_buf_pos; j != 4; ++j)
|
||||
decode_buf[j] = 0;
|
||||
final_truncate = (4 - decode_buf_pos);
|
||||
decode_buf_pos = 4;
|
||||
}
|
||||
produced = base64_encode(&output.front(),
|
||||
input, input_length,
|
||||
consumed, true);
|
||||
}
|
||||
|
||||
if(decode_buf_pos == 4)
|
||||
BOTAN_ASSERT_EQUAL(consumed, input_length, "Consumed the entire input");
|
||||
BOTAN_ASSERT_EQUAL(produced, output.size(), "Produced expected size");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
size_t base64_decode(uint8_t out[],
|
||||
const char in[],
|
||||
size_t input_length,
|
||||
size_t& input_consumed,
|
||||
bool final_inputs,
|
||||
bool ignore_ws)
|
||||
{
|
||||
out_ptr[0] = (decode_buf[0] << 2) | (decode_buf[1] >> 4);
|
||||
out_ptr[1] = (decode_buf[1] << 4) | (decode_buf[2] >> 2);
|
||||
out_ptr[2] = (decode_buf[2] << 6) | decode_buf[3];
|
||||
|
||||
out_ptr += 3;
|
||||
decode_buf_pos = 0;
|
||||
input_consumed = i+1;
|
||||
}
|
||||
}
|
||||
|
||||
while(input_consumed < input_length &&
|
||||
BASE64_TO_BIN[static_cast<uint8_t>(input[input_consumed])] == 0x80)
|
||||
{
|
||||
++input_consumed;
|
||||
}
|
||||
|
||||
size_t written = (out_ptr - output) - final_truncate;
|
||||
|
||||
return written;
|
||||
return base_decode(Base64(), out, in, input_length, input_consumed, final_inputs, ignore_ws);
|
||||
}
|
||||
|
||||
size_t base64_decode(uint8_t output[],
|
||||
@@ -214,7 +209,7 @@ size_t base64_decode(uint8_t output[],
|
||||
consumed, true, ignore_ws);
|
||||
|
||||
if(consumed != input_length)
|
||||
throw Invalid_Argument("base64_decode: input did not have full bytes");
|
||||
{ throw Invalid_Argument("base64_decode: input did not have full bytes"); }
|
||||
|
||||
return written;
|
||||
}
|
||||
@@ -230,7 +225,7 @@ secure_vector<uint8_t> base64_decode(const char input[],
|
||||
size_t input_length,
|
||||
bool ignore_ws)
|
||||
{
|
||||
const size_t output_length = base64_decode_max_output(input_length);
|
||||
const size_t output_length = Base64::decode_max_output(input_length);
|
||||
secure_vector<uint8_t> bin(output_length);
|
||||
|
||||
size_t written = base64_decode(bin.data(),
|
||||
@@ -250,12 +245,12 @@ secure_vector<uint8_t> base64_decode(const std::string& input,
|
||||
|
||||
size_t base64_encode_max_output(size_t input_length)
|
||||
{
|
||||
return (round_up(input_length, 3) / 3) * 4;
|
||||
return Base64::encode_max_output(input_length);
|
||||
}
|
||||
|
||||
size_t base64_decode_max_output(size_t input_length)
|
||||
{
|
||||
return (round_up(input_length, 4) * 3) / 4;
|
||||
return Base64::decode_max_output(input_length);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Darwin SecRandomCopyBytes EntropySource
|
||||
* (C) 2015 Daniel Seither (Kullo GmbH)
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
*/
|
||||
|
||||
#include <botan/internal/darwin_secrandom.h>
|
||||
#include <Security/Security.h>
|
||||
#include <Security/SecRandom.h>
|
||||
|
||||
namespace Botan {
|
||||
|
||||
/**
|
||||
* Gather entropy from SecRandomCopyBytes
|
||||
*/
|
||||
size_t Darwin_SecRandom::poll(RandomNumberGenerator& rng)
|
||||
{
|
||||
secure_vector<uint8_t> buf(BOTAN_SYSTEM_RNG_POLL_REQUEST);
|
||||
|
||||
if(0 == SecRandomCopyBytes(kSecRandomDefault, buf.size(), buf.data()))
|
||||
{
|
||||
rng.add_entropy(buf.data(), buf.size());
|
||||
return buf.size() * 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Darwin SecRandomCopyBytes EntropySource
|
||||
* (C) 2015 Daniel Seither (Kullo GmbH)
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_ENTROPY_SRC_DARWIN_SECRANDOM_H_
|
||||
#define BOTAN_ENTROPY_SRC_DARWIN_SECRANDOM_H_
|
||||
|
||||
#include <botan/entropy_src.h>
|
||||
|
||||
namespace Botan {
|
||||
|
||||
/**
|
||||
* Entropy source using SecRandomCopyBytes from Darwin's Security.framework
|
||||
*/
|
||||
class Darwin_SecRandom final : public Entropy_Source
|
||||
{
|
||||
public:
|
||||
std::string name() const override { return "darwin_secrandom"; }
|
||||
|
||||
size_t poll(RandomNumberGenerator& rng) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,16 +0,0 @@
|
||||
<defines>
|
||||
ENTROPY_SRC_DARWIN_SECRANDOM -> 20150925
|
||||
</defines>
|
||||
|
||||
<header:internal>
|
||||
darwin_secrandom.h
|
||||
</header:internal>
|
||||
|
||||
<os_features>
|
||||
security_framework
|
||||
</os_features>
|
||||
|
||||
<frameworks>
|
||||
darwin -> Security
|
||||
ios -> Security
|
||||
</frameworks>
|
@@ -30,10 +30,7 @@
|
||||
|
||||
#if defined(BOTAN_HAS_ENTROPY_SRC_PROC_WALKER)
|
||||
#include <botan/internal/proc_walk.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_ENTROPY_SRC_DARWIN_SECRANDOM)
|
||||
#include <botan/internal/darwin_secrandom.h>
|
||||
#include <botan/internal/os_utils.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY)
|
||||
@@ -86,13 +83,6 @@ std::unique_ptr<Entropy_Source> Entropy_Source::create(const std::string& name)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_ENTROPY_SRC_DARWIN_SECRANDOM)
|
||||
if(name == "darwin_secrandom")
|
||||
{
|
||||
return std::unique_ptr<Entropy_Source>(new Darwin_SecRandom);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY)
|
||||
if(name == "getentropy")
|
||||
{
|
||||
@@ -108,7 +98,7 @@ std::unique_ptr<Entropy_Source> Entropy_Source::create(const std::string& name)
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_ENTROPY_SRC_PROC_WALKER)
|
||||
if(name == "proc_walk")
|
||||
if(name == "proc_walk" && OS::running_in_privileged_state() == false)
|
||||
{
|
||||
const std::string root_dir = BOTAN_ENTROPY_PROC_FS_PATH;
|
||||
if(!root_dir.empty())
|
||||
|
@@ -8,12 +8,12 @@
|
||||
|
||||
#include <botan/internal/rdrand.h>
|
||||
#include <botan/rdrand_rng.h>
|
||||
#include <botan/cpuid.h>
|
||||
|
||||
namespace Botan {
|
||||
|
||||
size_t Intel_Rdrand::poll(RandomNumberGenerator& rng) {
|
||||
if(CPUID::has_rdrand() && BOTAN_ENTROPY_INTEL_RNG_POLLS > 0)
|
||||
size_t Intel_Rdrand::poll(RandomNumberGenerator& rng)
|
||||
{
|
||||
if(BOTAN_ENTROPY_INTEL_RNG_POLLS > 0 && RDRAND_RNG::available())
|
||||
{
|
||||
RDRAND_RNG rdrand_rng;
|
||||
secure_vector<uint8_t> buf(4 * BOTAN_ENTROPY_INTEL_RNG_POLLS);
|
||||
|
@@ -15,7 +15,8 @@
|
||||
namespace Botan {
|
||||
|
||||
BOTAN_FUNC_ISA("rdseed")
|
||||
size_t Intel_Rdseed::poll(RandomNumberGenerator& rng) {
|
||||
size_t Intel_Rdseed::poll(RandomNumberGenerator& rng)
|
||||
{
|
||||
if(CPUID::has_rdseed())
|
||||
{
|
||||
for(size_t p = 0; p != BOTAN_ENTROPY_INTEL_RNG_POLLS; ++p)
|
||||
|
20
src/libs/3rdparty/botan/src/lib/filters/filter.h
vendored
20
src/libs/3rdparty/botan/src/lib/filters/filter.h
vendored
@@ -67,28 +67,20 @@ class BOTAN_PUBLIC_API(2,0) Filter
|
||||
/**
|
||||
* @param in some input for the filter
|
||||
*/
|
||||
void send(const secure_vector<uint8_t>& in) { send(in.data(), in.size()); }
|
||||
|
||||
/**
|
||||
* @param in some input for the filter
|
||||
*/
|
||||
void send(const std::vector<uint8_t>& in) { send(in.data(), in.size()); }
|
||||
|
||||
/**
|
||||
* @param in some input for the filter
|
||||
* @param length the number of bytes of in to send
|
||||
*/
|
||||
void send(const secure_vector<uint8_t>& in, size_t length)
|
||||
template<typename Alloc>
|
||||
void send(const std::vector<uint8_t, Alloc>& in)
|
||||
{
|
||||
send(in.data(), length);
|
||||
send(in.data(), in.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in some input for the filter
|
||||
* @param length the number of bytes of in to send
|
||||
*/
|
||||
void send(const std::vector<uint8_t>& in, size_t length)
|
||||
template<typename Alloc>
|
||||
void send(const std::vector<uint8_t, Alloc>& in, size_t length)
|
||||
{
|
||||
BOTAN_ASSERT_NOMSG(length <= in.size());
|
||||
send(in.data(), length);
|
||||
}
|
||||
|
||||
|
20
src/libs/3rdparty/botan/src/lib/hash/hash.cpp
vendored
20
src/libs/3rdparty/botan/src/lib/hash/hash.cpp
vendored
@@ -101,11 +101,27 @@
|
||||
#include <botan/internal/openssl.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_COMMONCRYPTO)
|
||||
#include <botan/internal/commoncrypto.h>
|
||||
#endif
|
||||
|
||||
namespace Botan {
|
||||
|
||||
std::unique_ptr<HashFunction> HashFunction::create(const std::string& algo_spec,
|
||||
const std::string& provider)
|
||||
{
|
||||
|
||||
#if defined(BOTAN_HAS_COMMONCRYPTO)
|
||||
if(provider.empty() || provider == "commoncrypto")
|
||||
{
|
||||
if(auto hash = make_commoncrypto_hash(algo_spec))
|
||||
return hash;
|
||||
|
||||
if(!provider.empty())
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_OPENSSL)
|
||||
if(provider.empty() || provider == "openssl")
|
||||
{
|
||||
@@ -128,8 +144,6 @@ std::unique_ptr<HashFunction> HashFunction::create(const std::string& algo_spec,
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: CommonCrypto hashes
|
||||
|
||||
if(provider.empty() == false && provider != "base")
|
||||
return nullptr; // unknown provider
|
||||
|
||||
@@ -354,7 +368,7 @@ HashFunction::create_or_throw(const std::string& algo,
|
||||
|
||||
std::vector<std::string> HashFunction::providers(const std::string& algo_spec)
|
||||
{
|
||||
return probe_providers_of<HashFunction>(algo_spec, {"base", "bearssl", "openssl"});
|
||||
return probe_providers_of<HashFunction>(algo_spec, {"base", "bearssl", "openssl", "commoncrypto"});
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -20,15 +20,14 @@ namespace Botan {
|
||||
BOTAN_FUNC_ISA("+crypto")
|
||||
void SHA_160::sha1_armv8_compress_n(secure_vector<uint32_t>& digest, const uint8_t input8[], size_t blocks)
|
||||
{
|
||||
uint32x4_t C0, C1, C2, C3;
|
||||
uint32x4_t ABCD, ABCD_SAVED;
|
||||
uint32_t E0, E0_SAVED, E1;
|
||||
uint32x4_t ABCD;
|
||||
uint32_t E0;
|
||||
|
||||
// Load initial values
|
||||
C0 = vdupq_n_u32(0x5A827999);
|
||||
C1 = vdupq_n_u32(0x6ED9EBA1);
|
||||
C2 = vdupq_n_u32(0x8F1BBCDC);
|
||||
C3 = vdupq_n_u32(0xCA62C1D6);
|
||||
// Load magic constants
|
||||
const uint32x4_t C0 = vdupq_n_u32(0x5A827999);
|
||||
const uint32x4_t C1 = vdupq_n_u32(0x6ED9EBA1);
|
||||
const uint32x4_t C2 = vdupq_n_u32(0x8F1BBCDC);
|
||||
const uint32x4_t C3 = vdupq_n_u32(0xCA62C1D6);
|
||||
|
||||
ABCD = vld1q_u32(&digest[0]);
|
||||
E0 = digest[4];
|
||||
@@ -38,12 +37,13 @@ void SHA_160::sha1_armv8_compress_n(secure_vector<uint32_t>& digest, const uint8
|
||||
|
||||
while (blocks)
|
||||
{
|
||||
// Save current hash
|
||||
const uint32x4_t ABCD_SAVED = ABCD;
|
||||
const uint32_t E0_SAVED = E0;
|
||||
|
||||
uint32x4_t MSG0, MSG1, MSG2, MSG3;
|
||||
uint32x4_t TMP0, TMP1;
|
||||
|
||||
// Save current hash
|
||||
ABCD_SAVED = ABCD;
|
||||
E0_SAVED = E0;
|
||||
uint32_t E1;
|
||||
|
||||
MSG0 = vld1q_u32(input32 + 0);
|
||||
MSG1 = vld1q_u32(input32 + 4);
|
||||
|
@@ -12,6 +12,42 @@
|
||||
|
||||
namespace Botan {
|
||||
|
||||
std::string BigInt::to_dec_string() const
|
||||
{
|
||||
BigInt copy = *this;
|
||||
copy.set_sign(Positive);
|
||||
|
||||
BigInt remainder;
|
||||
std::vector<uint8_t> digits;
|
||||
|
||||
while(copy > 0)
|
||||
{
|
||||
divide(copy, 10, copy, remainder);
|
||||
digits.push_back(static_cast<uint8_t>(remainder.word_at(0)));
|
||||
}
|
||||
|
||||
std::string s;
|
||||
|
||||
for(auto i = digits.rbegin(); i != digits.rend(); ++i)
|
||||
{
|
||||
s.push_back(Charset::digit2char(*i));
|
||||
}
|
||||
|
||||
if(s.empty())
|
||||
s += "0";
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string BigInt::to_hex_string() const
|
||||
{
|
||||
const std::vector<uint8_t> bits = BigInt::encode(*this);
|
||||
if(bits.empty())
|
||||
return "00";
|
||||
else
|
||||
return hex_encode(bits);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a BigInt
|
||||
*/
|
||||
@@ -53,12 +89,15 @@ void BigInt::encode(uint8_t output[], const BigInt& n, Base base)
|
||||
*/
|
||||
std::vector<uint8_t> BigInt::encode(const BigInt& n, Base base)
|
||||
{
|
||||
if(base == Binary)
|
||||
return BigInt::encode(n);
|
||||
|
||||
std::vector<uint8_t> output(n.encoded_size(base));
|
||||
encode(output.data(), n, base);
|
||||
if(base != Binary)
|
||||
for(size_t j = 0; j != output.size(); ++j)
|
||||
if(output[j] == 0)
|
||||
output[j] = '0';
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -67,12 +106,15 @@ std::vector<uint8_t> BigInt::encode(const BigInt& n, Base base)
|
||||
*/
|
||||
secure_vector<uint8_t> BigInt::encode_locked(const BigInt& n, Base base)
|
||||
{
|
||||
if(base == Binary)
|
||||
return BigInt::encode_locked(n);
|
||||
|
||||
secure_vector<uint8_t> output(n.encoded_size(base));
|
||||
encode(output.data(), n, base);
|
||||
if(base != Binary)
|
||||
for(size_t j = 0; j != output.size(); ++j)
|
||||
if(output[j] == 0)
|
||||
output[j] = '0';
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
@@ -125,6 +125,24 @@ BigInt operator*(const BigInt& x, const BigInt& y)
|
||||
return z;
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiplication Operator
|
||||
*/
|
||||
BigInt operator*(const BigInt& x, word y)
|
||||
{
|
||||
const size_t x_sw = x.sig_words();
|
||||
|
||||
BigInt z(BigInt::Positive, x_sw + 1);
|
||||
|
||||
if(x_sw && y)
|
||||
{
|
||||
bigint_linmul3(z.mutable_data(), x.data(), x_sw, y);
|
||||
z.set_sign(x.sign());
|
||||
}
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
/*
|
||||
* Division Operator
|
||||
*/
|
||||
|
@@ -96,7 +96,7 @@ BigInt::BigInt(const uint8_t input[], size_t length, Base base)
|
||||
BigInt::BigInt(const uint8_t buf[], size_t length, size_t max_bits)
|
||||
{
|
||||
const size_t max_bytes = std::min(length, (max_bits + 7) / 8);
|
||||
*this = decode(buf, max_bytes);
|
||||
binary_decode(buf, max_bytes);
|
||||
|
||||
const size_t b = this->bits();
|
||||
if(b > max_bits)
|
||||
@@ -163,18 +163,19 @@ void BigInt::encode_words(word out[], size_t size) const
|
||||
*/
|
||||
uint32_t BigInt::get_substring(size_t offset, size_t length) const
|
||||
{
|
||||
if(length > 32)
|
||||
throw Invalid_Argument("BigInt::get_substring: Substring size " + std::to_string(length) + " too big");
|
||||
if(length == 0 || length > 32)
|
||||
throw Invalid_Argument("BigInt::get_substring invalid substring length");
|
||||
|
||||
uint64_t piece = 0;
|
||||
for(size_t i = 0; i != 8; ++i)
|
||||
{
|
||||
const uint8_t part = byte_at((offset / 8) + (7-i));
|
||||
piece = (piece << 8) | part;
|
||||
}
|
||||
|
||||
const uint64_t mask = (static_cast<uint64_t>(1) << length) - 1;
|
||||
const size_t byte_offset = offset / 8;
|
||||
const size_t shift = (offset % 8);
|
||||
const uint32_t mask = 0xFFFFFFFF >> (32 - length);
|
||||
|
||||
const uint8_t b0 = byte_at(byte_offset);
|
||||
const uint8_t b1 = byte_at(byte_offset + 1);
|
||||
const uint8_t b2 = byte_at(byte_offset + 2);
|
||||
const uint8_t b3 = byte_at(byte_offset + 3);
|
||||
const uint8_t b4 = byte_at(byte_offset + 4);
|
||||
const uint64_t piece = make_uint64(0, 0, 0, b4, b3, b2, b1, b0);
|
||||
|
||||
return static_cast<uint32_t>((piece >> shift) & mask);
|
||||
}
|
||||
@@ -341,6 +342,21 @@ void BigInt::binary_decode(const uint8_t buf[], size_t length)
|
||||
m_reg[length / WORD_BYTES] = (m_reg[length / WORD_BYTES] << 8) | buf[i];
|
||||
}
|
||||
|
||||
void BigInt::ct_cond_assign(bool predicate, BigInt& other)
|
||||
{
|
||||
const size_t t_words = size();
|
||||
const size_t o_words = other.size();
|
||||
|
||||
const size_t r_words = std::max(t_words, o_words);
|
||||
|
||||
const word mask = CT::expand_mask<word>(predicate);
|
||||
|
||||
for(size_t i = 0; i != r_words; ++i)
|
||||
{
|
||||
this->set_word_at(i, CT::select<word>(mask, other.word_at(i), this->word_at(i)));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOTAN_HAS_VALGRIND)
|
||||
void BigInt::const_time_poison() const
|
||||
{
|
||||
|
109
src/libs/3rdparty/botan/src/lib/math/bigint/bigint.h
vendored
109
src/libs/3rdparty/botan/src/lib/math/bigint/bigint.h
vendored
@@ -77,6 +77,13 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
|
||||
*/
|
||||
BigInt(const uint8_t buf[], size_t length);
|
||||
|
||||
/**
|
||||
* Create a BigInt from an integer in a byte array
|
||||
* @param vec the byte vector holding the value
|
||||
*/
|
||||
template<typename Alloc>
|
||||
explicit BigInt(const std::vector<uint8_t, Alloc>& vec) : BigInt(vec.data(), vec.size()) {}
|
||||
|
||||
/**
|
||||
* Create a BigInt from an integer in a byte array
|
||||
* @param buf the byte array holding the value
|
||||
@@ -422,6 +429,17 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
|
||||
*/
|
||||
uint32_t to_u32bit() const;
|
||||
|
||||
/**
|
||||
* Convert this value to a decimal string.
|
||||
* Warning: decimal conversions are relatively slow
|
||||
*/
|
||||
std::string to_dec_string() const;
|
||||
|
||||
/**
|
||||
* Convert this value to a hexadecimal string.
|
||||
*/
|
||||
std::string to_hex_string() const;
|
||||
|
||||
/**
|
||||
* @param n the offset to get a byte from
|
||||
* @result byte at offset n
|
||||
@@ -616,6 +634,12 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
|
||||
*/
|
||||
void encode_words(word out[], size_t size) const;
|
||||
|
||||
/**
|
||||
* If predicate is true assign other to *this
|
||||
* Uses a masked operation to avoid side channels
|
||||
*/
|
||||
void ct_cond_assign(bool predicate, BigInt& other);
|
||||
|
||||
#if defined(BOTAN_HAS_VALGRIND)
|
||||
void const_time_poison() const;
|
||||
void const_time_unpoison() const;
|
||||
@@ -646,13 +670,78 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the integer value from a BigInt to a std::vector of bytes
|
||||
* @param n the BigInt to use as integer source
|
||||
* @result secure_vector of bytes containing the bytes of the integer
|
||||
*/
|
||||
static std::vector<uint8_t> encode(const BigInt& n)
|
||||
{
|
||||
std::vector<uint8_t> output(n.bytes());
|
||||
n.binary_encode(output.data());
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the integer value from a BigInt to a secure_vector of bytes
|
||||
* @param n the BigInt to use as integer source
|
||||
* @result secure_vector of bytes containing the bytes of the integer
|
||||
*/
|
||||
static secure_vector<uint8_t> encode_locked(const BigInt& n)
|
||||
{
|
||||
secure_vector<uint8_t> output(n.bytes());
|
||||
n.binary_encode(output.data());
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the integer value from a BigInt to a byte array
|
||||
* @param buf destination byte array for the encoded integer
|
||||
* @param n the BigInt to use as integer source
|
||||
*/
|
||||
static void encode(uint8_t buf[], const BigInt& n)
|
||||
{
|
||||
n.binary_encode(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a BigInt from an integer in a byte array
|
||||
* @param buf the binary value to load
|
||||
* @param length size of buf
|
||||
* @result BigInt representing the integer in the byte array
|
||||
*/
|
||||
static BigInt decode(const uint8_t buf[], size_t length)
|
||||
{
|
||||
return BigInt(buf, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a BigInt from an integer in a byte array
|
||||
* @param buf the binary value to load
|
||||
* @result BigInt representing the integer in the byte array
|
||||
*/
|
||||
static BigInt decode(const secure_vector<uint8_t>& buf)
|
||||
{
|
||||
return BigInt(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a BigInt from an integer in a byte array
|
||||
* @param buf the binary value to load
|
||||
* @result BigInt representing the integer in the byte array
|
||||
*/
|
||||
static BigInt decode(const std::vector<uint8_t>& buf)
|
||||
{
|
||||
return BigInt(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the integer value from a BigInt to a std::vector of bytes
|
||||
* @param n the BigInt to use as integer source
|
||||
* @param base number-base of resulting byte array representation
|
||||
* @result secure_vector of bytes containing the integer with given base
|
||||
*/
|
||||
static std::vector<uint8_t> encode(const BigInt& n, Base base = Binary);
|
||||
static std::vector<uint8_t> encode(const BigInt& n, Base base);
|
||||
|
||||
/**
|
||||
* Encode the integer value from a BigInt to a secure_vector of bytes
|
||||
@@ -661,7 +750,7 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
|
||||
* @result secure_vector of bytes containing the integer with given base
|
||||
*/
|
||||
static secure_vector<uint8_t> encode_locked(const BigInt& n,
|
||||
Base base = Binary);
|
||||
Base base);
|
||||
|
||||
/**
|
||||
* Encode the integer value from a BigInt to a byte array
|
||||
@@ -670,7 +759,7 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
|
||||
* @param n the BigInt to use as integer source
|
||||
* @param base number-base of resulting byte array representation
|
||||
*/
|
||||
static void encode(uint8_t buf[], const BigInt& n, Base base = Binary);
|
||||
static void encode(uint8_t buf[], const BigInt& n, Base base);
|
||||
|
||||
/**
|
||||
* Create a BigInt from an integer in a byte array
|
||||
@@ -680,7 +769,7 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
|
||||
* @result BigInt representing the integer in the byte array
|
||||
*/
|
||||
static BigInt decode(const uint8_t buf[], size_t length,
|
||||
Base base = Binary);
|
||||
Base base);
|
||||
|
||||
/**
|
||||
* Create a BigInt from an integer in a byte array
|
||||
@@ -689,8 +778,10 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
|
||||
* @result BigInt representing the integer in the byte array
|
||||
*/
|
||||
static BigInt decode(const secure_vector<uint8_t>& buf,
|
||||
Base base = Binary)
|
||||
Base base)
|
||||
{
|
||||
if(base == Binary)
|
||||
return BigInt(buf);
|
||||
return BigInt::decode(buf.data(), buf.size(), base);
|
||||
}
|
||||
|
||||
@@ -700,9 +791,10 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
|
||||
* @param base number-base of the integer in buf
|
||||
* @result BigInt representing the integer in the byte array
|
||||
*/
|
||||
static BigInt decode(const std::vector<uint8_t>& buf,
|
||||
Base base = Binary)
|
||||
static BigInt decode(const std::vector<uint8_t>& buf, Base base)
|
||||
{
|
||||
if(base == Binary)
|
||||
return BigInt(buf);
|
||||
return BigInt::decode(buf.data(), buf.size(), base);
|
||||
}
|
||||
|
||||
@@ -750,6 +842,9 @@ BigInt BOTAN_PUBLIC_API(2,0) operator-(const BigInt& x, const BigInt& y);
|
||||
BigInt BOTAN_PUBLIC_API(2,7) operator-(const BigInt& x, word y);
|
||||
|
||||
BigInt BOTAN_PUBLIC_API(2,0) operator*(const BigInt& x, const BigInt& y);
|
||||
BigInt BOTAN_PUBLIC_API(2,8) operator*(const BigInt& x, word y);
|
||||
inline BigInt operator*(word x, const BigInt& y) { return y*x; }
|
||||
|
||||
BigInt BOTAN_PUBLIC_API(2,0) operator/(const BigInt& x, const BigInt& d);
|
||||
BigInt BOTAN_PUBLIC_API(2,0) operator%(const BigInt& x, const BigInt& m);
|
||||
word BOTAN_PUBLIC_API(2,0) operator%(const BigInt& x, word m);
|
||||
|
@@ -2,8 +2,6 @@
|
||||
BIGINT -> 20131128
|
||||
</defines>
|
||||
|
||||
load_on auto
|
||||
|
||||
<header:public>
|
||||
bigint.h
|
||||
divide.h
|
||||
|
@@ -353,11 +353,33 @@ void bigint_shl1(word x[], size_t x_size, size_t word_shift, size_t bit_shift)
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void bigint_shift_right_1(word x[], size_t x_size)
|
||||
{
|
||||
word carry = 0;
|
||||
size_t top = x_size;
|
||||
|
||||
while(top)
|
||||
{
|
||||
word w = x[top-1];
|
||||
x[top-1] = (w >> 1) | carry;
|
||||
carry = (w << (BOTAN_MP_WORD_BITS - 1));
|
||||
|
||||
top--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Single Operand Right Shift
|
||||
*/
|
||||
void bigint_shr1(word x[], size_t x_size, size_t word_shift, size_t bit_shift)
|
||||
{
|
||||
if(word_shift == 0 && bit_shift == 1)
|
||||
return bigint_shift_right_1(x, x_size);
|
||||
|
||||
if(x_size < word_shift)
|
||||
{
|
||||
clear_mem(x, x_size);
|
||||
|
@@ -14,15 +14,10 @@
|
||||
|
||||
namespace Botan {
|
||||
|
||||
#if (BOTAN_MP_WORD_BITS == 8)
|
||||
typedef uint16_t dword;
|
||||
#define BOTAN_HAS_MP_DWORD
|
||||
#elif (BOTAN_MP_WORD_BITS == 16)
|
||||
typedef uint32_t dword;
|
||||
#define BOTAN_HAS_MP_DWORD
|
||||
#elif (BOTAN_MP_WORD_BITS == 32)
|
||||
#if (BOTAN_MP_WORD_BITS == 32)
|
||||
typedef uint64_t dword;
|
||||
#define BOTAN_HAS_MP_DWORD
|
||||
|
||||
#elif (BOTAN_MP_WORD_BITS == 64)
|
||||
#if defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
|
||||
typedef uint128_t dword;
|
||||
@@ -32,21 +27,19 @@ namespace Botan {
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error BOTAN_MP_WORD_BITS must be 8, 16, 32, or 64
|
||||
#error BOTAN_MP_WORD_BITS must be 32 or 64
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_TARGET_ARCH_IS_X86_32) && (BOTAN_MP_WORD_BITS == 32)
|
||||
|
||||
#if defined(BOTAN_USE_GCC_INLINE_ASM)
|
||||
#define BOTAN_MP_USE_X86_32_ASM
|
||||
#define ASM(x) x "\n\t"
|
||||
#elif defined(BOTAN_BUILD_COMPILER_IS_MSVC)
|
||||
#define BOTAN_MP_USE_X86_32_MSVC_ASM
|
||||
#endif
|
||||
|
||||
#elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && (BOTAN_MP_WORD_BITS == 64) && (BOTAN_USE_GCC_INLINE_ASM)
|
||||
#define BOTAN_MP_USE_X86_64_ASM
|
||||
#define ASM(x) x "\n\t"
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_MP_USE_X86_32_ASM) || defined(BOTAN_MP_USE_X86_64_ASM)
|
||||
|
@@ -23,8 +23,6 @@ namespace Botan {
|
||||
BOTAN_PUBLIC_API(2,0) const BigInt& prime_p521();
|
||||
BOTAN_PUBLIC_API(2,0) void redc_p521(BigInt& x, secure_vector<word>& ws);
|
||||
|
||||
#if (BOTAN_MP_WORD_BITS == 32) || (BOTAN_MP_WORD_BITS == 64)
|
||||
|
||||
#define BOTAN_HAS_NIST_PRIME_REDUCERS_W32
|
||||
|
||||
BOTAN_PUBLIC_API(2,0) const BigInt& prime_p384();
|
||||
@@ -39,8 +37,6 @@ BOTAN_PUBLIC_API(2,0) void redc_p224(BigInt& x, secure_vector<word>& ws);
|
||||
BOTAN_PUBLIC_API(2,0) const BigInt& prime_p192();
|
||||
BOTAN_PUBLIC_API(2,0) void redc_p192(BigInt& x, secure_vector<word>& ws);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -2,8 +2,6 @@
|
||||
NUMBERTHEORY -> 20131128
|
||||
</defines>
|
||||
|
||||
load_on auto
|
||||
|
||||
<header:public>
|
||||
curve_nistp.h
|
||||
numthry.h
|
||||
@@ -13,6 +11,7 @@ monty.h
|
||||
</header:public>
|
||||
|
||||
<header:internal>
|
||||
primality.h
|
||||
def_powm.h
|
||||
monty_exp.h
|
||||
</header:internal>
|
||||
|
@@ -14,12 +14,11 @@ namespace Botan {
|
||||
*/
|
||||
int32_t jacobi(const BigInt& a, const BigInt& n)
|
||||
{
|
||||
if(a.is_negative())
|
||||
throw Invalid_Argument("jacobi: first argument must be non-negative");
|
||||
if(n.is_even() || n < 2)
|
||||
throw Invalid_Argument("jacobi: second argument must be odd and > 1");
|
||||
|
||||
BigInt x = a, y = n;
|
||||
BigInt x = a % n;
|
||||
BigInt y = n;
|
||||
int32_t J = 1;
|
||||
|
||||
while(y > 1)
|
||||
|
@@ -14,7 +14,7 @@ namespace Botan {
|
||||
|
||||
namespace {
|
||||
|
||||
class Prime_Sieve
|
||||
class Prime_Sieve final
|
||||
{
|
||||
public:
|
||||
Prime_Sieve(const BigInt& init_value) : m_sieve(PRIME_TABLE_SIZE)
|
||||
|
@@ -13,7 +13,7 @@ namespace Botan {
|
||||
Montgomery_Params::Montgomery_Params(const BigInt& p,
|
||||
const Modular_Reducer& mod_p)
|
||||
{
|
||||
if(p.is_negative() || p.is_even())
|
||||
if(p.is_even() || p < 3)
|
||||
throw Invalid_Argument("Montgomery_Params invalid modulus");
|
||||
|
||||
m_p = p;
|
||||
|
@@ -44,7 +44,7 @@ Montgomery_Exponentation_State::Montgomery_Exponentation_State(std::shared_ptr<c
|
||||
if(m_window_bits < 1 || m_window_bits > 12) // really even 8 is too large ...
|
||||
throw Invalid_Argument("Invalid window bits for Montgomery exponentiation");
|
||||
|
||||
const size_t window_size = (1U << m_window_bits);
|
||||
const size_t window_size = (static_cast<size_t>(1) << m_window_bits);
|
||||
|
||||
m_g.reserve(window_size);
|
||||
|
||||
@@ -233,10 +233,10 @@ BigInt monty_multi_exp(std::shared_ptr<const Montgomery_Params> params_p,
|
||||
H.square_this(ws);
|
||||
}
|
||||
|
||||
const uint8_t z1_b = z1.get_substring(z_bits - i - 2, 2);
|
||||
const uint8_t z2_b = z2.get_substring(z_bits - i - 2, 2);
|
||||
const uint32_t z1_b = z1.get_substring(z_bits - i - 2, 2);
|
||||
const uint32_t z2_b = z2.get_substring(z_bits - i - 2, 2);
|
||||
|
||||
const uint8_t z12 = (4*z2_b) + z1_b;
|
||||
const uint32_t z12 = (4*z2_b) + z1_b;
|
||||
|
||||
H.mul_by(*M[z12], ws);
|
||||
}
|
||||
|
@@ -43,7 +43,7 @@ void redc_p521(BigInt& x, secure_vector<word>& ws)
|
||||
BOTAN_ASSERT_EQUAL(carry, 0, "Final carry in P-521 reduction");
|
||||
|
||||
// Now find the actual carry in bit 522
|
||||
const uint8_t bit_522_set = x.word_at(p_full_words) >> (p_top_bits);
|
||||
const word bit_522_set = x.word_at(p_full_words) >> p_top_bits;
|
||||
|
||||
#if (BOTAN_MP_WORD_BITS == 64)
|
||||
static const word p521_words[9] = {
|
||||
@@ -91,10 +91,8 @@ inline uint32_t get_uint32_t(const BigInt& x, size_t i)
|
||||
{
|
||||
#if (BOTAN_MP_WORD_BITS == 32)
|
||||
return x.word_at(i);
|
||||
#elif (BOTAN_MP_WORD_BITS == 64)
|
||||
return static_cast<uint32_t>(x.word_at(i/2) >> ((i % 2)*32));
|
||||
#else
|
||||
#error "Not implemented"
|
||||
return static_cast<uint32_t>(x.word_at(i/2) >> ((i % 2)*32));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -103,10 +101,8 @@ inline void set_words(BigInt& x, size_t i, uint32_t R0, uint32_t R1)
|
||||
#if (BOTAN_MP_WORD_BITS == 32)
|
||||
x.set_word_at(i, R0);
|
||||
x.set_word_at(i+1, R1);
|
||||
#elif (BOTAN_MP_WORD_BITS == 64)
|
||||
x.set_word_at(i/2, (static_cast<uint64_t>(R1) << 32) | R0);
|
||||
#else
|
||||
#error "Not implemented"
|
||||
x.set_word_at(i/2, (static_cast<uint64_t>(R1) << 32) | R0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include <botan/internal/mp_core.h>
|
||||
#include <botan/internal/ct_utils.h>
|
||||
#include <botan/internal/monty_exp.h>
|
||||
#include <botan/internal/primality.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Botan {
|
||||
@@ -434,78 +435,43 @@ BigInt power_mod(const BigInt& base, const BigInt& exp, const BigInt& mod)
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool mr_witness(BigInt&& y,
|
||||
const Modular_Reducer& reducer_n,
|
||||
const BigInt& n_minus_1, size_t s)
|
||||
BigInt is_perfect_square(const BigInt& C)
|
||||
{
|
||||
if(y == 1 || y == n_minus_1)
|
||||
return false;
|
||||
if(C < 1)
|
||||
throw Invalid_Argument("is_perfect_square requires C >= 1");
|
||||
if(C == 1)
|
||||
return 1;
|
||||
|
||||
for(size_t i = 1; i != s; ++i)
|
||||
const size_t n = C.bits();
|
||||
const size_t m = (n + 1) / 2;
|
||||
const BigInt B = C + BigInt::power_of_2(m);
|
||||
|
||||
BigInt X = BigInt::power_of_2(m) - 1;
|
||||
BigInt X2 = (X*X);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
y = reducer_n.square(y);
|
||||
X = (X2 + C) / (2*X);
|
||||
X2 = (X*X);
|
||||
|
||||
if(y == 1) // found a non-trivial square root
|
||||
return true;
|
||||
|
||||
/*
|
||||
-1 is the trivial square root of unity, so ``a`` is not a
|
||||
witness for this number - give up
|
||||
*/
|
||||
if(y == n_minus_1)
|
||||
return false;
|
||||
if(X2 < B)
|
||||
break;
|
||||
}
|
||||
|
||||
return true; // is a witness
|
||||
if(X2 == C)
|
||||
return X;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t mr_test_iterations(size_t n_bits, size_t prob, bool random)
|
||||
{
|
||||
const size_t base = (prob + 2) / 2; // worst case 4^-t error rate
|
||||
|
||||
/*
|
||||
* If the candidate prime was maliciously constructed, we can't rely
|
||||
* on arguments based on p being random.
|
||||
*/
|
||||
if(random == false)
|
||||
return base;
|
||||
|
||||
/*
|
||||
* For randomly chosen numbers we can use the estimates from
|
||||
* http://www.math.dartmouth.edu/~carlp/PDF/paper88.pdf
|
||||
*
|
||||
* These values are derived from the inequality for p(k,t) given on
|
||||
* the second page.
|
||||
*/
|
||||
if(prob <= 128)
|
||||
{
|
||||
if(n_bits >= 1536)
|
||||
return 4; // < 2^-133
|
||||
if(n_bits >= 1024)
|
||||
return 6; // < 2^-133
|
||||
if(n_bits >= 512)
|
||||
return 12; // < 2^-129
|
||||
if(n_bits >= 256)
|
||||
return 29; // < 2^-128
|
||||
}
|
||||
|
||||
/*
|
||||
If the user desires a smaller error probability than we have
|
||||
precomputed error estimates for, just fall back to using the worst
|
||||
case error rate.
|
||||
*/
|
||||
return base;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Test for primality using Miller-Rabin
|
||||
*/
|
||||
bool is_prime(const BigInt& n, RandomNumberGenerator& rng,
|
||||
size_t prob, bool is_random)
|
||||
bool is_prime(const BigInt& n,
|
||||
RandomNumberGenerator& rng,
|
||||
size_t prob,
|
||||
bool is_random)
|
||||
{
|
||||
if(n == 2)
|
||||
return true;
|
||||
@@ -520,47 +486,21 @@ bool is_prime(const BigInt& n, RandomNumberGenerator& rng,
|
||||
return std::binary_search(PRIMES, PRIMES + PRIME_TABLE_SIZE, num);
|
||||
}
|
||||
|
||||
const size_t test_iterations =
|
||||
mr_test_iterations(n.bits(), prob, is_random && rng.is_seeded());
|
||||
const size_t t = miller_rabin_test_iterations(n.bits(), prob, is_random);
|
||||
|
||||
const BigInt n_minus_1 = n - 1;
|
||||
const size_t s = low_zero_bits(n_minus_1);
|
||||
const BigInt nm1_s = n_minus_1 >> s;
|
||||
const size_t n_bits = n.bits();
|
||||
|
||||
const Modular_Reducer mod_n(n);
|
||||
auto monty_n = std::make_shared<Montgomery_Params>(n, mod_n);
|
||||
|
||||
const size_t powm_window = 4;
|
||||
|
||||
for(size_t i = 0; i != test_iterations; ++i)
|
||||
{
|
||||
BigInt a;
|
||||
Modular_Reducer mod_n(n);
|
||||
|
||||
if(rng.is_seeded())
|
||||
{
|
||||
a = BigInt::random_integer(rng, 2, n_minus_1);
|
||||
if(is_miller_rabin_probable_prime(n, mod_n, rng, t) == false)
|
||||
return false;
|
||||
|
||||
return is_lucas_probable_prime(n, mod_n);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If passed a null RNG just use 2,3,5, ... as bases
|
||||
*
|
||||
* This is not ideal but in certain circumstances we need to
|
||||
* test for primality but have no RNG available.
|
||||
*/
|
||||
a = PRIMES[i];
|
||||
return is_bailie_psw_probable_prime(n, mod_n);
|
||||
}
|
||||
|
||||
auto powm_a_n = monty_precompute(monty_n, a, powm_window);
|
||||
|
||||
BigInt y = monty_execute(*powm_a_n, nm1_s, n_bits);
|
||||
|
||||
if(mr_witness(std::move(y), mod_n, n_minus_1, s))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Number Theory Functions
|
||||
* (C) 1999-2007 Jack Lloyd
|
||||
* (C) 1999-2007,2018 Jack Lloyd
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
*/
|
||||
@@ -126,8 +126,7 @@ BigInt BOTAN_PUBLIC_API(2,0) normalized_montgomery_inverse(const BigInt& a, cons
|
||||
* @param n is an odd integer > 1
|
||||
* @return (n / m)
|
||||
*/
|
||||
int32_t BOTAN_PUBLIC_API(2,0) jacobi(const BigInt& a,
|
||||
const BigInt& n);
|
||||
int32_t BOTAN_PUBLIC_API(2,0) jacobi(const BigInt& a, const BigInt& n);
|
||||
|
||||
/**
|
||||
* Modular exponentation
|
||||
@@ -175,9 +174,18 @@ size_t BOTAN_PUBLIC_API(2,0) low_zero_bits(const BigInt& x);
|
||||
*/
|
||||
bool BOTAN_PUBLIC_API(2,0) is_prime(const BigInt& n,
|
||||
RandomNumberGenerator& rng,
|
||||
size_t prob = 56,
|
||||
size_t prob = 64,
|
||||
bool is_random = false);
|
||||
|
||||
/**
|
||||
* Test if the positive integer x is a perfect square ie if there
|
||||
* exists some positive integer y st y*y == x
|
||||
* See FIPS 186-4 sec C.4
|
||||
* @return 0 if the integer is not a perfect square, otherwise
|
||||
* returns the positive y st y*y == x
|
||||
*/
|
||||
BigInt BOTAN_PUBLIC_API(2,8) is_perfect_square(const BigInt& x);
|
||||
|
||||
inline bool quick_check_prime(const BigInt& n, RandomNumberGenerator& rng)
|
||||
{ return is_prime(n, rng, 32); }
|
||||
|
||||
@@ -187,7 +195,6 @@ inline bool check_prime(const BigInt& n, RandomNumberGenerator& rng)
|
||||
inline bool verify_prime(const BigInt& n, RandomNumberGenerator& rng)
|
||||
{ return is_prime(n, rng, 80); }
|
||||
|
||||
|
||||
/**
|
||||
* Randomly generate a prime suitable for discrete logarithm parameters
|
||||
* @param rng a random number generator
|
||||
|
@@ -25,7 +25,7 @@ void Fixed_Window_Exponentiator::set_base(const BigInt& base)
|
||||
{
|
||||
m_window_bits = Power_Mod::window_bits(m_exp.bits(), base.bits(), m_hints);
|
||||
|
||||
m_g.resize(1U << m_window_bits);
|
||||
m_g.resize(static_cast<size_t>(1) << m_window_bits);
|
||||
m_g[0] = 1;
|
||||
m_g[1] = base;
|
||||
|
||||
|
206
src/libs/3rdparty/botan/src/lib/math/numbertheory/primality.cpp
vendored
Normal file
206
src/libs/3rdparty/botan/src/lib/math/numbertheory/primality.cpp
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* (C) 2016,2018 Jack Lloyd
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
*/
|
||||
|
||||
#include <botan/internal/primality.h>
|
||||
#include <botan/internal/monty_exp.h>
|
||||
#include <botan/bigint.h>
|
||||
#include <botan/monty.h>
|
||||
#include <botan/reducer.h>
|
||||
#include <botan/rng.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Botan {
|
||||
|
||||
bool is_lucas_probable_prime(const BigInt& C, const Modular_Reducer& mod_C)
|
||||
{
|
||||
if(C <= 1)
|
||||
return false;
|
||||
else if(C == 2)
|
||||
return true;
|
||||
else if(C.is_even())
|
||||
return false;
|
||||
else if(C == 3 || C == 5 || C == 7 || C == 11 || C == 13)
|
||||
return true;
|
||||
|
||||
BigInt D = 5;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int32_t j = jacobi(D, C);
|
||||
if(j == 0)
|
||||
return false;
|
||||
|
||||
if(j == -1)
|
||||
break;
|
||||
|
||||
// Check 5, -7, 9, -11, 13, -15, 17, ...
|
||||
if(D.is_negative())
|
||||
{
|
||||
D.flip_sign();
|
||||
D += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
D += 2;
|
||||
D.flip_sign();
|
||||
}
|
||||
|
||||
if(D == 17 && is_perfect_square(C).is_nonzero())
|
||||
return false;
|
||||
}
|
||||
|
||||
const BigInt K = C + 1;
|
||||
const size_t K_bits = K.bits() - 1;
|
||||
|
||||
BigInt U = 1;
|
||||
BigInt V = 1;
|
||||
|
||||
BigInt Ut, Vt, U2, V2;
|
||||
|
||||
for(size_t i = 0; i != K_bits; ++i)
|
||||
{
|
||||
const uint8_t k_bit = K.get_bit(K_bits - 1 - i);
|
||||
|
||||
Ut = mod_C.multiply(U, V);
|
||||
|
||||
Vt = mod_C.reduce(mod_C.square(V) + mod_C.multiply(D, mod_C.square(U)));
|
||||
if(Vt.is_odd())
|
||||
Vt += C;
|
||||
Vt >>= 1;
|
||||
Vt = mod_C.reduce(Vt);
|
||||
|
||||
U = Ut;
|
||||
V = Vt;
|
||||
|
||||
U2 = mod_C.reduce(Ut + Vt);
|
||||
if(U2.is_odd())
|
||||
U2 += C;
|
||||
U2 >>= 1;
|
||||
|
||||
V2 = mod_C.reduce(Vt + Ut*D);
|
||||
if(V2.is_odd())
|
||||
V2 += C;
|
||||
V2 >>= 1;
|
||||
|
||||
U.ct_cond_assign(k_bit, U2);
|
||||
V.ct_cond_assign(k_bit, V2);
|
||||
}
|
||||
|
||||
return (U == 0);
|
||||
}
|
||||
|
||||
bool is_bailie_psw_probable_prime(const BigInt& n, const Modular_Reducer& mod_n)
|
||||
{
|
||||
auto monty_n = std::make_shared<Montgomery_Params>(n, mod_n);
|
||||
return passes_miller_rabin_test(n, mod_n, monty_n, 2) && is_lucas_probable_prime(n, mod_n);
|
||||
}
|
||||
|
||||
bool is_bailie_psw_probable_prime(const BigInt& n)
|
||||
{
|
||||
Modular_Reducer mod_n(n);
|
||||
return is_bailie_psw_probable_prime(n, mod_n);
|
||||
}
|
||||
|
||||
bool passes_miller_rabin_test(const BigInt& n,
|
||||
const Modular_Reducer& mod_n,
|
||||
const std::shared_ptr<Montgomery_Params>& monty_n,
|
||||
const BigInt& a)
|
||||
{
|
||||
BOTAN_ASSERT_NOMSG(n > 1);
|
||||
|
||||
const BigInt n_minus_1 = n - 1;
|
||||
const size_t s = low_zero_bits(n_minus_1);
|
||||
const BigInt nm1_s = n_minus_1 >> s;
|
||||
const size_t n_bits = n.bits();
|
||||
|
||||
const size_t powm_window = 4;
|
||||
|
||||
auto powm_a_n = monty_precompute(monty_n, a, powm_window);
|
||||
|
||||
BigInt y = monty_execute(*powm_a_n, nm1_s, n_bits);
|
||||
|
||||
if(y == 1 || y == n_minus_1)
|
||||
return true;
|
||||
|
||||
for(size_t i = 1; i != s; ++i)
|
||||
{
|
||||
y = mod_n.square(y);
|
||||
|
||||
if(y == 1) // found a non-trivial square root
|
||||
return false;
|
||||
|
||||
/*
|
||||
-1 is the trivial square root of unity, so ``a`` is not a
|
||||
witness for this number - give up
|
||||
*/
|
||||
if(y == n_minus_1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_miller_rabin_probable_prime(const BigInt& n,
|
||||
const Modular_Reducer& mod_n,
|
||||
RandomNumberGenerator& rng,
|
||||
size_t test_iterations)
|
||||
{
|
||||
BOTAN_ASSERT_NOMSG(n > 1);
|
||||
|
||||
auto monty_n = std::make_shared<Montgomery_Params>(n, mod_n);
|
||||
|
||||
for(size_t i = 0; i != test_iterations; ++i)
|
||||
{
|
||||
const BigInt a = BigInt::random_integer(rng, 2, n);
|
||||
|
||||
if(!passes_miller_rabin_test(n, mod_n, monty_n, a))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Failed to find a counterexample
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
size_t miller_rabin_test_iterations(size_t n_bits, size_t prob, bool random)
|
||||
{
|
||||
const size_t base = (prob + 2) / 2; // worst case 4^-t error rate
|
||||
|
||||
/*
|
||||
* If the candidate prime was maliciously constructed, we can't rely
|
||||
* on arguments based on p being random.
|
||||
*/
|
||||
if(random == false)
|
||||
return base;
|
||||
|
||||
/*
|
||||
* For randomly chosen numbers we can use the estimates from
|
||||
* http://www.math.dartmouth.edu/~carlp/PDF/paper88.pdf
|
||||
*
|
||||
* These values are derived from the inequality for p(k,t) given on
|
||||
* the second page.
|
||||
*/
|
||||
if(prob <= 128)
|
||||
{
|
||||
if(n_bits >= 1536)
|
||||
return 4; // < 2^-133
|
||||
if(n_bits >= 1024)
|
||||
return 6; // < 2^-133
|
||||
if(n_bits >= 512)
|
||||
return 12; // < 2^-129
|
||||
if(n_bits >= 256)
|
||||
return 29; // < 2^-128
|
||||
}
|
||||
|
||||
/*
|
||||
If the user desires a smaller error probability than we have
|
||||
precomputed error estimates for, just fall back to using the worst
|
||||
case error rate.
|
||||
*/
|
||||
return base;
|
||||
}
|
||||
|
||||
}
|
100
src/libs/3rdparty/botan/src/lib/math/numbertheory/primality.h
vendored
Normal file
100
src/libs/3rdparty/botan/src/lib/math/numbertheory/primality.h
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* (C) 2018 Jack Lloyd
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_PRIMALITY_TEST_H_
|
||||
#define BOTAN_PRIMALITY_TEST_H_
|
||||
|
||||
#include <botan/types.h>
|
||||
#include <memory>
|
||||
|
||||
namespace Botan {
|
||||
|
||||
class BigInt;
|
||||
class Modular_Reducer;
|
||||
class Montgomery_Params;
|
||||
class RandomNumberGenerator;
|
||||
|
||||
/**
|
||||
* Perform Lucas primality test
|
||||
* @see FIPS 186-4 C.3.3
|
||||
*
|
||||
* @warning it is possible to construct composite integers which pass
|
||||
* this test alone.
|
||||
*
|
||||
* @param n the positive integer to test
|
||||
* @param mod_n a pre-created Modular_Reducer for n
|
||||
* @return true if n seems probably prime, false if n is composite
|
||||
*/
|
||||
bool BOTAN_TEST_API is_lucas_probable_prime(const BigInt& n, const Modular_Reducer& mod_n);
|
||||
|
||||
/**
|
||||
* Perform Bailie-PSW primality test
|
||||
*
|
||||
* This is a combination of Miller-Rabin with base 2 and a Lucas test. No known
|
||||
* composite integer passes both tests, though it is conjectured that infinitely
|
||||
* many composite counterexamples exist.
|
||||
*
|
||||
* @param n the positive integer to test
|
||||
* @param mod_n a pre-created Modular_Reducer for n
|
||||
* @return true if n seems probably prime, false if n is composite
|
||||
*/
|
||||
bool BOTAN_TEST_API is_bailie_psw_probable_prime(const BigInt& n, const Modular_Reducer& mod_n);
|
||||
|
||||
/**
|
||||
* Perform Bailie-PSW primality test
|
||||
*
|
||||
* This is a combination of Miller-Rabin with base 2 and a Lucas test. No known
|
||||
* composite integer passes both tests, though it is conjectured that infinitely
|
||||
* many composite counterexamples exist.
|
||||
*
|
||||
* @param n the positive integer to test
|
||||
* @return true if n seems probably prime, false if n is composite
|
||||
*/
|
||||
bool is_bailie_psw_probable_prime(const BigInt& n);
|
||||
|
||||
/**
|
||||
* Return required number of Miller-Rabin tests in order to
|
||||
* reach the specified probability of error.
|
||||
*
|
||||
* @param n_bits the bit-length of the integer being tested
|
||||
* @param prob chance of false positive is bounded by 1/2**prob
|
||||
* @param random is set if (and only if) the integer was randomly generated by us
|
||||
* and thus cannot have been maliciously constructed.
|
||||
*/
|
||||
size_t miller_rabin_test_iterations(size_t n_bits, size_t prob, bool random);
|
||||
|
||||
/**
|
||||
* Perform a single Miller-Rabin test with specified base
|
||||
*
|
||||
* @param n the positive integer to test
|
||||
* @param mod_n a pre-created Modular_Reducer for n
|
||||
* @param monty_n Montgomery parameters for n
|
||||
* @param a the base to check
|
||||
* @return result of primality test
|
||||
*/
|
||||
bool passes_miller_rabin_test(const BigInt& n,
|
||||
const Modular_Reducer& mod_n,
|
||||
const std::shared_ptr<Montgomery_Params>& monty_n,
|
||||
const BigInt& a);
|
||||
|
||||
/**
|
||||
* Perform t iterations of a Miller-Rabin primality test with random bases
|
||||
*
|
||||
* @param n the positive integer to test
|
||||
* @param mod_n a pre-created Modular_Reducer for n
|
||||
* @param rng a random number generator
|
||||
* @param t number of tests to perform
|
||||
*
|
||||
* @return result of primality test
|
||||
*/
|
||||
bool BOTAN_TEST_API is_miller_rabin_probable_prime(const BigInt& n,
|
||||
const Modular_Reducer& mod_n,
|
||||
RandomNumberGenerator& rng,
|
||||
size_t t);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -32,11 +32,18 @@ Modular_Reducer::Modular_Reducer(const BigInt& mod)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Barrett Reduction
|
||||
*/
|
||||
BigInt Modular_Reducer::reduce(const BigInt& x) const
|
||||
{
|
||||
BigInt r;
|
||||
secure_vector<word> ws;
|
||||
reduce(r, x, ws);
|
||||
return r;
|
||||
}
|
||||
|
||||
void Modular_Reducer::reduce(BigInt& t1, const BigInt& x, secure_vector<word>& ws) const
|
||||
{
|
||||
if(&t1 == &x)
|
||||
throw Invalid_State("Modular_Reducer arguments cannot alias");
|
||||
if(m_mod_words == 0)
|
||||
throw Invalid_State("Modular_Reducer: Never initalized");
|
||||
|
||||
@@ -45,12 +52,11 @@ BigInt Modular_Reducer::reduce(const BigInt& x) const
|
||||
if(x_sw >= (2*m_mod_words - 1) && x.cmp(m_modulus_2, false) >= 0)
|
||||
{
|
||||
// too big, fall back to normal division
|
||||
return (x % m_modulus);
|
||||
t1 = x % m_modulus;
|
||||
return;
|
||||
}
|
||||
|
||||
secure_vector<word> ws;
|
||||
|
||||
BigInt t1 = x;
|
||||
t1 = x;
|
||||
t1.set_sign(BigInt::Positive);
|
||||
t1 >>= (BOTAN_MP_WORD_BITS * (m_mod_words - 1));
|
||||
|
||||
@@ -83,8 +89,6 @@ BigInt Modular_Reducer::reduce(const BigInt& x) const
|
||||
{
|
||||
t1.rev_sub(m_modulus.data(), m_modulus.size(), ws);
|
||||
}
|
||||
|
||||
return t1;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -47,6 +47,8 @@ class BOTAN_PUBLIC_API(2,0) Modular_Reducer
|
||||
BigInt cube(const BigInt& x) const
|
||||
{ return multiply(x, this->square(x)); }
|
||||
|
||||
void reduce(BigInt& out, const BigInt& x, secure_vector<word>& ws) const;
|
||||
|
||||
bool initialized() const { return (m_mod_words != 0); }
|
||||
|
||||
Modular_Reducer() { m_mod_words = 0; }
|
||||
|
@@ -2,6 +2,7 @@
|
||||
* CBC Mode
|
||||
* (C) 1999-2007,2013,2017 Jack Lloyd
|
||||
* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
|
||||
* (C) 2018 Ribose Inc
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
*/
|
||||
@@ -15,9 +16,9 @@ namespace Botan {
|
||||
CBC_Mode::CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
|
||||
m_cipher(cipher),
|
||||
m_padding(padding),
|
||||
m_state(m_cipher->block_size())
|
||||
m_block_size(cipher->block_size())
|
||||
{
|
||||
if(m_padding && !m_padding->valid_blocksize(cipher->block_size()))
|
||||
if(m_padding && !m_padding->valid_blocksize(m_block_size))
|
||||
throw Invalid_Argument("Padding " + m_padding->name() +
|
||||
" cannot be used with " +
|
||||
cipher->name() + "/CBC");
|
||||
@@ -31,7 +32,7 @@ void CBC_Mode::clear()
|
||||
|
||||
void CBC_Mode::reset()
|
||||
{
|
||||
zeroise(m_state);
|
||||
m_state.clear();
|
||||
}
|
||||
|
||||
std::string CBC_Mode::name() const
|
||||
@@ -65,6 +66,7 @@ bool CBC_Mode::valid_nonce_length(size_t n) const
|
||||
void CBC_Mode::key_schedule(const uint8_t key[], size_t length)
|
||||
{
|
||||
m_cipher->set_key(key, length);
|
||||
m_state.clear();
|
||||
}
|
||||
|
||||
void CBC_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
|
||||
@@ -79,6 +81,9 @@ void CBC_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
|
||||
*/
|
||||
if(nonce_len)
|
||||
m_state.assign(nonce, nonce + nonce_len);
|
||||
else if(m_state.empty())
|
||||
m_state.resize(m_cipher->block_size());
|
||||
// else leave the state alone
|
||||
}
|
||||
|
||||
size_t CBC_Encryption::minimum_final_size() const
|
||||
@@ -96,6 +101,7 @@ size_t CBC_Encryption::output_length(size_t input_length) const
|
||||
|
||||
size_t CBC_Encryption::process(uint8_t buf[], size_t sz)
|
||||
{
|
||||
BOTAN_STATE_CHECK(state().empty() == false);
|
||||
const size_t BS = block_size();
|
||||
|
||||
BOTAN_ASSERT(sz % BS == 0, "CBC input is full blocks");
|
||||
@@ -120,6 +126,7 @@ size_t CBC_Encryption::process(uint8_t buf[], size_t sz)
|
||||
|
||||
void CBC_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
|
||||
{
|
||||
BOTAN_STATE_CHECK(state().empty() == false);
|
||||
BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
|
||||
|
||||
const size_t BS = block_size();
|
||||
@@ -151,6 +158,7 @@ size_t CTS_Encryption::output_length(size_t input_length) const
|
||||
|
||||
void CTS_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
|
||||
{
|
||||
BOTAN_STATE_CHECK(state().empty() == false);
|
||||
BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
|
||||
uint8_t* buf = buffer.data() + offset;
|
||||
const size_t sz = buffer.size() - offset;
|
||||
@@ -205,6 +213,8 @@ size_t CBC_Decryption::minimum_final_size() const
|
||||
|
||||
size_t CBC_Decryption::process(uint8_t buf[], size_t sz)
|
||||
{
|
||||
BOTAN_STATE_CHECK(state().empty() == false);
|
||||
|
||||
const size_t BS = block_size();
|
||||
|
||||
BOTAN_ASSERT(sz % BS == 0, "Input is full blocks");
|
||||
@@ -231,6 +241,7 @@ size_t CBC_Decryption::process(uint8_t buf[], size_t sz)
|
||||
|
||||
void CBC_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
|
||||
{
|
||||
BOTAN_STATE_CHECK(state().empty() == false);
|
||||
BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
|
||||
const size_t sz = buffer.size() - offset;
|
||||
|
||||
@@ -251,7 +262,7 @@ void CBC_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
|
||||
|
||||
void CBC_Decryption::reset()
|
||||
{
|
||||
zeroise(state());
|
||||
CBC_Mode::reset();
|
||||
zeroise(m_tempbuf);
|
||||
}
|
||||
|
||||
@@ -267,6 +278,7 @@ size_t CTS_Decryption::minimum_final_size() const
|
||||
|
||||
void CTS_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
|
||||
{
|
||||
BOTAN_STATE_CHECK(state().empty() == false);
|
||||
BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
|
||||
const size_t sz = buffer.size() - offset;
|
||||
uint8_t* buf = buffer.data() + offset;
|
||||
|
@@ -46,9 +46,9 @@ class BOTAN_PUBLIC_API(2,0) CBC_Mode : public Cipher_Mode
|
||||
return *m_padding;
|
||||
}
|
||||
|
||||
secure_vector<uint8_t>& state() { return m_state; }
|
||||
size_t block_size() const { return m_block_size; }
|
||||
|
||||
size_t block_size() const { return m_state.size(); }
|
||||
secure_vector<uint8_t>& state() { return m_state; }
|
||||
|
||||
uint8_t* state_ptr() { return m_state.data(); }
|
||||
|
||||
@@ -60,6 +60,7 @@ class BOTAN_PUBLIC_API(2,0) CBC_Mode : public Cipher_Mode
|
||||
std::unique_ptr<BlockCipher> m_cipher;
|
||||
std::unique_ptr<BlockCipherModePaddingMethod> m_padding;
|
||||
secure_vector<uint8_t> m_state;
|
||||
size_t m_block_size;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -35,6 +35,10 @@
|
||||
#include <botan/internal/openssl.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_COMMONCRYPTO)
|
||||
#include <botan/internal/commoncrypto.h>
|
||||
#endif
|
||||
|
||||
namespace Botan {
|
||||
|
||||
std::unique_ptr<Cipher_Mode> Cipher_Mode::create_or_throw(const std::string& algo,
|
||||
@@ -51,6 +55,19 @@ std::unique_ptr<Cipher_Mode> Cipher_Mode::create(const std::string& algo,
|
||||
Cipher_Dir direction,
|
||||
const std::string& provider)
|
||||
{
|
||||
#if defined(BOTAN_HAS_COMMONCRYPTO)
|
||||
if(provider.empty() || provider == "commoncrypto")
|
||||
{
|
||||
std::unique_ptr<Cipher_Mode> commoncrypto_cipher(make_commoncrypto_cipher_mode(algo, direction));
|
||||
|
||||
if(commoncrypto_cipher)
|
||||
return commoncrypto_cipher;
|
||||
|
||||
if(!provider.empty())
|
||||
return std::unique_ptr<Cipher_Mode>();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_OPENSSL)
|
||||
if(provider.empty() || provider == "openssl")
|
||||
{
|
||||
@@ -172,7 +189,7 @@ std::unique_ptr<Cipher_Mode> Cipher_Mode::create(const std::string& algo,
|
||||
//static
|
||||
std::vector<std::string> Cipher_Mode::providers(const std::string& algo_spec)
|
||||
{
|
||||
const std::vector<std::string>& possible = { "base", "openssl" };
|
||||
const std::vector<std::string>& possible = { "base", "openssl", "commoncrypto" };
|
||||
std::vector<std::string> providers;
|
||||
for(auto&& prov : possible)
|
||||
{
|
||||
|
@@ -9,9 +9,8 @@
|
||||
#define BOTAN_CIPHER_MODE_H_
|
||||
|
||||
#include <botan/secmem.h>
|
||||
#include <botan/key_spec.h>
|
||||
#include <botan/sym_algo.h>
|
||||
#include <botan/exceptn.h>
|
||||
#include <botan/symkey.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -26,11 +25,9 @@ enum Cipher_Dir : int { ENCRYPTION, DECRYPTION };
|
||||
/**
|
||||
* Interface for cipher modes
|
||||
*/
|
||||
class BOTAN_PUBLIC_API(2,0) Cipher_Mode
|
||||
class BOTAN_PUBLIC_API(2,0) Cipher_Mode : public SymmetricAlgorithm
|
||||
{
|
||||
public:
|
||||
virtual ~Cipher_Mode() = default;
|
||||
|
||||
/**
|
||||
* @return list of available providers for this algorithm, empty if not available
|
||||
* @param algo_spec algorithm name
|
||||
@@ -133,8 +130,9 @@ class BOTAN_PUBLIC_API(2,0) Cipher_Mode
|
||||
|
||||
/**
|
||||
* Returns the size of the output if this transform is used to process a
|
||||
* message with input_length bytes. Will throw if unable to give a precise
|
||||
* answer.
|
||||
* message with input_length bytes. In most cases the answer is precise.
|
||||
* If it is not possible to precise (namely for CBC decryption) instead a
|
||||
* lower bound is returned.
|
||||
*/
|
||||
virtual size_t output_length(size_t input_length) const = 0;
|
||||
|
||||
@@ -159,14 +157,6 @@ class BOTAN_PUBLIC_API(2,0) Cipher_Mode
|
||||
*/
|
||||
virtual bool valid_nonce_length(size_t nonce_len) const = 0;
|
||||
|
||||
virtual std::string name() const = 0;
|
||||
|
||||
/**
|
||||
* Zeroise all state
|
||||
* See also reset_msg()
|
||||
*/
|
||||
virtual void clear() = 0;
|
||||
|
||||
/**
|
||||
* Resets just the message specific state and allows encrypting again under the existing key
|
||||
*/
|
||||
@@ -183,60 +173,11 @@ class BOTAN_PUBLIC_API(2,0) Cipher_Mode
|
||||
*/
|
||||
virtual size_t tag_size() const { return 0; }
|
||||
|
||||
/**
|
||||
* @return object describing limits on key size
|
||||
*/
|
||||
virtual Key_Length_Specification key_spec() const = 0;
|
||||
|
||||
/**
|
||||
* Check whether a given key length is valid for this algorithm.
|
||||
* @param length the key length to be checked.
|
||||
* @return true if the key length is valid.
|
||||
*/
|
||||
bool valid_keylength(size_t length) const
|
||||
{
|
||||
return key_spec().valid_keylength(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the symmetric key of this transform
|
||||
* @param key contains the key material
|
||||
*/
|
||||
template<typename Alloc>
|
||||
void set_key(const std::vector<uint8_t, Alloc>& key)
|
||||
{
|
||||
set_key(key.data(), key.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the symmetric key of this transform
|
||||
* @param key contains the key material
|
||||
*/
|
||||
void set_key(const SymmetricKey& key)
|
||||
{
|
||||
set_key(key.begin(), key.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the symmetric key of this transform
|
||||
* @param key contains the key material
|
||||
* @param length in bytes of key param
|
||||
*/
|
||||
void set_key(const uint8_t key[], size_t length)
|
||||
{
|
||||
if(!valid_keylength(length))
|
||||
throw Invalid_Key_Length(name(), length);
|
||||
key_schedule(key, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return provider information about this implementation. Default is "base",
|
||||
* might also return "sse2", "avx2", "openssl", or some other arbitrary string.
|
||||
*/
|
||||
virtual std::string provider() const { return "base"; }
|
||||
|
||||
private:
|
||||
virtual void key_schedule(const uint8_t key[], size_t length) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* CBC Padding Methods
|
||||
* (C) 1999-2007,2013 Jack Lloyd
|
||||
* (C) 1999-2007,2013,2018 Jack Lloyd
|
||||
* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
@@ -51,26 +51,27 @@ void PKCS7_Padding::add_padding(secure_vector<uint8_t>& buffer,
|
||||
/*
|
||||
* Unpad with PKCS #7 Method
|
||||
*/
|
||||
size_t PKCS7_Padding::unpad(const uint8_t block[], size_t size) const
|
||||
size_t PKCS7_Padding::unpad(const uint8_t input[], size_t input_length) const
|
||||
{
|
||||
CT::poison(block,size);
|
||||
if(input_length <= 2)
|
||||
return input_length;
|
||||
|
||||
CT::poison(input, input_length);
|
||||
size_t bad_input = 0;
|
||||
const uint8_t last_byte = block[size-1];
|
||||
const uint8_t last_byte = input[input_length-1];
|
||||
|
||||
bad_input |= CT::expand_mask<size_t>(last_byte > size);
|
||||
bad_input |= CT::expand_mask<size_t>(last_byte > input_length);
|
||||
|
||||
size_t pad_pos = size - last_byte;
|
||||
size_t i = size - 2;
|
||||
while(i)
|
||||
const size_t pad_pos = input_length - last_byte;
|
||||
|
||||
for(size_t i = 0; i != input_length - 1; ++i)
|
||||
{
|
||||
bad_input |= (~CT::is_equal(block[i],last_byte)) & CT::expand_mask<uint8_t>(i >= pad_pos);
|
||||
--i;
|
||||
const uint8_t in_range = CT::expand_mask<uint8_t>(i >= pad_pos);
|
||||
bad_input |= in_range & (~CT::is_equal(input[i], last_byte));
|
||||
}
|
||||
|
||||
CT::conditional_copy_mem(bad_input,&pad_pos,&size,&pad_pos,1);
|
||||
CT::unpoison(block,size);
|
||||
CT::unpoison(pad_pos);
|
||||
return pad_pos;
|
||||
CT::unpoison(input, input_length);
|
||||
return CT::conditional_return(bad_input, input_length, pad_pos);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -92,25 +93,27 @@ void ANSI_X923_Padding::add_padding(secure_vector<uint8_t>& buffer,
|
||||
/*
|
||||
* Unpad with ANSI X9.23 Method
|
||||
*/
|
||||
size_t ANSI_X923_Padding::unpad(const uint8_t block[], size_t size) const
|
||||
size_t ANSI_X923_Padding::unpad(const uint8_t input[], size_t input_length) const
|
||||
{
|
||||
CT::poison(block,size);
|
||||
size_t bad_input = 0;
|
||||
const size_t last_byte = block[size-1];
|
||||
if(input_length <= 2)
|
||||
return input_length;
|
||||
|
||||
bad_input |= CT::expand_mask<size_t>(last_byte > size);
|
||||
CT::poison(input, input_length);
|
||||
const size_t last_byte = input[input_length-1];
|
||||
|
||||
size_t pad_pos = size - last_byte;
|
||||
size_t i = size - 2;
|
||||
while(i)
|
||||
uint8_t bad_input = 0;
|
||||
bad_input |= CT::expand_mask<uint8_t>(last_byte > input_length);
|
||||
|
||||
const size_t pad_pos = input_length - last_byte;
|
||||
|
||||
for(size_t i = 0; i != input_length - 1; ++i)
|
||||
{
|
||||
bad_input |= (~CT::is_zero(block[i])) & CT::expand_mask<uint8_t>(i >= pad_pos);
|
||||
--i;
|
||||
const uint8_t in_range = CT::expand_mask<uint8_t>(i >= pad_pos);
|
||||
bad_input |= CT::expand_mask(input[i]) & in_range;
|
||||
}
|
||||
CT::conditional_copy_mem(bad_input,&pad_pos,&size,&pad_pos,1);
|
||||
CT::unpoison(block,size);
|
||||
CT::unpoison(pad_pos);
|
||||
return pad_pos;
|
||||
|
||||
CT::unpoison(input, input_length);
|
||||
return CT::conditional_return(bad_input, input_length, pad_pos);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -129,28 +132,29 @@ void OneAndZeros_Padding::add_padding(secure_vector<uint8_t>& buffer,
|
||||
/*
|
||||
* Unpad with One and Zeros Method
|
||||
*/
|
||||
size_t OneAndZeros_Padding::unpad(const uint8_t block[], size_t size) const
|
||||
size_t OneAndZeros_Padding::unpad(const uint8_t input[], size_t input_length) const
|
||||
{
|
||||
CT::poison(block, size);
|
||||
if(input_length <= 2)
|
||||
return input_length;
|
||||
|
||||
CT::poison(input, input_length);
|
||||
|
||||
uint8_t bad_input = 0;
|
||||
uint8_t seen_one = 0;
|
||||
size_t pad_pos = size - 1;
|
||||
size_t i = size;
|
||||
size_t pad_pos = input_length - 1;
|
||||
size_t i = input_length;
|
||||
|
||||
while(i)
|
||||
{
|
||||
seen_one |= CT::is_equal<uint8_t>(block[i-1],0x80);
|
||||
seen_one |= CT::is_equal<uint8_t>(input[i-1], 0x80);
|
||||
pad_pos -= CT::select<uint8_t>(~seen_one, 1, 0);
|
||||
bad_input |= ~CT::is_zero<uint8_t>(block[i-1]) & ~seen_one;
|
||||
bad_input |= ~CT::is_zero<uint8_t>(input[i-1]) & ~seen_one;
|
||||
i--;
|
||||
}
|
||||
bad_input |= ~seen_one;
|
||||
|
||||
CT::conditional_copy_mem(size_t(bad_input),&pad_pos,&size,&pad_pos,1);
|
||||
CT::unpoison(block, size);
|
||||
CT::unpoison(pad_pos);
|
||||
|
||||
return pad_pos;
|
||||
CT::unpoison(input, input_length);
|
||||
return CT::conditional_return(bad_input, input_length, pad_pos);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -171,25 +175,28 @@ void ESP_Padding::add_padding(secure_vector<uint8_t>& buffer,
|
||||
/*
|
||||
* Unpad with ESP Padding Method
|
||||
*/
|
||||
size_t ESP_Padding::unpad(const uint8_t block[], size_t size) const
|
||||
size_t ESP_Padding::unpad(const uint8_t input[], size_t input_length) const
|
||||
{
|
||||
CT::poison(block,size);
|
||||
if(input_length <= 2)
|
||||
return input_length;
|
||||
|
||||
const size_t last_byte = block[size-1];
|
||||
size_t bad_input = 0;
|
||||
bad_input |= CT::expand_mask<size_t>(last_byte > size);
|
||||
CT::poison(input, input_length);
|
||||
|
||||
size_t pad_pos = size - last_byte;
|
||||
size_t i = size - 1;
|
||||
const size_t last_byte = input[input_length-1];
|
||||
uint8_t bad_input = 0;
|
||||
bad_input |= CT::is_zero(last_byte) | CT::expand_mask<uint8_t>(last_byte > input_length);
|
||||
|
||||
const size_t pad_pos = input_length - last_byte;
|
||||
size_t i = input_length - 1;
|
||||
while(i)
|
||||
{
|
||||
bad_input |= ~CT::is_equal<uint8_t>(size_t(block[i-1]),size_t(block[i])-1) & CT::expand_mask<uint8_t>(i > pad_pos);
|
||||
const uint8_t in_range = CT::expand_mask<uint8_t>(i > pad_pos);
|
||||
bad_input |= (~CT::is_equal<uint8_t>(input[i-1], input[i]-1)) & in_range;
|
||||
--i;
|
||||
}
|
||||
CT::conditional_copy_mem(bad_input,&pad_pos,&size,&pad_pos,1);
|
||||
CT::unpoison(block, size);
|
||||
CT::unpoison(pad_pos);
|
||||
return pad_pos;
|
||||
|
||||
CT::unpoison(input, input_length);
|
||||
return CT::conditional_return(bad_input, input_length, pad_pos);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -39,11 +39,10 @@ class BOTAN_PUBLIC_API(2,0) BlockCipherModePaddingMethod
|
||||
/**
|
||||
* Remove padding bytes from block
|
||||
* @param block the last block
|
||||
* @param size the size of the block in bytes
|
||||
* @return number of padding bytes
|
||||
* @param len the size of the block in bytes
|
||||
* @return number of data bytes, or if the padding is invalid returns len
|
||||
*/
|
||||
virtual size_t unpad(const uint8_t block[],
|
||||
size_t size) const = 0;
|
||||
virtual size_t unpad(const uint8_t block[], size_t len) const = 0;
|
||||
|
||||
/**
|
||||
* @param block_size of the cipher
|
||||
@@ -74,7 +73,7 @@ class BOTAN_PUBLIC_API(2,0) PKCS7_Padding final : public BlockCipherModePaddingM
|
||||
|
||||
size_t unpad(const uint8_t[], size_t) const override;
|
||||
|
||||
bool valid_blocksize(size_t bs) const override { return (bs > 0 && bs < 256); }
|
||||
bool valid_blocksize(size_t bs) const override { return (bs > 2 && bs < 256); }
|
||||
|
||||
std::string name() const override { return "PKCS7"; }
|
||||
};
|
||||
@@ -91,7 +90,7 @@ class BOTAN_PUBLIC_API(2,0) ANSI_X923_Padding final : public BlockCipherModePadd
|
||||
|
||||
size_t unpad(const uint8_t[], size_t) const override;
|
||||
|
||||
bool valid_blocksize(size_t bs) const override { return (bs > 0 && bs < 256); }
|
||||
bool valid_blocksize(size_t bs) const override { return (bs > 2 && bs < 256); }
|
||||
|
||||
std::string name() const override { return "X9.23"; }
|
||||
};
|
||||
@@ -108,7 +107,7 @@ class BOTAN_PUBLIC_API(2,0) OneAndZeros_Padding final : public BlockCipherModePa
|
||||
|
||||
size_t unpad(const uint8_t[], size_t) const override;
|
||||
|
||||
bool valid_blocksize(size_t bs) const override { return (bs > 0); }
|
||||
bool valid_blocksize(size_t bs) const override { return (bs > 2); }
|
||||
|
||||
std::string name() const override { return "OneAndZeros"; }
|
||||
};
|
||||
@@ -125,7 +124,7 @@ class BOTAN_PUBLIC_API(2,0) ESP_Padding final : public BlockCipherModePaddingMet
|
||||
|
||||
size_t unpad(const uint8_t[], size_t) const override;
|
||||
|
||||
bool valid_blocksize(size_t bs) const override { return (bs > 0); }
|
||||
bool valid_blocksize(size_t bs) const override { return (bs > 2 && bs < 256); }
|
||||
|
||||
std::string name() const override { return "ESP"; }
|
||||
};
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<defines>
|
||||
PBKDF -> 20150626
|
||||
PBKDF -> 20180902
|
||||
</defines>
|
||||
|
||||
<requires>
|
||||
@@ -8,5 +8,6 @@ hash
|
||||
</requires>
|
||||
|
||||
<header:public>
|
||||
pwdhash.h
|
||||
pbkdf.h
|
||||
</header:public>
|
||||
|
@@ -17,6 +17,9 @@ namespace Botan {
|
||||
* Base class for PBKDF (password based key derivation function)
|
||||
* implementations. Converts a password into a key using a salt
|
||||
* and iterated hashing to make brute force attacks harder.
|
||||
*
|
||||
* Starting in 2.8 this functionality is also offered by PasswordHash.
|
||||
* The PBKDF interface may be removed in a future release.
|
||||
*/
|
||||
class BOTAN_PUBLIC_API(2,0) PBKDF
|
||||
{
|
||||
@@ -216,7 +219,7 @@ class BOTAN_PUBLIC_API(2,0) PBKDF
|
||||
};
|
||||
|
||||
/*
|
||||
* Compatability typedef
|
||||
* Compatibility typedef
|
||||
*/
|
||||
typedef PBKDF S2K;
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<defines>
|
||||
PBKDF2 -> 20131128
|
||||
PBKDF2 -> 20180902
|
||||
</defines>
|
||||
|
||||
<requires>
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* PBKDF2
|
||||
* (C) 1999-2007 Jack Lloyd
|
||||
* (C) 2018 Ribose Inc
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
*/
|
||||
@@ -8,42 +9,116 @@
|
||||
#include <botan/pbkdf2.h>
|
||||
#include <botan/exceptn.h>
|
||||
#include <botan/internal/rounding.h>
|
||||
#include <botan/internal/timer.h>
|
||||
|
||||
namespace Botan {
|
||||
|
||||
namespace {
|
||||
|
||||
void pbkdf2_set_key(MessageAuthenticationCode& prf,
|
||||
const char* password,
|
||||
size_t password_len)
|
||||
{
|
||||
try
|
||||
{
|
||||
prf.set_key(cast_char_ptr_to_uint8(password), password_len);
|
||||
}
|
||||
catch(Invalid_Key_Length&)
|
||||
{
|
||||
throw Exception("PBKDF2 cannot accept passphrase of the given size");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t
|
||||
pbkdf2(MessageAuthenticationCode& prf,
|
||||
uint8_t out[],
|
||||
size_t out_len,
|
||||
const std::string& passphrase,
|
||||
const std::string& password,
|
||||
const uint8_t salt[], size_t salt_len,
|
||||
size_t iterations,
|
||||
std::chrono::milliseconds msec)
|
||||
{
|
||||
if(iterations == 0)
|
||||
{
|
||||
iterations = PBKDF2(prf, out_len, msec).iterations();
|
||||
}
|
||||
|
||||
PBKDF2 pbkdf2(prf, iterations);
|
||||
|
||||
pbkdf2.derive_key(out, out_len,
|
||||
password.c_str(), password.size(),
|
||||
salt, salt_len);
|
||||
|
||||
return iterations;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
size_t tune_pbkdf2(MessageAuthenticationCode& prf,
|
||||
size_t output_length,
|
||||
uint32_t msec)
|
||||
{
|
||||
const size_t prf_sz = prf.output_length();
|
||||
BOTAN_ASSERT_NOMSG(prf_sz > 0);
|
||||
secure_vector<uint8_t> U(prf_sz);
|
||||
|
||||
const size_t trial_iterations = 10000;
|
||||
|
||||
// Short output ensures we only need a single PBKDF2 block
|
||||
|
||||
Timer timer("PBKDF2");
|
||||
|
||||
const std::chrono::milliseconds tune_msec(30);
|
||||
|
||||
prf.set_key(nullptr, 0);
|
||||
|
||||
timer.run_until_elapsed(tune_msec, [&]() {
|
||||
uint8_t out[16] = { 0 };
|
||||
uint8_t salt[16] = { 0 };
|
||||
pbkdf2(prf, out, sizeof(out), salt, sizeof(salt), trial_iterations);
|
||||
});
|
||||
|
||||
if(timer.events() == 0)
|
||||
return trial_iterations;
|
||||
|
||||
const uint64_t duration_nsec = timer.value() / timer.events();
|
||||
|
||||
const uint64_t desired_nsec = static_cast<uint64_t>(msec) * 1000000;
|
||||
|
||||
if(duration_nsec > desired_nsec)
|
||||
return trial_iterations;
|
||||
|
||||
const size_t blocks_needed = (output_length + prf_sz - 1) / prf_sz;
|
||||
|
||||
const size_t multiplier = (desired_nsec / duration_nsec / blocks_needed);
|
||||
|
||||
if(multiplier == 0)
|
||||
return trial_iterations;
|
||||
else
|
||||
return trial_iterations * multiplier;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void pbkdf2(MessageAuthenticationCode& prf,
|
||||
uint8_t out[],
|
||||
size_t out_len,
|
||||
const uint8_t salt[],
|
||||
size_t salt_len,
|
||||
size_t iterations)
|
||||
{
|
||||
clear_mem(out, out_len);
|
||||
|
||||
if(out_len == 0)
|
||||
return 0;
|
||||
|
||||
try
|
||||
{
|
||||
prf.set_key(cast_char_ptr_to_uint8(passphrase.data()), passphrase.size());
|
||||
}
|
||||
catch(Invalid_Key_Length&)
|
||||
{
|
||||
throw Exception("PBKDF2 with " + prf.name() +
|
||||
" cannot accept passphrases of length " +
|
||||
std::to_string(passphrase.size()));
|
||||
}
|
||||
return;
|
||||
|
||||
const size_t prf_sz = prf.output_length();
|
||||
BOTAN_ASSERT_NOMSG(prf_sz > 0);
|
||||
|
||||
secure_vector<uint8_t> U(prf_sz);
|
||||
|
||||
const size_t blocks_needed = round_up(out_len, prf_sz) / prf_sz;
|
||||
|
||||
std::chrono::microseconds usec_per_block =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(msec) / blocks_needed;
|
||||
|
||||
uint32_t counter = 1;
|
||||
while(out_len)
|
||||
{
|
||||
@@ -55,64 +130,93 @@ pbkdf2(MessageAuthenticationCode& prf,
|
||||
|
||||
xor_buf(out, U.data(), prf_output);
|
||||
|
||||
if(iterations == 0)
|
||||
{
|
||||
/*
|
||||
If no iterations set, run the first block to calibrate based
|
||||
on how long hashing takes on whatever machine we're running on.
|
||||
*/
|
||||
|
||||
const auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
iterations = 1; // the first iteration we did above
|
||||
|
||||
while(true)
|
||||
{
|
||||
prf.update(U);
|
||||
prf.final(U.data());
|
||||
xor_buf(out, U.data(), prf_output);
|
||||
iterations++;
|
||||
|
||||
/*
|
||||
Only break on relatively 'even' iterations. For one it
|
||||
avoids confusion, and likely some broken implementations
|
||||
break on getting completely randomly distributed values
|
||||
*/
|
||||
if(iterations % 10000 == 0)
|
||||
{
|
||||
auto time_taken = std::chrono::high_resolution_clock::now() - start;
|
||||
auto usec_taken = std::chrono::duration_cast<std::chrono::microseconds>(time_taken);
|
||||
if(usec_taken > usec_per_block)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_t i = 1; i != iterations; ++i)
|
||||
{
|
||||
prf.update(U);
|
||||
prf.final(U.data());
|
||||
xor_buf(out, U.data(), prf_output);
|
||||
}
|
||||
}
|
||||
|
||||
out_len -= prf_output;
|
||||
out += prf_output;
|
||||
}
|
||||
|
||||
return iterations;
|
||||
}
|
||||
|
||||
// PBKDF interface
|
||||
size_t
|
||||
PKCS5_PBKDF2::pbkdf(uint8_t key[], size_t key_len,
|
||||
const std::string& passphrase,
|
||||
const std::string& password,
|
||||
const uint8_t salt[], size_t salt_len,
|
||||
size_t iterations,
|
||||
std::chrono::milliseconds msec) const
|
||||
{
|
||||
return pbkdf2(*m_mac.get(), key, key_len, passphrase, salt, salt_len, iterations, msec);
|
||||
if(iterations == 0)
|
||||
{
|
||||
iterations = PBKDF2(*m_mac, key_len, msec).iterations();
|
||||
}
|
||||
|
||||
PBKDF2 pbkdf2(*m_mac, iterations);
|
||||
|
||||
pbkdf2.derive_key(key, key_len,
|
||||
password.c_str(), password.size(),
|
||||
salt, salt_len);
|
||||
|
||||
return iterations;
|
||||
}
|
||||
|
||||
std::string PKCS5_PBKDF2::name() const
|
||||
{
|
||||
return "PBKDF2(" + m_mac->name() + ")";
|
||||
}
|
||||
|
||||
PBKDF* PKCS5_PBKDF2::clone() const
|
||||
{
|
||||
return new PKCS5_PBKDF2(m_mac->clone());
|
||||
}
|
||||
|
||||
// PasswordHash interface
|
||||
|
||||
PBKDF2::PBKDF2(const MessageAuthenticationCode& prf, size_t olen, std::chrono::milliseconds msec) :
|
||||
m_prf(prf.clone()),
|
||||
m_iterations(tune_pbkdf2(*m_prf, olen, static_cast<uint32_t>(msec.count())))
|
||||
{}
|
||||
|
||||
std::string PBKDF2::to_string() const
|
||||
{
|
||||
return "PBKDF2(" + m_prf->name() + "," + std::to_string(m_iterations) + ")";
|
||||
}
|
||||
|
||||
void PBKDF2::derive_key(uint8_t out[], size_t out_len,
|
||||
const char* password, const size_t password_len,
|
||||
const uint8_t salt[], size_t salt_len) const
|
||||
{
|
||||
pbkdf2_set_key(*m_prf, password, password_len);
|
||||
pbkdf2(*m_prf, out, out_len, salt, salt_len, m_iterations);
|
||||
}
|
||||
|
||||
std::string PBKDF2_Family::name() const
|
||||
{
|
||||
return "PBKDF2(" + m_prf->name() + ")";
|
||||
}
|
||||
|
||||
std::unique_ptr<PasswordHash> PBKDF2_Family::tune(size_t output_len, std::chrono::milliseconds msec, size_t) const
|
||||
{
|
||||
return std::unique_ptr<PasswordHash>(new PBKDF2(*m_prf, output_len, msec));
|
||||
}
|
||||
|
||||
std::unique_ptr<PasswordHash> PBKDF2_Family::default_params() const
|
||||
{
|
||||
return std::unique_ptr<PasswordHash>(new PBKDF2(*m_prf, 150000));
|
||||
}
|
||||
|
||||
std::unique_ptr<PasswordHash> PBKDF2_Family::from_params(size_t iter, size_t, size_t) const
|
||||
{
|
||||
return std::unique_ptr<PasswordHash>(new PBKDF2(*m_prf, iter));
|
||||
}
|
||||
|
||||
std::unique_ptr<PasswordHash> PBKDF2_Family::from_iterations(size_t iter) const
|
||||
{
|
||||
return std::unique_ptr<PasswordHash>(new PBKDF2(*m_prf, iter));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* PBKDF2
|
||||
* (C) 1999-2007,2012 Jack Lloyd
|
||||
* (C) 2018 Ribose Inc
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
*/
|
||||
@@ -9,6 +10,7 @@
|
||||
#define BOTAN_PBKDF2_H_
|
||||
|
||||
#include <botan/pbkdf.h>
|
||||
#include <botan/pwdhash.h>
|
||||
#include <botan/mac.h>
|
||||
|
||||
namespace Botan {
|
||||
@@ -22,20 +24,76 @@ BOTAN_PUBLIC_API(2,0) size_t pbkdf2(MessageAuthenticationCode& prf,
|
||||
std::chrono::milliseconds msec);
|
||||
|
||||
/**
|
||||
* PKCS #5 PBKDF2
|
||||
* Perform PBKDF2. The prf is assumed to be keyed already.
|
||||
*/
|
||||
BOTAN_PUBLIC_API(2,8) void pbkdf2(MessageAuthenticationCode& prf,
|
||||
uint8_t out[], size_t out_len,
|
||||
const uint8_t salt[], size_t salt_len,
|
||||
size_t iterations);
|
||||
|
||||
/**
|
||||
* PBKDF2
|
||||
*/
|
||||
class BOTAN_PUBLIC_API(2,8) PBKDF2 final : public PasswordHash
|
||||
{
|
||||
public:
|
||||
PBKDF2(const MessageAuthenticationCode& prf, size_t iter) :
|
||||
m_prf(prf.clone()),
|
||||
m_iterations(iter)
|
||||
{}
|
||||
|
||||
PBKDF2(const MessageAuthenticationCode& prf, size_t olen, std::chrono::milliseconds msec);
|
||||
|
||||
size_t iterations() const override { return m_iterations; }
|
||||
|
||||
std::string to_string() const override;
|
||||
|
||||
void derive_key(uint8_t out[], size_t out_len,
|
||||
const char* password, size_t password_len,
|
||||
const uint8_t salt[], size_t salt_len) const override;
|
||||
private:
|
||||
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
||||
size_t m_iterations;
|
||||
};
|
||||
|
||||
/**
|
||||
* Family of PKCS #5 PBKDF2 operations
|
||||
*/
|
||||
class BOTAN_PUBLIC_API(2,8) PBKDF2_Family final : public PasswordHashFamily
|
||||
{
|
||||
public:
|
||||
PBKDF2_Family(MessageAuthenticationCode* prf) : m_prf(prf) {}
|
||||
|
||||
std::string name() const override;
|
||||
|
||||
std::unique_ptr<PasswordHash> tune(size_t output_len,
|
||||
std::chrono::milliseconds msec,
|
||||
size_t max_memory) const override;
|
||||
|
||||
/**
|
||||
* Return some default parameter set for this PBKDF that should be good
|
||||
* enough for most users. The value returned may change over time as
|
||||
* processing power and attacks improve.
|
||||
*/
|
||||
std::unique_ptr<PasswordHash> default_params() const override;
|
||||
|
||||
std::unique_ptr<PasswordHash> from_iterations(size_t iter) const override;
|
||||
|
||||
std::unique_ptr<PasswordHash> from_params(
|
||||
size_t iter, size_t, size_t) const override;
|
||||
private:
|
||||
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
||||
};
|
||||
|
||||
/**
|
||||
* PKCS #5 PBKDF2 (old interface)
|
||||
*/
|
||||
class BOTAN_PUBLIC_API(2,0) PKCS5_PBKDF2 final : public PBKDF
|
||||
{
|
||||
public:
|
||||
std::string name() const override
|
||||
{
|
||||
return "PBKDF2(" + m_mac->name() + ")";
|
||||
}
|
||||
std::string name() const override;
|
||||
|
||||
PBKDF* clone() const override
|
||||
{
|
||||
return new PKCS5_PBKDF2(m_mac->clone());
|
||||
}
|
||||
PBKDF* clone() const override;
|
||||
|
||||
size_t pbkdf(uint8_t output_buf[], size_t output_len,
|
||||
const std::string& passphrase,
|
||||
|
88
src/libs/3rdparty/botan/src/lib/pbkdf/pwdhash.cpp
vendored
Normal file
88
src/libs/3rdparty/botan/src/lib/pbkdf/pwdhash.cpp
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* (C) 2018 Ribose Inc
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
*/
|
||||
|
||||
#include <botan/pbkdf.h>
|
||||
#include <botan/exceptn.h>
|
||||
#include <botan/scan_name.h>
|
||||
|
||||
#if defined(BOTAN_HAS_PBKDF2)
|
||||
#include <botan/pbkdf2.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_PGP_S2K)
|
||||
#include <botan/pgp_s2k.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_SCRYPT)
|
||||
#include <botan/scrypt.h>
|
||||
#endif
|
||||
|
||||
namespace Botan {
|
||||
|
||||
std::unique_ptr<PasswordHashFamily> PasswordHashFamily::create(const std::string& algo_spec,
|
||||
const std::string& provider)
|
||||
{
|
||||
const SCAN_Name req(algo_spec);
|
||||
|
||||
#if defined(BOTAN_HAS_PBKDF2)
|
||||
if(req.algo_name() == "PBKDF2")
|
||||
{
|
||||
// TODO OpenSSL
|
||||
|
||||
if(provider.empty() || provider == "base")
|
||||
{
|
||||
if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
|
||||
return std::unique_ptr<PasswordHashFamily>(new PBKDF2_Family(mac.release()));
|
||||
|
||||
if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")"))
|
||||
return std::unique_ptr<PasswordHashFamily>(new PBKDF2_Family(mac.release()));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_SCRYPT)
|
||||
if(req.algo_name() == "Scrypt")
|
||||
{
|
||||
return std::unique_ptr<PasswordHashFamily>(new Scrypt_Family);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_PGP_S2K)
|
||||
if(req.algo_name() == "OpenPGP-S2K" && req.arg_count() == 1)
|
||||
{
|
||||
if(auto hash = HashFunction::create(req.arg(0)))
|
||||
{
|
||||
return std::unique_ptr<PasswordHashFamily>(new RFC4880_S2K_Family(hash.release()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BOTAN_UNUSED(req);
|
||||
BOTAN_UNUSED(provider);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//static
|
||||
std::unique_ptr<PasswordHashFamily>
|
||||
PasswordHashFamily::create_or_throw(const std::string& algo,
|
||||
const std::string& provider)
|
||||
{
|
||||
if(auto pbkdf = PasswordHashFamily::create(algo, provider))
|
||||
{
|
||||
return pbkdf;
|
||||
}
|
||||
throw Lookup_Error("PasswordHashFamily", algo, provider);
|
||||
}
|
||||
|
||||
std::vector<std::string> PasswordHashFamily::providers(const std::string& algo_spec)
|
||||
{
|
||||
return probe_providers_of<PasswordHashFamily>(algo_spec, { "base", "openssl" });
|
||||
}
|
||||
|
||||
}
|
162
src/libs/3rdparty/botan/src/lib/pbkdf/pwdhash.h
vendored
Normal file
162
src/libs/3rdparty/botan/src/lib/pbkdf/pwdhash.h
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* (C) 2018 Ribose Inc
|
||||
*
|
||||
* Botan is released under the Simplified BSD License (see license.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_PWDHASH_H_
|
||||
#define BOTAN_PWDHASH_H_
|
||||
|
||||
#include <botan/types.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
namespace Botan {
|
||||
|
||||
/**
|
||||
* Base class for password based key derivation functions.
|
||||
*
|
||||
* Converts a password into a key using a salt and iterated hashing to
|
||||
* make brute force attacks harder.
|
||||
*/
|
||||
class BOTAN_PUBLIC_API(2,8) PasswordHash
|
||||
{
|
||||
public:
|
||||
virtual ~PasswordHash() = default;
|
||||
|
||||
virtual std::string to_string() const = 0;
|
||||
|
||||
/**
|
||||
* Most password hashes have some notion of iterations.
|
||||
*/
|
||||
virtual size_t iterations() const = 0;
|
||||
|
||||
/**
|
||||
* Some password hashing algorithms have a parameter which controls how
|
||||
* much memory is used. If not supported by some algorithm, returns 0.
|
||||
*/
|
||||
virtual size_t memory_param() const { return 0; }
|
||||
|
||||
/**
|
||||
* Some password hashing algorithms have a parallelism parameter.
|
||||
* If the algorithm does not support this notion, then the
|
||||
* function returns zero. This allows distinguishing between a
|
||||
* password hash which just does not support parallel operation,
|
||||
* vs one that does support parallel operation but which has been
|
||||
* configured to use a single lane.
|
||||
*/
|
||||
virtual size_t parallelism() const { return 0; }
|
||||
|
||||
/**
|
||||
* Returns an estimate of the total memory usage required to perform this
|
||||
* key derivation.
|
||||
*
|
||||
* If this algorithm uses a small and constant amount of memory, with no
|
||||
* effort made towards being memory hard, this function returns 0.
|
||||
*/
|
||||
virtual size_t total_memory_usage() const { return 0; }
|
||||
|
||||
/**
|
||||
* Derive a key from a password
|
||||
*
|
||||
* @param out buffer to store the derived key, must be of out_len bytes
|
||||
* @param out_len the desired length of the key to produce
|
||||
* @param password the password to derive the key from
|
||||
* @param password_len the length of password in bytes
|
||||
* @param salt a randomly chosen salt
|
||||
* @param salt_len length of salt in bytes
|
||||
*
|
||||
* This function is const, but is not thread safe. Different threads should
|
||||
* either use unique objects, or serialize all access.
|
||||
*/
|
||||
virtual void derive_key(uint8_t out[], size_t out_len,
|
||||
const char* password, size_t password_len,
|
||||
const uint8_t salt[], size_t salt_len) const = 0;
|
||||
};
|
||||
|
||||
class BOTAN_PUBLIC_API(2,8) PasswordHashFamily
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create an instance based on a name
|
||||
* If provider is empty then best available is chosen.
|
||||
* @param algo_spec algorithm name
|
||||
* @param provider provider implementation to choose
|
||||
* @return a null pointer if the algo/provider combination cannot be found
|
||||
*/
|
||||
static std::unique_ptr<PasswordHashFamily> create(const std::string& algo_spec,
|
||||
const std::string& provider = "");
|
||||
|
||||
/**
|
||||
* Create an instance based on a name, or throw if the
|
||||
* algo/provider combination cannot be found. If provider is
|
||||
* empty then best available is chosen.
|
||||
*/
|
||||
static std::unique_ptr<PasswordHashFamily>
|
||||
create_or_throw(const std::string& algo_spec,
|
||||
const std::string& provider = "");
|
||||
|
||||
/**
|
||||
* @return list of available providers for this algorithm, empty if not available
|
||||
*/
|
||||
static std::vector<std::string> providers(const std::string& algo_spec);
|
||||
|
||||
virtual ~PasswordHashFamily() = default;
|
||||
|
||||
/**
|
||||
* @return name of this PasswordHash
|
||||
*/
|
||||
virtual std::string name() const = 0;
|
||||
|
||||
/**
|
||||
* Return a new parameter set tuned for this machine
|
||||
* @param output_length how long the output length will be
|
||||
* @param msec the desired execution time in milliseconds
|
||||
*
|
||||
* @param max_memory_usage_mb some password hash functions can use a tunable
|
||||
* amount of memory, in this case max_memory_usage limits the amount of RAM
|
||||
* the returned parameters will require, in mebibytes (2**20 bytes). It may
|
||||
* require some small amount above the request. Set to zero to place no
|
||||
* limit at all.
|
||||
*/
|
||||
virtual std::unique_ptr<PasswordHash> tune(size_t output_length,
|
||||
std::chrono::milliseconds msec,
|
||||
size_t max_memory_usage_mb = 0) const = 0;
|
||||
|
||||
/**
|
||||
* Return some default parameter set for this PBKDF that should be good
|
||||
* enough for most users. The value returned may change over time as
|
||||
* processing power and attacks improve.
|
||||
*/
|
||||
virtual std::unique_ptr<PasswordHash> default_params() const = 0;
|
||||
|
||||
/**
|
||||
* Return a parameter chosen based on a rough approximation with the
|
||||
* specified iteration count. The exact value this returns for a particular
|
||||
* algorithm may change from over time. Think of it as an alternative to
|
||||
* tune, where time is expressed in terms of PBKDF2 iterations rather than
|
||||
* milliseconds.
|
||||
*/
|
||||
virtual std::unique_ptr<PasswordHash> from_iterations(size_t iterations) const = 0;
|
||||
|
||||
/**
|
||||
* Create a password hash using some scheme specific format.
|
||||
* Eg PBKDF2 and PGP-S2K set iterations in i1
|
||||
* Scrypt uses N,r,p in i{1-3}
|
||||
* Bcrypt-PBKDF just has iterations
|
||||
* Argon2{i,d,id} would use iterations, memory, parallelism for i{1-3},
|
||||
* and Argon2 type is part of the family.
|
||||
*
|
||||
* Values not needed should be set to 0
|
||||
*/
|
||||
virtual std::unique_ptr<PasswordHash> from_params(
|
||||
size_t i1,
|
||||
size_t i2 = 0,
|
||||
size_t i3 = 0) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
43
src/libs/3rdparty/botan/src/lib/pk_pad/emsa.cpp
vendored
43
src/libs/3rdparty/botan/src/lib/pk_pad/emsa.cpp
vendored
@@ -55,6 +55,7 @@ EMSA* get_emsa(const std::string& algo_spec)
|
||||
|
||||
#if defined(BOTAN_HAS_EMSA_PKCS1)
|
||||
if(req.algo_name() == "EMSA_PKCS1" ||
|
||||
req.algo_name() == "PKCS1v15" ||
|
||||
req.algo_name() == "EMSA-PKCS1-v1_5" ||
|
||||
req.algo_name() == "EMSA3")
|
||||
{
|
||||
@@ -80,26 +81,46 @@ EMSA* get_emsa(const std::string& algo_spec)
|
||||
#endif
|
||||
|
||||
#if defined(BOTAN_HAS_EMSA_PSSR)
|
||||
if(req.algo_name() == "PSSR" ||
|
||||
req.algo_name() == "EMSA-PSS" ||
|
||||
req.algo_name() == "PSS-MGF1" ||
|
||||
req.algo_name() == "EMSA4" ||
|
||||
if(req.algo_name() == "PSS_Raw" ||
|
||||
req.algo_name() == "PSSR_Raw")
|
||||
{
|
||||
if(req.arg_count_between(1, 3))
|
||||
if(req.arg_count_between(1, 3) && req.arg(1, "MGF1") == "MGF1")
|
||||
{
|
||||
if(req.arg(1, "MGF1") != "MGF1")
|
||||
return nullptr; // not supported
|
||||
|
||||
if(auto h = HashFunction::create(req.arg(0)))
|
||||
{
|
||||
const size_t salt_size = req.arg_as_integer(2, h->output_length());
|
||||
|
||||
if(req.algo_name() == "PSSR_Raw")
|
||||
if(req.arg_count() == 3)
|
||||
{
|
||||
const size_t salt_size = req.arg_as_integer(2, 0);
|
||||
return new PSSR_Raw(h.release(), salt_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new PSSR_Raw(h.release());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(req.algo_name() == "PSS" ||
|
||||
req.algo_name() == "PSSR" ||
|
||||
req.algo_name() == "EMSA-PSS" ||
|
||||
req.algo_name() == "PSS-MGF1" ||
|
||||
req.algo_name() == "EMSA4")
|
||||
{
|
||||
if(req.arg_count_between(1, 3) && req.arg(1, "MGF1") == "MGF1")
|
||||
{
|
||||
if(auto h = HashFunction::create(req.arg(0)))
|
||||
{
|
||||
if(req.arg_count() == 3)
|
||||
{
|
||||
const size_t salt_size = req.arg_as_integer(2, 0);
|
||||
return new PSSR(h.release(), salt_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new PSSR(h.release());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -55,9 +55,10 @@ secure_vector<uint8_t> pss_encode(HashFunction& hash,
|
||||
}
|
||||
|
||||
bool pss_verify(HashFunction& hash,
|
||||
const secure_vector<uint8_t>& const_coded,
|
||||
const secure_vector<uint8_t>& raw,
|
||||
size_t key_bits)
|
||||
const secure_vector<uint8_t>& pss_repr,
|
||||
const secure_vector<uint8_t>& message_hash,
|
||||
size_t key_bits,
|
||||
size_t* out_salt_size)
|
||||
{
|
||||
const size_t HASH_SIZE = hash.output_length();
|
||||
const size_t KEY_BYTES = (key_bits + 7) / 8;
|
||||
@@ -65,16 +66,16 @@ bool pss_verify(HashFunction& hash,
|
||||
if(key_bits < 8*HASH_SIZE + 9)
|
||||
return false;
|
||||
|
||||
if(raw.size() != HASH_SIZE)
|
||||
if(message_hash.size() != HASH_SIZE)
|
||||
return false;
|
||||
|
||||
if(const_coded.size() > KEY_BYTES || const_coded.size() <= 1)
|
||||
if(pss_repr.size() > KEY_BYTES || pss_repr.size() <= 1)
|
||||
return false;
|
||||
|
||||
if(const_coded[const_coded.size()-1] != 0xBC)
|
||||
if(pss_repr[pss_repr.size()-1] != 0xBC)
|
||||
return false;
|
||||
|
||||
secure_vector<uint8_t> coded = const_coded;
|
||||
secure_vector<uint8_t> coded = pss_repr;
|
||||
if(coded.size() < KEY_BYTES)
|
||||
{
|
||||
secure_vector<uint8_t> temp(KEY_BYTES);
|
||||
@@ -110,23 +111,32 @@ bool pss_verify(HashFunction& hash,
|
||||
|
||||
for(size_t j = 0; j != 8; ++j)
|
||||
hash.update(0);
|
||||
hash.update(raw);
|
||||
hash.update(message_hash);
|
||||
hash.update(&DB[salt_offset], salt_size);
|
||||
|
||||
secure_vector<uint8_t> H2 = hash.final();
|
||||
const secure_vector<uint8_t> H2 = hash.final();
|
||||
|
||||
return constant_time_compare(H, H2.data(), HASH_SIZE);
|
||||
const bool ok = constant_time_compare(H, H2.data(), HASH_SIZE);
|
||||
|
||||
if(out_salt_size && ok)
|
||||
*out_salt_size = salt_size;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PSSR::PSSR(HashFunction* h) :
|
||||
m_hash(h), m_SALT_SIZE(m_hash->output_length())
|
||||
m_hash(h),
|
||||
m_salt_size(m_hash->output_length()),
|
||||
m_required_salt_len(false)
|
||||
{
|
||||
}
|
||||
|
||||
PSSR::PSSR(HashFunction* h, size_t salt_size) :
|
||||
m_hash(h), m_SALT_SIZE(salt_size)
|
||||
m_hash(h),
|
||||
m_salt_size(salt_size),
|
||||
m_required_salt_len(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -150,7 +160,7 @@ secure_vector<uint8_t> PSSR::encoding_of(const secure_vector<uint8_t>& msg,
|
||||
size_t output_bits,
|
||||
RandomNumberGenerator& rng)
|
||||
{
|
||||
secure_vector<uint8_t> salt = rng.random_vec(m_SALT_SIZE);
|
||||
const secure_vector<uint8_t> salt = rng.random_vec(m_salt_size);
|
||||
return pss_encode(*m_hash, msg, salt, output_bits);
|
||||
}
|
||||
|
||||
@@ -161,12 +171,23 @@ bool PSSR::verify(const secure_vector<uint8_t>& coded,
|
||||
const secure_vector<uint8_t>& raw,
|
||||
size_t key_bits)
|
||||
{
|
||||
return pss_verify(*m_hash, coded, raw, key_bits);
|
||||
size_t salt_size = 0;
|
||||
const bool ok = pss_verify(*m_hash, coded, raw, key_bits, &salt_size);
|
||||
|
||||
if(m_required_salt_len && salt_size != m_salt_size)
|
||||
return false;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
EMSA* PSSR::clone()
|
||||
{
|
||||
return new PSSR(m_hash->clone(), m_salt_size);
|
||||
}
|
||||
|
||||
std::string PSSR::name() const
|
||||
{
|
||||
return "EMSA4(" + m_hash->name() + ",MGF1," + std::to_string(m_SALT_SIZE) + ")";
|
||||
return "EMSA4(" + m_hash->name() + ",MGF1," + std::to_string(m_salt_size) + ")";
|
||||
}
|
||||
|
||||
AlgorithmIdentifier PSSR::config_for_x509(const Private_Key& key,
|
||||
@@ -193,7 +214,7 @@ AlgorithmIdentifier PSSR::config_for_x509(const Private_Key& key,
|
||||
.start_cons(SEQUENCE)
|
||||
.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).encode(hash_id).end_cons()
|
||||
.start_cons(ASN1_Tag(1), CONTEXT_SPECIFIC).encode(mgf_id).end_cons()
|
||||
.start_cons(ASN1_Tag(2), CONTEXT_SPECIFIC).encode(m_SALT_SIZE).end_cons()
|
||||
.start_cons(ASN1_Tag(2), CONTEXT_SPECIFIC).encode(m_salt_size).end_cons()
|
||||
.start_cons(ASN1_Tag(3), CONTEXT_SPECIFIC).encode(size_t(1)).end_cons() // trailer field
|
||||
.end_cons();
|
||||
|
||||
@@ -201,12 +222,16 @@ AlgorithmIdentifier PSSR::config_for_x509(const Private_Key& key,
|
||||
}
|
||||
|
||||
PSSR_Raw::PSSR_Raw(HashFunction* h) :
|
||||
m_hash(h), m_SALT_SIZE(m_hash->output_length())
|
||||
m_hash(h),
|
||||
m_salt_size(m_hash->output_length()),
|
||||
m_required_salt_len(false)
|
||||
{
|
||||
}
|
||||
|
||||
PSSR_Raw::PSSR_Raw(HashFunction* h, size_t salt_size) :
|
||||
m_hash(h), m_SALT_SIZE(salt_size)
|
||||
m_hash(h),
|
||||
m_salt_size(salt_size),
|
||||
m_required_salt_len(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -236,7 +261,7 @@ secure_vector<uint8_t> PSSR_Raw::encoding_of(const secure_vector<uint8_t>& msg,
|
||||
size_t output_bits,
|
||||
RandomNumberGenerator& rng)
|
||||
{
|
||||
secure_vector<uint8_t> salt = rng.random_vec(m_SALT_SIZE);
|
||||
secure_vector<uint8_t> salt = rng.random_vec(m_salt_size);
|
||||
return pss_encode(*m_hash, msg, salt, output_bits);
|
||||
}
|
||||
|
||||
@@ -247,12 +272,23 @@ bool PSSR_Raw::verify(const secure_vector<uint8_t>& coded,
|
||||
const secure_vector<uint8_t>& raw,
|
||||
size_t key_bits)
|
||||
{
|
||||
return pss_verify(*m_hash, coded, raw, key_bits);
|
||||
size_t salt_size = 0;
|
||||
const bool ok = pss_verify(*m_hash, coded, raw, key_bits, &salt_size);
|
||||
|
||||
if(m_required_salt_len && salt_size != m_salt_size)
|
||||
return false;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
EMSA* PSSR_Raw::clone()
|
||||
{
|
||||
return new PSSR_Raw(m_hash->clone(), m_salt_size);
|
||||
}
|
||||
|
||||
std::string PSSR_Raw::name() const
|
||||
{
|
||||
return "PSSR_Raw(" + m_hash->name() + ",MGF1," + std::to_string(m_SALT_SIZE) + ")";
|
||||
return "PSSR_Raw(" + m_hash->name() + ",MGF1," + std::to_string(m_salt_size) + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ class BOTAN_PUBLIC_API(2,0) PSSR final : public EMSA
|
||||
*/
|
||||
PSSR(HashFunction* hash, size_t salt_size);
|
||||
|
||||
EMSA* clone() override { return new PSSR(m_hash->clone(), m_SALT_SIZE); }
|
||||
EMSA* clone() override;
|
||||
|
||||
std::string name() const override;
|
||||
|
||||
@@ -51,7 +51,8 @@ class BOTAN_PUBLIC_API(2,0) PSSR final : public EMSA
|
||||
size_t key_bits) override;
|
||||
|
||||
std::unique_ptr<HashFunction> m_hash;
|
||||
size_t m_SALT_SIZE;
|
||||
size_t m_salt_size;
|
||||
bool m_required_salt_len;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -73,7 +74,7 @@ class BOTAN_PUBLIC_API(2,3) PSSR_Raw final : public EMSA
|
||||
*/
|
||||
PSSR_Raw(HashFunction* hash, size_t salt_size);
|
||||
|
||||
EMSA* clone() override { return new PSSR_Raw(m_hash->clone(), m_SALT_SIZE); }
|
||||
EMSA* clone() override;
|
||||
|
||||
std::string name() const override;
|
||||
private:
|
||||
@@ -90,8 +91,9 @@ class BOTAN_PUBLIC_API(2,3) PSSR_Raw final : public EMSA
|
||||
size_t key_bits) override;
|
||||
|
||||
std::unique_ptr<HashFunction> m_hash;
|
||||
size_t m_SALT_SIZE;
|
||||
secure_vector<uint8_t> m_msg;
|
||||
size_t m_salt_size;
|
||||
bool m_required_salt_len;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -2,8 +2,6 @@
|
||||
PK_PADDING -> 20131128
|
||||
</defines>
|
||||
|
||||
load_on auto
|
||||
|
||||
<requires>
|
||||
asn1
|
||||
rng
|
||||
|
@@ -17,13 +17,14 @@ void mgf1_mask(HashFunction& hash,
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
|
||||
secure_vector<uint8_t> buffer(hash.output_length());
|
||||
while(out_len)
|
||||
{
|
||||
hash.update(in, in_len);
|
||||
hash.update_be(counter);
|
||||
secure_vector<uint8_t> buffer = hash.final();
|
||||
hash.final(buffer.data());
|
||||
|
||||
size_t xored = std::min<size_t>(buffer.size(), out_len);
|
||||
const size_t xored = std::min<size_t>(buffer.size(), out_len);
|
||||
xor_buf(out, buffer.data(), xored);
|
||||
out += xored;
|
||||
out_len -= xored;
|
||||
|
@@ -93,6 +93,8 @@ class DH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF
|
||||
[this](const BigInt& k) { return m_powermod_x_p(inverse_mod(k, m_p)); })
|
||||
{}
|
||||
|
||||
size_t agreed_value_size() const override { return m_p.bytes(); }
|
||||
|
||||
secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override;
|
||||
private:
|
||||
const BigInt& m_p;
|
||||
|
@@ -67,6 +67,7 @@ class DL_Group_Data final
|
||||
size_t p_bits() const { return m_p_bits; }
|
||||
size_t q_bits() const { return m_q_bits; }
|
||||
size_t p_bytes() const { return (m_p_bits + 7) / 8; }
|
||||
size_t q_bytes() const { return (m_q_bits + 7) / 8; }
|
||||
|
||||
size_t estimated_strength() const { return m_estimated_strength; }
|
||||
|
||||
@@ -448,6 +449,12 @@ size_t DL_Group::q_bits() const
|
||||
return data().q_bits();
|
||||
}
|
||||
|
||||
size_t DL_Group::q_bytes() const
|
||||
{
|
||||
data().assert_q_is_set("q_bytes");
|
||||
return data().q_bytes();
|
||||
}
|
||||
|
||||
size_t DL_Group::estimated_strength() const
|
||||
{
|
||||
return data().estimated_strength();
|
||||
|
@@ -268,6 +268,13 @@ class BOTAN_PUBLIC_API(2,0) DL_Group final
|
||||
*/
|
||||
size_t q_bits() const;
|
||||
|
||||
/**
|
||||
* Return the size of q in bytes
|
||||
* Same as get_q().bytes()
|
||||
* Throws if q is unset
|
||||
*/
|
||||
size_t q_bytes() const;
|
||||
|
||||
/**
|
||||
* Return size in bits of a secret exponent
|
||||
*
|
||||
|
@@ -89,7 +89,8 @@ class DSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
|
||||
m_b_inv = m_group.inverse_mod_q(m_b);
|
||||
}
|
||||
|
||||
size_t max_input_bits() const override { return m_group.get_q().bits(); }
|
||||
size_t signature_length() const override { return 2*m_group.q_bytes(); }
|
||||
size_t max_input_bits() const override { return m_group.q_bits(); }
|
||||
|
||||
secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
|
||||
RandomNumberGenerator& rng) override;
|
||||
@@ -157,7 +158,7 @@ class DSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
|
||||
{
|
||||
}
|
||||
|
||||
size_t max_input_bits() const override { return m_group.get_q().bits(); }
|
||||
size_t max_input_bits() const override { return m_group.q_bits(); }
|
||||
|
||||
bool with_recovery() const override { return false; }
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user