diff --git a/CHANGELOG.md b/CHANGELOG.md index def6b77e5e..7fb1c54475 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,12 +58,20 @@ Reference(s): [doc/sql.extensions/README.identity_columns](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.identity_columns.txt) Contributor(s): Adriano dos Santos Fernandes +* [CORE-5380](http://tracker.firebirdsql.org/browse/CORE-5380): Allow subroutines to call others subroutines and themself recursively + Reference(s): [doc/sql.extensions/README.subroutines.txt](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.subroutines.txt) + Contributor(s): Adriano dos Santos Fernandes + * [CORE-5119](http://tracker.firebirdsql.org/browse/CORE-5119): Support autocommit mode in SET TRANSACTION statement Contributor(s): Dmitry Yemanov * [CORE-5064](http://tracker.firebirdsql.org/browse/CORE-5064): Add datatypes (VAR)BINARY(n) and BINARY VARYING(n) as aliases for (VAR)CHAR(n) CHARACTER SET OCTETS Contributor(s): Dimitry Sibiryakov +* [CORE-4436](http://tracker.firebirdsql.org/browse/CORE-4436): Support for different hash algorithms in HASH system function + Reference(s): [doc/sql.extensions/README.builtin_functions.txt](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.builtin_functions.txt) + Contributor(s): Adriano dos Santos Fernandes + * [CORE-2557](http://tracker.firebirdsql.org/browse/CORE-2557): Grants on MON$ tables Contributor(s): Alex Peshkoff diff --git a/builds/install/arch-specific/linux/firebird-classic.service.in b/builds/install/arch-specific/linux/firebird-classic.service.in deleted file mode 100644 index aad7ae103a..0000000000 --- a/builds/install/arch-specific/linux/firebird-classic.service.in +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Firebird Database Server ( Classic ) -After=local-fs.target - -[Service] -User=firebird -Group=firebird -ExecStart=@FB_SBINDIR@/firebird -StandardInput=socket -StandardError=syslog diff --git a/builds/install/arch-specific/linux/firebird-classic.socket.in b/builds/install/arch-specific/linux/firebird-classic.socket.in deleted file mode 100644 index 6ce30741a5..0000000000 --- a/builds/install/arch-specific/linux/firebird-classic.socket.in +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Firebird Classic Activation Socket -Conflicts=firebird-superserver.service - -[Socket] -ListenStream=3050 -Accept=true -MaxConnections=2048 - -[Install] -WantedBy=sockets.target diff --git a/builds/install/arch-specific/linux/firebird.init.d.slackware.in b/builds/install/arch-specific/linux/firebird.init.d.slackware.in index a75a431670..328a91b4ad 100644 --- a/builds/install/arch-specific/linux/firebird.init.d.slackware.in +++ b/builds/install/arch-specific/linux/firebird.init.d.slackware.in @@ -2,7 +2,7 @@ # # /etc/rc.d/rc.firebirdss # -# Start/stop/restart the firebird super server. +# Start/stop/restart the firebird server. # fb_install_prefix=@prefix@ diff --git a/builds/install/arch-specific/linux/firebird.init.d.suse.in b/builds/install/arch-specific/linux/firebird.init.d.suse.in index 11eb6da47d..d8e2ea2046 100644 --- a/builds/install/arch-specific/linux/firebird.init.d.suse.in +++ b/builds/install/arch-specific/linux/firebird.init.d.suse.in @@ -9,7 +9,7 @@ # # /usr/sbin/rcfirebird # -# System startup script for the Firebird SuperServer +# System startup script for the Firebird Server # ### BEGIN INIT INFO # Provides: firebird diff --git a/builds/install/arch-specific/linux/firebird-superserver.service.in b/builds/install/arch-specific/linux/firebird.service.in similarity index 76% rename from builds/install/arch-specific/linux/firebird-superserver.service.in rename to builds/install/arch-specific/linux/firebird.service.in index a13b092c41..6abaf76dab 100644 --- a/builds/install/arch-specific/linux/firebird-superserver.service.in +++ b/builds/install/arch-specific/linux/firebird.service.in @@ -1,7 +1,6 @@ [Unit] -Description=Firebird Database Server ( SuperServer ) +Description=Firebird Database Server After=syslog.target network.target -Conflicts=firebird-classic.socket [Service] User=firebird diff --git a/builds/install/arch-specific/linux/firebird.xinetd.in b/builds/install/arch-specific/linux/firebird.xinetd.in deleted file mode 100644 index 93555709d7..0000000000 --- a/builds/install/arch-specific/linux/firebird.xinetd.in +++ /dev/null @@ -1,17 +0,0 @@ -# default: on -# description: FirebirdSQL server -# - -service @FB_SERVICE_NAME@ -{ - disable = no - flags = REUSE - socket_type = stream - wait = no - user = root -# These lines cause problems with Windows XP SP2 clients -# using default firewall configuration (SF#1065511) -# log_on_success += USERID -# log_on_failure += USERID - server = @FB_SBINDIR@/firebird -} diff --git a/builds/install/arch-specific/linux/linuxLibrary.sh.in b/builds/install/arch-specific/linux/linuxLibrary.sh.in index f6eb020730..82a0f25821 100644 --- a/builds/install/arch-specific/linux/linuxLibrary.sh.in +++ b/builds/install/arch-specific/linux/linuxLibrary.sh.in @@ -111,8 +111,7 @@ getInitScriptLocation() { # register/start/stop server using systemd SYSTEMCTL=systemctl -CLASSIC_CTRL=${fb_startup_name}-classic.socket -SUPER_CTRL=${fb_startup_name}-superserver.service +CTRL=${fb_startup_name}.service SYSTEMD_DIR=/usr/lib/systemd/system [ -d $SYSTEMD_DIR ] || SYSTEMD_DIR=/lib/systemd/system TMPFILE_CONF=/usr/lib/tmpfiles.d/firebird.conf @@ -140,13 +139,9 @@ installSystemdCtrlFiles() { exit 1 fi - editFile "@FB_MISCDIR@/firebird-superserver.service" ExecStart "ExecStart=${fb_install_prefix}/bin/fbguard -pidfile $PidDir/${fb_startup_name}.pid -daemon -forever" - editFile "@FB_MISCDIR@/firebird-superserver.service" PIDFile "PIDFile=$PidDir/${fb_startup_name}.pid" - editFile "@FB_MISCDIR@/firebird-classic@.service" ExecStart "ExecStart=${fb_install_prefix}/bin/firebird" - - cp @FB_MISCDIR@/firebird-superserver.service "${SYSTEMD_DIR}/${fb_startup_name}-superserver.service" - cp @FB_MISCDIR@/firebird-classic@.service "${SYSTEMD_DIR}/${fb_startup_name}-classic@.service" - cp @FB_MISCDIR@/firebird-classic.socket "${SYSTEMD_DIR}/${fb_startup_name}-classic.socket" + editFile "@FB_MISCDIR@/firebird.service" ExecStart "ExecStart=${fb_install_prefix}/bin/fbguard -pidfile $PidDir/${fb_startup_name}.pid -daemon -forever" + editFile "@FB_MISCDIR@/firebird.service" PIDFile "PIDFile=$PidDir/${fb_startup_name}.pid" + cp @FB_MISCDIR@/firebird.service "${SYSTEMD_DIR}/${fb_startup_name}.service" mkdir -p ${PidDir} chown $RunUser:$RunGroup ${PidDir} @@ -156,7 +151,7 @@ installSystemdCtrlFiles() { } osRemoveStartupFiles() { - rm -f ${SYSTEMD_DIR}/${fb_startup_name}-* + rm -f ${SYSTEMD_DIR}/${fb_startup_name}.* rm -f ${TMPFILE_CONF} } @@ -180,33 +175,10 @@ systemdSrv() { return 1 } -classicSrv() { - op=${1} - - systemdSrv ${op} ${CLASSIC_CTRL} -} - superSrv() { op=${1} - systemdSrv ${op} ${SUPER_CTRL} -} - -osRegisterClassicServer() { - installSystemdCtrlFiles - classicSrv enable -} - -osUnregisterClassicServer() { - classicSrv disable -} - -osStartClassicServer() { - classicSrv start -} - -osStopClassicServer() { - classicSrv stop + systemdSrv ${op} ${CTRL} } registerSuperServer() { @@ -236,9 +208,6 @@ stopSuperServer() { } -# Additional OS settings -systemdPresent && OS_Has_Specific_Classic_Startup=yes - #------------------------------------------------------------------------ # stop super server if it is running @@ -493,7 +462,7 @@ removeServiceAutostart() { standaloneServerInstalled() { if systemdPresent; then - ${SYSTEMCTL} --quiet is-enabled ${SUPER_CTRL} && return 0 + ${SYSTEMCTL} --quiet is-enabled ${CTRL} && return 0 return 1 fi diff --git a/builds/install/arch-specific/linux/makeInstallImage.sh.in b/builds/install/arch-specific/linux/makeInstallImage.sh.in index 0cf0fbe504..d6a8a840aa 100644 --- a/builds/install/arch-specific/linux/makeInstallImage.sh.in +++ b/builds/install/arch-specific/linux/makeInstallImage.sh.in @@ -285,10 +285,9 @@ copyFiles() { #misc cp $BuildRootDir/src/misc/intl.sql ${TargetDir}@FB_MISCDIR@ cp $BuildRootDir/src/misc/upgrade/v3.0/security_database* ${TargetDir}@FB_MISCDIR@/upgrade/security - cp $BuildRootDir/gen/install/misc/firebird.xinetd ${TargetDir}@FB_MISCDIR@ cp $BuildRootDir/gen/install/misc/firebird.init.d.* ${TargetDir}@FB_MISCDIR@ cp $BuildRootDir/gen/install/misc/rc.config.firebird ${TargetDir}@FB_MISCDIR@ - cp $BuildRootDir/gen/install/misc/firebird-* ${TargetDir}@FB_MISCDIR@ + cp $BuildRootDir/gen/install/misc/firebird.service ${TargetDir}@FB_MISCDIR@ chmod -R go-rwx ${TargetDir}@FB_MISCDIR@ diff --git a/builds/install/posix-common/FirebirdUninstall.sh.in b/builds/install/posix-common/FirebirdUninstall.sh.in index 98c3ce15ca..ad3ae94151 100644 --- a/builds/install/posix-common/FirebirdUninstall.sh.in +++ b/builds/install/posix-common/FirebirdUninstall.sh.in @@ -69,7 +69,6 @@ done removeLinksForBackCompatibility removeServiceAutostart -removeInetdServiceEntry if [ -d $PidDir ] then @@ -82,9 +81,4 @@ removeInstalledFiles # Remove installed files removeUninstallFiles # Remove the 'uninstall' utility files removeEmptyDirs # Remove empty directories -if [ "$OS_Has_Specific_Classic_Startup" ] -then - osRemoveStartupFiles -fi - displayMessage "Uninstall completed" diff --git a/builds/install/posix-common/changeServerMode.sh.in b/builds/install/posix-common/changeServerMode.sh.in index d9475ea08e..e0383d8837 100644 --- a/builds/install/posix-common/changeServerMode.sh.in +++ b/builds/install/posix-common/changeServerMode.sh.in @@ -27,6 +27,11 @@ cat < + @@ -62,6 +63,7 @@ + @@ -91,6 +93,11 @@ + + + + + @@ -158,6 +165,7 @@ + @@ -196,6 +204,19 @@ + + + + + + + + + + + + + @@ -283,7 +304,7 @@ 0x041d - ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Release\tommath.lib;%(AdditionalDependencies) + ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies) @@ -299,7 +320,7 @@ 0x041d - ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Debug\tommath.lib;%(AdditionalDependencies) + ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies) @@ -318,7 +339,7 @@ 0x041d - ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Release\tommath.lib;%(AdditionalDependencies) + ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies) @@ -336,7 +357,7 @@ 0x041d - ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Debug\tommath.lib;%(AdditionalDependencies) + ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies) diff --git a/builds/win32/msvc10/common.vcxproj.filters b/builds/win32/msvc10/common.vcxproj.filters index 871ca48d2f..1463f617a2 100644 --- a/builds/win32/msvc10/common.vcxproj.filters +++ b/builds/win32/msvc10/common.vcxproj.filters @@ -13,6 +13,9 @@ {03f83331-723e-4ba5-9ebb-348f0554a088} + + {dd0bb92e-0a1e-4406-96ff-5265e8d28258} + @@ -214,6 +217,27 @@ classes + common + + + classes + + + tomcrypt + + + tomcrypt + + + tomcrypt + + + tomcrypt + + + tomcrypt + + classes @@ -530,5 +554,47 @@ headers + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + \ No newline at end of file diff --git a/builds/win32/msvc12/common.vcxproj b/builds/win32/msvc12/common.vcxproj index 7fe6f7c086..9391f03c2a 100644 --- a/builds/win32/msvc12/common.vcxproj +++ b/builds/win32/msvc12/common.vcxproj @@ -45,6 +45,7 @@ + @@ -88,6 +89,11 @@ + + + + + @@ -194,6 +200,19 @@ + + + + + + + + + + + + + diff --git a/builds/win32/msvc12/common.vcxproj.filters b/builds/win32/msvc12/common.vcxproj.filters index 8fec78de3a..1463f617a2 100644 --- a/builds/win32/msvc12/common.vcxproj.filters +++ b/builds/win32/msvc12/common.vcxproj.filters @@ -13,6 +13,9 @@ {03f83331-723e-4ba5-9ebb-348f0554a088} + + {dd0bb92e-0a1e-4406-96ff-5265e8d28258} + @@ -219,6 +222,24 @@ classes + + tomcrypt + + + tomcrypt + + + tomcrypt + + + tomcrypt + + + tomcrypt + + + classes + @@ -536,5 +557,44 @@ headers + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + \ No newline at end of file diff --git a/builds/win32/msvc14/common.vcxproj b/builds/win32/msvc14/common.vcxproj index 26a2037c47..a02ed6ce87 100644 --- a/builds/win32/msvc14/common.vcxproj +++ b/builds/win32/msvc14/common.vcxproj @@ -45,6 +45,7 @@ + @@ -58,6 +59,7 @@ + @@ -87,6 +89,11 @@ + + + + + @@ -154,6 +161,7 @@ + @@ -192,6 +200,19 @@ + + + + + + + + + + + + + @@ -283,7 +304,7 @@ 0x041d - ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Release\tommath.lib;%(AdditionalDependencies) + ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies) @@ -299,7 +320,7 @@ 0x041d - ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Debug\tommath.lib;%(AdditionalDependencies) + ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies) @@ -318,7 +339,7 @@ 0x041d - ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Release\tommath.lib;%(AdditionalDependencies) + ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies) @@ -336,7 +357,7 @@ 0x041d - ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\Debug\tommath.lib;%(AdditionalDependencies) + ws2_32.lib;../../../extern/libtommath/lib/$(PlatformName)\$(Configuration)\tommath.lib;../../../extern/decNumber/lib/$(PlatformName)\$(Configuration)\decnumber.lib;%(AdditionalDependencies) diff --git a/builds/win32/msvc14/common.vcxproj.filters b/builds/win32/msvc14/common.vcxproj.filters index fb87986102..1463f617a2 100644 --- a/builds/win32/msvc14/common.vcxproj.filters +++ b/builds/win32/msvc14/common.vcxproj.filters @@ -13,6 +13,9 @@ {03f83331-723e-4ba5-9ebb-348f0554a088} + + {dd0bb92e-0a1e-4406-96ff-5265e8d28258} + @@ -216,6 +219,27 @@ common + + classes + + + tomcrypt + + + tomcrypt + + + tomcrypt + + + tomcrypt + + + tomcrypt + + + classes + @@ -530,5 +554,47 @@ headers + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + \ No newline at end of file diff --git a/configure.ac b/configure.ac index b89067f521..adf3940b3b 100644 --- a/configure.ac +++ b/configure.ac @@ -1264,7 +1264,6 @@ case "$PLATFORM" in INSTALL_SRC_DIR=builds/install/arch-specific/linux AC_CONFIG_FILES([ gen/install/makeInstallImage.sh:builds/install/arch-specific/linux/makeInstallImage.sh.in - gen/install/misc/firebird.xinetd:builds/install/arch-specific/linux/firebird.xinetd.in gen/install/misc/firebird.init.d.generic:builds/install/arch-specific/linux/firebird.init.d.generic.in gen/install/misc/firebird.init.d.mandrake:builds/install/arch-specific/linux/firebird.init.d.mandrake.in gen/install/misc/firebird.init.d.suse:builds/install/arch-specific/linux/firebird.init.d.suse.in @@ -1273,9 +1272,7 @@ case "$PLATFORM" in gen/install/misc/firebird.init.d.slackware:builds/install/arch-specific/linux/firebird.init.d.slackware.in gen/install/misc/rc.config.firebird:builds/install/arch-specific/linux/rc.config.firebird.in gen/Release/firebird/bin/linuxLibrary.sh:builds/install/arch-specific/linux/linuxLibrary.sh.in - gen/install/misc/firebird-classic@.service:builds/install/arch-specific/linux/firebird-classic.service.in - gen/install/misc/firebird-classic.socket:builds/install/arch-specific/linux/firebird-classic.socket.in - gen/install/misc/firebird-superserver.service:builds/install/arch-specific/linux/firebird-superserver.service.in + gen/install/misc/firebird.service:builds/install/arch-specific/linux/firebird.service.in ], [chmod a+x gen/install/*sh 2>/dev/null]) ;; diff --git a/doc/sql.extensions/README.builtin_functions.txt b/doc/sql.extensions/README.builtin_functions.txt index 564afced79..f397d52b90 100644 --- a/doc/sql.extensions/README.builtin_functions.txt +++ b/doc/sql.extensions/README.builtin_functions.txt @@ -473,13 +473,21 @@ HASH ---- Function: - Returns a HASH of a string. + Returns a HASH of a string using a specified algorithm. Format: - HASH( ) + HASH( [ USING ] ) + + algorithm ::= { MD5 | SHA1 | SHA256 | SHA512 } + +Important: + - The syntax without USING is very discouraged and maintained for backward compatibility. + It returns a 64 bit integer and produces very bad hashes that easily result in collisions. + - The syntax with USING is introduced in FB 4.0 and returns VARCHAR strings with OCTETS charset. Example: select hash(x) from y; + select hash(x using sha256) from y; ---- diff --git a/doc/sql.extensions/README.subroutines.txt b/doc/sql.extensions/README.subroutines.txt index 7077d9242b..5de6db5494 100644 --- a/doc/sql.extensions/README.subroutines.txt +++ b/doc/sql.extensions/README.subroutines.txt @@ -7,7 +7,7 @@ Author: Description: Support for PSQL subroutines (functions and procedures) inside functions, procedures, triggers - and EXECUTE BLOCK. Subroutines are declared in the main routine and may be used from there. + and EXECUTE BLOCK. Subroutines are declared in the main routine and may be used from there or others subroutines. Syntax: ::= @@ -15,7 +15,21 @@ Syntax: | DECLARE [VARIABLE] CURSOR FOR (); | - DECLARE FUNCTION RETURNS + + | + + + ::= + DECLARE FUNCTION [ () ] + RETURNS + [ [ NOT ] DETERMINISTIC ] ; + | + DECLARE PROCEDURE [ () ] [ RETURNS () ] ; + + ::= + DECLARE FUNCTION [ () ] + RETURNS + [ [ NOT ] DETERMINISTIC ] AS ... BEGIN @@ -32,8 +46,11 @@ Syntax: Limitations: 1) Subroutines may not be nested in another subroutine. They are only supported in the main routine. - 2) Currently, a subroutine may not directly access or use variables, cursors or another - subroutines of the main statements. This may be allowed in the future. + 2) Currently, a subroutine may not directly access or use variables or cursors of the + main statements. This may be allowed in the future. + +Notes: + 1) Starting in FB 4, subroutines may be recursive or call others subroutines. Examples: set term !; @@ -89,3 +106,57 @@ Examples: end! select func1(5, 6) from rdb$database! + + + -- 3) Recursive sub-function in EXECUTE BLOCK. + + execute block returns (i integer, o integer) + as + -- Recursive function without forward declaration. + declare function fibonacci(n integer) returns integer + as + begin + if (n = 0 or n = 1) then + return n; + else + return fibonacci(n - 1) + fibonacci(n - 2); + end + begin + i = 0; + + while (i < 10) + do + begin + o = fibonacci(i); + suspend; + i = i + 1; + end + end! + + + -- 4) Example with forward declaration and parameter with default values. + + execute block returns (o integer) + as + -- Forward declaration of P1. + declare procedure p1(i integer = 1) returns (o integer); + + -- Forward declaration of P2. + declare procedure p2(i integer) returns (o integer); + + -- Implementation of P1 should not re-declare parameter default value. + declare procedure p1(i integer) returns (o integer) + as + begin + execute procedure p2(i) returning_values o; + end + + declare procedure p2(i integer) returns (o integer) + as + begin + o = i; + end + begin + execute procedure p1 returning_values o; + suspend; + end! diff --git a/lang_helpers/gds_codes.ftn b/lang_helpers/gds_codes.ftn index e570469fa0..0814e509c9 100644 --- a/lang_helpers/gds_codes.ftn +++ b/lang_helpers/gds_codes.ftn @@ -1698,6 +1698,24 @@ C -- PARAMETER (GDS__decfloat_overflow = 335545142) INTEGER*4 GDS__decfloat_underflow PARAMETER (GDS__decfloat_underflow = 335545143) + INTEGER*4 GDS__subfunc_notdef + PARAMETER (GDS__subfunc_notdef = 335545144) + INTEGER*4 GDS__subproc_notdef + PARAMETER (GDS__subproc_notdef = 335545145) + INTEGER*4 GDS__subfunc_signat + PARAMETER (GDS__subfunc_signat = 335545146) + INTEGER*4 GDS__subproc_signat + PARAMETER (GDS__subproc_signat = 335545147) + INTEGER*4 GDS__subfunc_defvaldecl + PARAMETER (GDS__subfunc_defvaldecl = 335545148) + INTEGER*4 GDS__subproc_defvaldecl + PARAMETER (GDS__subproc_defvaldecl = 335545149) + INTEGER*4 GDS__subfunc_not_impl + PARAMETER (GDS__subfunc_not_impl = 335545150) + INTEGER*4 GDS__subproc_not_impl + PARAMETER (GDS__subproc_not_impl = 335545151) + INTEGER*4 GDS__sysf_invalid_hash_algorithm + PARAMETER (GDS__sysf_invalid_hash_algorithm = 335545152) INTEGER*4 GDS__gfix_db_name PARAMETER (GDS__gfix_db_name = 335740929) INTEGER*4 GDS__gfix_invalid_sw diff --git a/lang_helpers/gds_codes.pas b/lang_helpers/gds_codes.pas index b2a8f54aca..b77d7eeef2 100644 --- a/lang_helpers/gds_codes.pas +++ b/lang_helpers/gds_codes.pas @@ -1693,6 +1693,24 @@ const gds_decfloat_overflow = 335545142; isc_decfloat_underflow = 335545143; gds_decfloat_underflow = 335545143; + isc_subfunc_notdef = 335545144; + gds_subfunc_notdef = 335545144; + isc_subproc_notdef = 335545145; + gds_subproc_notdef = 335545145; + isc_subfunc_signat = 335545146; + gds_subfunc_signat = 335545146; + isc_subproc_signat = 335545147; + gds_subproc_signat = 335545147; + isc_subfunc_defvaldecl = 335545148; + gds_subfunc_defvaldecl = 335545148; + isc_subproc_defvaldecl = 335545149; + gds_subproc_defvaldecl = 335545149; + isc_subfunc_not_impl = 335545150; + gds_subfunc_not_impl = 335545150; + isc_subproc_not_impl = 335545151; + gds_subproc_not_impl = 335545151; + isc_sysf_invalid_hash_algorithm = 335545152; + gds_sysf_invalid_hash_algorithm = 335545152; isc_gfix_db_name = 335740929; gds_gfix_db_name = 335740929; isc_gfix_invalid_sw = 335740930; diff --git a/src/burp/restore.epp b/src/burp/restore.epp index 0ec78f67f3..615f87723b 100644 --- a/src/burp/restore.epp +++ b/src/burp/restore.epp @@ -2936,6 +2936,7 @@ rec_type get_data(BurpGlobals* tdgbl, burp_rel* relation, bool skip_relation) ULONG records = 0; rec_type record; + bool resync = false; while (true) { @@ -3027,11 +3028,13 @@ rec_type get_data(BurpGlobals* tdgbl, burp_rel* relation, bool skip_relation) // ASF: Preferable we should call isc_start_and_send only when records == 1, but this leaks // memory when there are blobs and arrays fields - CORE-3802. - if (records % 1000 == 1) + if (resync || records % 1000 == 1) s = isc_start_and_send(status_vector, &request, &gds_trans, 0, (USHORT) length, buffer, 0); else s = isc_send(status_vector, &request, 0, (USHORT) length, buffer, 0); + resync = (s != 0); + if (s) { if (status_vector[1] == isc_not_valid) @@ -3071,7 +3074,10 @@ rec_type get_data(BurpGlobals* tdgbl, burp_rel* relation, bool skip_relation) BURP_error_redirect (status_vector, 48); // msg 48 isc_send failed } + + records--; } + if (record != rec_data) break; } // while (true) diff --git a/src/common/classes/FpeControl.h b/src/common/classes/FpeControl.h index e0e36acafa..b3f0b66d4f 100644 --- a/src/common/classes/FpeControl.h +++ b/src/common/classes/FpeControl.h @@ -232,4 +232,15 @@ inline bool isinf(F x) #endif // isinf #endif // WIN_NT +namespace Firebird { + inline bool isNegativeInf(double x) + { +#ifdef WIN_NT + return _fpclass(x) == _FPCLASS_NINF; +#else + return x == -INFINITY; +#endif + } +} + #endif //CLASSES_FPE_CONTROL_H diff --git a/src/common/classes/Hash.cpp b/src/common/classes/Hash.cpp index afe31c9a84..605088fa06 100644 --- a/src/common/classes/Hash.cpp +++ b/src/common/classes/Hash.cpp @@ -108,3 +108,26 @@ unsigned int InternalHash::hash(unsigned int length, const UCHAR* value) { return internalHash(length, value); } + + +void WeakHashContext::update(const void* data, FB_SIZE_T length) +{ + const UCHAR* p = static_cast(data); + + for (const UCHAR* end = p + length; p != end; ++p) + { + hashNumber = (hashNumber << 4) + *p; + + const SINT64 n = hashNumber & FB_CONST64(0xF000000000000000); + if (n) + hashNumber ^= n >> 56; + + hashNumber &= ~n; + } +} + +void WeakHashContext::finish(Buffer& result) +{ + UCHAR* resultBuffer = result.getBuffer(sizeof(hashNumber)); + memcpy(resultBuffer, &hashNumber, sizeof(hashNumber)); +} diff --git a/src/common/classes/Hash.h b/src/common/classes/Hash.h index 39aaa5b46f..76501e7cc2 100644 --- a/src/common/classes/Hash.h +++ b/src/common/classes/Hash.h @@ -28,7 +28,7 @@ #ifndef CLASSES_HASH_H #define CLASSES_HASH_H -#include "../common/classes/vector.h" +#include "../common/classes/array.h" namespace Firebird { @@ -341,7 +341,78 @@ namespace Firebird } }; + + class HashContext + { + public: + typedef HalfStaticArray Buffer; + + public: + virtual ~HashContext() + { + } + + public: + virtual void update(const void* data, FB_SIZE_T length) = 0; + virtual void finish(Buffer& result) = 0; + }; + + class WeakHashContext FB_FINAL : public HashContext + { + public: + virtual void update(const void* data, FB_SIZE_T length); + virtual void finish(Buffer& result); + + private: + SINT64 hashNumber = 0; + }; + + class LibTomCryptHashContext : public HashContext + { + public: + struct Descriptor; + + private: + struct State; + + protected: + LibTomCryptHashContext(MemoryPool& pool, const Descriptor* descriptor); + + public: + virtual ~LibTomCryptHashContext(); + + public: + virtual void update(const void* data, FB_SIZE_T length); + virtual void finish(Buffer& result); + + private: + const Descriptor* descriptor; + State* statePtr; + }; + + class Md5HashContext FB_FINAL : public LibTomCryptHashContext + { + public: + Md5HashContext(MemoryPool& pool); + }; + + class Sha1HashContext FB_FINAL : public LibTomCryptHashContext + { + public: + Sha1HashContext(MemoryPool& pool); + }; + + class Sha256HashContext FB_FINAL : public LibTomCryptHashContext + { + public: + Sha256HashContext(MemoryPool& pool); + }; + + class Sha512HashContext FB_FINAL : public LibTomCryptHashContext + { + public: + Sha512HashContext(MemoryPool& pool); + }; } // namespace Firebird #endif // CLASSES_HASH_H - diff --git a/src/common/classes/TomCryptHash.cpp b/src/common/classes/TomCryptHash.cpp new file mode 100644 index 0000000000..14fba11623 --- /dev/null +++ b/src/common/classes/TomCryptHash.cpp @@ -0,0 +1,96 @@ +/* + * Hashing using libtomcrypt library. + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2017 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include "firebird.h" +#include "../common/classes/Hash.h" +#include "../common/tomcrypt/tomcrypt.h" + +using namespace Firebird; + + +struct LibTomCryptHashContext::Descriptor +{ + const ltc_hash_descriptor* tcDesc; +}; + +struct LibTomCryptHashContext::State +{ + hash_state tcState; +}; + + +LibTomCryptHashContext::LibTomCryptHashContext(MemoryPool& pool, const Descriptor* aDescriptor) + : descriptor(aDescriptor) +{ + statePtr = FB_NEW_POOL(pool) State(); + descriptor->tcDesc->init(&statePtr->tcState); +} + +LibTomCryptHashContext::~LibTomCryptHashContext() +{ + delete statePtr; +} + +void LibTomCryptHashContext::update(const void* data, FB_SIZE_T length) +{ + descriptor->tcDesc->process(&statePtr->tcState, static_cast(data), length); +} + +void LibTomCryptHashContext::finish(Buffer& result) +{ + unsigned char* hashResult = result.getBuffer(descriptor->tcDesc->hashsize); + descriptor->tcDesc->done(&statePtr->tcState, hashResult); +} + + +static LibTomCryptHashContext::Descriptor md5Descriptor{&md5_desc}; + +Md5HashContext::Md5HashContext(MemoryPool& pool) + : LibTomCryptHashContext(pool, &md5Descriptor) +{ +} + + +static LibTomCryptHashContext::Descriptor sha1Descriptor{&sha1_desc}; + +Sha1HashContext::Sha1HashContext(MemoryPool& pool) + : LibTomCryptHashContext(pool, &sha1Descriptor) +{ +} + + +static LibTomCryptHashContext::Descriptor sha256Descriptor{&sha256_desc}; + +Sha256HashContext::Sha256HashContext(MemoryPool& pool) + : LibTomCryptHashContext(pool, &sha256Descriptor) +{ +} + + +static LibTomCryptHashContext::Descriptor sha512Descriptor{&sha512_desc}; + +Sha512HashContext::Sha512HashContext(MemoryPool& pool) + : LibTomCryptHashContext(pool, &sha512Descriptor) +{ +} diff --git a/src/common/tomcrypt/crypt_argchk.c b/src/common/tomcrypt/crypt_argchk.c new file mode 100644 index 0000000000..c86f086254 --- /dev/null +++ b/src/common/tomcrypt/crypt_argchk.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" +#include + +/** + @file crypt_argchk.c + Perform argument checking, Tom St Denis +*/ + +#if (ARGTYPE == 0) +void crypt_argchk(char *v, char *s, int d) +{ + fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n", + v, d, s); + (void)raise(SIGABRT); +} +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/md5.c b/src/common/tomcrypt/md5.c new file mode 100644 index 0000000000..4fa1e9e172 --- /dev/null +++ b/src/common/tomcrypt/md5.c @@ -0,0 +1,368 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + + +/** + @file md5.c + LTC_MD5 hash function by Tom St Denis +*/ + +#ifdef LTC_MD5 + +const struct ltc_hash_descriptor md5_desc = +{ + "md5", + 3, + 16, + 64, + + /* OID */ + { 1, 2, 840, 113549, 2, 5, }, + 6, + + &md5_init, + &md5_process, + &md5_done, + &md5_test, + NULL +}; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define G(x,y,z) (y ^ (z & (y ^ x))) +#define H(x,y,z) (x^y^z) +#define I(x,y,z) (y^(x|(~z))) + +#ifdef LTC_SMALL_CODE + +#define FF(a,b,c,d,M,s,t) \ + a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b; + +#define GG(a,b,c,d,M,s,t) \ + a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b; + +#define HH(a,b,c,d,M,s,t) \ + a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b; + +#define II(a,b,c,d,M,s,t) \ + a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b; + +static const unsigned char Worder[64] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12, + 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2, + 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 +}; + +static const unsigned char Rorder[64] = { + 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, + 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, + 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, + 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21 +}; + +static const ulong32 Korder[64] = { +0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, +0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, +0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, +0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, +0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, +0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, +0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, +0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL +}; + +#else + +#define FF(a,b,c,d,M,s,t) \ + a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define GG(a,b,c,d,M,s,t) \ + a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define HH(a,b,c,d,M,s,t) \ + a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define II(a,b,c,d,M,s,t) \ + a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b; + + +#endif + +#ifdef LTC_CLEAN_STACK +static int _md5_compress(hash_state *md, unsigned char *buf) +#else +static int md5_compress(hash_state *md, unsigned char *buf) +#endif +{ + ulong32 i, W[16], a, b, c, d; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32L(W[i], buf + (4*i)); + } + + /* copy state */ + a = md->md5.state[0]; + b = md->md5.state[1]; + c = md->md5.state[2]; + d = md->md5.state[3]; + +#ifdef LTC_SMALL_CODE + for (i = 0; i < 16; ++i) { + FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 32; ++i) { + GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 48; ++i) { + HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 64; ++i) { + II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + +#else + FF(a,b,c,d,W[0],7,0xd76aa478UL) + FF(d,a,b,c,W[1],12,0xe8c7b756UL) + FF(c,d,a,b,W[2],17,0x242070dbUL) + FF(b,c,d,a,W[3],22,0xc1bdceeeUL) + FF(a,b,c,d,W[4],7,0xf57c0fafUL) + FF(d,a,b,c,W[5],12,0x4787c62aUL) + FF(c,d,a,b,W[6],17,0xa8304613UL) + FF(b,c,d,a,W[7],22,0xfd469501UL) + FF(a,b,c,d,W[8],7,0x698098d8UL) + FF(d,a,b,c,W[9],12,0x8b44f7afUL) + FF(c,d,a,b,W[10],17,0xffff5bb1UL) + FF(b,c,d,a,W[11],22,0x895cd7beUL) + FF(a,b,c,d,W[12],7,0x6b901122UL) + FF(d,a,b,c,W[13],12,0xfd987193UL) + FF(c,d,a,b,W[14],17,0xa679438eUL) + FF(b,c,d,a,W[15],22,0x49b40821UL) + GG(a,b,c,d,W[1],5,0xf61e2562UL) + GG(d,a,b,c,W[6],9,0xc040b340UL) + GG(c,d,a,b,W[11],14,0x265e5a51UL) + GG(b,c,d,a,W[0],20,0xe9b6c7aaUL) + GG(a,b,c,d,W[5],5,0xd62f105dUL) + GG(d,a,b,c,W[10],9,0x02441453UL) + GG(c,d,a,b,W[15],14,0xd8a1e681UL) + GG(b,c,d,a,W[4],20,0xe7d3fbc8UL) + GG(a,b,c,d,W[9],5,0x21e1cde6UL) + GG(d,a,b,c,W[14],9,0xc33707d6UL) + GG(c,d,a,b,W[3],14,0xf4d50d87UL) + GG(b,c,d,a,W[8],20,0x455a14edUL) + GG(a,b,c,d,W[13],5,0xa9e3e905UL) + GG(d,a,b,c,W[2],9,0xfcefa3f8UL) + GG(c,d,a,b,W[7],14,0x676f02d9UL) + GG(b,c,d,a,W[12],20,0x8d2a4c8aUL) + HH(a,b,c,d,W[5],4,0xfffa3942UL) + HH(d,a,b,c,W[8],11,0x8771f681UL) + HH(c,d,a,b,W[11],16,0x6d9d6122UL) + HH(b,c,d,a,W[14],23,0xfde5380cUL) + HH(a,b,c,d,W[1],4,0xa4beea44UL) + HH(d,a,b,c,W[4],11,0x4bdecfa9UL) + HH(c,d,a,b,W[7],16,0xf6bb4b60UL) + HH(b,c,d,a,W[10],23,0xbebfbc70UL) + HH(a,b,c,d,W[13],4,0x289b7ec6UL) + HH(d,a,b,c,W[0],11,0xeaa127faUL) + HH(c,d,a,b,W[3],16,0xd4ef3085UL) + HH(b,c,d,a,W[6],23,0x04881d05UL) + HH(a,b,c,d,W[9],4,0xd9d4d039UL) + HH(d,a,b,c,W[12],11,0xe6db99e5UL) + HH(c,d,a,b,W[15],16,0x1fa27cf8UL) + HH(b,c,d,a,W[2],23,0xc4ac5665UL) + II(a,b,c,d,W[0],6,0xf4292244UL) + II(d,a,b,c,W[7],10,0x432aff97UL) + II(c,d,a,b,W[14],15,0xab9423a7UL) + II(b,c,d,a,W[5],21,0xfc93a039UL) + II(a,b,c,d,W[12],6,0x655b59c3UL) + II(d,a,b,c,W[3],10,0x8f0ccc92UL) + II(c,d,a,b,W[10],15,0xffeff47dUL) + II(b,c,d,a,W[1],21,0x85845dd1UL) + II(a,b,c,d,W[8],6,0x6fa87e4fUL) + II(d,a,b,c,W[15],10,0xfe2ce6e0UL) + II(c,d,a,b,W[6],15,0xa3014314UL) + II(b,c,d,a,W[13],21,0x4e0811a1UL) + II(a,b,c,d,W[4],6,0xf7537e82UL) + II(d,a,b,c,W[11],10,0xbd3af235UL) + II(c,d,a,b,W[2],15,0x2ad7d2bbUL) + II(b,c,d,a,W[9],21,0xeb86d391UL) +#endif + + md->md5.state[0] = md->md5.state[0] + a; + md->md5.state[1] = md->md5.state[1] + b; + md->md5.state[2] = md->md5.state[2] + c; + md->md5.state[3] = md->md5.state[3] + d; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int md5_compress(hash_state *md, unsigned char *buf) +{ + int err; + err = _md5_compress(md, buf); + burn_stack(sizeof(ulong32) * 21); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int md5_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->md5.state[0] = 0x67452301UL; + md->md5.state[1] = 0xefcdab89UL; + md->md5.state[2] = 0x98badcfeUL; + md->md5.state[3] = 0x10325476UL; + md->md5.curlen = 0; + md->md5.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(md5_process, md5_compress, md5, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (16 bytes) + @return CRYPT_OK if successful +*/ +int md5_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->md5.curlen >= sizeof(md->md5.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->md5.length += md->md5.curlen * 8; + + /* append the '1' bit */ + md->md5.buf[md->md5.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->md5.curlen > 56) { + while (md->md5.curlen < 64) { + md->md5.buf[md->md5.curlen++] = (unsigned char)0; + } + md5_compress(md, md->md5.buf); + md->md5.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->md5.curlen < 56) { + md->md5.buf[md->md5.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->md5.length, md->md5.buf+56); + md5_compress(md, md->md5.buf); + + /* copy output */ + for (i = 0; i < 4; i++) { + STORE32L(md->md5.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int md5_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, + { "a", + {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, + 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, + { "abc", + { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, + { "message digest", + { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, + 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, + 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, + 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, + 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + md5_init(&md); + md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + md5_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 16) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/sha1.c b/src/common/tomcrypt/sha1.c new file mode 100644 index 0000000000..8c846b089c --- /dev/null +++ b/src/common/tomcrypt/sha1.c @@ -0,0 +1,288 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file sha1.c + LTC_SHA1 code by Tom St Denis +*/ + + +#ifdef LTC_SHA1 + +const struct ltc_hash_descriptor sha1_desc = +{ + "sha1", + 2, + 20, + 64, + + /* OID */ + { 1, 3, 14, 3, 2, 26, }, + 6, + + &sha1_init, + &sha1_process, + &sha1_done, + &sha1_test, + NULL +}; + +#define F0(x,y,z) (z ^ (x & (y ^ z))) +#define F1(x,y,z) (x ^ y ^ z) +#define F2(x,y,z) ((x & y) | (z & (x | y))) +#define F3(x,y,z) (x ^ y ^ z) + +#ifdef LTC_CLEAN_STACK +static int _sha1_compress(hash_state *md, unsigned char *buf) +#else +static int sha1_compress(hash_state *md, unsigned char *buf) +#endif +{ + ulong32 a,b,c,d,e,W[80],i; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* copy state */ + a = md->sha1.state[0]; + b = md->sha1.state[1]; + c = md->sha1.state[2]; + d = md->sha1.state[3]; + e = md->sha1.state[4]; + + /* expand it */ + for (i = 16; i < 80; i++) { + W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); + } + + /* compress */ + /* round one */ + #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); + #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); + #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); + #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); + +#ifdef LTC_SMALL_CODE + + for (i = 0; i < 20; ) { + FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; ) { + FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; ) { + FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; ) { + FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + +#else + + for (i = 0; i < 20; ) { + FF0(a,b,c,d,e,i++); + FF0(e,a,b,c,d,i++); + FF0(d,e,a,b,c,i++); + FF0(c,d,e,a,b,i++); + FF0(b,c,d,e,a,i++); + } + + /* round two */ + for (; i < 40; ) { + FF1(a,b,c,d,e,i++); + FF1(e,a,b,c,d,i++); + FF1(d,e,a,b,c,i++); + FF1(c,d,e,a,b,i++); + FF1(b,c,d,e,a,i++); + } + + /* round three */ + for (; i < 60; ) { + FF2(a,b,c,d,e,i++); + FF2(e,a,b,c,d,i++); + FF2(d,e,a,b,c,i++); + FF2(c,d,e,a,b,i++); + FF2(b,c,d,e,a,i++); + } + + /* round four */ + for (; i < 80; ) { + FF3(a,b,c,d,e,i++); + FF3(e,a,b,c,d,i++); + FF3(d,e,a,b,c,i++); + FF3(c,d,e,a,b,i++); + FF3(b,c,d,e,a,i++); + } +#endif + + #undef FF0 + #undef FF1 + #undef FF2 + #undef FF3 + + /* store */ + md->sha1.state[0] = md->sha1.state[0] + a; + md->sha1.state[1] = md->sha1.state[1] + b; + md->sha1.state[2] = md->sha1.state[2] + c; + md->sha1.state[3] = md->sha1.state[3] + d; + md->sha1.state[4] = md->sha1.state[4] + e; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int sha1_compress(hash_state *md, unsigned char *buf) +{ + int err; + err = _sha1_compress(md, buf); + burn_stack(sizeof(ulong32) * 87); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha1_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->sha1.state[0] = 0x67452301UL; + md->sha1.state[1] = 0xefcdab89UL; + md->sha1.state[2] = 0x98badcfeUL; + md->sha1.state[3] = 0x10325476UL; + md->sha1.state[4] = 0xc3d2e1f0UL; + md->sha1.curlen = 0; + md->sha1.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sha1_process, sha1_compress, sha1, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (20 bytes) + @return CRYPT_OK if successful +*/ +int sha1_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha1.curlen >= sizeof(md->sha1.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->sha1.length += md->sha1.curlen * 8; + + /* append the '1' bit */ + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha1.curlen > 56) { + while (md->sha1.curlen < 64) { + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; + } + sha1_compress(md, md->sha1.buf); + md->sha1.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->sha1.curlen < 56) { + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha1.length, md->sha1.buf+56); + sha1_compress(md, md->sha1.buf); + + /* copy output */ + for (i = 0; i < 5; i++) { + STORE32H(md->sha1.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha1_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + char *msg; + unsigned char hash[20]; + } tests[] = { + { "abc", + { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, + 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, + 0x9c, 0xd0, 0xd8, 0x9d } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, + 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, + 0xE5, 0x46, 0x70, 0xF1 } + } + }; + + int i; + unsigned char tmp[20]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha1_init(&md); + sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + sha1_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 20) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/sha256.c b/src/common/tomcrypt/sha256.c new file mode 100644 index 0000000000..ad1386a551 --- /dev/null +++ b/src/common/tomcrypt/sha256.c @@ -0,0 +1,340 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file sha256.c + LTC_SHA256 by Tom St Denis +*/ + +#ifdef LTC_SHA256 + +const struct ltc_hash_descriptor sha256_desc = +{ + "sha256", + 0, + 32, + 64, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 1, }, + 9, + + &sha256_init, + &sha256_process, + &sha256_done, + &sha256_test, + NULL +}; + +#ifdef LTC_SMALL_CODE +/* the K array */ +static const ulong32 K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; +#endif + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x),(n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + +/* compress 512-bits */ +#ifdef LTC_CLEAN_STACK +static int _sha256_compress(hash_state * md, unsigned char *buf) +#else +static int sha256_compress(hash_state * md, unsigned char *buf) +#endif +{ + ulong32 S[8], W[64], t0, t1; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->sha256.state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#ifdef LTC_SMALL_CODE +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 64; ++i) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } +#else +#define RND(a,b,c,d,e,f,g,h,i,ki) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); + +#undef RND + +#endif + + /* feedback */ + for (i = 0; i < 8; i++) { + md->sha256.state[i] = md->sha256.state[i] + S[i]; + } + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int sha256_compress(hash_state * md, unsigned char *buf) +{ + int err; + err = _sha256_compress(md, buf); + burn_stack(sizeof(ulong32) * 74); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha256_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha256.curlen = 0; + md->sha256.length = 0; + md->sha256.state[0] = 0x6A09E667UL; + md->sha256.state[1] = 0xBB67AE85UL; + md->sha256.state[2] = 0x3C6EF372UL; + md->sha256.state[3] = 0xA54FF53AUL; + md->sha256.state[4] = 0x510E527FUL; + md->sha256.state[5] = 0x9B05688CUL; + md->sha256.state[6] = 0x1F83D9ABUL; + md->sha256.state[7] = 0x5BE0CD19UL; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sha256_process, sha256_compress, sha256, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful +*/ +int sha256_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha256.curlen >= sizeof(md->sha256.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->sha256.length += md->sha256.curlen * 8; + + /* append the '1' bit */ + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha256.curlen > 56) { + while (md->sha256.curlen < 64) { + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; + } + sha256_compress(md, md->sha256.buf); + md->sha256.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->sha256.curlen < 56) { + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha256.length, md->sha256.buf+56); + sha256_compress(md, md->sha256.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32H(md->sha256.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha256_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + char *msg; + unsigned char hash[32]; + } tests[] = { + { "abc", + { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } + }, + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha256_init(&md); + sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + sha256_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 32) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#ifdef LTC_SHA224 +#include "sha224.c" +#endif + +#endif + + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/sha512.c b/src/common/tomcrypt/sha512.c new file mode 100644 index 0000000000..4b7e7612fd --- /dev/null +++ b/src/common/tomcrypt/sha512.c @@ -0,0 +1,319 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @param sha512.c + LTC_SHA512 by Tom St Denis +*/ + +#ifdef LTC_SHA512 + +const struct ltc_hash_descriptor sha512_desc = +{ + "sha512", + 5, + 64, + 128, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 3, }, + 9, + + &sha512_init, + &sha512_process, + &sha512_done, + &sha512_test, + NULL +}; + +/* the K array */ +static const ulong64 K[80] = { +CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), +CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc), +CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), +CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118), +CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), +CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2), +CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), +CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694), +CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), +CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65), +CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), +CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5), +CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), +CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4), +CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), +CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70), +CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), +CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df), +CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), +CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b), +CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001), +CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30), +CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), +CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8), +CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), +CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8), +CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), +CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3), +CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), +CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec), +CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), +CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b), +CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), +CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178), +CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), +CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b), +CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), +CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c), +CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), +CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817) +}; + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) ROR64c(x, n) +#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n)) +#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) +#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) +#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) +#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) + +/* compress 1024-bits */ +#ifdef LTC_CLEAN_STACK +static int _sha512_compress(hash_state * md, unsigned char *buf) +#else +static int sha512_compress(hash_state * md, unsigned char *buf) +#endif +{ + ulong64 S[8], W[80], t0, t1; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->sha512.state[i]; + } + + /* copy the state into 1024-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD64H(W[i], buf + (8*i)); + } + + /* fill W[16..79] */ + for (i = 16; i < 80; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#ifdef LTC_SMALL_CODE + for (i = 0; i < 80; i++) { + t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; + t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); + S[7] = S[6]; + S[6] = S[5]; + S[5] = S[4]; + S[4] = S[3] + t0; + S[3] = S[2]; + S[2] = S[1]; + S[1] = S[0]; + S[0] = t0 + t1; + } +#else +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 80; i += 8) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); + } +#endif + + + /* feedback */ + for (i = 0; i < 8; i++) { + md->sha512.state[i] = md->sha512.state[i] + S[i]; + } + + return CRYPT_OK; +} + +/* compress 1024-bits */ +#ifdef LTC_CLEAN_STACK +static int sha512_compress(hash_state * md, unsigned char *buf) +{ + int err; + err = _sha512_compress(md, buf); + burn_stack(sizeof(ulong64) * 90 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha512_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->sha512.curlen = 0; + md->sha512.length = 0; + md->sha512.state[0] = CONST64(0x6a09e667f3bcc908); + md->sha512.state[1] = CONST64(0xbb67ae8584caa73b); + md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b); + md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1); + md->sha512.state[4] = CONST64(0x510e527fade682d1); + md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f); + md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b); + md->sha512.state[7] = CONST64(0x5be0cd19137e2179); + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sha512_process, sha512_compress, sha512, 128) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (64 bytes) + @return CRYPT_OK if successful +*/ +int sha512_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha512.curlen >= sizeof(md->sha512.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->sha512.length += md->sha512.curlen * CONST64(8); + + /* append the '1' bit */ + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 112 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha512.curlen > 112) { + while (md->sha512.curlen < 128) { + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; + } + sha512_compress(md, md->sha512.buf); + md->sha512.curlen = 0; + } + + /* pad upto 120 bytes of zeroes + * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash + * > 2^64 bits of data... :-) + */ + while (md->sha512.curlen < 120) { + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha512.length, md->sha512.buf+120); + sha512_compress(md, md->sha512.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE64H(md->sha512.state[i], out+(8*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha512_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + char *msg; + unsigned char hash[64]; + } tests[] = { + { "abc", + { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } + }, + }; + + int i; + unsigned char tmp[64]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha512_init(&md); + sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + sha512_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 64) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#ifdef LTC_SHA384 + #include "sha384.c" +#endif + +#endif + + + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt.h b/src/common/tomcrypt/tomcrypt.h new file mode 100644 index 0000000000..2ef21ffb5d --- /dev/null +++ b/src/common/tomcrypt/tomcrypt.h @@ -0,0 +1,87 @@ +#ifndef TOMCRYPT_H_ +#define TOMCRYPT_H_ +#include +#include +#include +#include +#include +#include +#include + +/* use configuration data */ +#include "tomcrypt_custom.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* version */ +#define CRYPT 0x0117 +#define SCRYPT "1.17" + +/* max size of either a cipher/hash block or symmetric key [largest of the two] */ +#define MAXBLOCKSIZE 128 + +/* descriptor table size */ +#define TAB_SIZE 32 + +/* error codes [will be expanded in future releases] */ +enum { + CRYPT_OK=0, /* Result OK */ + CRYPT_ERROR, /* Generic Error */ + CRYPT_NOP, /* Not a failure but no operation was performed */ + + CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ + CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ + CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ + + CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ + CRYPT_INVALID_PACKET, /* Invalid input packet given */ + + CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ + CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ + + CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ + CRYPT_INVALID_HASH, /* Invalid hash specified */ + CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ + + CRYPT_MEM, /* Out of memory */ + + CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ + CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ + + CRYPT_INVALID_ARG, /* Generic invalid argument */ + CRYPT_FILE_NOTFOUND, /* File Not Found */ + + CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ + CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */ + CRYPT_PK_DUP, /* Duplicate key already in key ring */ + CRYPT_PK_NOT_FOUND, /* Key not found in keyring */ + CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ + + CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */ + CRYPT_PK_INVALID_PADDING /* Invalid padding on input */ +}; + +#include "tomcrypt_cfg.h" +#include "tomcrypt_macros.h" +#include "tomcrypt_cipher.h" +#include "tomcrypt_hash.h" +#include "tomcrypt_mac.h" +#include "tomcrypt_prng.h" +#include "tomcrypt_pk.h" +#include "tomcrypt_math.h" +#include "tomcrypt_misc.h" +#include "tomcrypt_argchk.h" +#include "tomcrypt_pkcs.h" + +#ifdef __cplusplus + } +#endif + +#endif /* TOMCRYPT_H_ */ + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_argchk.h b/src/common/tomcrypt/tomcrypt_argchk.h new file mode 100644 index 0000000000..c4014b8f0d --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_argchk.h @@ -0,0 +1,38 @@ +/* Defines the LTC_ARGCHK macro used within the library */ +/* ARGTYPE is defined in mycrypt_cfg.h */ +#if ARGTYPE == 0 + +#include + +/* this is the default LibTomCrypt macro */ +void crypt_argchk(char *v, char *s, int d); +#define LTC_ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 1 + +/* fatal type of error */ +#define LTC_ARGCHK(x) assert((x)) +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 2 + +#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); } +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 3 + +#define LTC_ARGCHK(x) +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 4 + +#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG; +#define LTC_ARGCHKVD(x) if (!(x)) return; + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_cfg.h b/src/common/tomcrypt/tomcrypt_cfg.h new file mode 100644 index 0000000000..f7ad3cc0c9 --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_cfg.h @@ -0,0 +1,136 @@ +/* This is the build config file. + * + * With this you can setup what to inlcude/exclude automatically during any build. Just comment + * out the line that #define's the word for the thing you want to remove. phew! + */ + +#ifndef TOMCRYPT_CFG_H +#define TOMCRYPT_CFG_H + +#if defined(_WIN32) || defined(_MSC_VER) +#define LTC_CALL __cdecl +#else +#ifndef LTC_CALL + #define LTC_CALL +#endif +#endif + +#ifndef LTC_EXPORT +#define LTC_EXPORT +#endif + +/* certain platforms use macros for these, making the prototypes broken */ +#ifndef LTC_NO_PROTOTYPES + +/* you can change how memory allocation works ... */ +LTC_EXPORT void * LTC_CALL XMALLOC(size_t n); +LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n); +LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s); +LTC_EXPORT void LTC_CALL XFREE(void *p); + +LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); + + +/* change the clock function too */ +LTC_EXPORT clock_t LTC_CALL XCLOCK(void); + +/* various other functions */ +LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n); +LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n); +LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n); + +LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2); + +#endif + +/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */ +#ifndef ARGTYPE + #define ARGTYPE 0 +#endif + +/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code + * + * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes. + * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST** + * use the portable [slower] macros. + */ + +/* detect x86-32 machines somewhat */ +#if !defined(__STRICT_ANSI__) && (defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__)))) + #define ENDIAN_LITTLE + #define ENDIAN_32BITWORD + #define LTC_FAST + #define LTC_FAST_TYPE unsigned long +#endif + +/* detects MIPS R5900 processors (PS2) */ +#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips)) + #define ENDIAN_LITTLE + #define ENDIAN_64BITWORD +#endif + +/* detect amd64 */ +#if !defined(__STRICT_ANSI__) && defined(__x86_64__) + #define ENDIAN_LITTLE + #define ENDIAN_64BITWORD + #define LTC_FAST + #define LTC_FAST_TYPE unsigned long +#endif + +/* detect PPC32 */ +#if !defined(__STRICT_ANSI__) && defined(LTC_PPC32) + #define ENDIAN_BIG + #define ENDIAN_32BITWORD + #define LTC_FAST + #define LTC_FAST_TYPE unsigned long +#endif + +/* detect sparc and sparc64 */ +#if defined(__sparc__) + #define ENDIAN_BIG + #if defined(__arch64__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + + +#ifdef LTC_NO_FAST + #ifdef LTC_FAST + #undef LTC_FAST + #endif +#endif + +/* No asm is a quick way to disable anything "not portable" */ +#ifdef LTC_NO_ASM + #undef ENDIAN_LITTLE + #undef ENDIAN_BIG + #undef ENDIAN_32BITWORD + #undef ENDIAN_64BITWORD + #undef LTC_FAST + #undef LTC_FAST_TYPE + #define LTC_NO_ROLC + #define LTC_NO_BSWAP +#endif + +/* #define ENDIAN_LITTLE */ +/* #define ENDIAN_BIG */ + +/* #define ENDIAN_32BITWORD */ +/* #define ENDIAN_64BITWORD */ + +#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD)) + #error You must specify a word size as well as endianess in tomcrypt_cfg.h +#endif + +#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) + #define ENDIAN_NEUTRAL +#endif + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_cipher.h b/src/common/tomcrypt/tomcrypt_cipher.h new file mode 100644 index 0000000000..f23fd977c2 --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_cipher.h @@ -0,0 +1,891 @@ +/* ---- SYMMETRIC KEY STUFF ----- + * + * We put each of the ciphers scheduled keys in their own structs then we put all of + * the key formats in one union. This makes the function prototypes easier to use. + */ +#ifdef LTC_BLOWFISH +struct blowfish_key { + ulong32 S[4][256]; + ulong32 K[18]; +}; +#endif + +#ifdef LTC_RC5 +struct rc5_key { + int rounds; + ulong32 K[50]; +}; +#endif + +#ifdef LTC_RC6 +struct rc6_key { + ulong32 K[44]; +}; +#endif + +#ifdef LTC_SAFERP +struct saferp_key { + unsigned char K[33][16]; + long rounds; +}; +#endif + +#ifdef LTC_RIJNDAEL +struct rijndael_key { + ulong32 eK[60], dK[60]; + int Nr; +}; +#endif + +#ifdef LTC_KSEED +struct kseed_key { + ulong32 K[32], dK[32]; +}; +#endif + +#ifdef LTC_KASUMI +struct kasumi_key { + ulong32 KLi1[8], KLi2[8], + KOi1[8], KOi2[8], KOi3[8], + KIi1[8], KIi2[8], KIi3[8]; +}; +#endif + +#ifdef LTC_XTEA +struct xtea_key { + unsigned long A[32], B[32]; +}; +#endif + +#ifdef LTC_TWOFISH +#ifndef LTC_TWOFISH_SMALL + struct twofish_key { + ulong32 S[4][256], K[40]; + }; +#else + struct twofish_key { + ulong32 K[40]; + unsigned char S[32], start; + }; +#endif +#endif + +#ifdef LTC_SAFER +#define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS 6 +#define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS 10 +#define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS 8 +#define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS 10 +#define LTC_SAFER_MAX_NOF_ROUNDS 13 +#define LTC_SAFER_BLOCK_LEN 8 +#define LTC_SAFER_KEY_LEN (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS)) +typedef unsigned char safer_block_t[LTC_SAFER_BLOCK_LEN]; +typedef unsigned char safer_key_t[LTC_SAFER_KEY_LEN]; +struct safer_key { safer_key_t key; }; +#endif + +#ifdef LTC_RC2 +struct rc2_key { unsigned xkey[64]; }; +#endif + +#ifdef LTC_DES +struct des_key { + ulong32 ek[32], dk[32]; +}; + +struct des3_key { + ulong32 ek[3][32], dk[3][32]; +}; +#endif + +#ifdef LTC_CAST5 +struct cast5_key { + ulong32 K[32], keylen; +}; +#endif + +#ifdef LTC_NOEKEON +struct noekeon_key { + ulong32 K[4], dK[4]; +}; +#endif + +#ifdef LTC_SKIPJACK +struct skipjack_key { + unsigned char key[10]; +}; +#endif + +#ifdef LTC_KHAZAD +struct khazad_key { + ulong64 roundKeyEnc[8 + 1]; + ulong64 roundKeyDec[8 + 1]; +}; +#endif + +#ifdef LTC_ANUBIS +struct anubis_key { + int keyBits; + int R; + ulong32 roundKeyEnc[18 + 1][4]; + ulong32 roundKeyDec[18 + 1][4]; +}; +#endif + +#ifdef LTC_MULTI2 +struct multi2_key { + int N; + ulong32 uk[8]; +}; +#endif + +typedef union Symmetric_key { +#ifdef LTC_DES + struct des_key des; + struct des3_key des3; +#endif +#ifdef LTC_RC2 + struct rc2_key rc2; +#endif +#ifdef LTC_SAFER + struct safer_key safer; +#endif +#ifdef LTC_TWOFISH + struct twofish_key twofish; +#endif +#ifdef LTC_BLOWFISH + struct blowfish_key blowfish; +#endif +#ifdef LTC_RC5 + struct rc5_key rc5; +#endif +#ifdef LTC_RC6 + struct rc6_key rc6; +#endif +#ifdef LTC_SAFERP + struct saferp_key saferp; +#endif +#ifdef LTC_RIJNDAEL + struct rijndael_key rijndael; +#endif +#ifdef LTC_XTEA + struct xtea_key xtea; +#endif +#ifdef LTC_CAST5 + struct cast5_key cast5; +#endif +#ifdef LTC_NOEKEON + struct noekeon_key noekeon; +#endif +#ifdef LTC_SKIPJACK + struct skipjack_key skipjack; +#endif +#ifdef LTC_KHAZAD + struct khazad_key khazad; +#endif +#ifdef LTC_ANUBIS + struct anubis_key anubis; +#endif +#ifdef LTC_KSEED + struct kseed_key kseed; +#endif +#ifdef LTC_KASUMI + struct kasumi_key kasumi; +#endif +#ifdef LTC_MULTI2 + struct multi2_key multi2; +#endif + void *data; +} symmetric_key; + +#ifdef LTC_ECB_MODE +/** A block cipher ECB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen; + /** The scheduled key */ + symmetric_key key; +} symmetric_ECB; +#endif + +#ifdef LTC_CFB_MODE +/** A block cipher CFB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE], + /** The pad used to encrypt/decrypt */ + pad[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CFB; +#endif + +#ifdef LTC_OFB_MODE +/** A block cipher OFB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_OFB; +#endif + +#ifdef LTC_CBC_MODE +/** A block cipher CBC structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CBC; +#endif + + +#ifdef LTC_CTR_MODE +/** A block cipher CTR structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen, + /** The mode (endianess) of the CTR, 0==little, 1==big */ + mode, + /** counter width */ + ctrlen; + + /** The counter */ + unsigned char ctr[MAXBLOCKSIZE], + /** The pad used to encrypt/decrypt */ + pad[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CTR; +#endif + + +#ifdef LTC_LRW_MODE +/** A LRW structure */ +typedef struct { + /** The index of the cipher chosen (must be a 128-bit block cipher) */ + int cipher; + + /** The current IV */ + unsigned char IV[16], + + /** the tweak key */ + tweak[16], + + /** The current pad, it's the product of the first 15 bytes against the tweak key */ + pad[16]; + + /** The scheduled symmetric key */ + symmetric_key key; + +#ifdef LRW_TABLES + /** The pre-computed multiplication table */ + unsigned char PC[16][256][16]; +#endif +} symmetric_LRW; +#endif + +#ifdef LTC_F8_MODE +/** A block cipher F8 structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE], + MIV[MAXBLOCKSIZE]; + /** Current block count */ + ulong32 blockcnt; + /** The scheduled key */ + symmetric_key key; +} symmetric_F8; +#endif + + +/** cipher descriptor table, last entry has "name == NULL" to mark the end of table */ +extern struct ltc_cipher_descriptor { + /** name of cipher */ + char *name; + /** internal ID */ + unsigned char ID; + /** min keysize (octets) */ + int min_key_length, + /** max keysize (octets) */ + max_key_length, + /** block size (octets) */ + block_length, + /** default number of rounds */ + default_rounds; + /** Setup the cipher + @param key The input symmetric key + @param keylen The length of the input key (octets) + @param num_rounds The requested number of rounds (0==default) + @param skey [out] The destination of the scheduled key + @return CRYPT_OK if successful + */ + int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); + /** Encrypt a block + @param pt The plaintext + @param ct [out] The ciphertext + @param skey The scheduled key + @return CRYPT_OK if successful + */ + int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); + /** Decrypt a block + @param ct The ciphertext + @param pt [out] The plaintext + @param skey The scheduled key + @return CRYPT_OK if successful + */ + int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); + /** Test the block cipher + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled + */ + int (*test)(void); + + /** Terminate the context + @param skey The scheduled key + */ + void (*done)(symmetric_key *skey); + + /** Determine a key size + @param keysize [in/out] The size of the key desired and the suggested size + @return CRYPT_OK if successful + */ + int (*keysize)(int *keysize); + +/** Accelerators **/ + /** Accelerated ECB encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey); + + /** Accelerated ECB decryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey); + + /** Accelerated CBC encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey); + + /** Accelerated CBC decryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey); + + /** Accelerated CTR encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param mode little or big endian counter (mode=0 or mode=1) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey); + + /** Accelerated LRW + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param tweak The LRW tweak + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey); + + /** Accelerated LRW + @param ct Ciphertext + @param pt Plaintext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param tweak The LRW tweak + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey); + + /** Accelerated CCM packet (one-shot) + @param key The secret key to use + @param keylen The length of the secret key (octets) + @param uskey A previously scheduled key [optional can be NULL] + @param nonce The session nonce [use once] + @param noncelen The length of the nonce + @param header The header for the session + @param headerlen The length of the header (octets) + @param pt [out] The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext + @param tag [out] The destination tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @param direction Encrypt or Decrypt direction (0 or 1) + @return CRYPT_OK if successful + */ + int (*accel_ccm_memory)( + const unsigned char *key, unsigned long keylen, + symmetric_key *uskey, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + + /** Accelerated GCM packet (one shot) + @param key The secret key + @param keylen The length of the secret key + @param IV The initial vector + @param IVlen The length of the initial vector + @param adata The additional authentication data (header) + @param adatalen The length of the adata + @param pt The plaintext + @param ptlen The length of the plaintext (ciphertext length is the same) + @param ct The ciphertext + @param tag [out] The MAC tag + @param taglen [in/out] The MAC tag length + @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) + @return CRYPT_OK on success + */ + int (*accel_gcm_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + + /** Accelerated one shot LTC_OMAC + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + */ + int (*omac_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + + /** Accelerated one shot XCBC + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + */ + int (*xcbc_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + + /** Accelerated one shot F9 + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + @remark Requires manual padding + */ + int (*f9_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +} cipher_descriptor[]; + +#ifdef LTC_BLOWFISH +int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int blowfish_test(void); +void blowfish_done(symmetric_key *skey); +int blowfish_keysize(int *keysize); +extern const struct ltc_cipher_descriptor blowfish_desc; +#endif + +#ifdef LTC_RC5 +int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int rc5_test(void); +void rc5_done(symmetric_key *skey); +int rc5_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc5_desc; +#endif + +#ifdef LTC_RC6 +int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int rc6_test(void); +void rc6_done(symmetric_key *skey); +int rc6_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc6_desc; +#endif + +#ifdef LTC_RC2 +int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int rc2_test(void); +void rc2_done(symmetric_key *skey); +int rc2_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc2_desc; +#endif + +#ifdef LTC_SAFERP +int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int saferp_test(void); +void saferp_done(symmetric_key *skey); +int saferp_keysize(int *keysize); +extern const struct ltc_cipher_descriptor saferp_desc; +#endif + +#ifdef LTC_SAFER +int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key); +int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key); +int safer_k64_test(void); +int safer_sk64_test(void); +int safer_sk128_test(void); +void safer_done(symmetric_key *skey); +int safer_64_keysize(int *keysize); +int safer_128_keysize(int *keysize); +extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc; +#endif + +#ifdef LTC_RIJNDAEL + +/* make aes an alias */ +#define aes_setup rijndael_setup +#define aes_ecb_encrypt rijndael_ecb_encrypt +#define aes_ecb_decrypt rijndael_ecb_decrypt +#define aes_test rijndael_test +#define aes_done rijndael_done +#define aes_keysize rijndael_keysize + +#define aes_enc_setup rijndael_enc_setup +#define aes_enc_ecb_encrypt rijndael_enc_ecb_encrypt +#define aes_enc_keysize rijndael_enc_keysize + +int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int rijndael_test(void); +void rijndael_done(symmetric_key *skey); +int rijndael_keysize(int *keysize); +int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +void rijndael_enc_done(symmetric_key *skey); +int rijndael_enc_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc; +extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc; +#endif + +#ifdef LTC_XTEA +int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int xtea_test(void); +void xtea_done(symmetric_key *skey); +int xtea_keysize(int *keysize); +extern const struct ltc_cipher_descriptor xtea_desc; +#endif + +#ifdef LTC_TWOFISH +int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int twofish_test(void); +void twofish_done(symmetric_key *skey); +int twofish_keysize(int *keysize); +extern const struct ltc_cipher_descriptor twofish_desc; +#endif + +#ifdef LTC_DES +int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int des_test(void); +void des_done(symmetric_key *skey); +int des_keysize(int *keysize); +int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int des3_test(void); +void des3_done(symmetric_key *skey); +int des3_keysize(int *keysize); +extern const struct ltc_cipher_descriptor des_desc, des3_desc; +#endif + +#ifdef LTC_CAST5 +int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int cast5_test(void); +void cast5_done(symmetric_key *skey); +int cast5_keysize(int *keysize); +extern const struct ltc_cipher_descriptor cast5_desc; +#endif + +#ifdef LTC_NOEKEON +int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int noekeon_test(void); +void noekeon_done(symmetric_key *skey); +int noekeon_keysize(int *keysize); +extern const struct ltc_cipher_descriptor noekeon_desc; +#endif + +#ifdef LTC_SKIPJACK +int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int skipjack_test(void); +void skipjack_done(symmetric_key *skey); +int skipjack_keysize(int *keysize); +extern const struct ltc_cipher_descriptor skipjack_desc; +#endif + +#ifdef LTC_KHAZAD +int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int khazad_test(void); +void khazad_done(symmetric_key *skey); +int khazad_keysize(int *keysize); +extern const struct ltc_cipher_descriptor khazad_desc; +#endif + +#ifdef LTC_ANUBIS +int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int anubis_test(void); +void anubis_done(symmetric_key *skey); +int anubis_keysize(int *keysize); +extern const struct ltc_cipher_descriptor anubis_desc; +#endif + +#ifdef LTC_KSEED +int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int kseed_test(void); +void kseed_done(symmetric_key *skey); +int kseed_keysize(int *keysize); +extern const struct ltc_cipher_descriptor kseed_desc; +#endif + +#ifdef LTC_KASUMI +int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int kasumi_test(void); +void kasumi_done(symmetric_key *skey); +int kasumi_keysize(int *keysize); +extern const struct ltc_cipher_descriptor kasumi_desc; +#endif + + +#ifdef LTC_MULTI2 +int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int multi2_test(void); +void multi2_done(symmetric_key *skey); +int multi2_keysize(int *keysize); +extern const struct ltc_cipher_descriptor multi2_desc; +#endif + +#ifdef LTC_ECB_MODE +int ecb_start(int cipher, const unsigned char *key, + int keylen, int num_rounds, symmetric_ECB *ecb); +int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb); +int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb); +int ecb_done(symmetric_ECB *ecb); +#endif + +#ifdef LTC_CFB_MODE +int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CFB *cfb); +int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb); +int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb); +int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb); +int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb); +int cfb_done(symmetric_CFB *cfb); +#endif + +#ifdef LTC_OFB_MODE +int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_OFB *ofb); +int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb); +int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb); +int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb); +int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb); +int ofb_done(symmetric_OFB *ofb); +#endif + +#ifdef LTC_CBC_MODE +int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CBC *cbc); +int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc); +int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc); +int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc); +int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc); +int cbc_done(symmetric_CBC *cbc); +#endif + +#ifdef LTC_CTR_MODE + +#define CTR_COUNTER_LITTLE_ENDIAN 0x0000 +#define CTR_COUNTER_BIG_ENDIAN 0x1000 +#define LTC_CTR_RFC3686 0x2000 + +int ctr_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + int num_rounds, int ctr_mode, + symmetric_CTR *ctr); +int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr); +int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr); +int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr); +int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr); +int ctr_done(symmetric_CTR *ctr); +int ctr_test(void); +#endif + +#ifdef LTC_LRW_MODE + +#define LRW_ENCRYPT 0 +#define LRW_DECRYPT 1 + +int lrw_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *tweak, + int num_rounds, + symmetric_LRW *lrw); +int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw); +int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw); +int lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw); +int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw); +int lrw_done(symmetric_LRW *lrw); +int lrw_test(void); + +/* don't call */ +int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw); +#endif + +#ifdef LTC_F8_MODE +int f8_start( int cipher, const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *salt_key, int skeylen, + int num_rounds, symmetric_F8 *f8); +int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8); +int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8); +int f8_getiv(unsigned char *IV, unsigned long *len, symmetric_F8 *f8); +int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8); +int f8_done(symmetric_F8 *f8); +int f8_test_mode(void); +#endif + +#ifdef LTC_XTS_MODE +typedef struct { + symmetric_key key1, key2; + int cipher; +} symmetric_xts; + +int xts_start( int cipher, + const unsigned char *key1, + const unsigned char *key2, + unsigned long keylen, + int num_rounds, + symmetric_xts *xts); + +int xts_encrypt( + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + const unsigned char *tweak, + symmetric_xts *xts); +int xts_decrypt( + const unsigned char *ct, unsigned long ptlen, + unsigned char *pt, + const unsigned char *tweak, + symmetric_xts *xts); + +void xts_done(symmetric_xts *xts); +int xts_test(void); +void xts_mult_x(unsigned char *I); +#endif + +int find_cipher(const char *name); +int find_cipher_any(const char *name, int blocklen, int keylen); +int find_cipher_id(unsigned char ID); +int register_cipher(const struct ltc_cipher_descriptor *cipher); +int unregister_cipher(const struct ltc_cipher_descriptor *cipher); +int cipher_is_valid(int idx); + +LTC_MUTEX_PROTO(ltc_cipher_mutex) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_custom.h b/src/common/tomcrypt/tomcrypt_custom.h new file mode 100644 index 0000000000..f7dbdd4c0a --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_custom.h @@ -0,0 +1,431 @@ +#ifndef TOMCRYPT_CUSTOM_H_ +#define TOMCRYPT_CUSTOM_H_ + +/*** Firebird customizations - begin ***/ + +#define LTC_NO_ASM // ASF: Defined to not use assembly + +#define LTC_NO_CIPHERS +#define LTC_NO_HASHES +#define LTC_NO_MODES +#define LTC_NO_MACS +#define LTC_NO_PRNGS +#define LTC_NO_MATH +#define LTC_NO_PK +#define LTC_NO_PKCS +#define LTC_NO_CURVES + +#define LTC_MD5 +#define LTC_SHA1 +#define LTC_SHA256 +#define LTC_SHA512 + +#if defined(_MSC_VER) +#define LTC_NO_PROTOTYPES +#endif + +/*** Firebird customizations - end ***/ + +/* macros for various libc functions you can change for embedded targets */ +#ifndef XMALLOC + #ifdef malloc + #define LTC_NO_PROTOTYPES + #endif +#define XMALLOC malloc +#endif +#ifndef XREALLOC + #ifdef realloc + #define LTC_NO_PROTOTYPES + #endif +#define XREALLOC realloc +#endif +#ifndef XCALLOC + #ifdef calloc + #define LTC_NO_PROTOTYPES + #endif +#define XCALLOC calloc +#endif +#ifndef XFREE + #ifdef free + #define LTC_NO_PROTOTYPES + #endif +#define XFREE free +#endif + +#ifndef XMEMSET + #ifdef memset + #define LTC_NO_PROTOTYPES + #endif +#define XMEMSET memset +#endif +#ifndef XMEMCPY + #ifdef memcpy + #define LTC_NO_PROTOTYPES + #endif +#define XMEMCPY memcpy +#endif +#ifndef XMEMCMP + #ifdef memcmp + #define LTC_NO_PROTOTYPES + #endif +#define XMEMCMP memcmp +#endif +#ifndef XSTRCMP + #ifdef strcmp + #define LTC_NO_PROTOTYPES + #endif +#define XSTRCMP strcmp +#endif + +#ifndef XCLOCK +#define XCLOCK clock +#endif +#ifndef XCLOCKS_PER_SEC +#define XCLOCKS_PER_SEC CLOCKS_PER_SEC +#endif + +#ifndef XQSORT + #ifdef qsort + #define LTC_NO_PROTOTYPES + #endif +#define XQSORT qsort +#endif + +/* Easy button? */ +#ifdef LTC_EASY + #define LTC_NO_CIPHERS + #define LTC_RIJNDAEL + #define LTC_BLOWFISH + #define LTC_DES + #define LTC_CAST5 + + #define LTC_NO_MODES + #define LTC_ECB_MODE + #define LTC_CBC_MODE + #define LTC_CTR_MODE + + #define LTC_NO_HASHES + #define LTC_SHA1 + #define LTC_SHA512 + #define LTC_SHA384 + #define LTC_SHA256 + #define LTC_SHA224 + + #define LTC_NO_MACS + #define LTC_HMAC + #define LTC_OMAC + #define LTC_CCM_MODE + + #define LTC_NO_PRNGS + #define LTC_SPRNG + #define LTC_YARROW + #define LTC_DEVRANDOM + #define TRY_URANDOM_FIRST + + #define LTC_NO_PK + #define LTC_MRSA + #define LTC_MECC +#endif + +/* Use small code where possible */ +/* #define LTC_SMALL_CODE */ + +/* Enable self-test test vector checking */ +#ifndef LTC_NO_TEST + #define LTC_TEST +#endif + +/* clean the stack of functions which put private information on stack */ +/* #define LTC_CLEAN_STACK */ + +/* disable all file related functions */ +/* #define LTC_NO_FILE */ + +/* disable all forms of ASM */ +/* #define LTC_NO_ASM */ + +/* disable FAST mode */ +/* #define LTC_NO_FAST */ + +/* disable BSWAP on x86 */ +/* #define LTC_NO_BSWAP */ + +/* ---> Symmetric Block Ciphers <--- */ +#ifndef LTC_NO_CIPHERS + +#define LTC_BLOWFISH +#define LTC_RC2 +#define LTC_RC5 +#define LTC_RC6 +#define LTC_SAFERP +#define LTC_RIJNDAEL +#define LTC_XTEA +/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format + * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */ +#define LTC_TWOFISH +#ifndef LTC_NO_TABLES + #define LTC_TWOFISH_TABLES + /* #define LTC_TWOFISH_ALL_TABLES */ +#else + #define LTC_TWOFISH_SMALL +#endif +/* #define LTC_TWOFISH_SMALL */ +/* LTC_DES includes EDE triple-LTC_DES */ +#define LTC_DES +#define LTC_CAST5 +#define LTC_NOEKEON +#define LTC_SKIPJACK +#define LTC_SAFER +#define LTC_KHAZAD +#define LTC_ANUBIS +#define LTC_ANUBIS_TWEAK +#define LTC_KSEED +#define LTC_KASUMI + +#endif /* LTC_NO_CIPHERS */ + + +/* ---> Block Cipher Modes of Operation <--- */ +#ifndef LTC_NO_MODES + +#define LTC_CFB_MODE +#define LTC_OFB_MODE +#define LTC_ECB_MODE +#define LTC_CBC_MODE +#define LTC_CTR_MODE + +/* F8 chaining mode */ +#define LTC_F8_MODE + +/* LRW mode */ +#define LTC_LRW_MODE +#ifndef LTC_NO_TABLES + /* like GCM mode this will enable 16 8x128 tables [64KB] that make + * seeking very fast. + */ + #define LRW_TABLES +#endif + +/* XTS mode */ +#define LTC_XTS_MODE + +#endif /* LTC_NO_MODES */ + +/* ---> One-Way Hash Functions <--- */ +#ifndef LTC_NO_HASHES + +#define LTC_CHC_HASH +#define LTC_WHIRLPOOL +#define LTC_SHA512 +#define LTC_SHA384 +#define LTC_SHA256 +#define LTC_SHA224 +#define LTC_TIGER +#define LTC_SHA1 +#define LTC_MD5 +#define LTC_MD4 +#define LTC_MD2 +#define LTC_RIPEMD128 +#define LTC_RIPEMD160 +#define LTC_RIPEMD256 +#define LTC_RIPEMD320 + +#endif /* LTC_NO_HASHES */ + +/* ---> MAC functions <--- */ +#ifndef LTC_NO_MACS + +#define LTC_HMAC +#define LTC_OMAC +#define LTC_PMAC +#define LTC_XCBC +#define LTC_F9_MODE +#define LTC_PELICAN + +#if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL) + #error Pelican-MAC requires LTC_RIJNDAEL +#endif + +/* ---> Encrypt + Authenticate Modes <--- */ + +#define LTC_EAX_MODE +#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC)) + #error LTC_EAX_MODE requires CTR and LTC_OMAC mode +#endif + +#define LTC_OCB_MODE +#define LTC_CCM_MODE +#define LTC_GCM_MODE + +/* Use 64KiB tables */ +#ifndef LTC_NO_TABLES + #define LTC_GCM_TABLES +#endif + +/* USE SSE2? requires GCC works on x86_32 and x86_64*/ +#ifdef LTC_GCM_TABLES +/* #define LTC_GCM_TABLES_SSE2 */ +#endif + +#endif /* LTC_NO_MACS */ + +/* Various tidbits of modern neatoness */ +#define LTC_BASE64 + +/* --> Pseudo Random Number Generators <--- */ +#ifndef LTC_NO_PRNGS + +/* Yarrow */ +#define LTC_YARROW +/* which descriptor of AES to use? */ +/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */ +#define LTC_YARROW_AES 0 + +#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE) + #error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined! +#endif + +/* a PRNG that simply reads from an available system source */ +#define LTC_SPRNG + +/* The LTC_RC4 stream cipher */ +#define LTC_RC4 + +/* Fortuna PRNG */ +#define LTC_FORTUNA +/* reseed every N calls to the read function */ +#define LTC_FORTUNA_WD 10 +/* number of pools (4..32) can save a bit of ram by lowering the count */ +#define LTC_FORTUNA_POOLS 32 + +/* Greg's LTC_SOBER128 PRNG ;-0 */ +#define LTC_SOBER128 + +/* the *nix style /dev/random device */ +#define LTC_DEVRANDOM +/* try /dev/urandom before trying /dev/random */ +#define TRY_URANDOM_FIRST + +#endif /* LTC_NO_PRNGS */ + +/* ---> math provider? <--- */ +#ifndef LTC_NO_MATH + +/* LibTomMath */ +/* #define LTM_LTC_DESC */ + +/* TomsFastMath */ +/* #define TFM_LTC_DESC */ + +#endif /* LTC_NO_MATH */ + +/* ---> Public Key Crypto <--- */ +#ifndef LTC_NO_PK + +/* Include RSA support */ +#define LTC_MRSA + +/* Include Katja (a Rabin variant like RSA) */ +/* #define MKAT */ + +/* Digital Signature Algorithm */ +#define LTC_MDSA + +/* ECC */ +#define LTC_MECC + +/* use Shamir's trick for point mul (speeds up signature verification) */ +#define LTC_ECC_SHAMIR + +#if defined(TFM_LTC_DESC) && defined(LTC_MECC) + #define LTC_MECC_ACCEL +#endif + +/* do we want fixed point ECC */ +/* #define LTC_MECC_FP */ + +/* Timing Resistant? */ +/* #define LTC_ECC_TIMING_RESISTANT */ + +#endif /* LTC_NO_PK */ + +/* LTC_PKCS #1 (RSA) and #5 (Password Handling) stuff */ +#ifndef LTC_NO_PKCS + +#define LTC_PKCS_1 +#define LTC_PKCS_5 + +/* Include ASN.1 DER (required by DSA/RSA) */ +#define LTC_DER + +#endif /* LTC_NO_PKCS */ + +/* cleanup */ + +#ifdef LTC_MECC +/* Supported ECC Key Sizes */ +#ifndef LTC_NO_CURVES + #define ECC112 + #define ECC128 + #define ECC160 + #define ECC192 + #define ECC224 + #define ECC256 + #define ECC384 + #define ECC521 +#endif +#endif + +#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(MKATJA) + /* Include the MPI functionality? (required by the PK algorithms) */ + #define MPI +#endif + +#ifdef LTC_MRSA + #define LTC_PKCS_1 +#endif + +#if defined(LTC_DER) && !defined(MPI) + #error ASN.1 DER requires MPI functionality +#endif + +#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC) || defined(MKATJA)) && !defined(LTC_DER) + #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled +#endif + +/* THREAD management */ +#ifdef LTC_PTHREAD + +#include + +#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; +#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x; +#define LTC_MUTEX_TYPE(x) pthread_mutex_t x; +#define LTC_MUTEX_INIT(x) pthread_mutex_init(x, NULL); +#define LTC_MUTEX_LOCK(x) pthread_mutex_lock(x); +#define LTC_MUTEX_UNLOCK(x) pthread_mutex_unlock(x); + +#else + +/* default no functions */ +#define LTC_MUTEX_GLOBAL(x) +#define LTC_MUTEX_PROTO(x) +#define LTC_MUTEX_TYPE(x) +#define LTC_MUTEX_INIT(x) +#define LTC_MUTEX_LOCK(x) +#define LTC_MUTEX_UNLOCK(x) + +#endif + +/* Debuggers */ + +/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and LTC_RC4 work (see the code) */ +/* #define LTC_VALGRIND */ + +#endif + + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_hash.h b/src/common/tomcrypt/tomcrypt_hash.h new file mode 100644 index 0000000000..56b272ad91 --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_hash.h @@ -0,0 +1,379 @@ +/* ---- HASH FUNCTIONS ---- */ +#ifdef LTC_SHA512 +struct sha512_state { + ulong64 length, state[8]; + unsigned long curlen; + unsigned char buf[128]; +}; +#endif + +#ifdef LTC_SHA256 +struct sha256_state { + ulong64 length; + ulong32 state[8], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_SHA1 +struct sha1_state { + ulong64 length; + ulong32 state[5], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_MD5 +struct md5_state { + ulong64 length; + ulong32 state[4], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_MD4 +struct md4_state { + ulong64 length; + ulong32 state[4], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_TIGER +struct tiger_state { + ulong64 state[3], length; + unsigned long curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_MD2 +struct md2_state { + unsigned char chksum[16], X[48], buf[16]; + unsigned long curlen; +}; +#endif + +#ifdef LTC_RIPEMD128 +struct rmd128_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[4]; +}; +#endif + +#ifdef LTC_RIPEMD160 +struct rmd160_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[5]; +}; +#endif + +#ifdef LTC_RIPEMD256 +struct rmd256_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[8]; +}; +#endif + +#ifdef LTC_RIPEMD320 +struct rmd320_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[10]; +}; +#endif + +#ifdef LTC_WHIRLPOOL +struct whirlpool_state { + ulong64 length, state[8]; + unsigned char buf[64]; + ulong32 curlen; +}; +#endif + +#ifdef LTC_CHC_HASH +struct chc_state { + ulong64 length; + unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE]; + ulong32 curlen; +}; +#endif + +typedef union Hash_state { + char dummy[1]; +#ifdef LTC_CHC_HASH + struct chc_state chc; +#endif +#ifdef LTC_WHIRLPOOL + struct whirlpool_state whirlpool; +#endif +#ifdef LTC_SHA512 + struct sha512_state sha512; +#endif +#ifdef LTC_SHA256 + struct sha256_state sha256; +#endif +#ifdef LTC_SHA1 + struct sha1_state sha1; +#endif +#ifdef LTC_MD5 + struct md5_state md5; +#endif +#ifdef LTC_MD4 + struct md4_state md4; +#endif +#ifdef LTC_MD2 + struct md2_state md2; +#endif +#ifdef LTC_TIGER + struct tiger_state tiger; +#endif +#ifdef LTC_RIPEMD128 + struct rmd128_state rmd128; +#endif +#ifdef LTC_RIPEMD160 + struct rmd160_state rmd160; +#endif +#ifdef LTC_RIPEMD256 + struct rmd256_state rmd256; +#endif +#ifdef LTC_RIPEMD320 + struct rmd320_state rmd320; +#endif + void *data; +} hash_state; + +/** hash descriptor */ +extern struct ltc_hash_descriptor { + /** name of hash */ + char *name; + /** internal ID */ + unsigned char ID; + /** Size of digest in octets */ + unsigned long hashsize; + /** Input block size in octets */ + unsigned long blocksize; + /** ASN.1 OID */ + unsigned long OID[16]; + /** Length of DER encoding */ + unsigned long OIDlen; + + /** Init a hash state + @param hash The hash to initialize + @return CRYPT_OK if successful + */ + int (*init)(hash_state *hash); + /** Process a block of data + @param hash The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ + int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen); + /** Produce the digest and store it + @param hash The hash state + @param out [out] The destination of the digest + @return CRYPT_OK if successful + */ + int (*done)(hash_state *hash, unsigned char *out); + /** Self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled + */ + int (*test)(void); + + /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */ + int (*hmac_block)(const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +} hash_descriptor[]; + +#ifdef LTC_CHC_HASH +int chc_register(int cipher); +int chc_init(hash_state * md); +int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int chc_done(hash_state * md, unsigned char *hash); +int chc_test(void); +extern const struct ltc_hash_descriptor chc_desc; +#endif + +#ifdef LTC_WHIRLPOOL +int whirlpool_init(hash_state * md); +int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int whirlpool_done(hash_state * md, unsigned char *hash); +int whirlpool_test(void); +extern const struct ltc_hash_descriptor whirlpool_desc; +#endif + +#ifdef LTC_SHA512 +int sha512_init(hash_state * md); +int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha512_done(hash_state * md, unsigned char *hash); +int sha512_test(void); +extern const struct ltc_hash_descriptor sha512_desc; +#endif + +#ifdef LTC_SHA384 +#ifndef LTC_SHA512 + #error LTC_SHA512 is required for LTC_SHA384 +#endif +int sha384_init(hash_state * md); +#define sha384_process sha512_process +int sha384_done(hash_state * md, unsigned char *hash); +int sha384_test(void); +extern const struct ltc_hash_descriptor sha384_desc; +#endif + +#ifdef LTC_SHA256 +int sha256_init(hash_state * md); +int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha256_done(hash_state * md, unsigned char *hash); +int sha256_test(void); +extern const struct ltc_hash_descriptor sha256_desc; + +#ifdef LTC_SHA224 +#ifndef LTC_SHA256 + #error LTC_SHA256 is required for LTC_SHA224 +#endif +int sha224_init(hash_state * md); +#define sha224_process sha256_process +int sha224_done(hash_state * md, unsigned char *hash); +int sha224_test(void); +extern const struct ltc_hash_descriptor sha224_desc; +#endif +#endif + +#ifdef LTC_SHA1 +int sha1_init(hash_state * md); +int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha1_done(hash_state * md, unsigned char *hash); +int sha1_test(void); +extern const struct ltc_hash_descriptor sha1_desc; +#endif + +#ifdef LTC_MD5 +int md5_init(hash_state * md); +int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md5_done(hash_state * md, unsigned char *hash); +int md5_test(void); +extern const struct ltc_hash_descriptor md5_desc; +#endif + +#ifdef LTC_MD4 +int md4_init(hash_state * md); +int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md4_done(hash_state * md, unsigned char *hash); +int md4_test(void); +extern const struct ltc_hash_descriptor md4_desc; +#endif + +#ifdef LTC_MD2 +int md2_init(hash_state * md); +int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md2_done(hash_state * md, unsigned char *hash); +int md2_test(void); +extern const struct ltc_hash_descriptor md2_desc; +#endif + +#ifdef LTC_TIGER +int tiger_init(hash_state * md); +int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int tiger_done(hash_state * md, unsigned char *hash); +int tiger_test(void); +extern const struct ltc_hash_descriptor tiger_desc; +#endif + +#ifdef LTC_RIPEMD128 +int rmd128_init(hash_state * md); +int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd128_done(hash_state * md, unsigned char *hash); +int rmd128_test(void); +extern const struct ltc_hash_descriptor rmd128_desc; +#endif + +#ifdef LTC_RIPEMD160 +int rmd160_init(hash_state * md); +int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd160_done(hash_state * md, unsigned char *hash); +int rmd160_test(void); +extern const struct ltc_hash_descriptor rmd160_desc; +#endif + +#ifdef LTC_RIPEMD256 +int rmd256_init(hash_state * md); +int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd256_done(hash_state * md, unsigned char *hash); +int rmd256_test(void); +extern const struct ltc_hash_descriptor rmd256_desc; +#endif + +#ifdef LTC_RIPEMD320 +int rmd320_init(hash_state * md); +int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd320_done(hash_state * md, unsigned char *hash); +int rmd320_test(void); +extern const struct ltc_hash_descriptor rmd320_desc; +#endif + + +int find_hash(const char *name); +int find_hash_id(unsigned char ID); +int find_hash_oid(const unsigned long *ID, unsigned long IDlen); +int find_hash_any(const char *name, int digestlen); +int register_hash(const struct ltc_hash_descriptor *hash); +int unregister_hash(const struct ltc_hash_descriptor *hash); +int hash_is_valid(int idx); + +LTC_MUTEX_PROTO(ltc_hash_mutex) + +int hash_memory(int hash, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen); +int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen); + +/* a simple macro for making hash "process" functions */ +#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ +int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \ +{ \ + unsigned long n; \ + int err; \ + LTC_ARGCHK(md != NULL); \ + LTC_ARGCHK(in != NULL); \ + if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ + return CRYPT_INVALID_ARG; \ + } \ + while (inlen > 0) { \ + if (md-> state_var .curlen == 0 && inlen >= block_size) { \ + if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \ + return err; \ + } \ + md-> state_var .length += block_size * 8; \ + in += block_size; \ + inlen -= block_size; \ + } else { \ + n = MIN(inlen, (block_size - md-> state_var .curlen)); \ + memcpy(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \ + md-> state_var .curlen += n; \ + in += n; \ + inlen -= n; \ + if (md-> state_var .curlen == block_size) { \ + if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \ + return err; \ + } \ + md-> state_var .length += 8*block_size; \ + md-> state_var .curlen = 0; \ + } \ + } \ + } \ + return CRYPT_OK; \ +} + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_mac.h b/src/common/tomcrypt/tomcrypt_mac.h new file mode 100644 index 0000000000..d030d734b6 --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_mac.h @@ -0,0 +1,384 @@ +#ifdef LTC_HMAC +typedef struct Hmac_state { + hash_state md; + int hash; + hash_state hashstate; + unsigned char *key; +} hmac_state; + +int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen); +int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen); +int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen); +int hmac_test(void); +int hmac_memory(int hash, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int hmac_memory_multi(int hash, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int hmac_file(int hash, const char *fname, const unsigned char *key, + unsigned long keylen, + unsigned char *dst, unsigned long *dstlen); +#endif + +#ifdef LTC_OMAC + +typedef struct { + int cipher_idx, + buflen, + blklen; + unsigned char block[MAXBLOCKSIZE], + prev[MAXBLOCKSIZE], + Lu[2][MAXBLOCKSIZE]; + symmetric_key key; +} omac_state; + +int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen); +int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen); +int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen); +int omac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int omac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int omac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int omac_test(void); +#endif /* LTC_OMAC */ + +#ifdef LTC_PMAC + +typedef struct { + unsigned char Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ + Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ + Lr[MAXBLOCKSIZE], /* L * x^-1 */ + block[MAXBLOCKSIZE], /* currently accumulated block */ + checksum[MAXBLOCKSIZE]; /* current checksum */ + + symmetric_key key; /* scheduled key for cipher */ + unsigned long block_index; /* index # for current block */ + int cipher_idx, /* cipher idx */ + block_len, /* length of block */ + buflen; /* number of bytes in the buffer */ +} pmac_state; + +int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen); +int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen); +int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen); + +int pmac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *msg, unsigned long msglen, + unsigned char *out, unsigned long *outlen); + +int pmac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); + +int pmac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); + +int pmac_test(void); + +/* internal functions */ +int pmac_ntz(unsigned long x); +void pmac_shift_xor(pmac_state *pmac); + +#endif /* PMAC */ + +#ifdef LTC_EAX_MODE + +#if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE)) + #error LTC_EAX_MODE requires LTC_OMAC and CTR +#endif + +typedef struct { + unsigned char N[MAXBLOCKSIZE]; + symmetric_CTR ctr; + omac_state headeromac, ctomac; +} eax_state; + +int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen); + +int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length); +int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length); +int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length); +int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen); + +int eax_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int eax_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + unsigned char *tag, unsigned long taglen, + int *stat); + + int eax_test(void); +#endif /* EAX MODE */ + +#ifdef LTC_OCB_MODE +typedef struct { + unsigned char L[MAXBLOCKSIZE], /* L value */ + Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ + Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ + Lr[MAXBLOCKSIZE], /* L * x^-1 */ + R[MAXBLOCKSIZE], /* R value */ + checksum[MAXBLOCKSIZE]; /* current checksum */ + + symmetric_key key; /* scheduled key for cipher */ + unsigned long block_index; /* index # for current block */ + int cipher, /* cipher idx */ + block_len; /* length of block */ +} ocb_state; + +int ocb_init(ocb_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, const unsigned char *nonce); + +int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct); +int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt); + +int ocb_done_encrypt(ocb_state *ocb, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int ocb_done_decrypt(ocb_state *ocb, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, int *stat); + +int ocb_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int ocb_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat); + +int ocb_test(void); + +/* internal functions */ +void ocb_shift_xor(ocb_state *ocb, unsigned char *Z); +int ocb_ntz(unsigned long x); +int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode); + +#endif /* LTC_OCB_MODE */ + +#ifdef LTC_CCM_MODE + +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + +int ccm_memory(int cipher, + const unsigned char *key, unsigned long keylen, + symmetric_key *uskey, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + +int ccm_test(void); + +#endif /* LTC_CCM_MODE */ + +#if defined(LRW_MODE) || defined(LTC_GCM_MODE) +void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c); +#endif + + +/* table shared between GCM and LRW */ +#if defined(LTC_GCM_TABLES) || defined(LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST)) +extern const unsigned char gcm_shift_table[]; +#endif + +#ifdef LTC_GCM_MODE + +#define GCM_ENCRYPT 0 +#define GCM_DECRYPT 1 + +#define LTC_GCM_MODE_IV 0 +#define LTC_GCM_MODE_AAD 1 +#define LTC_GCM_MODE_TEXT 2 + +typedef struct { + symmetric_key K; + unsigned char H[16], /* multiplier */ + X[16], /* accumulator */ + Y[16], /* counter */ + Y_0[16], /* initial counter */ + buf[16]; /* buffer for stuff */ + + int cipher, /* which cipher */ + ivmode, /* Which mode is the IV in? */ + mode, /* mode the GCM code is in */ + buflen; /* length of data in buf */ + + ulong64 totlen, /* 64-bit counter used for IV and AAD */ + pttotlen; /* 64-bit counter for the PT */ + +#ifdef LTC_GCM_TABLES + unsigned char PC[16][256][16] /* 16 tables of 8x128 */ +#ifdef LTC_GCM_TABLES_SSE2 +__attribute__ ((aligned (16))) +#endif +; +#endif +} gcm_state; + +void gcm_mult_h(gcm_state *gcm, unsigned char *I); + +int gcm_init(gcm_state *gcm, int cipher, + const unsigned char *key, int keylen); + +int gcm_reset(gcm_state *gcm); + +int gcm_add_iv(gcm_state *gcm, + const unsigned char *IV, unsigned long IVlen); + +int gcm_add_aad(gcm_state *gcm, + const unsigned char *adata, unsigned long adatalen); + +int gcm_process(gcm_state *gcm, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + int direction); + +int gcm_done(gcm_state *gcm, + unsigned char *tag, unsigned long *taglen); + +int gcm_memory( int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); +int gcm_test(void); + +#endif /* LTC_GCM_MODE */ + +#ifdef LTC_PELICAN + +typedef struct pelican_state +{ + symmetric_key K; + unsigned char state[16]; + int buflen; +} pelican_state; + +int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen); +int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen); +int pelican_done(pelican_state *pelmac, unsigned char *out); +int pelican_test(void); + +int pelican_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out); + +#endif + +#ifdef LTC_XCBC + +/* add this to "keylen" to xcbc_init to use a pure three-key XCBC MAC */ +#define LTC_XCBC_PURE 0x8000UL + +typedef struct { + unsigned char K[3][MAXBLOCKSIZE], + IV[MAXBLOCKSIZE]; + + symmetric_key key; + + int cipher, + buflen, + blocksize; +} xcbc_state; + +int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen); +int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen); +int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen); +int xcbc_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int xcbc_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int xcbc_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int xcbc_test(void); + +#endif + +#ifdef LTC_F9_MODE + +typedef struct { + unsigned char akey[MAXBLOCKSIZE], + ACC[MAXBLOCKSIZE], + IV[MAXBLOCKSIZE]; + + symmetric_key key; + + int cipher, + buflen, + keylen, + blocksize; +} f9_state; + +int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen); +int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen); +int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen); +int f9_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int f9_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int f9_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int f9_test(void); + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_macros.h b/src/common/tomcrypt/tomcrypt_macros.h new file mode 100644 index 0000000000..6e4d757af8 --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_macros.h @@ -0,0 +1,424 @@ +/* fix for MSVC ...evil! */ +#ifdef _MSC_VER + #define CONST64(n) n ## ui64 + typedef unsigned __int64 ulong64; +#else + #define CONST64(n) n ## ULL + typedef unsigned long long ulong64; +#endif + +/* this is the "32-bit at least" data type + * Re-define it to suit your platform but it must be at least 32-bits + */ +#if defined(__x86_64__) || (defined(__sparc__) && defined(__arch64__)) + typedef unsigned ulong32; +#else + typedef unsigned long ulong32; +#endif + +/* ---- HELPER MACROS ---- */ +#ifdef ENDIAN_NEUTRAL + +#define STORE32L(x, y) \ + { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD32L(x, y) \ + { x = ((unsigned long)((y)[3] & 255)<<24) | \ + ((unsigned long)((y)[2] & 255)<<16) | \ + ((unsigned long)((y)[1] & 255)<<8) | \ + ((unsigned long)((y)[0] & 255)); } + +#define STORE64L(x, y) \ + { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD64L(x, y) \ + { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } + +#define STORE32H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } + +#define LOAD32H(x, y) \ + { x = ((unsigned long)((y)[0] & 255)<<24) | \ + ((unsigned long)((y)[1] & 255)<<16) | \ + ((unsigned long)((y)[2] & 255)<<8) | \ + ((unsigned long)((y)[3] & 255)); } + +#define STORE64H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define LOAD64H(x, y) \ + { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ + (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } + +#endif /* ENDIAN_NEUTRAL */ + +#ifdef ENDIAN_LITTLE + +#if !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__)))) + +#define STORE32H(x, y) \ +asm __volatile__ ( \ + "bswapl %0 \n\t" \ + "movl %0,(%1)\n\t" \ + "bswapl %0 \n\t" \ + ::"r"(x), "r"(y)); + +#define LOAD32H(x, y) \ +asm __volatile__ ( \ + "movl (%1),%0\n\t" \ + "bswapl %0\n\t" \ + :"=r"(x): "r"(y)); + +#else + +#define STORE32H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } + +#define LOAD32H(x, y) \ + { x = ((unsigned long)((y)[0] & 255)<<24) | \ + ((unsigned long)((y)[1] & 255)<<16) | \ + ((unsigned long)((y)[2] & 255)<<8) | \ + ((unsigned long)((y)[3] & 255)); } + +#endif + + +/* x86_64 processor */ +#if !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__)) + +#define STORE64H(x, y) \ +asm __volatile__ ( \ + "bswapq %0 \n\t" \ + "movq %0,(%1)\n\t" \ + "bswapq %0 \n\t" \ + ::"r"(x), "r"(y)); + +#define LOAD64H(x, y) \ +asm __volatile__ ( \ + "movq (%1),%0\n\t" \ + "bswapq %0\n\t" \ + :"=r"(x): "r"(y)); + +#else + +#define STORE64H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define LOAD64H(x, y) \ + { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ + (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } + +#endif + +#ifdef ENDIAN_32BITWORD + +#define STORE32L(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32L(x, y) \ + XMEMCPY(&(x), y, 4); + +#define STORE64L(x, y) \ + { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD64L(x, y) \ + { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } + +#else /* 64-bit words then */ + +#define STORE32L(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32L(x, y) \ + { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } + +#define STORE64L(x, y) \ + { ulong64 __t = (x); XMEMCPY(y, &__t, 8); } + +#define LOAD64L(x, y) \ + { XMEMCPY(&(x), y, 8); } + +#endif /* ENDIAN_64BITWORD */ + +#endif /* ENDIAN_LITTLE */ + +#ifdef ENDIAN_BIG +#define STORE32L(x, y) \ + { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD32L(x, y) \ + { x = ((unsigned long)((y)[3] & 255)<<24) | \ + ((unsigned long)((y)[2] & 255)<<16) | \ + ((unsigned long)((y)[1] & 255)<<8) | \ + ((unsigned long)((y)[0] & 255)); } + +#define STORE64L(x, y) \ + { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD64L(x, y) \ + { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } + +#ifdef ENDIAN_32BITWORD + +#define STORE32H(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32H(x, y) \ + XMEMCPY(&(x), y, 4); + +#define STORE64H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define LOAD64H(x, y) \ + { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \ + (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } + +#else /* 64-bit words then */ + +#define STORE32H(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32H(x, y) \ + { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } + +#define STORE64H(x, y) \ + { ulong64 __t = (x); XMEMCPY(y, &__t, 8); } + +#define LOAD64H(x, y) \ + { XMEMCPY(&(x), y, 8); } + +#endif /* ENDIAN_64BITWORD */ +#endif /* ENDIAN_BIG */ + +#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \ + ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) ) + + +/* 32-bit Rotates */ +#if defined(_MSC_VER) + +/* instrinsic rotate */ +#include +#pragma intrinsic(_lrotr,_lrotl) +#define ROR(x,n) _lrotr(x,n) +#define ROL(x,n) _lrotl(x,n) +#define RORc(x,n) _lrotr(x,n) +#define ROLc(x,n) _lrotl(x,n) + +#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) + +static inline unsigned ROL(unsigned word, int i) +{ + asm ("roll %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline unsigned ROR(unsigned word, int i) +{ + asm ("rorl %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline unsigned ROLc(unsigned word, const int i) +{ + asm ("roll %2,%0" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +static inline unsigned RORc(unsigned word, const int i) +{ + asm ("rorl %2,%0" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +#else + +#define ROLc ROL +#define RORc ROR + +#endif + +#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32) + +static inline unsigned ROL(unsigned word, int i) +{ + asm ("rotlw %0,%0,%2" + :"=r" (word) + :"0" (word),"r" (i)); + return word; +} + +static inline unsigned ROR(unsigned word, int i) +{ + asm ("rotlw %0,%0,%2" + :"=r" (word) + :"0" (word),"r" (32-i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline unsigned ROLc(unsigned word, const int i) +{ + asm ("rotlwi %0,%0,%2" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +static inline unsigned RORc(unsigned word, const int i) +{ + asm ("rotrwi %0,%0,%2" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +#else + +#define ROLc ROL +#define RORc ROR + +#endif + + +#else + +/* rotates the hard way */ +#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) +#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) +#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) +#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + +#endif + + +/* 64-bit Rotates */ +#if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(LTC_NO_ASM) + +static inline unsigned long ROL64(unsigned long word, int i) +{ + asm("rolq %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline unsigned long ROR64(unsigned long word, int i) +{ + asm("rorq %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline unsigned long ROL64c(unsigned long word, const int i) +{ + asm("rolq %2,%0" + :"=r" (word) + :"0" (word),"J" (i)); + return word; +} + +static inline unsigned long ROR64c(unsigned long word, const int i) +{ + asm("rorq %2,%0" + :"=r" (word) + :"0" (word),"J" (i)); + return word; +} + +#else /* LTC_NO_ROLC */ + +#define ROL64c ROL64 +#define ROR64c ROR64 + +#endif + +#else /* Not x86_64 */ + +#define ROL64(x, y) \ + ( (((x)<<((ulong64)(y)&63)) | \ + (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ + ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROL64c(x, y) \ + ( (((x)<<((ulong64)(y)&63)) | \ + (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64c(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ + ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#endif + +#ifndef MAX + #define MAX(x, y) ( ((x)>(y))?(x):(y) ) +#endif + +#ifndef MIN + #define MIN(x, y) ( ((x)<(y))?(x):(y) ) +#endif + +/* extract a byte portably */ +#ifdef _MSC_VER + #define byte(x, n) ((unsigned char)((x) >> (8 * (n)))) +#else + #define byte(x, n) (((x) >> (8 * (n))) & 255) +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_math.h b/src/common/tomcrypt/tomcrypt_math.h new file mode 100644 index 0000000000..aee61053ec --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_math.h @@ -0,0 +1,500 @@ +/** math functions **/ + +#define LTC_MP_LT -1 +#define LTC_MP_EQ 0 +#define LTC_MP_GT 1 + +#define LTC_MP_NO 0 +#define LTC_MP_YES 1 + +#ifndef LTC_MECC + typedef void ecc_point; +#endif + +#ifndef LTC_MRSA + typedef void rsa_key; +#endif + +/** math descriptor */ +typedef struct { + /** Name of the math provider */ + char *name; + + /** Bits per digit, amount of bits must fit in an unsigned long */ + int bits_per_digit; + +/* ---- init/deinit functions ---- */ + + /** initialize a bignum + @param a The number to initialize + @return CRYPT_OK on success + */ + int (*init)(void **a); + + /** init copy + @param dst The number to initialize and write to + @param src The number to copy from + @return CRYPT_OK on success + */ + int (*init_copy)(void **dst, void *src); + + /** deinit + @param a The number to free + @return CRYPT_OK on success + */ + void (*deinit)(void *a); + +/* ---- data movement ---- */ + + /** negate + @param src The number to negate + @param dst The destination + @return CRYPT_OK on success + */ + int (*neg)(void *src, void *dst); + + /** copy + @param src The number to copy from + @param dst The number to write to + @return CRYPT_OK on success + */ + int (*copy)(void *src, void *dst); + +/* ---- trivial low level functions ---- */ + + /** set small constant + @param a Number to write to + @param n Source upto bits_per_digit (actually meant for very small constants) + @return CRYPT_OK on succcess + */ + int (*set_int)(void *a, unsigned long n); + + /** get small constant + @param a Number to read, only fetches upto bits_per_digit from the number + @return The lower bits_per_digit of the integer (unsigned) + */ + unsigned long (*get_int)(void *a); + + /** get digit n + @param a The number to read from + @param n The number of the digit to fetch + @return The bits_per_digit sized n'th digit of a + */ + unsigned long (*get_digit)(void *a, int n); + + /** Get the number of digits that represent the number + @param a The number to count + @return The number of digits used to represent the number + */ + int (*get_digit_count)(void *a); + + /** compare two integers + @param a The left side integer + @param b The right side integer + @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison) + */ + int (*compare)(void *a, void *b); + + /** compare against int + @param a The left side integer + @param b The right side integer (upto bits_per_digit) + @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison) + */ + int (*compare_d)(void *a, unsigned long n); + + /** Count the number of bits used to represent the integer + @param a The integer to count + @return The number of bits required to represent the integer + */ + int (*count_bits)(void * a); + + /** Count the number of LSB bits which are zero + @param a The integer to count + @return The number of contiguous zero LSB bits + */ + int (*count_lsb_bits)(void *a); + + /** Compute a power of two + @param a The integer to store the power in + @param n The power of two you want to store (a = 2^n) + @return CRYPT_OK on success + */ + int (*twoexpt)(void *a , int n); + +/* ---- radix conversions ---- */ + + /** read ascii string + @param a The integer to store into + @param str The string to read + @param radix The radix the integer has been represented in (2-64) + @return CRYPT_OK on success + */ + int (*read_radix)(void *a, const char *str, int radix); + + /** write number to string + @param a The integer to store + @param str The destination for the string + @param radix The radix the integer is to be represented in (2-64) + @return CRYPT_OK on success + */ + int (*write_radix)(void *a, char *str, int radix); + + /** get size as unsigned char string + @param a The integer to get the size (when stored in array of octets) + @return The length of the integer + */ + unsigned long (*unsigned_size)(void *a); + + /** store an integer as an array of octets + @param src The integer to store + @param dst The buffer to store the integer in + @return CRYPT_OK on success + */ + int (*unsigned_write)(void *src, unsigned char *dst); + + /** read an array of octets and store as integer + @param dst The integer to load + @param src The array of octets + @param len The number of octets + @return CRYPT_OK on success + */ + int (*unsigned_read)(void *dst, unsigned char *src, unsigned long len); + +/* ---- basic math ---- */ + + /** add two integers + @param a The first source integer + @param b The second source integer + @param c The destination of "a + b" + @return CRYPT_OK on success + */ + int (*add)(void *a, void *b, void *c); + + + /** add two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a + b" + @return CRYPT_OK on success + */ + int (*addi)(void *a, unsigned long b, void *c); + + /** subtract two integers + @param a The first source integer + @param b The second source integer + @param c The destination of "a - b" + @return CRYPT_OK on success + */ + int (*sub)(void *a, void *b, void *c); + + /** subtract two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a - b" + @return CRYPT_OK on success + */ + int (*subi)(void *a, unsigned long b, void *c); + + /** multiply two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a * b" + @return CRYPT_OK on success + */ + int (*mul)(void *a, void *b, void *c); + + /** multiply two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a * b" + @return CRYPT_OK on success + */ + int (*muli)(void *a, unsigned long b, void *c); + + /** Square an integer + @param a The integer to square + @param b The destination + @return CRYPT_OK on success + */ + int (*sqr)(void *a, void *b); + + /** Divide an integer + @param a The dividend + @param b The divisor + @param c The quotient (can be NULL to signify don't care) + @param d The remainder (can be NULL to signify don't care) + @return CRYPT_OK on success + */ + int (*mpdiv)(void *a, void *b, void *c, void *d); + + /** divide by two + @param a The integer to divide (shift right) + @param b The destination + @return CRYPT_OK on success + */ + int (*div_2)(void *a, void *b); + + /** Get remainder (small value) + @param a The integer to reduce + @param b The modulus (upto bits_per_digit in length) + @param c The destination for the residue + @return CRYPT_OK on success + */ + int (*modi)(void *a, unsigned long b, unsigned long *c); + + /** gcd + @param a The first integer + @param b The second integer + @param c The destination for (a, b) + @return CRYPT_OK on success + */ + int (*gcd)(void *a, void *b, void *c); + + /** lcm + @param a The first integer + @param b The second integer + @param c The destination for [a, b] + @return CRYPT_OK on success + */ + int (*lcm)(void *a, void *b, void *c); + + /** Modular multiplication + @param a The first source + @param b The second source + @param c The modulus + @param d The destination (a*b mod c) + @return CRYPT_OK on success + */ + int (*mulmod)(void *a, void *b, void *c, void *d); + + /** Modular squaring + @param a The first source + @param b The modulus + @param c The destination (a*a mod b) + @return CRYPT_OK on success + */ + int (*sqrmod)(void *a, void *b, void *c); + + /** Modular inversion + @param a The value to invert + @param b The modulus + @param c The destination (1/a mod b) + @return CRYPT_OK on success + */ + int (*invmod)(void *, void *, void *); + +/* ---- reduction ---- */ + + /** setup montgomery + @param a The modulus + @param b The destination for the reduction digit + @return CRYPT_OK on success + */ + int (*montgomery_setup)(void *a, void **b); + + /** get normalization value + @param a The destination for the normalization value + @param b The modulus + @return CRYPT_OK on success + */ + int (*montgomery_normalization)(void *a, void *b); + + /** reduce a number + @param a The number [and dest] to reduce + @param b The modulus + @param c The value "b" from montgomery_setup() + @return CRYPT_OK on success + */ + int (*montgomery_reduce)(void *a, void *b, void *c); + + /** clean up (frees memory) + @param a The value "b" from montgomery_setup() + @return CRYPT_OK on success + */ + void (*montgomery_deinit)(void *a); + +/* ---- exponentiation ---- */ + + /** Modular exponentiation + @param a The base integer + @param b The power (can be negative) integer + @param c The modulus integer + @param d The destination + @return CRYPT_OK on success + */ + int (*exptmod)(void *a, void *b, void *c, void *d); + + /** Primality testing + @param a The integer to test + @param b The destination of the result (FP_YES if prime) + @return CRYPT_OK on success + */ + int (*isprime)(void *a, int *b); + +/* ---- (optional) ecc point math ---- */ + + /** ECC GF(p) point multiplication (from the NIST curves) + @param k The integer to multiply the point by + @param G The point to multiply + @param R The destination for kG + @param modulus The modulus for the field + @param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only) + @return CRYPT_OK on success + */ + int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); + + /** ECC GF(p) point addition + @param P The first point + @param Q The second point + @param R The destination of P + Q + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + */ + int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp); + + /** ECC GF(p) point double + @param P The first point + @param R The destination of 2P + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + */ + int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *mp); + + /** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1) + @param P The point to map + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + @remark The mapping can be different but keep in mind a ecc_point only has three + integers (x,y,z) so if you use a different mapping you have to make it fit. + */ + int (*ecc_map)(ecc_point *P, void *modulus, void *mp); + + /** Computes kA*A + kB*B = C using Shamir's Trick + @param A First point to multiply + @param kA What to multiple A by + @param B Second point to multiply + @param kB What to multiple B by + @param C [out] Destination point (can overlap with A or B + @param modulus Modulus for curve + @return CRYPT_OK on success + */ + int (*ecc_mul2add)(ecc_point *A, void *kA, + ecc_point *B, void *kB, + ecc_point *C, + void *modulus); + +/* ---- (optional) rsa optimized math (for internal CRT) ---- */ + + /** RSA Key Generation + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param size The size of the modulus (key size) desired (octets) + @param e The "e" value (public key). e==65537 is a good choice + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful, upon error all allocated ram is freed + */ + int (*rsa_keygen)(prng_state *prng, int wprng, int size, long e, rsa_key *key); + + + /** RSA exponentiation + @param in The octet array representing the base + @param inlen The length of the input + @param out The destination (to be stored in an octet array format) + @param outlen The length of the output buffer and the resulting size (zero padded to the size of the modulus) + @param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA + @param key The RSA key to use + @return CRYPT_OK on success + */ + int (*rsa_me)(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + rsa_key *key); +} ltc_math_descriptor; + +extern ltc_math_descriptor ltc_mp; + +int ltc_init_multi(void **a, ...); +void ltc_deinit_multi(void *a, ...); + +#ifdef LTM_DESC +extern const ltc_math_descriptor ltm_desc; +#endif + +#ifdef TFM_DESC +extern const ltc_math_descriptor tfm_desc; +#endif + +#ifdef GMP_DESC +extern const ltc_math_descriptor gmp_desc; +#endif + +#if !defined(DESC_DEF_ONLY) && defined(LTC_SOURCE) + +#define MP_DIGIT_BIT ltc_mp.bits_per_digit + +/* some handy macros */ +#define mp_init(a) ltc_mp.init(a) +#define mp_init_multi ltc_init_multi +#define mp_clear(a) ltc_mp.deinit(a) +#define mp_clear_multi ltc_deinit_multi +#define mp_init_copy(a, b) ltc_mp.init_copy(a, b) + +#define mp_neg(a, b) ltc_mp.neg(a, b) +#define mp_copy(a, b) ltc_mp.copy(a, b) + +#define mp_set(a, b) ltc_mp.set_int(a, b) +#define mp_set_int(a, b) ltc_mp.set_int(a, b) +#define mp_get_int(a) ltc_mp.get_int(a) +#define mp_get_digit(a, n) ltc_mp.get_digit(a, n) +#define mp_get_digit_count(a) ltc_mp.get_digit_count(a) +#define mp_cmp(a, b) ltc_mp.compare(a, b) +#define mp_cmp_d(a, b) ltc_mp.compare_d(a, b) +#define mp_count_bits(a) ltc_mp.count_bits(a) +#define mp_cnt_lsb(a) ltc_mp.count_lsb_bits(a) +#define mp_2expt(a, b) ltc_mp.twoexpt(a, b) + +#define mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c) +#define mp_toradix(a, b, c) ltc_mp.write_radix(a, b, c) +#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) +#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) +#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) + +#define mp_add(a, b, c) ltc_mp.add(a, b, c) +#define mp_add_d(a, b, c) ltc_mp.addi(a, b, c) +#define mp_sub(a, b, c) ltc_mp.sub(a, b, c) +#define mp_sub_d(a, b, c) ltc_mp.subi(a, b, c) +#define mp_mul(a, b, c) ltc_mp.mul(a, b, c) +#define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c) +#define mp_sqr(a, b) ltc_mp.sqr(a, b) +#define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d) +#define mp_div_2(a, b) ltc_mp.div_2(a, b) +#define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c) +#define mp_mod_d(a, b, c) ltc_mp.modi(a, b, c) +#define mp_gcd(a, b, c) ltc_mp.gcd(a, b, c) +#define mp_lcm(a, b, c) ltc_mp.lcm(a, b, c) + +#define mp_mulmod(a, b, c, d) ltc_mp.mulmod(a, b, c, d) +#define mp_sqrmod(a, b, c) ltc_mp.sqrmod(a, b, c) +#define mp_invmod(a, b, c) ltc_mp.invmod(a, b, c) + +#define mp_montgomery_setup(a, b) ltc_mp.montgomery_setup(a, b) +#define mp_montgomery_normalization(a, b) ltc_mp.montgomery_normalization(a, b) +#define mp_montgomery_reduce(a, b, c) ltc_mp.montgomery_reduce(a, b, c) +#define mp_montgomery_free(a) ltc_mp.montgomery_deinit(a) + +#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) +#define mp_prime_is_prime(a, b, c) ltc_mp.isprime(a, c) + +#define mp_iszero(a) (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO) +#define mp_isodd(a) (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO) +#define mp_exch(a, b) do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while(0); + +#define mp_tohex(a, b) mp_toradix(a, b, 16) + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_misc.h b/src/common/tomcrypt/tomcrypt_misc.h new file mode 100644 index 0000000000..239ad775bf --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_misc.h @@ -0,0 +1,23 @@ +/* ---- LTC_BASE64 Routines ---- */ +#ifdef LTC_BASE64 +int base64_encode(const unsigned char *in, unsigned long len, + unsigned char *out, unsigned long *outlen); + +int base64_decode(const unsigned char *in, unsigned long len, + unsigned char *out, unsigned long *outlen); +#endif + +/* ---- MEM routines ---- */ +void zeromem(void *dst, size_t len); +void burn_stack(unsigned long len); + +const char *error_to_string(int err); + +extern const char *crypt_build_settings; + +/* ---- HMM ---- */ +int crypt_fsa(void *mp, ...); + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_pk.h b/src/common/tomcrypt/tomcrypt_pk.h new file mode 100644 index 0000000000..cc05f6cb29 --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_pk.h @@ -0,0 +1,552 @@ +/* ---- NUMBER THEORY ---- */ + +enum { + PK_PUBLIC=0, + PK_PRIVATE=1 +}; + +int rand_prime(void *N, long len, prng_state *prng, int wprng); + +/* ---- RSA ---- */ +#ifdef LTC_MRSA + +/* Min and Max RSA key sizes (in bits) */ +#define MIN_RSA_SIZE 1024 +#define MAX_RSA_SIZE 4096 + +/** RSA LTC_PKCS style key */ +typedef struct Rsa_key { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + /** The public exponent */ + void *e; + /** The private exponent */ + void *d; + /** The modulus */ + void *N; + /** The p factor of N */ + void *p; + /** The q factor of N */ + void *q; + /** The 1/q mod p CRT param */ + void *qP; + /** The d mod (p - 1) CRT param */ + void *dP; + /** The d mod (q - 1) CRT param */ + void *dQ; +} rsa_key; + +int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key); + +int rsa_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + rsa_key *key); + +void rsa_free(rsa_key *key); + +/* These use LTC_PKCS #1 v2.0 padding */ +#define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, _key) \ + rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, LTC_LTC_PKCS_1_OAEP, _key) + +#define rsa_decrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, _stat, _key) \ + rsa_decrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, LTC_LTC_PKCS_1_OAEP, _stat, _key) + +#define rsa_sign_hash(_in, _inlen, _out, _outlen, _prng, _prng_idx, _hash_idx, _saltlen, _key) \ + rsa_sign_hash_ex(_in, _inlen, _out, _outlen, LTC_LTC_PKCS_1_PSS, _prng, _prng_idx, _hash_idx, _saltlen, _key) + +#define rsa_verify_hash(_sig, _siglen, _hash, _hashlen, _hash_idx, _saltlen, _stat, _key) \ + rsa_verify_hash_ex(_sig, _siglen, _hash, _hashlen, LTC_LTC_PKCS_1_PSS, _hash_idx, _saltlen, _stat, _key) + +/* These can be switched between LTC_PKCS #1 v2.x and LTC_PKCS #1 v1.5 paddings */ +int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, int hash_idx, int padding, rsa_key *key); + +int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + int hash_idx, int padding, + int *stat, rsa_key *key); + +int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int padding, + prng_state *prng, int prng_idx, + int hash_idx, unsigned long saltlen, + rsa_key *key); + +int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int padding, + int hash_idx, unsigned long saltlen, + int *stat, rsa_key *key); + +/* LTC_PKCS #1 import/export */ +int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key); +int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); + +#endif + +/* ---- Katja ---- */ +#ifdef MKAT + +/* Min and Max KAT key sizes (in bits) */ +#define MIN_KAT_SIZE 1024 +#define MAX_KAT_SIZE 4096 + +/** Katja LTC_PKCS style key */ +typedef struct KAT_key { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + /** The private exponent */ + void *d; + /** The modulus */ + void *N; + /** The p factor of N */ + void *p; + /** The q factor of N */ + void *q; + /** The 1/q mod p CRT param */ + void *qP; + /** The d mod (p - 1) CRT param */ + void *dP; + /** The d mod (q - 1) CRT param */ + void *dQ; + /** The pq param */ + void *pq; +} katja_key; + +int katja_make_key(prng_state *prng, int wprng, int size, katja_key *key); + +int katja_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + katja_key *key); + +void katja_free(katja_key *key); + +/* These use LTC_PKCS #1 v2.0 padding */ +int katja_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, int hash_idx, katja_key *key); + +int katja_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + int hash_idx, int *stat, + katja_key *key); + +/* LTC_PKCS #1 import/export */ +int katja_export(unsigned char *out, unsigned long *outlen, int type, katja_key *key); +int katja_import(const unsigned char *in, unsigned long inlen, katja_key *key); + +#endif + +/* ---- ECC Routines ---- */ +#ifdef LTC_MECC + +/* size of our temp buffers for exported keys */ +#define ECC_BUF_SIZE 256 + +/* max private key size */ +#define ECC_MAXSIZE 66 + +/** Structure defines a NIST GF(p) curve */ +typedef struct { + /** The size of the curve in octets */ + int size; + + /** name of curve */ + char *name; + + /** The prime that defines the field the curve is in (encoded in hex) */ + char *prime; + + /** The fields B param (hex) */ + char *B; + + /** The order of the curve (hex) */ + char *order; + + /** The x co-ordinate of the base point on the curve (hex) */ + char *Gx; + + /** The y co-ordinate of the base point on the curve (hex) */ + char *Gy; +} ltc_ecc_set_type; + +/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */ +typedef struct { + /** The x co-ordinate */ + void *x; + + /** The y co-ordinate */ + void *y; + + /** The z co-ordinate */ + void *z; +} ecc_point; + +/** An ECC key */ +typedef struct { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + + /** Index into the ltc_ecc_sets[] for the parameters of this curve; if -1, then this key is using user supplied curve in dp */ + int idx; + + /** pointer to domain parameters; either points to NIST curves (identified by idx >= 0) or user supplied curve */ + const ltc_ecc_set_type *dp; + + /** The public key */ + ecc_point pubkey; + + /** The private key */ + void *k; +} ecc_key; + +/** the ECC params provided */ +extern const ltc_ecc_set_type ltc_ecc_sets[]; + +int ecc_test(void); +void ecc_sizes(int *low, int *high); +int ecc_get_size(ecc_key *key); + +int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key); +int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp); +void ecc_free(ecc_key *key); + +int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); +int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key); +int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp); + +int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen); +int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key); +int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp); + +int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, + unsigned char *out, unsigned long *outlen); + +int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + ecc_key *key); + +int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + ecc_key *key); + +int ecc_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, ecc_key *key); + +int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, ecc_key *key); + +/* low level functions */ +ecc_point *ltc_ecc_new_point(void); +void ltc_ecc_del_point(ecc_point *p); +int ltc_ecc_is_valid_idx(int n); + +/* point ops (mp == montgomery digit) */ +#if !defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC) || defined(GMP_LTC_DESC) +/* R = 2P */ +int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp); + +/* R = P + Q */ +int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp); +#endif + +#if defined(LTC_MECC_FP) +/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */ +int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); + +/* functions for saving/loading/freeing/adding to fixed point cache */ +int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen); +int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen); +void ltc_ecc_fp_free(void); +int ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock); + +/* lock/unlock all points currently in fixed point cache */ +void ltc_ecc_fp_tablelock(int lock); +#endif + +/* R = kG */ +int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); + +#ifdef LTC_ECC_SHAMIR +/* kA*A + kB*B = C */ +int ltc_ecc_mul2add(ecc_point *A, void *kA, + ecc_point *B, void *kB, + ecc_point *C, + void *modulus); + +#ifdef LTC_MECC_FP +/* Shamir's trick with optimized point multiplication using fixed point cache */ +int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, + ecc_point *B, void *kB, + ecc_point *C, void *modulus); +#endif + +#endif + + +/* map P to affine from projective */ +int ltc_ecc_map(ecc_point *P, void *modulus, void *mp); + +#endif + +#ifdef LTC_MDSA + +/* Max diff between group and modulus size in bytes */ +#define LTC_MDSA_DELTA 512 + +/* Max DSA group size in bytes (default allows 4k-bit groups) */ +#define LTC_MDSA_MAX_GROUP 512 + +/** DSA key structure */ +typedef struct { + /** The key type, PK_PRIVATE or PK_PUBLIC */ + int type; + + /** The order of the sub-group used in octets */ + int qord; + + /** The generator */ + void *g; + + /** The prime used to generate the sub-group */ + void *q; + + /** The large prime that generats the field the contains the sub-group */ + void *p; + + /** The private key */ + void *x; + + /** The public key */ + void *y; +} dsa_key; + +int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); +void dsa_free(dsa_key *key); + +int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, + void *r, void *s, + prng_state *prng, int wprng, dsa_key *key); + +int dsa_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, dsa_key *key); + +int dsa_verify_hash_raw( void *r, void *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, dsa_key *key); + +int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, dsa_key *key); + +int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + dsa_key *key); + +int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + dsa_key *key); + +int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key); +int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key); +int dsa_verify_key(dsa_key *key, int *stat); + +int dsa_shared_secret(void *private_key, void *base, + dsa_key *public_key, + unsigned char *out, unsigned long *outlen); +#endif + +#ifdef LTC_DER +/* DER handling */ + +enum { + LTC_ASN1_EOL, + LTC_ASN1_BOOLEAN, + LTC_ASN1_INTEGER, + LTC_ASN1_SHORT_INTEGER, + LTC_ASN1_BIT_STRING, + LTC_ASN1_OCTET_STRING, + LTC_ASN1_NULL, + LTC_ASN1_OBJECT_IDENTIFIER, + LTC_ASN1_IA5_STRING, + LTC_ASN1_PRINTABLE_STRING, + LTC_ASN1_UTF8_STRING, + LTC_ASN1_UTCTIME, + LTC_ASN1_CHOICE, + LTC_ASN1_SEQUENCE, + LTC_ASN1_SET, + LTC_ASN1_SETOF +}; + +/** A LTC ASN.1 list type */ +typedef struct ltc_asn1_list_ { + /** The LTC ASN.1 enumerated type identifier */ + int type; + /** The data to encode or place for decoding */ + void *data; + /** The size of the input or resulting output */ + unsigned long size; + /** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */ + int used; + /** prev/next entry in the list */ + struct ltc_asn1_list_ *prev, *next, *child, *parent; +} ltc_asn1_list; + +#define LTC_SET_ASN1(list, index, Type, Data, Size) \ + do { \ + int LTC_MACRO_temp = (index); \ + ltc_asn1_list *LTC_MACRO_list = (list); \ + LTC_MACRO_list[LTC_MACRO_temp].type = (Type); \ + LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \ + LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \ + LTC_MACRO_list[LTC_MACRO_temp].used = 0; \ + } while (0); + +/* SEQUENCE */ +int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int type_of); + +#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE) + +int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *list, unsigned long outlen, int ordered); + +#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1) + +int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen); + +/* SET */ +#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0) +#define der_length_set der_length_sequence +int der_encode_set(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_encode_setof(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +/* VA list handy helpers with triplets of */ +int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...); +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...); + +/* FLEXI DECODER handle unknown list decoder */ +int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out); +void der_free_sequence_flexi(ltc_asn1_list *list); +void der_sequence_free(ltc_asn1_list *in); + +/* BOOLEAN */ +int der_length_boolean(unsigned long *outlen); +int der_encode_boolean(int in, + unsigned char *out, unsigned long *outlen); +int der_decode_boolean(const unsigned char *in, unsigned long inlen, + int *out); +/* INTEGER */ +int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen); +int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num); +int der_length_integer(void *num, unsigned long *len); + +/* INTEGER -- handy for 0..2^32-1 values */ +int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num); +int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen); +int der_length_short_integer(unsigned long num, unsigned long *outlen); + +/* BIT STRING */ +int der_encode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_bit_string(unsigned long nbits, unsigned long *outlen); + +/* OCTET STRING */ +int der_encode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_octet_string(unsigned long noctets, unsigned long *outlen); + +/* OBJECT IDENTIFIER */ +int der_encode_object_identifier(unsigned long *words, unsigned long nwords, + unsigned char *out, unsigned long *outlen); +int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, + unsigned long *words, unsigned long *outlen); +int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen); +unsigned long der_object_identifier_bits(unsigned long x); + +/* IA5 STRING */ +int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +int der_ia5_char_encode(int c); +int der_ia5_value_decode(int v); + +/* Printable STRING */ +int der_encode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +int der_printable_char_encode(int c); +int der_printable_value_decode(int v); + +/* UTF-8 */ +#if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR) +#include +#else +typedef ulong32 wchar_t; +#endif + +int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, + wchar_t *out, unsigned long *outlen); +unsigned long der_utf8_charsize(const wchar_t c); +int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen); + + +/* CHOICE */ +int der_decode_choice(const unsigned char *in, unsigned long *inlen, + ltc_asn1_list *list, unsigned long outlen); + +/* UTCTime */ +typedef struct { + unsigned YY, /* year */ + MM, /* month */ + DD, /* day */ + hh, /* hour */ + mm, /* minute */ + ss, /* second */ + off_dir, /* timezone offset direction 0 == +, 1 == - */ + off_hh, /* timezone offset hours */ + off_mm; /* timezone offset minutes */ +} ltc_utctime; + +int der_encode_utctime(ltc_utctime *utctime, + unsigned char *out, unsigned long *outlen); + +int der_decode_utctime(const unsigned char *in, unsigned long *inlen, + ltc_utctime *out); + +int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen); + + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_pkcs.h b/src/common/tomcrypt/tomcrypt_pkcs.h new file mode 100644 index 0000000000..8c8c7e4381 --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_pkcs.h @@ -0,0 +1,89 @@ +/* LTC_PKCS Header Info */ + +/* ===> LTC_PKCS #1 -- RSA Cryptography <=== */ +#ifdef LTC_PKCS_1 + +enum ltc_pkcs_1_v1_5_blocks +{ + LTC_LTC_PKCS_1_EMSA = 1, /* Block type 1 (LTC_PKCS #1 v1.5 signature padding) */ + LTC_LTC_PKCS_1_EME = 2 /* Block type 2 (LTC_PKCS #1 v1.5 encryption padding) */ +}; + +enum ltc_pkcs_1_paddings +{ + LTC_LTC_PKCS_1_V1_5 = 1, /* LTC_PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */ + LTC_LTC_PKCS_1_OAEP = 2, /* LTC_PKCS #1 v2.0 encryption padding */ + LTC_LTC_PKCS_1_PSS = 3 /* LTC_PKCS #1 v2.1 signature padding */ +}; + +int pkcs_1_mgf1( int hash_idx, + const unsigned char *seed, unsigned long seedlen, + unsigned char *mask, unsigned long masklen); + +int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out); +int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen); + +/* *** v1.5 padding */ +int pkcs_1_v1_5_encode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + prng_state *prng, + int prng_idx, + unsigned char *out, + unsigned long *outlen); + +int pkcs_1_v1_5_decode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + unsigned char *out, + unsigned long *outlen, + int *is_valid); + +/* *** v2.1 padding */ +int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + unsigned char *out, unsigned long *outlen, + int *res); + +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res); + +#endif /* LTC_PKCS_1 */ + +/* ===> LTC_PKCS #5 -- Password Based Cryptography <=== */ +#ifdef LTC_PKCS_5 + +/* Algorithm #1 (old) */ +int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + +/* Algorithm #2 (new) */ +int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + +#endif /* LTC_PKCS_5 */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/common/tomcrypt/tomcrypt_prng.h b/src/common/tomcrypt/tomcrypt_prng.h new file mode 100644 index 0000000000..508159d209 --- /dev/null +++ b/src/common/tomcrypt/tomcrypt_prng.h @@ -0,0 +1,199 @@ +/* ---- PRNG Stuff ---- */ +#ifdef LTC_YARROW +struct yarrow_prng { + int cipher, hash; + unsigned char pool[MAXBLOCKSIZE]; + symmetric_CTR ctr; + LTC_MUTEX_TYPE(prng_lock) +}; +#endif + +#ifdef LTC_RC4 +struct rc4_prng { + int x, y; + unsigned char buf[256]; +}; +#endif + +#ifdef LTC_FORTUNA +struct fortuna_prng { + hash_state pool[LTC_FORTUNA_POOLS]; /* the pools */ + + symmetric_key skey; + + unsigned char K[32], /* the current key */ + IV[16]; /* IV for CTR mode */ + + unsigned long pool_idx, /* current pool we will add to */ + pool0_len, /* length of 0'th pool */ + wd; + + ulong64 reset_cnt; /* number of times we have reset */ + LTC_MUTEX_TYPE(prng_lock) +}; +#endif + +#ifdef LTC_SOBER128 +struct sober128_prng { + ulong32 R[17], /* Working storage for the shift register */ + initR[17], /* saved register contents */ + konst, /* key dependent constant */ + sbuf; /* partial word encryption buffer */ + + int nbuf, /* number of part-word stream bits buffered */ + flag, /* first add_entropy call or not? */ + set; /* did we call add_entropy to set key? */ + +}; +#endif + +typedef union Prng_state { + char dummy[1]; +#ifdef LTC_YARROW + struct yarrow_prng yarrow; +#endif +#ifdef LTC_RC4 + struct rc4_prng rc4; +#endif +#ifdef LTC_FORTUNA + struct fortuna_prng fortuna; +#endif +#ifdef LTC_SOBER128 + struct sober128_prng sober128; +#endif +} prng_state; + +/** PRNG descriptor */ +extern struct ltc_prng_descriptor { + /** Name of the PRNG */ + char *name; + /** size in bytes of exported state */ + int export_size; + /** Start a PRNG state + @param prng [out] The state to initialize + @return CRYPT_OK if successful + */ + int (*start)(prng_state *prng); + /** Add entropy to the PRNG + @param in The entropy + @param inlen Length of the entropy (octets)\ + @param prng The PRNG state + @return CRYPT_OK if successful + */ + int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng); + /** Ready a PRNG state to read from + @param prng The PRNG state to ready + @return CRYPT_OK if successful + */ + int (*ready)(prng_state *prng); + /** Read from the PRNG + @param out [out] Where to store the data + @param outlen Length of data desired (octets) + @param prng The PRNG state to read from + @return Number of octets read + */ + unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng); + /** Terminate a PRNG state + @param prng The PRNG state to terminate + @return CRYPT_OK if successful + */ + int (*done)(prng_state *prng); + /** Export a PRNG state + @param out [out] The destination for the state + @param outlen [in/out] The max size and resulting size of the PRNG state + @param prng The PRNG to export + @return CRYPT_OK if successful + */ + int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng); + /** Import a PRNG state + @param in The data to import + @param inlen The length of the data to import (octets) + @param prng The PRNG to initialize/import + @return CRYPT_OK if successful + */ + int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng); + /** Self-test the PRNG + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled + */ + int (*test)(void); +} prng_descriptor[]; + +#ifdef LTC_YARROW +int yarrow_start(prng_state *prng); +int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int yarrow_ready(prng_state *prng); +unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int yarrow_done(prng_state *prng); +int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int yarrow_test(void); +extern const struct ltc_prng_descriptor yarrow_desc; +#endif + +#ifdef LTC_FORTUNA +int fortuna_start(prng_state *prng); +int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int fortuna_ready(prng_state *prng); +unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int fortuna_done(prng_state *prng); +int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int fortuna_test(void); +extern const struct ltc_prng_descriptor fortuna_desc; +#endif + +#ifdef LTC_RC4 +int rc4_start(prng_state *prng); +int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int rc4_ready(prng_state *prng); +unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int rc4_done(prng_state *prng); +int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int rc4_test(void); +extern const struct ltc_prng_descriptor rc4_desc; +#endif + +#ifdef LTC_SPRNG +int sprng_start(prng_state *prng); +int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sprng_ready(prng_state *prng); +unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int sprng_done(prng_state *prng); +int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sprng_test(void); +extern const struct ltc_prng_descriptor sprng_desc; +#endif + +#ifdef LTC_SOBER128 +int sober128_start(prng_state *prng); +int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sober128_ready(prng_state *prng); +unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int sober128_done(prng_state *prng); +int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sober128_test(void); +extern const struct ltc_prng_descriptor sober128_desc; +#endif + +int find_prng(const char *name); +int register_prng(const struct ltc_prng_descriptor *prng); +int unregister_prng(const struct ltc_prng_descriptor *prng); +int prng_is_valid(int idx); +LTC_MUTEX_PROTO(ltc_prng_mutex) + +/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this + * might not work on all platforms as planned + */ +unsigned long rng_get_bytes(unsigned char *out, + unsigned long outlen, + void (*callback)(void)); + +int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)); + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/dsql/DsqlCompilerScratch.cpp b/src/dsql/DsqlCompilerScratch.cpp index 7d6800e56f..c91e8d1cbd 100644 --- a/src/dsql/DsqlCompilerScratch.cpp +++ b/src/dsql/DsqlCompilerScratch.cpp @@ -320,6 +320,37 @@ void DsqlCompilerScratch::putLocalVariables(CompoundStmtNode* parameters, USHORT else fb_assert(false); } + + if (!(flags & DsqlCompilerScratch::FLAG_SUB_ROUTINE)) + { + // Check not implemented sub-functions. + + GenericMap >::ConstAccessor funcAccessor(&subFunctions); + + for (bool found = funcAccessor.getFirst(); found; found = funcAccessor.getNext()) + { + if (!funcAccessor.current()->second->dsqlBlock) + { + status_exception::raise( + Arg::Gds(isc_subfunc_not_impl) << + funcAccessor.current()->first.c_str()); + } + } + + // Check not implemented sub-procedures. + + GenericMap >::ConstAccessor procAccessor(&subProcedures); + + for (bool found = procAccessor.getFirst(); found; found = procAccessor.getNext()) + { + if (!procAccessor.current()->second->dsqlBlock) + { + status_exception::raise( + Arg::Gds(isc_subproc_not_impl) << + procAccessor.current()->first.c_str()); + } + } + } } // Write out local variable field data type. @@ -586,6 +617,50 @@ void DsqlCompilerScratch::checkUnusedCTEs() const } } +DeclareSubFuncNode* DsqlCompilerScratch::getSubFunction(const Firebird::MetaName& name) +{ + DeclareSubFuncNode* subFunc = NULL; + subFunctions.get(name, subFunc); + + if (!subFunc && mainScratch) + subFunc = mainScratch->getSubFunction(name); + + return subFunc; +} + +void DsqlCompilerScratch::putSubFunction(DeclareSubFuncNode* subFunc, bool replace) +{ + if (!replace && subFunctions.exist(subFunc->name)) + { + status_exception::raise( + Arg::Gds(isc_dsql_duplicate_spec) << subFunc->name); + } + + subFunctions.put(subFunc->name, subFunc); +} + +DeclareSubProcNode* DsqlCompilerScratch::getSubProcedure(const Firebird::MetaName& name) +{ + DeclareSubProcNode* subProc = NULL; + subProcedures.get(name, subProc); + + if (!subProc && mainScratch) + subProc = mainScratch->getSubProcedure(name); + + return subProc; +} + +void DsqlCompilerScratch::putSubProcedure(DeclareSubProcNode* subProc, bool replace) +{ + if (!replace && subProcedures.exist(subProc->name)) + { + status_exception::raise( + Arg::Gds(isc_dsql_duplicate_spec) << subProc->name); + } + + subProcedures.put(subProc->name, subProc); +} + // Process derived table which can be recursive CTE. // If it is non-recursive return input node unchanged. // If it is recursive return new derived table which is an union of union of anchor (non-recursive) diff --git a/src/dsql/DsqlCompilerScratch.h b/src/dsql/DsqlCompilerScratch.h index c6755ef637..a8c91b243c 100644 --- a/src/dsql/DsqlCompilerScratch.h +++ b/src/dsql/DsqlCompilerScratch.h @@ -70,7 +70,7 @@ public: public: DsqlCompilerScratch(MemoryPool& p, dsql_dbb* aDbb, jrd_tra* aTransaction, - DsqlCompiledStatement* aStatement) + DsqlCompiledStatement* aStatement, DsqlCompilerScratch* aMainScratch = NULL) : BlrDebugWriter(p), dbb(aDbb), transaction(aTransaction), @@ -79,7 +79,6 @@ public: nestingLevel(0), ports(p), relation(NULL), - procedure(NULL), mainContext(p), context(&mainContext), unionContext(p), @@ -115,6 +114,7 @@ public: ctes(p), cteAliases(p), psql(false), + mainScratch(aMainScratch), subFunctions(p), subProcedures(p) { @@ -247,43 +247,11 @@ public: bool isPsql() const { return psql; } void setPsql(bool value) { psql = value; } - dsql_udf* getSubFunction(const Firebird::MetaName& name) - { - dsql_udf* subFunc = NULL; - subFunctions.get(name, subFunc); - return subFunc; - } + DeclareSubFuncNode* getSubFunction(const Firebird::MetaName& name); + void putSubFunction(DeclareSubFuncNode* subFunc, bool replace = false); - void putSubFunction(dsql_udf* subFunc) - { - if (subFunctions.exist(subFunc->udf_name.identifier)) - { - using namespace Firebird; - status_exception::raise( - Arg::Gds(isc_dsql_duplicate_spec) << subFunc->udf_name.identifier); - } - - subFunctions.put(subFunc->udf_name.identifier, subFunc); - } - - dsql_prc* getSubProcedure(const Firebird::MetaName& name) - { - dsql_prc* subProc = NULL; - subProcedures.get(name, subProc); - return subProc; - } - - void putSubProcedure(dsql_prc* subProc) - { - if (subProcedures.exist(subProc->prc_name.identifier)) - { - using namespace Firebird; - status_exception::raise( - Arg::Gds(isc_dsql_duplicate_spec) << subProc->prc_name.identifier); - } - - subProcedures.put(subProc->prc_name.identifier, subProc); - } + DeclareSubProcNode* getSubProcedure(const Firebird::MetaName& name); + void putSubProcedure(DeclareSubProcNode* subProc, bool replace = false); private: SelectExprNode* pass1RecursiveCte(SelectExprNode* input); @@ -300,7 +268,6 @@ public: unsigned nestingLevel; // begin...end nesting level Firebird::Array ports; // Port messages dsql_rel* relation; // relation created by this request (for DDL) - dsql_prc* procedure; // procedure created by this request (for DDL) DsqlContextStack mainContext; DsqlContextStack* context; DsqlContextStack unionContext; // Save contexts for views of unions @@ -340,8 +307,9 @@ private: Firebird::HalfStaticArray ctes; // common table expressions Firebird::HalfStaticArray cteAliases; // CTE aliases in recursive members bool psql; - Firebird::GenericMap > subFunctions; - Firebird::GenericMap > subProcedures; + DsqlCompilerScratch* mainScratch; + Firebird::GenericMap > subFunctions; + Firebird::GenericMap > subProcedures; }; class PsqlChanger diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp index b182d78b0f..a80ea8f7fb 100644 --- a/src/dsql/ExprNodes.cpp +++ b/src/dsql/ExprNodes.cpp @@ -11589,8 +11589,12 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* if (blrOp == blr_subfunc) { DeclareSubFuncNode* declareNode; - if (csb->subFunctions.get(name.identifier, declareNode)) - node->function = declareNode->routine; + + for (auto curCsb = csb; curCsb && !node->function; curCsb = curCsb->mainCsb) + { + if (curCsb->subFunctions.get(name.identifier, declareNode)) + node->function = declareNode->routine; + } } Function* function = node->function; @@ -12023,7 +12027,10 @@ ValueExprNode* UdfCallNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) doDsqlPass(dsqlScratch, args)); if (name.package.isEmpty()) - node->dsqlFunction = dsqlScratch->getSubFunction(name.identifier); + { + DeclareSubFuncNode* subFunction = dsqlScratch->getSubFunction(name.identifier); + node->dsqlFunction = subFunction ? subFunction->dsqlFunction : NULL; + } if (!node->dsqlFunction) node->dsqlFunction = METD_get_function(dsqlScratch->getTransaction(), dsqlScratch, name); diff --git a/src/dsql/PackageNodes.epp b/src/dsql/PackageNodes.epp index 75daf789c6..a00c92f036 100644 --- a/src/dsql/PackageNodes.epp +++ b/src/dsql/PackageNodes.epp @@ -51,164 +51,6 @@ DATABASE DB = STATIC "ODS.RDB"; namespace { - struct ParameterInfo - { - explicit ParameterInfo(MemoryPool& p) - : type(0), - number(0), - name(p), - fieldSource(p), - fieldName(p), - relationName(p), - mechanism(0) - { - defaultSource.clear(); - defaultValue.clear(); - } - - ParameterInfo(MemoryPool& p, const ParameterInfo& o) - : type(o.type), - number(o.number), - name(p, o.name), - fieldSource(p, o.fieldSource), - fieldName(p, o.fieldName), - relationName(p, o.relationName), - collationId(o.collationId), - nullFlag(o.nullFlag), - mechanism(o.mechanism), - fieldLength(o.fieldLength), - fieldScale(o.fieldScale), - fieldType(o.fieldType), - fieldSubType(o.fieldSubType), - fieldSegmentLength(o.fieldSegmentLength), - fieldNullFlag(o.fieldNullFlag), - fieldCharLength(o.fieldCharLength), - fieldCollationId(o.fieldCollationId), - fieldCharSetId(o.fieldCharSetId), - fieldPrecision(o.fieldPrecision), - defaultSource(o.defaultSource), - defaultValue(o.defaultValue) - { - } - - SSHORT type; - SSHORT number; - MetaName name; - MetaName fieldSource; - MetaName fieldName; - MetaName relationName; - Nullable collationId; - Nullable nullFlag; - SSHORT mechanism; - Nullable fieldLength; - Nullable fieldScale; - Nullable fieldType; - Nullable fieldSubType; - Nullable fieldSegmentLength; - Nullable fieldNullFlag; - Nullable fieldCharLength; - Nullable fieldCollationId; - Nullable fieldCharSetId; - Nullable fieldPrecision; - - // Not compared - bid defaultSource; - bid defaultValue; - - bool operator >(const ParameterInfo& o) const - { - return type > o.type || (type == o.type && number > o.number); - } - - bool operator ==(const ParameterInfo& o) const - { - return type == o.type && number == o.number && name == o.name && - (fieldSource == o.fieldSource || - (fb_utils::implicit_domain(fieldSource.c_str()) && - fb_utils::implicit_domain(o.fieldSource.c_str()))) && - fieldName == o.fieldName && relationName == o.relationName && - collationId == o.collationId && nullFlag == o.nullFlag && - mechanism == o.mechanism && fieldLength == o.fieldLength && - fieldScale == o.fieldScale && fieldType == o.fieldType && - fieldSubType == o.fieldSubType && fieldSegmentLength == o.fieldSegmentLength && - fieldNullFlag == o.fieldNullFlag && fieldCharLength == o.fieldCharLength && - fieldCollationId == o.fieldCollationId && fieldCharSetId == o.fieldCharSetId && - fieldPrecision == o.fieldPrecision; - } - - bool operator !=(const ParameterInfo& o) const - { - return !(*this == o); - } - }; - - struct Signature - { - Signature(MemoryPool& p, const MetaName& aName) - : name(p, aName), - parameters(p), - defined(false) - { - } - - explicit Signature(const MetaName& aName) - : name(aName), - parameters(*getDefaultMemoryPool()), - defined(false) - { - } - - explicit Signature(MemoryPool& p) - : name(p), - parameters(p), - defined(false) - { - } - - Signature(MemoryPool& p, const Signature& o) - : name(p, o.name), - parameters(p), - defined(o.defined) - { - for (SortedObjectsArray::const_iterator i = o.parameters.begin(); - i != o.parameters.end(); ++i) - { - parameters.add(*i); - } - } - - bool operator >(const Signature& o) const - { - return name > o.name; - } - - bool operator ==(const Signature& o) const - { - if (name != o.name || parameters.getCount() != o.parameters.getCount()) - return false; - - for (SortedObjectsArray::const_iterator i = parameters.begin(), - j = o.parameters.begin(); - i != parameters.end(); ++i, ++j) - { - if (*i != *j) - return false; - } - - return true; - } - - bool operator !=(const Signature& o) const - { - return !(*this == o); - } - - MetaName name; - SortedObjectsArray parameters; - bool defined; - }; - - // Return function and procedure names (in the user charset) and optionally its details for a // given package. void collectPackagedItems(thread_db* tdbb, jrd_tra* transaction, const MetaName& metaName, @@ -225,6 +67,9 @@ namespace Signature function(FUN.RDB$FUNCTION_NAME); function.defined = !FUN.RDB$FUNCTION_BLR.NULL || !FUN.RDB$ENTRYPOINT.NULL; + if (!FUN.RDB$DETERMINISTIC_FLAG.NULL && FUN.RDB$DETERMINISTIC_FLAG != 0) + function.flags |= Signature::FLAG_DETERMINISTIC; + if (details) { FOR (REQUEST_HANDLE requestHandle2 TRANSACTION_HANDLE transaction) @@ -234,7 +79,7 @@ namespace ARG.RDB$FUNCTION_NAME EQ FUN.RDB$FUNCTION_NAME AND FLD.RDB$FIELD_NAME EQ ARG.RDB$FIELD_SOURCE { - ParameterInfo parameter(*getDefaultMemoryPool()); + SignatureParameter parameter(*getDefaultMemoryPool()); parameter.number = ARG.RDB$ARGUMENT_POSITION; parameter.name = ARG.RDB$ARGUMENT_NAME; @@ -271,11 +116,6 @@ namespace if (!FLD.RDB$FIELD_PRECISION.NULL) parameter.fieldPrecision = FLD.RDB$FIELD_PRECISION; - if (!ARG.RDB$DEFAULT_SOURCE.NULL) - parameter.defaultSource = ARG.RDB$DEFAULT_SOURCE; - if (!ARG.RDB$DEFAULT_VALUE.NULL) - parameter.defaultValue = ARG.RDB$DEFAULT_VALUE; - function.parameters.add(parameter); } END_FOR @@ -304,7 +144,7 @@ namespace PRM.RDB$PROCEDURE_NAME EQ PRC.RDB$PROCEDURE_NAME AND FLD.RDB$FIELD_NAME EQ PRM.RDB$FIELD_SOURCE { - ParameterInfo parameter(*getDefaultMemoryPool()); + SignatureParameter parameter(*getDefaultMemoryPool()); parameter.type = PRM.RDB$PARAMETER_TYPE; parameter.number = PRM.RDB$PARAMETER_NUMBER; parameter.name = PRM.RDB$PARAMETER_NAME; @@ -341,11 +181,6 @@ namespace if (!FLD.RDB$FIELD_PRECISION.NULL) parameter.fieldPrecision = FLD.RDB$FIELD_PRECISION; - if (!PRM.RDB$DEFAULT_SOURCE.NULL) - parameter.defaultSource = PRM.RDB$DEFAULT_SOURCE; - if (!PRM.RDB$DEFAULT_VALUE.NULL) - parameter.defaultValue = PRM.RDB$DEFAULT_VALUE; - procedure.parameters.add(parameter); } END_FOR diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp index 04e2a29979..9d9f222fc4 100644 --- a/src/dsql/StmtNodes.cpp +++ b/src/dsql/StmtNodes.cpp @@ -1402,7 +1402,8 @@ DmlNode* DeclareSubFuncNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerSc { // scope CompilerScratch* const subCsb = node->subCsb = - FB_NEW_POOL(csb->csb_pool) CompilerScratch(csb->csb_pool); + FB_NEW_POOL(csb->csb_pool) CompilerScratch(csb->csb_pool, csb); + subCsb->csb_g_flags |= csb_subroutine | (csb->csb_g_flags & csb_get_dependencies); subCsb->csb_blr_reader = csb->csb_blr_reader; @@ -1520,6 +1521,97 @@ DeclareSubFuncNode* DeclareSubFuncNode::dsqlPass(DsqlCompilerScratch* dsqlScratc if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_SUB_ROUTINE) ERR_post(Arg::Gds(isc_wish_list) << Arg::Gds(isc_random) << "nested sub function"); + DeclareSubFuncNode* prevDecl = dsqlScratch->getSubFunction(name); + bool implemetingForward = prevDecl && !prevDecl->dsqlBlock && dsqlBlock; + + dsqlFunction = implemetingForward ? prevDecl->dsqlFunction : FB_NEW_POOL(pool) dsql_udf(pool); + + dsqlFunction->udf_flags = UDF_subfunc; + dsqlFunction->udf_name.identifier = name; + + fb_assert(dsqlReturns.getCount() == 1); + const TypeClause* returnType = dsqlReturns[0]->type; + + dsqlFunction->udf_dtype = returnType->dtype; + dsqlFunction->udf_scale = returnType->scale; + dsqlFunction->udf_sub_type = returnType->subType; + dsqlFunction->udf_length = returnType->length; + dsqlFunction->udf_character_set_id = returnType->charSetId; + + if (dsqlDeterministic) + dsqlSignature.flags |= Signature::FLAG_DETERMINISTIC; + + SignatureParameter sigRet(pool); + sigRet.type = 1; + sigRet.number = -1; + sigRet.fromType(returnType); + dsqlSignature.parameters.add(sigRet); + + Array >& paramArray = dsqlParameters; + bool defaultFound = false; + + for (NestConst* i = paramArray.begin(); i != paramArray.end(); ++i) + { + ParameterClause* param = *i; + const unsigned paramIndex = i - paramArray.begin(); + + SignatureParameter sigParam(pool); + sigParam.type = 0; + sigParam.number = (SSHORT) dsqlSignature.parameters.getCount(); + sigParam.name = param->name; + sigParam.fromType(param->type); + dsqlSignature.parameters.add(sigParam); + + if (!implemetingForward) + { + // ASF: dsqlFunction->udf_arguments is only checked for its count for now. + dsqlFunction->udf_arguments.add(dsc()); + } + + if (param->defaultClause) + { + if (prevDecl) + { + status_exception::raise( + Arg::Gds(isc_subfunc_defvaldecl) << + name.c_str()); + } + + defaultFound = true; + + if (!implemetingForward && dsqlFunction->udf_def_count == 0) + dsqlFunction->udf_def_count = paramArray.end() - i; + } + else + { + if (defaultFound) + { + // Parameter without default value after parameters with default. + ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) << + Arg::Gds(isc_bad_default_value) << + Arg::Gds(isc_invalid_clause) << Arg::Str("defaults must be last")); + } + + if (prevDecl && paramIndex < prevDecl->dsqlParameters.getCount()) + param->defaultClause = prevDecl->dsqlParameters[paramIndex]->defaultClause; + } + } + + if (!implemetingForward) + dsqlScratch->putSubFunction(this); + else if (dsqlSignature != prevDecl->dsqlSignature) + { + status_exception::raise( + Arg::Gds(isc_subfunc_signat) << + name.c_str()); + } + + if (!dsqlBlock) // forward decl + return this; + + if (prevDecl) + dsqlScratch->putSubFunction(this, true); + DsqlCompiledStatement* statement = FB_NEW_POOL(pool) DsqlCompiledStatement(pool); if (dsqlScratch->clientDialect > SQL_DIALECT_V5) @@ -1535,58 +1627,23 @@ DeclareSubFuncNode* DeclareSubFuncNode::dsqlPass(DsqlCompilerScratch* dsqlScratc statement->setType(DsqlCompiledStatement::TYPE_SELECT); blockScratch = FB_NEW_POOL(pool) DsqlCompilerScratch(pool, - dsqlScratch->getAttachment(), dsqlScratch->getTransaction(), statement); + dsqlScratch->getAttachment(), dsqlScratch->getTransaction(), statement, dsqlScratch); blockScratch->clientDialect = dsqlScratch->clientDialect; - blockScratch->flags |= DsqlCompilerScratch::FLAG_FUNCTION | DsqlCompilerScratch::FLAG_SUB_ROUTINE; - blockScratch->flags |= dsqlScratch->flags & DsqlCompilerScratch::FLAG_DDL; + blockScratch->flags |= + DsqlCompilerScratch::FLAG_FUNCTION | + DsqlCompilerScratch::FLAG_SUB_ROUTINE | + (dsqlScratch->flags & DsqlCompilerScratch::FLAG_DDL); dsqlBlock = dsqlBlock->dsqlPass(blockScratch); - dsqlFunction = FB_NEW_POOL(pool) dsql_udf(pool); - dsqlFunction->udf_flags = UDF_subfunc; - dsqlFunction->udf_name.identifier = name; - - fb_assert(dsqlBlock->returns.getCount() == 1); - const TypeClause* returnType = dsqlBlock->returns[0]->type; - dsqlFunction->udf_dtype = returnType->dtype; - dsqlFunction->udf_scale = returnType->scale; - dsqlFunction->udf_sub_type = returnType->subType; - dsqlFunction->udf_length = returnType->length; - dsqlFunction->udf_character_set_id = returnType->charSetId; - - const Array >& paramArray = dsqlBlock->parameters; - bool defaultFound = false; - - for (const NestConst* i = paramArray.begin(); i != paramArray.end(); ++i) - { - // ASF: dsqlFunction->udf_arguments is only checked for its count for now. - dsqlFunction->udf_arguments.add(dsc()); - - const ParameterClause* param = *i; - - if (param->defaultClause) - { - defaultFound = true; - - if (dsqlFunction->udf_def_count == 0) - dsqlFunction->udf_def_count = paramArray.end() - i; - } - else if (defaultFound) - { - // Parameter without default value after parameters with default. - ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) << - Arg::Gds(isc_bad_default_value) << - Arg::Gds(isc_invalid_clause) << Arg::Str("defaults must be last")); - } - } - - dsqlScratch->putSubFunction(dsqlFunction); - return this; } void DeclareSubFuncNode::genBlr(DsqlCompilerScratch* dsqlScratch) { + if (!dsqlBlock) // forward decl + return; + GEN_request(blockScratch, dsqlBlock); dsqlScratch->appendUChar(blr_subfunc_decl); @@ -1677,7 +1734,8 @@ DmlNode* DeclareSubProcNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerSc { // scope CompilerScratch* const subCsb = node->subCsb = - FB_NEW_POOL(csb->csb_pool) CompilerScratch(csb->csb_pool); + FB_NEW_POOL(csb->csb_pool) CompilerScratch(csb->csb_pool, csb); + subCsb->csb_g_flags |= csb_subroutine | (csb->csb_g_flags & csb_get_dependencies); subCsb->csb_blr_reader = csb->csb_blr_reader; @@ -1803,6 +1861,100 @@ DeclareSubProcNode* DeclareSubProcNode::dsqlPass(DsqlCompilerScratch* dsqlScratc if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_SUB_ROUTINE) ERR_post(Arg::Gds(isc_wish_list) << Arg::Gds(isc_random) << "nested sub procedure"); + DeclareSubProcNode* prevDecl = dsqlScratch->getSubProcedure(name); + bool implemetingForward = prevDecl && !prevDecl->dsqlBlock && dsqlBlock; + + dsqlProcedure = implemetingForward ? prevDecl->dsqlProcedure : FB_NEW_POOL(pool) dsql_prc(pool); + + dsqlProcedure->prc_flags = PRC_subproc; + dsqlProcedure->prc_name.identifier = name; + dsqlProcedure->prc_in_count = USHORT(dsqlParameters.getCount()); + dsqlProcedure->prc_out_count = USHORT(dsqlReturns.getCount()); + + if (dsqlParameters.hasData()) + { + Array >& paramArray = dsqlParameters; + bool defaultFound = false; + + dsqlProcedure->prc_inputs = paramArray.front()->type; + + for (NestConst* i = paramArray.begin(); i != paramArray.end(); ++i) + { + ParameterClause* param = *i; + const unsigned paramIndex = i - paramArray.begin(); + + SignatureParameter sigParam(pool); + sigParam.type = 0; // input + sigParam.number = (SSHORT) dsqlSignature.parameters.getCount(); + sigParam.name = param->name; + sigParam.fromType(param->type); + dsqlSignature.parameters.add(sigParam); + + if (param->defaultClause) + { + if (prevDecl) + { + status_exception::raise( + Arg::Gds(isc_subproc_defvaldecl) << + name.c_str()); + } + + defaultFound = true; + + if (!implemetingForward && dsqlProcedure->prc_def_count == 0) + dsqlProcedure->prc_def_count = paramArray.end() - i; + } + else + { + if (defaultFound) + { + // Parameter without default value after parameters with default. + ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) << + Arg::Gds(isc_bad_default_value) << + Arg::Gds(isc_invalid_clause) << Arg::Str("defaults must be last")); + } + + if (prevDecl && paramIndex < prevDecl->dsqlParameters.getCount()) + param->defaultClause = prevDecl->dsqlParameters[paramIndex]->defaultClause; + } + } + } + + if (dsqlReturns.hasData()) + { + Array >& paramArray = dsqlReturns; + + dsqlProcedure->prc_outputs = paramArray.front()->type; + + for (NestConst* i = paramArray.begin(); i != paramArray.end(); ++i) + { + ParameterClause* param = *i; + const unsigned paramIndex = i - paramArray.begin(); + + SignatureParameter sigParam(pool); + sigParam.type = 1; // output + sigParam.number = (SSHORT) dsqlSignature.parameters.getCount(); + sigParam.name = param->name; + sigParam.fromType(param->type); + dsqlSignature.parameters.add(sigParam); + } + } + + if (!implemetingForward) + dsqlScratch->putSubProcedure(this); + else if (dsqlSignature != prevDecl->dsqlSignature) + { + status_exception::raise( + Arg::Gds(isc_subproc_signat) << + name.c_str()); + } + + if (!dsqlBlock) // forward decl + return this; + + if (prevDecl) + dsqlScratch->putSubProcedure(this, true); + DsqlCompiledStatement* statement = FB_NEW_POOL(pool) DsqlCompiledStatement(pool); if (dsqlScratch->clientDialect > SQL_DIALECT_V5) @@ -1818,54 +1970,21 @@ DeclareSubProcNode* DeclareSubProcNode::dsqlPass(DsqlCompilerScratch* dsqlScratc statement->setType(DsqlCompiledStatement::TYPE_SELECT); blockScratch = FB_NEW_POOL(pool) DsqlCompilerScratch(pool, - dsqlScratch->getAttachment(), dsqlScratch->getTransaction(), statement); + dsqlScratch->getAttachment(), dsqlScratch->getTransaction(), statement, dsqlScratch); blockScratch->clientDialect = dsqlScratch->clientDialect; blockScratch->flags |= DsqlCompilerScratch::FLAG_PROCEDURE | DsqlCompilerScratch::FLAG_SUB_ROUTINE; blockScratch->flags |= dsqlScratch->flags & DsqlCompilerScratch::FLAG_DDL; dsqlBlock = dsqlBlock->dsqlPass(blockScratch); - dsqlProcedure = FB_NEW_POOL(pool) dsql_prc(pool); - dsqlProcedure->prc_flags = PRC_subproc; - dsqlProcedure->prc_name.identifier = name; - dsqlProcedure->prc_in_count = USHORT(dsqlBlock->parameters.getCount()); - dsqlProcedure->prc_out_count = USHORT(dsqlBlock->returns.getCount()); - - if (dsqlBlock->parameters.hasData()) - { - Array >& paramArray = dsqlBlock->parameters; - - dsqlProcedure->prc_inputs = paramArray.front()->type; - - for (const NestConst* i = paramArray.begin(); i != paramArray.end(); ++i) - { - const ParameterClause* param = *i; - - if (param->defaultClause) - { - if (dsqlProcedure->prc_def_count == 0) - dsqlProcedure->prc_def_count = paramArray.end() - i; - } - else if (dsqlProcedure->prc_def_count != 0) - { - // Parameter without default value after parameters with default. - ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) << - Arg::Gds(isc_bad_default_value) << - Arg::Gds(isc_invalid_clause) << Arg::Str("defaults must be last")); - } - } - } - - if (dsqlBlock->returns.hasData()) - dsqlProcedure->prc_outputs = dsqlBlock->returns.front()->type; - - dsqlScratch->putSubProcedure(dsqlProcedure); - return this; } void DeclareSubProcNode::genBlr(DsqlCompilerScratch* dsqlScratch) { + if (!dsqlBlock) // forward decl + return; + GEN_request(blockScratch, dsqlBlock); dsqlScratch->appendUChar(blr_subproc_decl); @@ -2636,8 +2755,12 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr if (blrOp == blr_exec_subproc) { DeclareSubProcNode* declareNode; - if (csb->subProcedures.get(name.identifier, declareNode)) - procedure = declareNode->routine; + + for (auto curCsb = csb; curCsb && !procedure; curCsb = curCsb->mainCsb) + { + if (curCsb->subProcedures.get(name.identifier, declareNode)) + procedure = declareNode->routine; + } } else procedure = MET_lookup_procedure(tdbb, name, false); @@ -2669,7 +2792,10 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) dsql_prc* procedure = NULL; if (dsqlName.package.isEmpty()) - procedure = dsqlScratch->getSubProcedure(dsqlName.identifier); + { + DeclareSubProcNode* subProcedure = dsqlScratch->getSubProcedure(dsqlName.identifier); + procedure = subProcedure ? subProcedure->dsqlProcedure : NULL; + } if (!procedure) procedure = METD_get_procedure(dsqlScratch->getTransaction(), dsqlScratch, dsqlName); @@ -2683,10 +2809,7 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) } if (!dsqlScratch->isPsql()) - { - dsqlScratch->procedure = procedure; dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_EXEC_PROCEDURE); - } ExecProcedureNode* node = FB_NEW_POOL(getPool()) ExecProcedureNode(getPool(), dsqlName); node->dsqlProcedure = procedure; @@ -2740,7 +2863,7 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) Arg::Gds(isc_random) << Arg::Str("RETURNING_VALUES")); } - node->outputSources = explodeOutputs(dsqlScratch, dsqlScratch->procedure); + node->outputSources = explodeOutputs(dsqlScratch, procedure); } if (node->outputSources) diff --git a/src/dsql/StmtNodes.h b/src/dsql/StmtNodes.h index 60c0d1f475..b3310b4810 100644 --- a/src/dsql/StmtNodes.h +++ b/src/dsql/StmtNodes.h @@ -420,6 +420,9 @@ public: : TypedNode(pool), name(pool, aName), dsqlDeterministic(false), + dsqlParameters(pool), + dsqlReturns(pool), + dsqlSignature(pool, aName), dsqlBlock(NULL), blockScratch(NULL), dsqlFunction(NULL), @@ -451,6 +454,9 @@ private: public: Firebird::MetaName name; bool dsqlDeterministic; + Firebird::Array > dsqlParameters; + Firebird::Array > dsqlReturns; + Signature dsqlSignature; NestConst dsqlBlock; DsqlCompilerScratch* blockScratch; dsql_udf* dsqlFunction; @@ -467,6 +473,9 @@ public: explicit DeclareSubProcNode(MemoryPool& pool, const Firebird::MetaName& aName) : TypedNode(pool), name(pool, aName), + dsqlParameters(pool), + dsqlReturns(pool), + dsqlSignature(pool, aName), dsqlBlock(NULL), blockScratch(NULL), dsqlProcedure(NULL), @@ -497,6 +506,9 @@ private: public: Firebird::MetaName name; + Firebird::Array > dsqlParameters; + Firebird::Array > dsqlReturns; + Signature dsqlSignature; NestConst dsqlBlock; DsqlCompilerScratch* blockScratch; dsql_prc* dsqlProcedure; diff --git a/src/dsql/dsql.h b/src/dsql/dsql.h index 21ce846320..2e9b801562 100644 --- a/src/dsql/dsql.h +++ b/src/dsql/dsql.h @@ -1000,6 +1000,196 @@ private: int scale; }; +struct SignatureParameter +{ + explicit SignatureParameter(MemoryPool& p) + : type(0), + number(0), + name(p), + fieldSource(p), + fieldName(p), + relationName(p), + charSetName(p), + collationName(p), + subTypeName(p), + mechanism(0) + { + } + + SignatureParameter(MemoryPool& p, const SignatureParameter& o) + : type(o.type), + number(o.number), + name(p, o.name), + fieldSource(p, o.fieldSource), + fieldName(p, o.fieldName), + relationName(p, o.relationName), + charSetName(p, o.charSetName), + collationName(p, o.collationName), + subTypeName(p, o.subTypeName), + collationId(o.collationId), + nullFlag(o.nullFlag), + mechanism(o.mechanism), + fieldLength(o.fieldLength), + fieldScale(o.fieldScale), + fieldType(o.fieldType), + fieldSubType(o.fieldSubType), + fieldSegmentLength(o.fieldSegmentLength), + fieldNullFlag(o.fieldNullFlag), + fieldCharLength(o.fieldCharLength), + fieldCollationId(o.fieldCollationId), + fieldCharSetId(o.fieldCharSetId), + fieldPrecision(o.fieldPrecision) + { + } + + void fromType(const TypeClause* type) + { + fieldType = type->dtype; + fieldScale = type->scale; + subTypeName = type->subTypeName; + fieldSubType = type->subType; + fieldLength = type->length; + fieldCharLength = type->charLength; + charSetName = type->charSet; + fieldCharSetId = type->charSetId; + collationName = type->collate; + fieldCollationId = type->collationId; + fieldSource = type->fieldSource; + fieldName = type->typeOfName; + relationName = type->typeOfTable; + fieldSegmentLength = type->segLength; + fieldPrecision = type->precision; + nullFlag = (SSHORT) type->notNull; + mechanism = (SSHORT) type->fullDomain; + } + + SSHORT type; + SSHORT number; + Firebird::MetaName name; + Firebird::MetaName fieldSource; + Firebird::MetaName fieldName; + Firebird::MetaName relationName; + Firebird::MetaName charSetName; + Firebird::MetaName collationName; + Firebird::MetaName subTypeName; + Nullable collationId; + Nullable nullFlag; + SSHORT mechanism; + Nullable fieldLength; + Nullable fieldScale; + Nullable fieldType; + Nullable fieldSubType; + Nullable fieldSegmentLength; + Nullable fieldNullFlag; + Nullable fieldCharLength; + Nullable fieldCollationId; + Nullable fieldCharSetId; + Nullable fieldPrecision; + + bool operator >(const SignatureParameter& o) const + { + return type > o.type || (type == o.type && number > o.number); + } + + bool operator ==(const SignatureParameter& o) const + { + return type == o.type && number == o.number && name == o.name && + (fieldSource == o.fieldSource || + (fb_utils::implicit_domain(fieldSource.c_str()) && + fb_utils::implicit_domain(o.fieldSource.c_str()))) && + fieldName == o.fieldName && relationName == o.relationName && + collationId == o.collationId && nullFlag == o.nullFlag && + mechanism == o.mechanism && fieldLength == o.fieldLength && + fieldScale == o.fieldScale && fieldType == o.fieldType && + fieldSubType == o.fieldSubType && fieldSegmentLength == o.fieldSegmentLength && + fieldNullFlag == o.fieldNullFlag && fieldCharLength == o.fieldCharLength && + charSetName == o.charSetName && collationName == o.collationName && subTypeName == o.subTypeName && + fieldCollationId == o.fieldCollationId && fieldCharSetId == o.fieldCharSetId && + fieldPrecision == o.fieldPrecision; + } + + bool operator !=(const SignatureParameter& o) const + { + return !(*this == o); + } +}; + +struct Signature +{ + const static unsigned FLAG_DETERMINISTIC = 0x01; + + Signature(MemoryPool& p, const Firebird::MetaName& aName) + : name(p, aName), + parameters(p), + flags(0), + defined(false) + { + } + + explicit Signature(const Firebird::MetaName& aName) + : name(aName), + parameters(*getDefaultMemoryPool()), + flags(0), + defined(false) + { + } + + explicit Signature(MemoryPool& p) + : name(p), + parameters(p), + flags(0), + defined(false) + { + } + + Signature(MemoryPool& p, const Signature& o) + : name(p, o.name), + parameters(p), + flags(o.flags), + defined(o.defined) + { + for (Firebird::SortedObjectsArray::const_iterator i = o.parameters.begin(); + i != o.parameters.end(); + ++i) + { + parameters.add(*i); + } + } + + bool operator >(const Signature& o) const + { + return name > o.name; + } + + bool operator ==(const Signature& o) const + { + if (name != o.name || flags != o.flags || parameters.getCount() != o.parameters.getCount()) + return false; + + for (Firebird::SortedObjectsArray::const_iterator i = parameters.begin(), + j = o.parameters.begin(); + i != parameters.end(); + ++i, ++j) + { + if (*i != *j) + return false; + } + + return true; + } + + bool operator !=(const Signature& o) const + { + return !(*this == o); + } + + Firebird::MetaName name; + Firebird::SortedObjectsArray parameters; + unsigned flags; + bool defined; +}; + + } // namespace /*! \var unsigned DSQL_debug diff --git a/src/dsql/parse-conflicts.txt b/src/dsql/parse-conflicts.txt index e5687e47f2..417d595d60 100644 --- a/src/dsql/parse-conflicts.txt +++ b/src/dsql/parse-conflicts.txt @@ -1 +1 @@ -48 shift/reduce conflicts, 17 reduce/reduce conflicts. +56 shift/reduce conflicts, 17 reduce/reduce conflicts. diff --git a/src/dsql/parse.y b/src/dsql/parse.y index 723b7c2471..c2869ed3fd 100644 --- a/src/dsql/parse.y +++ b/src/dsql/parse.y @@ -2540,7 +2540,7 @@ procedure_clause %type psql_procedure_clause psql_procedure_clause - : procedure_clause_start sql_security_clause AS local_declaration_list full_proc_block + : procedure_clause_start sql_security_clause AS local_declarations_opt full_proc_block { $$ = $1; $$->ssDefiner = $2; @@ -2671,7 +2671,7 @@ function_clause %type psql_function_clause psql_function_clause - : function_clause_start sql_security_clause AS local_declaration_list full_proc_block + : function_clause_start sql_security_clause AS local_declarations_opt full_proc_block { $$ = $1; $$->ssDefiner = $2; @@ -2870,73 +2870,131 @@ package_body_item ; -%type local_declaration_list -local_declaration_list - : /* nothing */ { $$ = NULL; } - | local_declarations +%type local_declarations_opt +local_declarations_opt + : local_forward_declarations_opt local_nonforward_declarations_opt + { + CompoundStmtNode* forward = $1; + CompoundStmtNode* nonForward = $2; + + if (!forward) + $$ = nonForward; + else + { + if (nonForward) + forward->statements.add(nonForward->statements.begin(), nonForward->statements.getCount()); + + $$ = forward; + } + } ; -%type local_declarations -local_declarations - : local_declaration +%type local_forward_declarations_opt +local_forward_declarations_opt + : /* nothing */ { $$ = NULL; } + | local_forward_declarations + ; + +%type local_forward_declarations +local_forward_declarations + : local_forward_declaration { $$ = newNode(); $$->statements.add($1); } - | local_declarations local_declaration + | local_forward_declarations local_forward_declaration { $1->statements.add($2); $$ = $1; } ; -%type local_declaration -local_declaration +%type local_forward_declaration +local_forward_declaration + : local_declaration_subproc_start ';' { $$ = $1; } + | local_declaration_subfunc_start ';' { $$ = $1; } + ; + +%type local_nonforward_declarations_opt +local_nonforward_declarations_opt + : /* nothing */ { $$ = NULL; } + | local_nonforward_declarations + ; + +%type local_nonforward_declarations +local_nonforward_declarations + : local_nonforward_declaration + { + $$ = newNode(); + $$->statements.add($1); + } + | local_nonforward_declarations local_nonforward_declaration + { + $1->statements.add($2); + $$ = $1; + } + ; + +%type local_nonforward_declaration +local_nonforward_declaration : DECLARE var_decl_opt local_declaration_item ';' { $$ = $3; $$->line = YYPOSNARG(1).firstLine; $$->column = YYPOSNARG(1).firstColumn; } - | DECLARE PROCEDURE symbol_procedure_name - { $$ = newNode(); } - input_parameters(NOTRIAL(&$4->parameters)) - output_parameters(NOTRIAL(&$4->returns)) AS - local_declaration_list - full_proc_block + | local_declaration_subproc_start AS local_declarations_opt full_proc_block { - DeclareSubProcNode* node = newNode(*$3); - node->dsqlBlock = $4; - node->dsqlBlock->localDeclList = $8; - node->dsqlBlock->body = $9; + DeclareSubProcNode* node = $1; + node->dsqlBlock = newNode(); + node->dsqlBlock->parameters = node->dsqlParameters; + node->dsqlBlock->returns = node->dsqlReturns; + node->dsqlBlock->localDeclList = $3; + node->dsqlBlock->body = $4; for (FB_SIZE_T i = 0; i < node->dsqlBlock->parameters.getCount(); ++i) node->dsqlBlock->parameters[i]->parameterExpr = make_parameter(); $$ = node; } - | DECLARE FUNCTION symbol_UDF_name - { $$ = newNode(); } - input_parameters(NOTRIAL(&$4->parameters)) - RETURNS domain_or_non_array_type collate_clause deterministic_opt AS - local_declaration_list - full_proc_block + | local_declaration_subfunc_start AS local_declarations_opt full_proc_block { - DeclareSubFuncNode* node = newNode(*$3); - node->dsqlDeterministic = $9; - node->dsqlBlock = $4; - node->dsqlBlock->localDeclList = $11; - node->dsqlBlock->body = $12; + DeclareSubFuncNode* node = $1; + node->dsqlBlock = newNode(); + node->dsqlBlock->parameters = node->dsqlParameters; + node->dsqlBlock->returns = node->dsqlReturns; + node->dsqlBlock->localDeclList = $3; + node->dsqlBlock->body = $4; for (FB_SIZE_T i = 0; i < node->dsqlBlock->parameters.getCount(); ++i) node->dsqlBlock->parameters[i]->parameterExpr = make_parameter(); - node->dsqlBlock->returns.add(newNode($7, optName($8))); - $$ = node; } ; +%type local_declaration_subproc_start +local_declaration_subproc_start + : DECLARE PROCEDURE symbol_procedure_name + { $$ = newNode(NOTRIAL(*$3)); } + input_parameters(NOTRIAL(&$4->dsqlParameters)) + output_parameters(NOTRIAL(&$4->dsqlReturns)) + { $$ = $4; } + ; + +%type local_declaration_subfunc_start +local_declaration_subfunc_start + : DECLARE FUNCTION symbol_UDF_name + { $$ = newNode(NOTRIAL(*$3)); } + input_parameters(NOTRIAL(&$4->dsqlParameters)) + RETURNS domain_or_non_array_type collate_clause deterministic_opt + { + $$ = $4; + $$->dsqlReturns.add(newNode($7, optName($8))); + $$->dsqlDeterministic = $9; + } + ; + %type local_declaration_item local_declaration_item : var_declaration_item @@ -3527,7 +3585,7 @@ exec_block { $$ = newNode(); } block_input_params(NOTRIAL(&$3->parameters)) output_parameters(NOTRIAL(&$3->returns)) AS - local_declaration_list + local_declarations_opt full_proc_block { ExecBlockNode* node = $3; @@ -3598,7 +3656,7 @@ check_opt %type trigger_clause trigger_clause - : create_trigger_start trg_sql_security_clause AS local_declaration_list full_proc_block + : create_trigger_start trg_sql_security_clause AS local_declarations_opt full_proc_block { $$ = $1; $$->ssDefiner = $2; @@ -4245,7 +4303,7 @@ crypt_key_clause($alterDatabaseNode) %type alter_trigger_clause alter_trigger_clause : symbol_trigger_name trigger_active trigger_type_opt trigger_position trg_sql_security_clause - AS local_declaration_list full_proc_block + AS local_declarations_opt full_proc_block { $$ = newNode(*$1); $$->alter = true; @@ -7653,7 +7711,6 @@ system_function_std_syntax | EXP | FLOOR | GEN_UUID - | HASH | LEFT | LN | LOG @@ -7713,6 +7770,14 @@ system_function_special_syntax newNode(MAKE_const_slong($3))->add($5)->add($7)); $$->dsqlSpecialSyntax = true; } + | HASH '(' value ')' + { $$ = newNode(*$1, newNode($3)); } + | HASH '(' value USING valid_symbol_name ')' + { + $$ = newNode(*$1, + newNode($3)->add(MAKE_str_constant(newIntlString($5->c_str()), CS_ASCII))); + $$->dsqlSpecialSyntax = true; + } | OVERLAY '(' value PLACING value FROM value FOR value ')' { $$ = newNode(*$1, diff --git a/src/dsql/pass1.cpp b/src/dsql/pass1.cpp index 74ed71b620..bfc9738d02 100644 --- a/src/dsql/pass1.cpp +++ b/src/dsql/pass1.cpp @@ -367,7 +367,10 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, RecordSourceNode* else if (procNode && (procNode->dsqlName.package.hasData() || procNode->sourceList)) { if (procNode->dsqlName.package.isEmpty()) - procedure = dsqlScratch->getSubProcedure(procNode->dsqlName.identifier); + { + DeclareSubProcNode* subProcedure = dsqlScratch->getSubProcedure(procNode->dsqlName.identifier); + procedure = subProcedure ? subProcedure->dsqlProcedure : NULL; + } if (!procedure) { @@ -390,7 +393,10 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, RecordSourceNode* else { if (procNode && procNode->dsqlName.package.isEmpty()) - procedure = dsqlScratch->getSubProcedure(procNode->dsqlName.identifier); + { + DeclareSubProcNode* subProcedure = dsqlScratch->getSubProcedure(procNode->dsqlName.identifier); + procedure = subProcedure ? subProcedure->dsqlProcedure : NULL; + } if (!procedure) relation = METD_get_relation(dsqlScratch->getTransaction(), dsqlScratch, relation_name); diff --git a/src/include/firebird/FirebirdInterface.idl b/src/include/firebird/FirebirdInterface.idl index 5739224c5b..44c5b7b732 100644 --- a/src/include/firebird/FirebirdInterface.idl +++ b/src/include/firebird/FirebirdInterface.idl @@ -1081,6 +1081,9 @@ interface TraceParams : Versioned { uint getCount(); const dsc* getParam(uint idx); + +version: + const string getTextUTF8(Status status, uint idx); } interface TraceStatement : Versioned diff --git a/src/include/firebird/IdlFbInterfaces.h b/src/include/firebird/IdlFbInterfaces.h index 423c01322f..a6616dd9b7 100644 --- a/src/include/firebird/IdlFbInterfaces.h +++ b/src/include/firebird/IdlFbInterfaces.h @@ -4260,6 +4260,7 @@ namespace Firebird { unsigned (CLOOP_CARG *getCount)(ITraceParams* self) throw(); const dsc* (CLOOP_CARG *getParam)(ITraceParams* self, unsigned idx) throw(); + const char* (CLOOP_CARG *getTextUTF8)(ITraceParams* self, IStatus* status, unsigned idx) throw(); }; protected: @@ -4273,7 +4274,7 @@ namespace Firebird } public: - static const unsigned VERSION = 2; + static const unsigned VERSION = 3; unsigned getCount() { @@ -4286,6 +4287,20 @@ namespace Firebird const dsc* ret = static_cast(this->cloopVTable)->getParam(this, idx); return ret; } + + template const char* getTextUTF8(StatusType* status, unsigned idx) + { + if (cloopVTable->version < 3) + { + StatusType::setVersionError(status, "ITraceParams", cloopVTable->version, 3); + StatusType::checkException(status); + return 0; + } + StatusType::clearException(status); + const char* ret = static_cast(this->cloopVTable)->getTextUTF8(this, status, idx); + StatusType::checkException(status); + return ret; + } }; class ITraceStatement : public IVersioned @@ -14255,6 +14270,7 @@ namespace Firebird this->version = Base::VERSION; this->getCount = &Name::cloopgetCountDispatcher; this->getParam = &Name::cloopgetParamDispatcher; + this->getTextUTF8 = &Name::cloopgetTextUTF8Dispatcher; } } vTable; @@ -14286,6 +14302,21 @@ namespace Firebird return static_cast(0); } } + + static const char* CLOOP_CARG cloopgetTextUTF8Dispatcher(ITraceParams* self, IStatus* status, unsigned idx) throw() + { + StatusType status2(status); + + try + { + return static_cast(self)->Name::getTextUTF8(&status2, idx); + } + catch (...) + { + StatusType::catchException(&status2); + return static_cast(0); + } + } }; template > > @@ -14303,6 +14334,7 @@ namespace Firebird virtual unsigned getCount() = 0; virtual const dsc* getParam(unsigned idx) = 0; + virtual const char* getTextUTF8(StatusType* status, unsigned idx) = 0; }; template diff --git a/src/include/gen/codetext.h b/src/include/gen/codetext.h index 6d1069a761..efc8dab155 100644 --- a/src/include/gen/codetext.h +++ b/src/include/gen/codetext.h @@ -845,6 +845,15 @@ static const struct { {"decfloat_invalid_operation", 335545141}, {"decfloat_overflow", 335545142}, {"decfloat_underflow", 335545143}, + {"subfunc_notdef", 335545144}, + {"subproc_notdef", 335545145}, + {"subfunc_signat", 335545146}, + {"subproc_signat", 335545147}, + {"subfunc_defvaldecl", 335545148}, + {"subproc_defvaldecl", 335545149}, + {"subfunc_not_impl", 335545150}, + {"subproc_not_impl", 335545151}, + {"sysf_invalid_hash_algorithm", 335545152}, {"gfix_db_name", 335740929}, {"gfix_invalid_sw", 335740930}, {"gfix_incmp_sw", 335740932}, diff --git a/src/include/gen/iberror.h b/src/include/gen/iberror.h index 142dd0db2a..e28e087c71 100644 --- a/src/include/gen/iberror.h +++ b/src/include/gen/iberror.h @@ -879,6 +879,15 @@ const ISC_STATUS isc_decfloat_inexact_result = 335545140L; const ISC_STATUS isc_decfloat_invalid_operation = 335545141L; const ISC_STATUS isc_decfloat_overflow = 335545142L; const ISC_STATUS isc_decfloat_underflow = 335545143L; +const ISC_STATUS isc_subfunc_notdef = 335545144L; +const ISC_STATUS isc_subproc_notdef = 335545145L; +const ISC_STATUS isc_subfunc_signat = 335545146L; +const ISC_STATUS isc_subproc_signat = 335545147L; +const ISC_STATUS isc_subfunc_defvaldecl = 335545148L; +const ISC_STATUS isc_subproc_defvaldecl = 335545149L; +const ISC_STATUS isc_subfunc_not_impl = 335545150L; +const ISC_STATUS isc_subproc_not_impl = 335545151L; +const ISC_STATUS isc_sysf_invalid_hash_algorithm = 335545152L; const ISC_STATUS isc_gfix_db_name = 335740929L; const ISC_STATUS isc_gfix_invalid_sw = 335740930L; const ISC_STATUS isc_gfix_incmp_sw = 335740932L; @@ -1353,7 +1362,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L; const ISC_STATUS isc_trace_switch_param_miss = 337182758L; const ISC_STATUS isc_trace_param_act_notcompat = 337182759L; const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L; -const ISC_STATUS isc_err_max = 1297; +const ISC_STATUS isc_err_max = 1306; #else /* c definitions */ @@ -2202,6 +2211,15 @@ const ISC_STATUS isc_err_max = 1297; #define isc_decfloat_invalid_operation 335545141L #define isc_decfloat_overflow 335545142L #define isc_decfloat_underflow 335545143L +#define isc_subfunc_notdef 335545144L +#define isc_subproc_notdef 335545145L +#define isc_subfunc_signat 335545146L +#define isc_subproc_signat 335545147L +#define isc_subfunc_defvaldecl 335545148L +#define isc_subproc_defvaldecl 335545149L +#define isc_subfunc_not_impl 335545150L +#define isc_subproc_not_impl 335545151L +#define isc_sysf_invalid_hash_algorithm 335545152L #define isc_gfix_db_name 335740929L #define isc_gfix_invalid_sw 335740930L #define isc_gfix_incmp_sw 335740932L @@ -2676,7 +2694,7 @@ const ISC_STATUS isc_err_max = 1297; #define isc_trace_switch_param_miss 337182758L #define isc_trace_param_act_notcompat 337182759L #define isc_trace_mandatory_switch_miss 337182760L -#define isc_err_max 1297 +#define isc_err_max 1306 #endif diff --git a/src/include/gen/msgs.h b/src/include/gen/msgs.h index 6fe2b426d3..20b2f0ab2d 100644 --- a/src/include/gen/msgs.h +++ b/src/include/gen/msgs.h @@ -848,6 +848,15 @@ Data source : @4"}, /* eds_statement */ {335545141, "Decimal float invalid operation. An indeterminant error occurred during an operation."}, /* decfloat_invalid_operation */ {335545142, "Decimal float overflow. The exponent of a result is greater than the magnitude allowed."}, /* decfloat_overflow */ {335545143, "Decimal float underflow. The exponent of a result is less than the magnitude allowed."}, /* decfloat_underflow */ + {335545144, "Sub-function @1 has not been defined"}, /* subfunc_notdef */ + {335545145, "Sub-procedure @1 has not been defined"}, /* subproc_notdef */ + {335545146, "Sub-function @1 has a signature mismatch with its forward declaration"}, /* subfunc_signat */ + {335545147, "Sub-procedure @1 has a signature mismatch with its forward declaration"}, /* subproc_signat */ + {335545148, "Default values for parameters are not allowed in definition of the previously declared sub-function @1"}, /* subfunc_defvaldecl */ + {335545149, "Default values for parameters are not allowed in definition of the previously declared sub-procedure @1"}, /* subproc_defvaldecl */ + {335545150, "Sub-function @1 was declared but not implemented"}, /* subfunc_not_impl */ + {335545151, "Sub-procedure @1 was declared but not implemented"}, /* subproc_not_impl */ + {335545152, "Invalid HASH algorithm @1"}, /* sysf_invalid_hash_algorithm */ {335740929, "data base file name (@1) already given"}, /* gfix_db_name */ {335740930, "invalid switch @1"}, /* gfix_invalid_sw */ {335740932, "incompatible switch combination"}, /* gfix_incmp_sw */ @@ -976,7 +985,7 @@ Data source : @4"}, /* eds_statement */ {336068872, "Procedure @1 has not been defined on the package body @2"}, /* dyn_procnotdef_package */ {336068873, "Function @1 has a signature mismatch on package body @2"}, /* dyn_funcsignat_package */ {336068874, "Procedure @1 has a signature mismatch on package body @2"}, /* dyn_procsignat_package */ - {336068875, "Default values for parameters are allowed only in declaration of packaged procedure @1.@2"}, /* dyn_defvaldecl_package_proc */ + {336068875, "Default values for parameters are not allowed in the definition of a previously declared packaged procedure @1.@2"}, /* dyn_defvaldecl_package_proc */ {336068877, "Package body @1 already exists"}, /* dyn_package_body_exists */ {336068878, "Invalid DDL statement for function @1"}, /* dyn_invalid_ddl_func */ {336068879, "Cannot alter new style function @1 with ALTER EXTERNAL FUNCTION. Use ALTER FUNCTION instead."}, /* dyn_newfc_oldsyntax */ @@ -990,7 +999,7 @@ Data source : @4"}, /* eds_statement */ {336068895, "System @1 @2 cannot be modified"}, /* dyn_cant_modify_sysobj */ {336068896, "INCREMENT BY 0 is an illegal option for sequence @1"}, /* dyn_cant_use_zero_increment */ {336068897, "Can't use @1 in FOREIGN KEY constraint"}, /* dyn_cant_use_in_foreignkey */ - {336068898, "Default values for parameters are allowed only in declaration of packaged function @1.@2"}, /* dyn_defvaldecl_package_func */ + {336068898, "Default values for parameters are not allowed in the definition of a previously declared packaged function @1.@2"}, /* dyn_defvaldecl_package_func */ {336068904, "INCREMENT BY 0 is an illegal option for identity column @1 of table @2"}, /* dyn_cant_use_zero_inc_ident */ {336330753, "found unknown switch"}, /* gbak_unknown_switch */ {336330754, "page size parameter missing"}, /* gbak_page_size_missing */ diff --git a/src/include/gen/sql_code.h b/src/include/gen/sql_code.h index fd926c2db2..363b018a4d 100644 --- a/src/include/gen/sql_code.h +++ b/src/include/gen/sql_code.h @@ -844,6 +844,15 @@ static const struct { {335545141, -901}, /* 821 decfloat_invalid_operation */ {335545142, -901}, /* 822 decfloat_overflow */ {335545143, -901}, /* 823 decfloat_underflow */ + {335545144, -901}, /* 824 subfunc_notdef */ + {335545145, -901}, /* 825 subproc_notdef */ + {335545146, -901}, /* 826 subfunc_signat */ + {335545147, -901}, /* 827 subproc_signat */ + {335545148, -901}, /* 828 subfunc_defvaldecl */ + {335545149, -901}, /* 829 subproc_defvaldecl */ + {335545150, -901}, /* 830 subfunc_not_impl */ + {335545151, -901}, /* 831 subproc_not_impl */ + {335545152, -901}, /* 832 sysf_invalid_hash_algorithm */ {335740929, -901}, /* 1 gfix_db_name */ {335740930, -901}, /* 2 gfix_invalid_sw */ {335740932, -901}, /* 4 gfix_incmp_sw */ diff --git a/src/include/gen/sql_state.h b/src/include/gen/sql_state.h index 17bd675509..69949ec9ab 100644 --- a/src/include/gen/sql_state.h +++ b/src/include/gen/sql_state.h @@ -844,6 +844,15 @@ static const struct { {335545141, "22000"}, // 821 decfloat_invalid_operation {335545142, "22003"}, // 822 decfloat_overflow {335545143, "22003"}, // 823 decfloat_underflow + {335545144, "42000"}, // 824 subfunc_notdef + {335545145, "42000"}, // 825 subproc_notdef + {335545146, "42000"}, // 826 subfunc_signat + {335545147, "42000"}, // 827 subproc_signat + {335545148, "42000"}, // 828 subfunc_defvaldecl + {335545149, "42000"}, // 829 subproc_defvaldecl + {335545150, "42000"}, // 830 subfunc_not_impl + {335545151, "42000"}, // 831 subproc_not_impl + {335545152, "42000"}, // 832 sysf_invalid_hash_algorithm {335740929, "00000"}, // 1 gfix_db_name {335740930, "00000"}, // 2 gfix_invalid_sw {335740932, "00000"}, // 4 gfix_incmp_sw diff --git a/src/isql/isql.epp b/src/isql/isql.epp index 0dc1f6bfaa..4a49fbe11e 100644 --- a/src/isql/isql.epp +++ b/src/isql/isql.epp @@ -395,8 +395,7 @@ static processing_state print_performance(const SINT64* perf_before); static void print_message(Firebird::IMessageMetadata* msg, const char* dir); static void process_header(Firebird::IMessageMetadata*, const unsigned pad[], TEXT header[], TEXT header2[]); static void process_plan(); -static SINT64 process_record_count(const int statement_type); -static int process_request_type(); +static SINT64 process_record_count(const unsigned statement_type); static unsigned process_message_display(Firebird::IMessageMetadata* msg, unsigned pad[]); static processing_state process_statement(const TEXT*); #ifdef WIN_NT @@ -2703,7 +2702,7 @@ static processing_state bulk_insert_hack(const char* command) ISQL_warning(fbStatus); // Find out what kind of statement this is - const int statement_type = process_request_type(); + const unsigned statement_type = global_Stmt->getType(fbStatus); if (!statement_type) return ps_ERR; @@ -6982,7 +6981,7 @@ static bool checkSpecial(TEXT* const p, const int length, const double value) if (isnan(value)) t = "NaN"; else if (isinf(value)) - t = "Infinity"; + t = Firebird::isNegativeInf(value) ? "-Infinity" : "Infinity"; else return false; @@ -7705,7 +7704,7 @@ static processing_state print_performance(const SINT64* perf_before) { TEXT report_1[MSG_LENGTH]; IUTILS_msg_get(REPORT_NEW1, report_1); - // Current memory = !\nDelta memory = !\nMax memory = !\nElapsed time= ~ sec\n + // Current memory = !\nDelta memory = !\nMax memory = !\nElapsed time = ~ sec\n diag->assign(report_1); #ifndef WIN_NT @@ -7933,7 +7932,7 @@ static void process_plan() // Get number of records affected for updates, deletions and insertions. // Return -1 if the statement is not one of those or if there's an error // retrieving the information from the server. -static SINT64 process_record_count(const int statement_type) +static SINT64 process_record_count(const unsigned statement_type) { if (!global_Stmt) return -1; @@ -7988,34 +7987,6 @@ static SINT64 process_record_count(const int statement_type) } -// *************************************** -// p r o c e s s _ r e q u e s t _ t y p e -// *************************************** -// Retrieve the statement type according to the DSQL layer. -// A failure is indicated by returning zero. -static int process_request_type() -{ - if (!global_Stmt) - return 0; - const UCHAR sqlda_info[] = { isc_info_sql_stmt_type }; - UCHAR info_buffer[16]; - global_Stmt->getInfo(fbStatus, sizeof(sqlda_info), sqlda_info, sizeof(info_buffer), info_buffer); - if (!ISQL_errmsg(fbStatus)) - { - if (info_buffer[0] == isc_info_sql_stmt_type) - { - const UCHAR* b = info_buffer; - const SSHORT len = gds__vax_integer(b + 1, 2); - return gds__vax_integer(b + 3, len); - } - - //IUTILS_msg_get(UNKNOWN_STATEMENT_TYPE, errmsg); - STDERROUT("Cannot determine statement type"); - } - return 0; -} - - // ********************************************* // p r o c e s s _ m e s s a g e _ d i s p l a y // ********************************************* @@ -8261,7 +8232,7 @@ static processing_state process_statement(const TEXT* str2) setValues.StmtTimeout = 0; // Find out what kind of statement this is - const int statement_type = process_request_type(); + const unsigned statement_type = global_Stmt->getType(fbStatus); if (!statement_type) return ps_ERR; diff --git a/src/isql/isql.h b/src/isql/isql.h index 328754d10b..77014fef22 100644 --- a/src/isql/isql.h +++ b/src/isql/isql.h @@ -140,7 +140,7 @@ const int HLP_QUIT = 40; // QUIT -- Exit program and rollback changes\n\n const int HLP_ALL = 41; // All commands may be abbreviated to letters in CAPs\n const int HLP_SETSCHEMA = 42; // \tSET SCHema/DB -- changes current database\n const int YES_ANS = 43; // Yes -const int REPORT1 = 44; // Current memory = !c\nDelta memory = !d\nMax memory = !x\nElapsed time= !e sec\n +const int REPORT1 = 44; // Current memory = !c\nDelta memory = !d\nMax memory = !x\nElapsed time = !e sec\n #if (defined WIN_NT) const int REPORT2 = 93; // Buffers = !b\nReads = !r\nWrites = !w\nFetches = !f\n #else @@ -255,7 +255,7 @@ const int NO_GRANT_ON_CS = 177; // There is no privilege granted on character const int NO_GRANT_ON_COLL = 178; // There is no privilege granted on collation @1 in this database const int NO_GRANT_ON_PKG = 179; // There is no privilege granted on package @1 in this database const int NO_GRANT_ON_FUN = 180; // There is no privilege granted on function @1 in this database -const int REPORT_NEW1 = 181; // Current memory = !\nDelta memory = !\nMax memory = !\nElapsed time= ~ sec\n +const int REPORT_NEW1 = 181; // Current memory = !\nDelta memory = !\nMax memory = !\nElapsed time = ~ sec\n const int REPORT_NEW2 = 182; // Cpu = ~ sec\n (skipped on windows) const int REPORT_NEW3 = 183; // Buffers = !\nReads = !\nWrites = !\nFetches = !\n const int NO_MAP = 184; // There is no mapping from @1 in this database diff --git a/src/jrd/CryptoManager.cpp b/src/jrd/CryptoManager.cpp index dc0024f990..86aa30d630 100644 --- a/src/jrd/CryptoManager.cpp +++ b/src/jrd/CryptoManager.cpp @@ -395,6 +395,18 @@ namespace Jrd { checkDigitalSignature(tdbb, hdr); } + void CryptoManager::setDbInfo(IDbCryptPlugin* cp) + { + FbLocalStatus status; + cp->setInfo(&status, dbInfo); + if (status->getState() & IStatus::STATE_ERRORS) + { + const ISC_STATUS* v = status->getErrors(); + if (v[0] == isc_arg_gds && v[1] != isc_arg_end && v[1] != isc_interface_version_too_old) + status_exception::raise(&status); + } + } + void CryptoManager::loadPlugin(thread_db* tdbb, const char* pluginName) { if (cryptPlugin) @@ -416,15 +428,7 @@ namespace Jrd { // do not assign cryptPlugin directly before key init complete IDbCryptPlugin* p = cryptControl->plugin(); - - FbLocalStatus status; - p->setInfo(&status, dbInfo); - if (status->getState() & IStatus::STATE_ERRORS) - { - const ISC_STATUS* v = status->getErrors(); - if (v[0] == isc_arg_gds && v[1] != isc_arg_end && v[1] != isc_interface_version_too_old) - status_exception::raise(&status); - } + setDbInfo(p); keyHolderPlugins.init(p, keyName); cryptPlugin = p; @@ -1321,6 +1325,7 @@ namespace Jrd { FbLocalStatus st; AutoPtr crypt(mgr->checkFactory->makeInstance()); + mgr->setDbInfo(crypt); crypt->setKey(&st, keyHolder ? 1 : 0, &keyHolder, keyName.c_str()); if (st.isSuccess()) diff --git a/src/jrd/CryptoManager.h b/src/jrd/CryptoManager.h index 69fef7d79a..ba42533690 100644 --- a/src/jrd/CryptoManager.h +++ b/src/jrd/CryptoManager.h @@ -298,6 +298,7 @@ public: void cryptThread(); bool checkValidation(Firebird::IDbCryptPlugin* crypt); + void setDbInfo(Firebird::IDbCryptPlugin* cp); ULONG getCurrentPage() const; UCHAR getCurrentState() const; diff --git a/src/jrd/RecordSourceNodes.cpp b/src/jrd/RecordSourceNodes.cpp index 9ecb738b8d..7aa18d2404 100644 --- a/src/jrd/RecordSourceNodes.cpp +++ b/src/jrd/RecordSourceNodes.cpp @@ -910,9 +910,13 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch if (blrOp == blr_subproc) { - DeclareSubProcNode* node; - if (csb->subProcedures.get(name.identifier, node)) - procedure = node->routine; + DeclareSubProcNode* declareNode; + + for (auto curCsb = csb; curCsb && !procedure; curCsb = curCsb->mainCsb) + { + if (curCsb->subProcedures.get(name.identifier, declareNode)) + procedure = declareNode->routine; + } } else procedure = MET_lookup_procedure(tdbb, name, false); diff --git a/src/jrd/SysFunction.cpp b/src/jrd/SysFunction.cpp index a72f23bf66..e272e4cd29 100644 --- a/src/jrd/SysFunction.cpp +++ b/src/jrd/SysFunction.cpp @@ -30,6 +30,7 @@ #include "firebird.h" #include "../common/classes/VaryStr.h" +#include "../common/classes/Hash.h" #include "../jrd/SysFunction.h" #include "../jrd/DataTypeUtil.h" #include "../include/fb_blk.h" @@ -100,6 +101,58 @@ enum TrigonFunction }; +struct HashAlgorithmDescriptor +{ + const char* name; + USHORT length; + HashContext* (*create)(MemoryPool&); + + static const HashAlgorithmDescriptor* find(const char* name); +}; + +template +struct HashAlgorithmDescriptorFactory +{ + static HashAlgorithmDescriptor* getInstance(const char* name, USHORT length) + { + desc.name = name; + desc.length = length; + desc.create = createContext; + return &desc; + } + + static HashContext* createContext(MemoryPool& pool) + { + return FB_NEW_POOL(pool) T(pool); + } + + static HashAlgorithmDescriptor desc; +}; + +template HashAlgorithmDescriptor HashAlgorithmDescriptorFactory::desc; + +static const HashAlgorithmDescriptor* hashAlgorithmDescriptors[] = { + HashAlgorithmDescriptorFactory::getInstance("MD5", 16), + HashAlgorithmDescriptorFactory::getInstance("SHA1", 20), + HashAlgorithmDescriptorFactory::getInstance("SHA256", 32), + HashAlgorithmDescriptorFactory::getInstance("SHA512", 64) +}; + +const HashAlgorithmDescriptor* HashAlgorithmDescriptor::find(const char* name) +{ + unsigned count = FB_NELEM(hashAlgorithmDescriptors); + + for (unsigned i = 0; i < count; ++i) + { + if (strcmp(name, hashAlgorithmDescriptors[i]->name) == 0) + return hashAlgorithmDescriptors[i]; + } + + status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << name); + return nullptr; +} + + // constants const int oneDay = 86400; @@ -144,6 +197,7 @@ void makeBinShift(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, d void makeCeilFloor(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeDateAdd(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeGetSetContext(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); +void makeHash(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeLeftRight(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeMod(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); void makeOverlay(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args); @@ -900,6 +954,27 @@ void makeGetSetContext(DataTypeUtilBase* /*dataTypeUtil*/, const SysFunction* fu } +void makeHash(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, + int argsCount, const dsc** args) +{ + fb_assert(argsCount >= function->minArgCount); + + if (argsCount == 1) + makeInt64Result(dataTypeUtil, function, result, argsCount, args); + else if (argsCount >= 2) + { + if (!args[1]->dsc_address || !args[1]->isText()) // not a constant + status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << ""); + + MetaName algorithmName; + MOV_get_metaname(JRD_get_thread_data(), args[1], algorithmName); + + result->makeVarying(HashAlgorithmDescriptor::find(algorithmName.c_str())->length, ttype_binary); + result->setNullable(args[0]->isNullable()); + } +} + + void makeLeftRight(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, int argsCount, const dsc** args) { @@ -2639,7 +2714,7 @@ dsc* evlSetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args, impure_value* impure) { - fb_assert(args.getCount() == 1); + fb_assert(args.getCount() >= 1); jrd_req* request = tdbb->getRequest(); @@ -2647,9 +2722,27 @@ dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args, if (request->req_flags & req_null) // return NULL if value is NULL return NULL; - impure->vlu_misc.vlu_int64 = 0; + AutoPtr hashContext; + MemoryPool& pool = *request->req_pool; - UCHAR* address; + if (args.getCount() >= 2) + { + const dsc* algorithmDesc = EVL_expr(tdbb, request, args[1]); + if (request->req_flags & req_null) // return NULL if algorithm is NULL + return NULL; + + if (!algorithmDesc->isText()) + status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << ""); + + MetaName algorithmName; + MOV_get_metaname(tdbb, algorithmDesc, algorithmName); + hashContext.reset(HashAlgorithmDescriptor::find(algorithmName.c_str())->create(pool)); + } + else + { + hashContext.reset(FB_NEW_POOL(pool) WeakHashContext()); + impure->vlu_misc.vlu_int64 = 0; + } if (value->isBlob()) { @@ -2659,40 +2752,37 @@ dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args, while (!(blob->blb_flags & BLB_eof)) { - address = buffer; - const ULONG length = blob->BLB_get_data(tdbb, address, sizeof(buffer), false); - - for (const UCHAR* end = address + length; address < end; ++address) - { - impure->vlu_misc.vlu_int64 = (impure->vlu_misc.vlu_int64 << 4) + *address; - - const SINT64 n = impure->vlu_misc.vlu_int64 & FB_CONST64(0xF000000000000000); - if (n) - impure->vlu_misc.vlu_int64 ^= n >> 56; - impure->vlu_misc.vlu_int64 &= ~n; - } + const ULONG length = blob->BLB_get_data(tdbb, buffer, sizeof(buffer), false); + hashContext->update(buffer, length); } blob->BLB_close(tdbb); } else { + UCHAR* address; MoveBuffer buffer; const ULONG length = MOV_make_string2(tdbb, value, value->getTextType(), &address, buffer, false); - - for (const UCHAR* end = address + length; address < end; ++address) - { - impure->vlu_misc.vlu_int64 = (impure->vlu_misc.vlu_int64 << 4) + *address; - - const SINT64 n = impure->vlu_misc.vlu_int64 & FB_CONST64(0xF000000000000000); - if (n) - impure->vlu_misc.vlu_int64 ^= n >> 56; - impure->vlu_misc.vlu_int64 &= ~n; - } + hashContext->update(address, length); } - // make descriptor for return value - impure->vlu_desc.makeInt64(0, &impure->vlu_misc.vlu_int64); + HashContext::Buffer resultBuffer; + hashContext->finish(resultBuffer); + + if (args.getCount() >= 2) + { + dsc result; + result.makeText(resultBuffer.getCount(), ttype_binary, resultBuffer.begin()); + EVL_make_value(tdbb, &result, impure); + } + else + { + fb_assert(resultBuffer.getCount() == sizeof(SINT64)); + memcpy(&impure->vlu_misc.vlu_int64, resultBuffer.begin(), sizeof(SINT64)); + + // make descriptor for return value + impure->vlu_desc.makeInt64(0, &impure->vlu_misc.vlu_int64); + } return &impure->vlu_desc; } @@ -4274,7 +4364,7 @@ const SysFunction SysFunction::functions[] = {"EXP", 1, 1, setParamsDblDec, makeDblDecResult, evlExp, NULL}, {"FLOOR", 1, 1, setParamsDblDec, makeCeilFloor, evlFloor, NULL}, {"GEN_UUID", 0, 0, NULL, makeUuid, evlGenUuid, NULL}, - {"HASH", 1, 1, NULL, makeInt64Result, evlHash, NULL}, + {"HASH", 1, 2, NULL, makeHash, evlHash, NULL}, {"LEFT", 2, 2, setParamsSecondInteger, makeLeftRight, evlLeft, NULL}, {"LN", 1, 1, setParamsDblDec, makeDblDecResult, evlLnLog10, (void*) funLnat}, {"LOG", 2, 2, setParamsDblDec, makeDblDecResult, evlLog, NULL}, diff --git a/src/jrd/btr.cpp b/src/jrd/btr.cpp index 97a05f4ff4..ddc45c7ebf 100644 --- a/src/jrd/btr.cpp +++ b/src/jrd/btr.cpp @@ -1754,7 +1754,6 @@ bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, in if ((trans_state == tra_dead) || (trans_state == tra_committed)) { // clean up this left-over index - root = (index_root_page*) CCH_FETCH(tdbb, window, LCK_write, pag_root); irt_desc = root->irt_rpt + id; diff --git a/src/jrd/build_no.h b/src/jrd/build_no.h index a457bfe524..46efe46c1f 100644 --- a/src/jrd/build_no.h +++ b/src/jrd/build_no.h @@ -3,16 +3,16 @@ *** DO NOT EDIT *** TO CHANGE ANY INFORMATION IN HERE PLEASE EDIT src/misc/writeBuildNum.sh - FORMAL BUILD NUMBER:686 + FORMAL BUILD NUMBER:715 */ -#define PRODUCT_VER_STRING "4.0.0.686" -#define FILE_VER_STRING "WI-T4.0.0.686" -#define LICENSE_VER_STRING "WI-T4.0.0.686" -#define FILE_VER_NUMBER 4, 0, 0, 686 +#define PRODUCT_VER_STRING "4.0.0.715" +#define FILE_VER_STRING "WI-T4.0.0.715" +#define LICENSE_VER_STRING "WI-T4.0.0.715" +#define FILE_VER_NUMBER 4, 0, 0, 715 #define FB_MAJOR_VER "4" #define FB_MINOR_VER "0" #define FB_REV_NO "0" -#define FB_BUILD_NO "686" +#define FB_BUILD_NO "715" #define FB_BUILD_TYPE "T" #define FB_BUILD_SUFFIX "Firebird 4.0 Alpha 1" diff --git a/src/jrd/exe.h b/src/jrd/exe.h index f288e44848..bc6f3b5d5f 100644 --- a/src/jrd/exe.h +++ b/src/jrd/exe.h @@ -427,7 +427,7 @@ public: SLONG subNumber; }; - explicit CompilerScratch(MemoryPool& p) + explicit CompilerScratch(MemoryPool& p, CompilerScratch* aMainCsb = NULL) : /*csb_node(0), csb_variables(0), csb_dependencies(0), @@ -439,6 +439,7 @@ public: #ifdef CMP_DEBUG csb_dump(p), #endif + mainCsb(aMainCsb), csb_external(p), csb_access(p), csb_resources(p), @@ -486,6 +487,7 @@ public: Firebird::string csb_dump; #endif + CompilerScratch* mainCsb; Firebird::BlrReader csb_blr_reader; DmlNode* csb_node; ExternalAccessList csb_external; // Access to outside procedures/triggers to be checked diff --git a/src/jrd/idx.cpp b/src/jrd/idx.cpp index 1418e7ea61..f8dbd250bd 100644 --- a/src/jrd/idx.cpp +++ b/src/jrd/idx.cpp @@ -368,7 +368,8 @@ void IDX_create_index(thread_db* tdbb, continue; // If there are any back-versions left make an attempt at intermediate GC. - if (primary.rpb_b_page) { + if (primary.rpb_b_page) + { VIO_intermediate_gc(tdbb, &primary, transaction); if (!DPM_get(tdbb, &primary, LCK_read)) diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 7e0bba6f64..3db974c944 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -6829,9 +6829,8 @@ bool JRD_shutdown_database(Database* dbb, const unsigned flags) CCH_shutdown(tdbb); - if (dbb->dbb_tip_cache) { + if (dbb->dbb_tip_cache) dbb->dbb_tip_cache->finalizeTpc(tdbb); - } if (dbb->dbb_backup_manager) dbb->dbb_backup_manager->shutdown(tdbb); diff --git a/src/jrd/mov.cpp b/src/jrd/mov.cpp index 1b9d85803c..77a73d164f 100644 --- a/src/jrd/mov.cpp +++ b/src/jrd/mov.cpp @@ -176,7 +176,7 @@ void MOV_get_metaname(Jrd::thread_db* tdbb, const dsc* desc, MetaName& name) fb_assert(length && ptr); fb_assert(length <= MAX_SQL_IDENTIFIER_LEN); - fb_assert(ttype == ttype_metadata); + fb_assert(ttype == ttype_ascii || ttype == ttype_metadata); name.assign(reinterpret_cast(ptr), length); } diff --git a/src/jrd/tpc.cpp b/src/jrd/tpc.cpp index e3a959e87f..bf518ffc45 100644 --- a/src/jrd/tpc.cpp +++ b/src/jrd/tpc.cpp @@ -424,7 +424,7 @@ TraNumber TipCache::findLimbo(TraNumber minNumber, TraNumber maxNumber) blockNumber = minNumber / m_transactionsPerBlock; transOffset = minNumber % m_transactionsPerBlock; statusBlock = getTransactionStatusBlock(blockNumber); - } while(!statusBlock); + } while (!statusBlock); for (TraNumber t = minNumber; ; ) { diff --git a/src/jrd/tpc_proto.h b/src/jrd/tpc_proto.h index b0fba4d5d6..327ec46a59 100644 --- a/src/jrd/tpc_proto.h +++ b/src/jrd/tpc_proto.h @@ -287,11 +287,12 @@ private: inline int TPC_cache_state(thread_db* tdbb, TraNumber number) { CommitNumber stateCn = tdbb->getDatabase()->dbb_tip_cache->cacheState(number); - switch(stateCn) { - case CN_ACTIVE: return tra_active; - case CN_LIMBO: return tra_limbo; - case CN_DEAD: return tra_dead; - default: return tra_committed; + switch(stateCn) + { + case CN_ACTIVE: return tra_active; + case CN_LIMBO: return tra_limbo; + case CN_DEAD: return tra_dead; + default: return tra_committed; } } diff --git a/src/jrd/tra.cpp b/src/jrd/tra.cpp index 0ae6e1b81d..e0df3bc7bd 100644 --- a/src/jrd/tra.cpp +++ b/src/jrd/tra.cpp @@ -75,6 +75,7 @@ #include "../jrd/Collation.h" #include "../jrd/Mapping.h" #include "../jrd/DbCreators.h" +#include "../common/os/fbsyslog.h" const int DYN_MSG_FAC = 8; @@ -98,7 +99,6 @@ static tx_inv_page* fetch_inventory_page(thread_db*, WIN* window, ULONG sequence static const char* get_lockname_v3(const UCHAR lock); static ULONG inventory_page(thread_db*, ULONG); static int limbo_transaction(thread_db*, TraNumber id); -static void link_transaction(thread_db*, jrd_tra*); static void restart_requests(thread_db*, jrd_tra*); static void start_sweeper(thread_db*); static THREAD_ENTRY_DECLARE sweep_database(THREAD_ENTRY_PARAM); @@ -672,7 +672,7 @@ void TRA_get_inventory(thread_db* tdbb, UCHAR* bit_vector, TraNumber base, TraNu UCHAR* p = bit_vector; ULONG l = base % trans_per_tip; const UCHAR* q = tip->tip_transactions + TRANS_OFFSET(l); - l = TRANS_OFFSET(MIN((top + 1 + TRA_MASK - base), trans_per_tip - l)); + l = TRANS_OFFSET(MIN((top + TRA_MASK + 1 - base), trans_per_tip - l)); memcpy(p, q, l); p += l; @@ -688,7 +688,7 @@ void TRA_get_inventory(thread_db* tdbb, UCHAR* bit_vector, TraNumber base, TraNu tip = (tx_inv_page*) CCH_HANDOFF(tdbb, &window, inventory_page(tdbb, sequence++), LCK_read, pag_transactions); - l = TRANS_OFFSET(MIN((top + 1 + TRA_MASK - base), trans_per_tip)); + l = TRANS_OFFSET(MIN((top + TRA_MASK + 1 - base), trans_per_tip)); memcpy(p, tip->tip_transactions, l); p += l; } @@ -1177,7 +1177,7 @@ jrd_tra* TRA_reconnect(thread_db* tdbb, const UCHAR* id, USHORT length) trans->tra_number = number; trans->tra_flags |= TRA_prepared | TRA_reconnected | TRA_write; - link_transaction(tdbb, trans); + trans->linkToAttachment(attachment); return trans; } @@ -1300,14 +1300,7 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr // Unlink the transaction from the attachment block - for (jrd_tra** ptr = &attachment->att_transactions; *ptr; ptr = &(*ptr)->tra_next) - { - if (*ptr == transaction) - { - *ptr = transaction->tra_next; - break; - } - } + transaction->unlinkFromAttachment(); // Release transaction's under-modification-rpb list @@ -2386,7 +2379,22 @@ static int limbo_transaction(thread_db* tdbb, TraNumber id) } -static void link_transaction(thread_db* tdbb, jrd_tra* transaction) +void jrd_tra::unlinkFromAttachment() +{ + for (jrd_tra** ptr = &tra_attachment->att_transactions; *ptr; ptr = &(*ptr)->tra_next) + { + if (*ptr == this) + { + *ptr = tra_next; + return; + } + } + + tra_abort("transaction to unlink is missing in the attachment"); +} + + +void jrd_tra::linkToAttachment(Attachment* attachment) { /************************************** * @@ -2398,11 +2406,20 @@ static void link_transaction(thread_db* tdbb, jrd_tra* transaction) * Link transaction block into database attachment. * **************************************/ - SET_TDBB(tdbb); + tra_next = attachment->att_transactions; + attachment->att_transactions = this; +} - Jrd::Attachment* attachment = tdbb->getAttachment(); - transaction->tra_next = attachment->att_transactions; - attachment->att_transactions = transaction; + +void jrd_tra::tra_abort(const char* reason) +{ + string buff; + buff.printf("Failure working with transactions list: %s", reason); + Syslog::Record(Syslog::Error, buff.c_str()); + gds__log(buff.c_str()); +#ifdef DEV_BUILD + abort(); +#endif } @@ -3246,180 +3263,192 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans) // Link the transaction to the attachment block before releasing // header page for handling signals. - link_transaction(tdbb, trans); + trans->linkToAttachment(attachment); + try + { #ifndef SUPERSERVER_V2 - if (!dbb->readOnly()) - CCH_RELEASE(tdbb, &window); + if (!dbb->readOnly()) + CCH_RELEASE(tdbb, &window); #endif - if (dbb->readOnly()) - { - // Set transaction flags to TRA_precommitted, TRA_readonly - trans->tra_flags |= (TRA_readonly | TRA_precommitted); - } - - // Next, take a snapshot of all transactions between the oldest interesting - // transaction and the current. Don't bother to get a snapshot for - // read-committed transactions; they use the snapshot off the dbb block - // since they need to know what is currently committed. - - if (!(trans->tra_flags & TRA_read_committed)) { - trans->tra_snapshot_handle = - dbb->dbb_tip_cache->beginSnapshot(tdbb, - attachment->att_attachment_id, &trans->tra_snapshot_number); - } - - // Next task is to find the oldest active transaction on the system. This - // is needed for garbage collection. Things are made ever so slightly - // more complicated by the fact that existing transaction may have oldest - // actives older than they are. - - Lock temp_lock(tdbb, sizeof(TraNumber), LCK_tra, trans); - - trans->tra_oldest_active = number; - oldest_active = number; - bool cleanup = !(number % TRA_ACTIVE_CLEANUP); - int oldest_state; - - for (; active < number; active++) - { - oldest_state = TPC_cache_state(tdbb, active); - - if (oldest_state == tra_active) + if (dbb->readOnly()) { - temp_lock.setKey(active); - TraNumber data = LCK_read_data(tdbb, &temp_lock); - if (!data) + // Set transaction flags to TRA_precommitted, TRA_readonly + trans->tra_flags |= (TRA_readonly | TRA_precommitted); + } + + // Next, take a snapshot of all transactions between the oldest interesting + // transaction and the current. Don't bother to get a snapshot for + // read-committed transactions; they use the snapshot off the dbb block + // since they need to know what is currently committed. + + if (!(trans->tra_flags & TRA_read_committed)) + { + trans->tra_snapshot_handle = + dbb->dbb_tip_cache->beginSnapshot(tdbb, + attachment->att_attachment_id, &trans->tra_snapshot_number); + } + + // Next task is to find the oldest active transaction on the system. This + // is needed for garbage collection. Things are made ever so slightly + // more complicated by the fact that existing transaction may have oldest + // actives older than they are. + + Lock temp_lock(tdbb, sizeof(TraNumber), LCK_tra, trans); + + trans->tra_oldest_active = number; + oldest_active = number; + bool cleanup = !(number % TRA_ACTIVE_CLEANUP); + int oldest_state; + + for (; active < number; active++) + { + oldest_state = TPC_cache_state(tdbb, active); + + if (oldest_state == tra_active) { - if (cleanup) + temp_lock.setKey(active); + TraNumber data = LCK_read_data(tdbb, &temp_lock); + if (!data) { - if (TRA_wait(tdbb, trans, active, jrd_tra::tra_no_wait) == tra_committed) - cleanup = false; - continue; + if (cleanup) + { + if (TRA_wait(tdbb, trans, active, jrd_tra::tra_no_wait) == tra_committed) + cleanup = false; + continue; + } + + data = active; } - data = active; + oldest_active = active; + break; } - - oldest_active = active; - break; } - } - // Calculate attachment-local oldest active and oldest snapshot numbers - // looking at current attachment's transactions only. Calculated values - // are used to determine garbage collection threshold for attachment-local - // data such as temporary tables (GTT's). + // Calculate attachment-local oldest active and oldest snapshot numbers + // looking at current attachment's transactions only. Calculated values + // are used to determine garbage collection threshold for attachment-local + // data such as temporary tables (GTT's). - trans->tra_att_oldest_active = number; - TraNumber att_oldest_active = number; - TraNumber att_oldest_snapshot = number; + trans->tra_att_oldest_active = number; + TraNumber att_oldest_active = number; + TraNumber att_oldest_snapshot = number; - for (jrd_tra* tx_att = attachment->att_transactions; tx_att; tx_att = tx_att->tra_next) - { - att_oldest_active = MIN(att_oldest_active, tx_att->tra_number); - att_oldest_snapshot = MIN(att_oldest_snapshot, tx_att->tra_att_oldest_active); - } - - trans->tra_att_oldest_active = ((trans->tra_flags & TRA_read_committed) && - !(trans->tra_flags & TRA_read_consistency)) ? number : att_oldest_active; - - if (attachment->att_oldest_snapshot < att_oldest_snapshot) - attachment->att_oldest_snapshot = att_oldest_snapshot; - - // Put the TID of the oldest active transaction (just calculated) - // in the new transaction's lock. - // hvlad: for read-committed transaction put tra_number to prevent - // unnecessary blocking of garbage collection by read-committed - // transactions - - const TraNumber lck_data = ((trans->tra_flags & TRA_read_committed) - && !(trans->tra_flags & TRA_read_consistency)) ? number : oldest_active; - - static_assert(sizeof(lock->lck_data) == sizeof(lck_data), "Check lock data type !"); - if (lock->lck_data != lck_data) - LCK_write_data(tdbb, lock, lck_data); - - // Query the minimum lock data for all active transaction locks. - // This will be the oldest active snapshot used for regulating garbage collection. - - const TraNumber data = LCK_query_data(tdbb, LCK_tra, LCK_MIN); - if (data && data < trans->tra_oldest_active) - trans->tra_oldest_active = data; - - // Finally, scan transactions looking for the oldest interesting transaction -- the oldest - // non-commited transaction. This will not be updated immediately, but saved until the - // next update access to the header page - - oldest_state = tra_committed; - - for (oldest = trans->tra_oldest; oldest < number; oldest++) - { - oldest_state = TPC_cache_state(tdbb, oldest); - if (oldest_state != tra_committed && oldest_state != tra_precommitted) - break; - } - - if (--oldest > dbb->dbb_oldest_transaction) - dbb->dbb_oldest_transaction = oldest; - - if (oldest_active > dbb->dbb_oldest_active) - dbb->dbb_oldest_active = oldest_active; - - if (trans->tra_oldest_active > dbb->dbb_oldest_snapshot) - { - dbb->dbb_oldest_snapshot = trans->tra_oldest_active; - - if (!(dbb->dbb_flags & DBB_gc_active) && (dbb->dbb_flags & DBB_gc_background)) + for (jrd_tra* tx_att = attachment->att_transactions; tx_att; tx_att = tx_att->tra_next) { - dbb->dbb_flags |= DBB_gc_pending; - dbb->dbb_gc_sem.release(); + att_oldest_active = MIN(att_oldest_active, tx_att->tra_number); + att_oldest_snapshot = MIN(att_oldest_snapshot, tx_att->tra_att_oldest_active); + } + + trans->tra_att_oldest_active = ((trans->tra_flags & TRA_read_committed) && + !(trans->tra_flags & TRA_read_consistency)) ? number : att_oldest_active; + + if (attachment->att_oldest_snapshot < att_oldest_snapshot) + attachment->att_oldest_snapshot = att_oldest_snapshot; + + // Put the TID of the oldest active transaction (just calculated) + // in the new transaction's lock. + // hvlad: for read-committed transaction put tra_number to prevent + // unnecessary blocking of garbage collection by read-committed + // transactions + + const TraNumber lck_data = ((trans->tra_flags & TRA_read_committed) + && !(trans->tra_flags & TRA_read_consistency)) ? number : oldest_active; + + static_assert(sizeof(lock->lck_data) == sizeof(lck_data), "Check lock data type !"); + if (lock->lck_data != lck_data) + LCK_write_data(tdbb, lock, lck_data); + + // Query the minimum lock data for all active transaction locks. + // This will be the oldest active snapshot used for regulating garbage collection. + + const TraNumber data = LCK_query_data(tdbb, LCK_tra, LCK_MIN); + if (data && data < trans->tra_oldest_active) + trans->tra_oldest_active = data; + + // Finally, scan transactions looking for the oldest interesting transaction -- the oldest + // non-commited transaction. This will not be updated immediately, but saved until the + // next update access to the header page + + oldest_state = tra_committed; + + for (oldest = trans->tra_oldest; oldest < number; oldest++) + { + oldest_state = TPC_cache_state(tdbb, oldest); + if (oldest_state != tra_committed && oldest_state != tra_precommitted) + break; + } + + if (oldest >= number && dbb->dbb_flags & DBB_read_only) + oldest = number; + + if (--oldest > dbb->dbb_oldest_transaction) + dbb->dbb_oldest_transaction = oldest; + + if (oldest_active > dbb->dbb_oldest_active) + dbb->dbb_oldest_active = oldest_active; + + if (trans->tra_oldest_active > dbb->dbb_oldest_snapshot) + { + dbb->dbb_oldest_snapshot = trans->tra_oldest_active; + + if (!(dbb->dbb_flags & DBB_gc_active) && (dbb->dbb_flags & DBB_gc_background)) + { + dbb->dbb_flags |= DBB_gc_pending; + dbb->dbb_gc_sem.release(); + } + } + + // Release TPC shared memory if counters moved sufficently forward + dbb->dbb_tip_cache->updateOldestTransaction(tdbb, + dbb->dbb_oldest_transaction, dbb->dbb_oldest_snapshot); + + // If the transaction block is getting out of hand, force a sweep + + if (dbb->dbb_sweep_interval && + (trans->tra_oldest_active > oldest) && + (trans->tra_oldest_active - oldest > dbb->dbb_sweep_interval) && + oldest_state != tra_limbo) + { + start_sweeper(tdbb); + } + + // Start a 'transaction-level' savepoint, unless this is the + // system transaction, or unless the transactions doesn't want + // a savepoint to be started. This savepoint will be used to + // undo the transaction if it rolls back. + + if (!(trans->tra_flags & TRA_system) && !(trans->tra_flags & TRA_no_auto_undo)) + trans->startSavepoint(true); + + // if the user asked us to restart all requests in this attachment, + // do so now using the new transaction + + if (trans->tra_flags & TRA_restart_requests) + restart_requests(tdbb, trans); + + // If the transaction is read-only and read committed, it can be + // precommitted because it can't modify any records. + // 2014-08-26 NS XXX: with latest changes in TIP cache semantics and read + // consistency changes precommitted transactions offer almost no benefit, but + // complicate implementation considerably. It might make sense to remove + // precommitted transactions logic completely. + + if ((trans->tra_flags & TRA_readonly) && (trans->tra_flags & TRA_read_committed)) + { + TRA_set_state(tdbb, trans, trans->tra_number, tra_committed); + if (!(trans->tra_flags & TRA_read_consistency)) + LCK_write_data(tdbb, lock, 0); // Fully disinhibit GC for this transaction + trans->tra_flags |= TRA_precommitted; } } - - // Release TPC shared memory if counters moved sufficently forward - dbb->dbb_tip_cache->updateOldestTransaction(tdbb, - dbb->dbb_oldest_transaction, dbb->dbb_oldest_snapshot); - - // If the transaction block is getting out of hand, force a sweep - - if (dbb->dbb_sweep_interval && - (trans->tra_oldest_active > oldest) && - (trans->tra_oldest_active - oldest > dbb->dbb_sweep_interval) && - oldest_state != tra_limbo) + catch (const Firebird::Exception&) { - start_sweeper(tdbb); - } - - // Start a 'transaction-level' savepoint, unless this is the - // system transaction, or unless the transactions doesn't want - // a savepoint to be started. This savepoint will be used to - // undo the transaction if it rolls back. - - if (!(trans->tra_flags & TRA_system) && !(trans->tra_flags & TRA_no_auto_undo)) - trans->startSavepoint(true); - - // if the user asked us to restart all requests in this attachment, - // do so now using the new transaction - - if (trans->tra_flags & TRA_restart_requests) - restart_requests(tdbb, trans); - - // If the transaction is read-only and read committed, it can be - // precommitted because it can't modify any records. - // 2014-08-26 NS XXX: with latest changes in TIP cache semantics and read - // consistency changes precommitted transactions offer almost no benefit, but - // complicate implementation considerably. It might make sense to remove - // precommitted transactions logic completely. - - if ((trans->tra_flags & TRA_readonly) && (trans->tra_flags & TRA_read_committed)) - { - TRA_set_state(tdbb, trans, trans->tra_number, tra_committed); - if (!(trans->tra_flags & TRA_read_consistency)) - LCK_write_data(tdbb, lock, 0); // Fully disinhibit GC for this transaction - trans->tra_flags |= TRA_precommitted; - } + trans->unlinkFromAttachment(); + throw; + } } diff --git a/src/jrd/tra.h b/src/jrd/tra.h index 9f37c5dd43..b2502e14c7 100644 --- a/src/jrd/tra.h +++ b/src/jrd/tra.h @@ -273,7 +273,7 @@ public: TraNumber tra_oldest_active; // record versions older than this can be // gargage-collected by this tx TraNumber tra_att_oldest_active; // oldest active transaction in the same attachment - jrd_tra* tra_next; // next transaction in attachment + jrd_tra* tra_next; // next transaction in attachment MemoryPool* const tra_pool; // pool for transaction Firebird::MemoryStats tra_memory_stats; BlobIndexTree tra_blobs_tree; // list of active blobs @@ -381,6 +381,10 @@ public: return record; } + void unlinkFromAttachment(); + void linkToAttachment(Attachment* attachment); + static void tra_abort(const char* reason); + UserManagement* getUserManagement(); SecDbContext* getSecDbContext(); SecDbContext* setSecDbContext(Firebird::IAttachment* att, Firebird::ITransaction* tra); diff --git a/src/jrd/trace/TraceObjects.cpp b/src/jrd/trace/TraceObjects.cpp index b43e819101..e60508075c 100644 --- a/src/jrd/trace/TraceObjects.cpp +++ b/src/jrd/trace/TraceObjects.cpp @@ -283,6 +283,33 @@ const dsc* TraceSQLStatementImpl::DSQLParamsImpl::getParam(FB_SIZE_T idx) return NULL; } +const char* TraceSQLStatementImpl::DSQLParamsImpl::getTextUTF8(CheckStatusWrapper* status, FB_SIZE_T idx) +{ + const dsc* param = getParam(idx); + UCHAR* address; + + switch (param->dsc_dtype) + { + case dtype_text: + address = param->dsc_address; + break; + + case dtype_varying: + address = param->dsc_address + sizeof(USHORT); + break; + + default: + return NULL; + } + + string src(address); + + if (DataTypeUtil::convertToUTF8(src, temp_utf8_text, param->dsc_sub_type)) + return temp_utf8_text.c_str(); + else + return (const char*)address; +} + /// TraceFailedSQLStatement @@ -310,6 +337,33 @@ const dsc* TraceParamsImpl::getParam(FB_SIZE_T idx) return m_descs->getParam(idx); } +const char* TraceParamsImpl::getTextUTF8(CheckStatusWrapper* status, FB_SIZE_T idx) +{ + const dsc* param = getParam(idx); + UCHAR* address; + + switch (param->dsc_dtype) + { + case dtype_text: + address = param->dsc_address; + break; + + case dtype_varying: + address = param->dsc_address + sizeof(USHORT); + break; + + default: + return NULL; + } + + string src(address); + + if (DataTypeUtil::convertToUTF8(src, temp_utf8_text, param->dsc_sub_type)) + return temp_utf8_text.c_str(); + else + return (const char*)address; +} + /// TraceDscFromValues diff --git a/src/jrd/trace/TraceObjects.h b/src/jrd/trace/TraceObjects.h index aea9e371a1..c10100c2f6 100644 --- a/src/jrd/trace/TraceObjects.h +++ b/src/jrd/trace/TraceObjects.h @@ -206,6 +206,7 @@ private: FB_SIZE_T getCount(); const dsc* getParam(FB_SIZE_T idx); + const char* getTextUTF8(Firebird::CheckStatusWrapper* status, FB_SIZE_T idx); private: void fillParams(); @@ -213,6 +214,7 @@ private: const dsql_req* const m_stmt; const Firebird::Array* m_params; Firebird::HalfStaticArray m_descs; + Firebird::string temp_utf8_text; }; void fillPlan(bool explained); @@ -285,9 +287,11 @@ public: // TraceParams implementation FB_SIZE_T getCount(); const dsc* getParam(FB_SIZE_T idx); + const char* getTextUTF8(Firebird::CheckStatusWrapper* status, FB_SIZE_T idx); private: TraceDescriptors* m_descs; + Firebird::string temp_utf8_text; }; diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index 0765e3720a..6e0d1972f2 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -3869,7 +3869,6 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction, TraceSweepEvent* traceSwee gc->sweptRelation(transaction->tra_oldest_active, relation->rel_id); } - while (VIO_next_record(tdbb, &rpb, transaction, 0, false)) { CCH_RELEASE(tdbb, &rpb.getWindow(tdbb)); @@ -5551,11 +5550,7 @@ static int prepare_update( thread_db* tdbb, int state = TRA_snapshot_state(tdbb, transaction, rpb->rpb_transaction_nr); - // Reset the garbage collect active flag if the transaction state is - // in a terminal state. If committed it must have been a precommitted - // transaction that was backing out a dead record version and the - // system crashed. Clear the flag and set the state to tra_dead to - // reattempt the backout. + // Reset (if appropriate) the garbage collect active flag to reattempt the backout if (rpb->rpb_flags & rpb_gc_active) { diff --git a/src/misc/writeBuildNum.sh b/src/misc/writeBuildNum.sh index b64176978b..a01b4e3135 100755 --- a/src/misc/writeBuildNum.sh +++ b/src/misc/writeBuildNum.sh @@ -9,7 +9,7 @@ BuildType=T MajorVer=4 MinorVer=0 RevNo=0 -BuildNum=686 +BuildNum=715 NowAt=`pwd` cd `dirname $0` diff --git a/src/msgs/facilities2.sql b/src/msgs/facilities2.sql index fe9b3794e2..4cc0705e59 100644 --- a/src/msgs/facilities2.sql +++ b/src/msgs/facilities2.sql @@ -1,7 +1,7 @@ /* MAX_NUMBER is the next number to be used, always one more than the highest message number. */ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?); -- -('2017-05-23 16:08:00', 'JRD', 0, 824) +('2017-07-24 12:10:00', 'JRD', 0, 833) ('2015-03-17 18:33:00', 'QLI', 1, 533) ('2015-01-07 18:01:51', 'GFIX', 3, 134) ('1996-11-07 13:39:40', 'GPRE', 4, 1) diff --git a/src/msgs/messages2.sql b/src/msgs/messages2.sql index 1cc8b62e52..88e363d8c1 100644 --- a/src/msgs/messages2.sql +++ b/src/msgs/messages2.sql @@ -931,6 +931,15 @@ Data source : @4', NULL, NULL) ('decfloat_invalid_operation', 'DecimalContext::checkForExceptions', 'DecFloat.cpp', NULL, 0, 821, NULL, 'Decimal float invalid operation. An indeterminant error occurred during an operation.', NULL, NULL); ('decfloat_overflow', 'DecimalContext::checkForExceptions', 'DecFloat.cpp', NULL, 0, 822, NULL, 'Decimal float overflow. The exponent of a result is greater than the magnitude allowed.', NULL, NULL); ('decfloat_underflow', 'DecimalContext::checkForExceptions', 'DecFloat.cpp', NULL, 0, 823, NULL, 'Decimal float underflow. The exponent of a result is less than the magnitude allowed.', NULL, NULL); +('subfunc_notdef', NULL, 'StmtNodes.cpp', NULL, 0, 824, NULL, 'Sub-function @1 has not been defined', NULL, NULL); +('subproc_notdef', NULL, 'StmtNodes.cpp', NULL, 0, 825, NULL, 'Sub-procedure @1 has not been defined', NULL, NULL); +('subfunc_signat', NULL, 'StmtNodes.cpp', NULL, 0, 826, NULL, 'Sub-function @1 has a signature mismatch with its forward declaration', NULL, NULL); +('subproc_signat', NULL, 'StmtNodes.cpp', NULL, 0, 827, NULL, 'Sub-procedure @1 has a signature mismatch with its forward declaration', NULL, NULL); +('subfunc_defvaldecl', NULL, 'StmtNodes.cpp', NULL, 0, 828, NULL, 'Default values for parameters are not allowed in definition of the previously declared sub-function @1', NULL, NULL); +('subproc_defvaldecl', NULL, 'StmtNodes.cpp', NULL, 0, 829, NULL, 'Default values for parameters are not allowed in definition of the previously declared sub-procedure @1', NULL, NULL); +('subfunc_not_impl', NULL, 'StmtNodes.cpp', NULL, 0, 830, NULL, 'Sub-function @1 was declared but not implemented', NULL, NULL); +('subproc_not_impl', NULL, 'StmtNodes.cpp', NULL, 0, 831, NULL, 'Sub-procedure @1 was declared but not implemented', NULL, NULL); +('sysf_invalid_hash_algorithm', NULL, 'SysFunction.cpp', NULL, 0, 832, NULL, 'Invalid HASH algorithm @1', NULL, NULL); -- QLI (NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL); (NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL); @@ -1981,7 +1990,7 @@ COMMIT WORK; ('dyn_procnotdef_package', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 264, NULL, 'Procedure @1 has not been defined on the package body @2', NULL, NULL); ('dyn_funcsignat_package', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 265, NULL, 'Function @1 has a signature mismatch on package body @2', NULL, NULL); ('dyn_procsignat_package', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 266, NULL, 'Procedure @1 has a signature mismatch on package body @2', NULL, NULL); -('dyn_defvaldecl_package_proc', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 267, NULL, 'Default values for parameters are allowed only in declaration of packaged procedure @1.@2', NULL, NULL); +('dyn_defvaldecl_package_proc', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 267, NULL, 'Default values for parameters are not allowed in the definition of a previously declared packaged procedure @1.@2', NULL, NULL); ('dyn_dup_function', 'DYN_define_function', 'dyn_def.epp', NULL, 8, 268, NULL, 'Function @1 already exists', NULL, NULL); ('dyn_package_body_exists', NULL, 'DdlNodes.epp/PackageNodes.epp', NULL, 8, 269, NULL, 'Package body @1 already exists', NULL, NULL); ('dyn_invalid_ddl_func', 'CreateAlterFunctionNode::compile', 'DdlNodes.epp', NULL, 8, 270, NULL, 'Invalid DDL statement for function @1', NULL, NULL); @@ -2004,7 +2013,7 @@ COMMIT WORK; ('dyn_cant_modify_sysobj', NULL, 'DdlNodes.epp', NULL, 8, 287, NULL, 'System @1 @2 cannot be modified', NULL, 'Ex: System generator rdb$... cannot be modified'); ('dyn_cant_use_zero_increment', NULL, 'DdlNodes.epp', NULL, 8, 288, NULL, 'INCREMENT BY 0 is an illegal option for sequence @1', NULL, NULL); ('dyn_cant_use_in_foreignkey', NULL, 'DdlNodes.epp', NULL, 8, 289, NULL, 'Can''t use @1 in FOREIGN KEY constraint', NULL, NULL); -('dyn_defvaldecl_package_func', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 290, NULL, 'Default values for parameters are allowed only in declaration of packaged function @1.@2', NULL, NULL); +('dyn_defvaldecl_package_func', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 290, NULL, 'Default values for parameters are not allowed in the definition of a previously declared packaged function @1.@2', NULL, NULL); ('dyn_create_user_no_password', 'CreateAlterUserNode', 'DdlNodes.epp', NULL, 8, 291, NULL, 'Password must be specified when creating user', NULL, NULL); ('dyn_cyclic_role', 'GrantRevokeNode::grantRevoke', 'DdlNodes.epp', NULL, 8, 292, NULL, 'role @1 can not be granted to role @2', NULL, NULL); (NULL, 'CreateAlterRoleNode::execute', 'DdlNodes.epp', NULL, 8, 293, NULL, 'DROP SYSTEM PRIVILEGES should not be used in CREATE ROLE operator', NULL, NULL); @@ -2926,7 +2935,7 @@ This message begins with a TAB (''\t'') and ends with a newline (''\n'').', 17, ('REPORT1', 'process_statement', 'isql.e', 'Each of these 4 items is followed by a newline (''\n'').', 17, 44, NULL, 'Current memory = !c Delta memory = !d Max memory = !x -Elapsed time= !e sec +Elapsed time = !e sec ', NULL, NULL); ('REPORT2', 'process_statement', 'isql.e', 'Each of these 5 items is followed by a newline (''\n'').', 17, 45, NULL, 'Cpu = !u sec Buffers = !b @@ -3074,7 +3083,7 @@ Fetches = !f', NULL, NULL); ('REPORT_NEW1', 'print_performance', 'isql.epp', 'Each of these 4 items is followed by a newline (''\n'').', 17, 181, NULL, 'Current memory = ! Delta memory = ! Max memory = ! -Elapsed time= ~ sec +Elapsed time = ~ sec ', NULL, NULL); ('REPORT_NEW2', 'print_performance', 'isql.epp', 'Each of these 5 items is followed by a newline (''\n'').', 17, 182, NULL, 'Cpu = ~ sec ', NULL, NULL); diff --git a/src/msgs/system_errors2.sql b/src/msgs/system_errors2.sql index d8a425cd72..4db7057ec5 100644 --- a/src/msgs/system_errors2.sql +++ b/src/msgs/system_errors2.sql @@ -830,6 +830,15 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA (-901, '22', '000', 0, 821, 'decfloat_invalid_operation', NULL, NULL) (-901, '22', '003', 0, 822, 'decfloat_overflow', NULL, NULL) (-901, '22', '003', 0, 823, 'decfloat_underflow', NULL, NULL) +(-901, '42', '000', 0, 824, 'subfunc_notdef', NULL, NULL) +(-901, '42', '000', 0, 825, 'subproc_notdef', NULL, NULL) +(-901, '42', '000', 0, 826, 'subfunc_signat', NULL, NULL) +(-901, '42', '000', 0, 827, 'subproc_signat', NULL, NULL) +(-901, '42', '000', 0, 828, 'subfunc_defvaldecl', NULL, NULL) +(-901, '42', '000', 0, 829, 'subproc_defvaldecl', NULL, NULL) +(-901, '42', '000', 0, 830, 'subfunc_not_impl', NULL, NULL) +(-901, '42', '000', 0, 831, 'subproc_not_impl', NULL, NULL) +(-901, '42', '000', 0, 832, 'sysf_invalid_hash_algorithm', NULL, NULL) -- GFIX (-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL) (-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL) diff --git a/src/msgs/transmsgs.de_DE2.sql b/src/msgs/transmsgs.de_DE2.sql index 45d4d4e978..7f637833ce 100644 --- a/src/msgs/transmsgs.de_DE2.sql +++ b/src/msgs/transmsgs.de_DE2.sql @@ -2395,7 +2395,7 @@ ERROR: Backup incomplete', NULL, NULL, 12, 229, '#', NULL, NULL, 'truser', '1000 ('Current memory = !c Delta memory = !d Max memory = !x -Elapsed time= !e sec +Elapsed time = !e sec ', NULL, NULL, 17, 44, '#', NULL, NULL, 'truser', '1000-01-01 00:00:00') ('Cpu = !u sec Buffers = !b diff --git a/src/msgs/transmsgs.fr_FR2.sql b/src/msgs/transmsgs.fr_FR2.sql index ef4c079461..881c62afaa 100644 --- a/src/msgs/transmsgs.fr_FR2.sql +++ b/src/msgs/transmsgs.fr_FR2.sql @@ -2395,7 +2395,7 @@ ERROR: Backup incomplete', NULL, NULL, 12, 229, '#', NULL, NULL, 'truser', '1000 ('Current memory = !c Delta memory = !d Max memory = !x -Elapsed time= !e sec +Elapsed time = !e sec ', NULL, NULL, 17, 44, '#', NULL, NULL, 'truser', '1000-01-01 00:00:00') ('Cpu = !u sec Buffers = !b diff --git a/src/utilities/ntrace/TracePluginImpl.cpp b/src/utilities/ntrace/TracePluginImpl.cpp index ce9c50f4ab..c4a05bdaaa 100644 --- a/src/utilities/ntrace/TracePluginImpl.cpp +++ b/src/utilities/ntrace/TracePluginImpl.cpp @@ -46,6 +46,7 @@ #include "../../dsql/sqlda_pub.h" #include "../../common/classes/ImplementHelper.h" #include "../../common/SimpleStatusVector.h" +#include "../../jrd/status.h" using namespace Firebird; using namespace Jrd; @@ -789,19 +790,41 @@ void TracePluginImpl::appendParams(ITraceParams* params) { // Handle potentially long string values case dtype_text: - formatStringArgument(paramvalue, - parameters->dsc_address, parameters->dsc_length); + { + FbLocalStatus status; + const char* text = params->getTextUTF8(&status, i); + + if (status->getState() & IStatus::STATE_ERRORS) + { + formatStringArgument(paramvalue, + parameters->dsc_address, parameters->dsc_length); + } + else + formatStringArgument(paramvalue, (UCHAR*)text, strlen(text)); + break; + } case dtype_cstring: formatStringArgument(paramvalue, parameters->dsc_address, strlen(reinterpret_cast(parameters->dsc_address))); break; case dtype_varying: - formatStringArgument(paramvalue, - parameters->dsc_address + 2, - *(USHORT*)parameters->dsc_address); + { + FbLocalStatus status; + const char* text = params->getTextUTF8(&status, i); + + if (status->getState() & IStatus::STATE_ERRORS) + { + formatStringArgument(paramvalue, + parameters->dsc_address + 2, + *(USHORT*)parameters->dsc_address); + } + else + formatStringArgument(paramvalue, (UCHAR*)text, strlen(text)); + break; + } // Handle quad case dtype_quad: @@ -1497,24 +1520,18 @@ void TracePluginImpl::register_sql_statement(ITraceSQLStatement* statement) if (!sql_length) return; - if (config.include_filter.hasData() || config.exclude_filter.hasData()) + if (config.include_filter.hasData()) { - const char* sqlUtf8 = statement->getTextUTF8(); - FB_SIZE_T utf8_length = fb_strlen(sqlUtf8); + include_matcher->reset(); + include_matcher->process((const UCHAR*)sql, sql_length); + need_statement = include_matcher->result(); + } - if (config.include_filter.hasData()) - { - include_matcher->reset(); - include_matcher->process((const UCHAR*) sqlUtf8, utf8_length); - need_statement = include_matcher->result(); - } - - if (need_statement && config.exclude_filter.hasData()) - { - exclude_matcher->reset(); - exclude_matcher->process((const UCHAR*) sqlUtf8, utf8_length); - need_statement = !exclude_matcher->result(); - } + if (need_statement && config.exclude_filter.hasData()) + { + exclude_matcher->reset(); + exclude_matcher->process((const UCHAR*)sql, sql_length); + need_statement = !exclude_matcher->result(); } if (need_statement)