From e24852d9433d165d04897751549b4a00170e37e9 Mon Sep 17 00:00:00 2001 From: Alexandre Lision <alexandre.lision@savoirfairelinux.com> Date: Tue, 4 Feb 2014 13:13:02 -0500 Subject: [PATCH] * #40116: Switch to 2.3.0 libzrtpcpp version --- jni/Android.mk | 5 +- jni/libzrtp/Android.mk | 134 +- jni/libzrtp/sources/.gitignore | 6 +- jni/libzrtp/sources/CMakeLists.txt | 294 +- jni/libzrtp/sources/COPYING | 829 +++- jni/libzrtp/sources/NEWS | 127 +- jni/libzrtp/sources/README.md | 90 +- jni/libzrtp/sources/bnlib/bn.c | 104 - jni/libzrtp/sources/bnlib/bn.h | 236 - jni/libzrtp/sources/bnlib/bn00.c | 28 - jni/libzrtp/sources/bnlib/bn16.c | 1188 ----- jni/libzrtp/sources/bnlib/bn16.h | 63 - jni/libzrtp/sources/bnlib/bn32.c | 1188 ----- jni/libzrtp/sources/bnlib/bn32.h | 63 - jni/libzrtp/sources/bnlib/bn64.c | 1188 ----- jni/libzrtp/sources/bnlib/bn64.h | 63 - jni/libzrtp/sources/bnlib/bnconfig.h.cmake | 68 - jni/libzrtp/sources/bnlib/bninit16.c | 16 - jni/libzrtp/sources/bnlib/bninit32.c | 16 - jni/libzrtp/sources/bnlib/bninit64.c | 16 - jni/libzrtp/sources/bnlib/bnprint.c | 118 - jni/libzrtp/sources/bnlib/bnprint.h | 35 - jni/libzrtp/sources/bnlib/bnsize00.h | 35 - .../sources/bnlib/ec/curve25519-donna.c | 731 --- jni/libzrtp/sources/bnlib/ec/ec.c | 1695 ------- jni/libzrtp/sources/bnlib/ec/ec.h | 272 -- jni/libzrtp/sources/bnlib/ec/ecdh.c | 42 - jni/libzrtp/sources/bnlib/ec/ecdh.h | 61 - jni/libzrtp/sources/bnlib/germain.c | 608 --- jni/libzrtp/sources/bnlib/germain.h | 8 - jni/libzrtp/sources/bnlib/jacobi.c | 67 - jni/libzrtp/sources/bnlib/jacobi.h | 7 - jni/libzrtp/sources/bnlib/kludge.h | 125 - jni/libzrtp/sources/bnlib/lbn.h | 133 - jni/libzrtp/sources/bnlib/lbn00.c | 24 - jni/libzrtp/sources/bnlib/lbn16.c | 4073 ----------------- jni/libzrtp/sources/bnlib/lbn16.h | 152 - jni/libzrtp/sources/bnlib/lbn32.c | 4073 ----------------- jni/libzrtp/sources/bnlib/lbn32.h | 152 - jni/libzrtp/sources/bnlib/lbn64.c | 4073 ----------------- jni/libzrtp/sources/bnlib/lbn64.h | 152 - jni/libzrtp/sources/bnlib/lbnmem.c | 153 - jni/libzrtp/sources/bnlib/lbnmem.h | 63 - jni/libzrtp/sources/bnlib/legal.c | 380 -- jni/libzrtp/sources/bnlib/legal.h | 11 - jni/libzrtp/sources/bnlib/prime.c | 679 --- jni/libzrtp/sources/bnlib/prime.h | 12 - jni/libzrtp/sources/bnlib/sieve.c | 685 --- jni/libzrtp/sources/bnlib/sieve.h | 23 - .../cmake/Modules/GeneratePackage.cmake | 31 +- jni/libzrtp/sources/common/EventClass.cpp | 197 - jni/libzrtp/sources/common/EventClass.h | 49 - jni/libzrtp/sources/common/MutexClass.cpp | 128 - jni/libzrtp/sources/common/MutexClass.h | 57 - jni/libzrtp/sources/common/Thread.cpp | 1129 ----- jni/libzrtp/sources/common/Thread.h | 315 -- jni/libzrtp/sources/common/osSpecifics.c | 77 - jni/libzrtp/sources/common/osSpecifics.h | 120 - .../sources/cryptcommon/ZrtpRandom.cpp | 161 - jni/libzrtp/sources/cryptcommon/ZrtpRandom.h | 86 - jni/libzrtp/sources/cryptcommon/aes.h | 198 - jni/libzrtp/sources/cryptcommon/aes_modes.c | 946 ---- jni/libzrtp/sources/cryptcommon/aescpp.h | 141 - jni/libzrtp/sources/cryptcommon/aescrypt.c | 294 -- jni/libzrtp/sources/cryptcommon/aeskey.c | 550 --- jni/libzrtp/sources/cryptcommon/aesopt.h | 742 --- jni/libzrtp/sources/cryptcommon/aestab.c | 391 -- jni/libzrtp/sources/cryptcommon/aestab.h | 173 - jni/libzrtp/sources/demo/CMakeLists.txt | 28 +- jni/libzrtp/sources/demo/sdestest.cpp | 231 - jni/libzrtp/sources/demo/zrtptest.cpp | 185 +- jni/libzrtp/sources/demo/zrtptestMulti.cpp | 30 +- jni/libzrtp/sources/doc/Doxymini | 1642 +++---- jni/libzrtp/sources/libzrtpcpp.pc.cmake | 2 +- jni/libzrtp/sources/{zrtp => src}/Base32.cpp | 0 jni/libzrtp/sources/src/CMakeLists.txt | 87 + jni/libzrtp/sources/src/ZIDFile.cpp | 430 ++ .../ZIDRecordFile.cpp => src/ZIDRecord.cpp} | 64 +- jni/libzrtp/sources/{zrtp => src}/ZRtp.cpp | 1163 ++--- .../sources/{zrtp => src}/ZrtpCWrapper.cpp | 26 +- .../{zrtp => src}/ZrtpCallbackWrapper.cpp | 4 +- .../sources/{zrtp => src}/ZrtpConfigure.cpp | 65 +- .../sources/{zrtp => src}/ZrtpCrc32.cpp | 77 +- .../{zrtp => src}/ZrtpPacketClearAck.cpp | 4 +- .../{zrtp => src}/ZrtpPacketCommit.cpp | 4 +- .../{zrtp => src}/ZrtpPacketConf2Ack.cpp | 4 +- .../{zrtp => src}/ZrtpPacketConfirm.cpp | 15 +- .../{zrtp => src}/ZrtpPacketDHPart.cpp | 24 +- .../sources/{zrtp => src}/ZrtpPacketError.cpp | 4 +- .../{zrtp => src}/ZrtpPacketErrorAck.cpp | 4 +- .../{zrtp => src}/ZrtpPacketGoClear.cpp | 0 .../sources/{zrtp => src}/ZrtpPacketHello.cpp | 36 +- .../{zrtp => src}/ZrtpPacketHelloAck.cpp | 4 +- .../sources/{zrtp => src}/ZrtpPacketPing.cpp | 6 +- .../{zrtp => src}/ZrtpPacketPingAck.cpp | 6 +- .../{zrtp => src}/ZrtpPacketRelayAck.cpp | 4 +- .../{zrtp => src}/ZrtpPacketSASrelay.cpp | 4 +- .../sources/{zrtp => src}/ZrtpQueue.cpp | 34 +- .../sources/{zrtp => src}/ZrtpStateClass.cpp | 305 +- jni/libzrtp/sources/src/ZrtpTextData.cpp | 97 + .../sources/{zrtp => src}/libzrtpcpp/Base32.h | 0 .../sources/src/libzrtpcpp/CMakeLists.txt | 9 + .../libzrtpcpp/TimeoutProvider.h} | 160 +- jni/libzrtp/sources/src/libzrtpcpp/ZIDFile.h | 157 + .../libzrtpcpp/ZIDRecord.h} | 83 +- .../sources/{zrtp => src}/libzrtpcpp/ZRtp.h | 267 +- .../{zrtp => src}/libzrtpcpp/ZrtpCWrapper.h | 55 +- .../{zrtp => src}/libzrtpcpp/ZrtpCallback.h | 25 +- .../libzrtpcpp/ZrtpCallbackWrapper.h | 4 +- .../{zrtp => src}/libzrtpcpp/ZrtpCodes.h | 16 +- .../{zrtp => src}/libzrtpcpp/ZrtpConfigure.h | 41 +- .../{zrtp => src}/libzrtpcpp/ZrtpCrc32.h | 4 +- .../{zrtp => src}/libzrtpcpp/ZrtpPacketBase.h | 15 +- .../libzrtpcpp/ZrtpPacketClearAck.h | 4 +- .../libzrtpcpp/ZrtpPacketCommit.h | 18 +- .../libzrtpcpp/ZrtpPacketConf2Ack.h | 4 +- .../libzrtpcpp/ZrtpPacketConfirm.h | 13 +- .../libzrtpcpp/ZrtpPacketDHPart.h | 7 +- .../libzrtpcpp/ZrtpPacketError.h | 8 +- .../libzrtpcpp/ZrtpPacketErrorAck.h | 4 +- .../libzrtpcpp/ZrtpPacketGoClear.h | 0 .../libzrtpcpp/ZrtpPacketHello.h | 23 +- .../libzrtpcpp/ZrtpPacketHelloAck.h | 4 +- .../{zrtp => src}/libzrtpcpp/ZrtpPacketPing.h | 4 +- .../libzrtpcpp/ZrtpPacketPingAck.h | 8 +- .../libzrtpcpp/ZrtpPacketRelayAck.h | 4 +- .../libzrtpcpp/ZrtpPacketSASrelay.h | 13 +- .../{zrtp => src}/libzrtpcpp/ZrtpQueue.h | 43 +- .../{zrtp => src}/libzrtpcpp/ZrtpStateClass.h | 10 +- .../{zrtp => src}/libzrtpcpp/ZrtpStates.h | 4 +- .../{zrtp => src}/libzrtpcpp/ZrtpTextData.h | 18 +- .../libzrtpcpp/ZrtpUserCallback.h | 4 +- .../libzrtpcpp/crypto/TwoCFB.cpp} | 10 +- .../libzrtpcpp/crypto/ZrtpDH.h} | 20 +- .../{zrtp => src/libzrtpcpp}/crypto/aesCFB.h | 6 +- .../crypto/gcrypt/InitializeGcrypt.cpp | 6 +- .../crypto/gcrypt/gcryptAesCFB.cpp | 8 +- .../crypto/gcrypt/gcryptZrtpDH.cpp | 8 +- .../crypto/gcrypt/gcrypthmac256.cpp | 6 +- .../crypto/gcrypt/gcrypthmac384.cpp | 2 +- .../crypto/gcrypt/gcryptsha256.cpp | 6 +- .../crypto/gcrypt/gcryptsha384.cpp | 6 +- .../{zrtp => src/libzrtpcpp}/crypto/hmac256.h | 0 .../{zrtp => src/libzrtpcpp}/crypto/hmac384.h | 0 .../libzrtpcpp/crypto/openssl/AesCFB.cpp} | 6 +- .../crypto/openssl/InitializeOpenSSL.cpp | 4 +- .../libzrtpcpp/crypto/openssl/ZrtpDH.cpp} | 4 +- .../libzrtpcpp}/crypto/openssl/hmac256.cpp | 2 +- .../libzrtpcpp}/crypto/openssl/hmac384.cpp | 6 +- .../libzrtpcpp}/crypto/openssl/sha256.cpp | 2 +- .../libzrtpcpp}/crypto/openssl/sha384.cpp | 2 +- .../{zrtp => src/libzrtpcpp}/crypto/sha256.h | 4 +- .../{zrtp => src/libzrtpcpp}/crypto/sha384.h | 4 +- .../{zrtp => src/libzrtpcpp}/crypto/twoCFB.h | 10 +- .../libzrtpcpp/crypto}/twofish.c | 3475 +++++++------- .../libzrtpcpp/crypto}/twofish.h | 530 +-- .../libzrtpcpp/crypto}/twofish_cfb.c | 176 +- .../{zrtp => src}/libzrtpcpp/zrtpPacket.h | 4 +- .../{zrtp => src}/libzrtpcpp/zrtpccrtp.h | 2 +- jni/libzrtp/sources/srtp/CryptoContext.cpp | 70 +- jni/libzrtp/sources/srtp/CryptoContext.h | 244 +- .../sources/srtp/CryptoContextCtrl.cpp | 62 +- jni/libzrtp/sources/srtp/CryptoContextCtrl.h | 235 +- jni/libzrtp/sources/srtp/SrtpHandler.cpp | 261 -- jni/libzrtp/sources/srtp/SrtpHandler.h | 112 - .../sources/srtp/crypto/SrtpSymCrypto.cpp | 328 -- .../sources/srtp/crypto/SrtpSymCrypto.h | 68 +- .../{cryptcommon => srtp/crypto}/brg_endian.h | 64 +- .../{cryptcommon => srtp/crypto}/brg_types.h | 115 +- .../srtp/crypto/gcrypt/InitializeGcrypt.cpp | 6 +- jni/libzrtp/sources/srtp/crypto/hmac.cpp | 186 - jni/libzrtp/sources/srtp/crypto/hmac.h | 4 +- .../{cryptcommon => srtp/crypto}/macSkein.cpp | 6 +- .../{cryptcommon => srtp/crypto}/macSkein.h | 6 +- .../srtp/crypto/openssl/SrtpSymCrypto.cpp | 19 +- .../sources/srtp/crypto/openssl/hmac.cpp | 8 +- jni/libzrtp/sources/srtp/crypto/sha1.c | 258 -- jni/libzrtp/sources/srtp/crypto/sha1.h | 73 - .../{cryptcommon => srtp/crypto}/skein.c | 4 +- .../{cryptcommon => srtp/crypto}/skein.h | 2 +- .../{cryptcommon => srtp/crypto}/skeinApi.c | 2 +- .../{cryptcommon => srtp/crypto}/skeinApi.h | 16 +- .../crypto}/skein_block.c | 2 +- .../{cryptcommon => srtp/crypto}/skein_iv.h | 2 +- .../{cryptcommon => srtp/crypto}/skein_port.h | 4 +- jni/libzrtp/sources/zrtp/ZIDCacheDb.cpp | 137 - jni/libzrtp/sources/zrtp/ZIDCacheFile.cpp | 249 - jni/libzrtp/sources/zrtp/ZIDRecordDb.cpp | 80 - jni/libzrtp/sources/zrtp/ZrtpSdesStream.cpp | 729 --- jni/libzrtp/sources/zrtp/ZrtpTextData.cpp | 621 --- jni/libzrtp/sources/zrtp/crypto/aesCFB.cpp | 73 - jni/libzrtp/sources/zrtp/crypto/hmac256.cpp | 186 - jni/libzrtp/sources/zrtp/crypto/hmac384.cpp | 186 - jni/libzrtp/sources/zrtp/crypto/sha2.c | 773 ---- jni/libzrtp/sources/zrtp/crypto/sha2.h | 151 - jni/libzrtp/sources/zrtp/crypto/sha256.cpp | 94 - jni/libzrtp/sources/zrtp/crypto/sha384.cpp | 94 - jni/libzrtp/sources/zrtp/crypto/skein256.cpp | 100 - jni/libzrtp/sources/zrtp/crypto/skein256.h | 146 - jni/libzrtp/sources/zrtp/crypto/skein384.cpp | 103 - jni/libzrtp/sources/zrtp/crypto/skein384.h | 146 - .../sources/zrtp/crypto/skeinMac256.cpp | 73 - jni/libzrtp/sources/zrtp/crypto/skeinMac256.h | 91 - .../sources/zrtp/crypto/skeinMac384.cpp | 76 - jni/libzrtp/sources/zrtp/crypto/skeinMac384.h | 91 - jni/libzrtp/sources/zrtp/crypto/zrtpDH.cpp | 532 --- .../sources/zrtp/libzrtpcpp/ZIDCache.h | 175 - .../sources/zrtp/libzrtpcpp/ZIDCacheDb.h | 93 - .../sources/zrtp/libzrtpcpp/ZIDCacheFile.h | 87 - .../sources/zrtp/libzrtpcpp/ZIDRecord.h | 213 - .../sources/zrtp/libzrtpcpp/ZIDRecordDb.h | 279 -- .../sources/zrtp/libzrtpcpp/ZrtpSdesStream.h | 547 --- .../sources/zrtp/libzrtpcpp/zrtpB64Decode.h | 39 - .../sources/zrtp/libzrtpcpp/zrtpB64Encode.h | 42 - .../zrtp/libzrtpcpp/zrtpCacheDbBackend.h | 317 -- jni/libzrtp/sources/zrtp/zrtpB64Decode.c | 88 - jni/libzrtp/sources/zrtp/zrtpB64Encode.c | 116 - .../sources/zrtp/zrtpCacheSqliteBackend.c | 789 ---- 218 files changed, 5956 insertions(+), 43793 deletions(-) delete mode 100644 jni/libzrtp/sources/bnlib/bn.c delete mode 100644 jni/libzrtp/sources/bnlib/bn.h delete mode 100644 jni/libzrtp/sources/bnlib/bn00.c delete mode 100644 jni/libzrtp/sources/bnlib/bn16.c delete mode 100644 jni/libzrtp/sources/bnlib/bn16.h delete mode 100644 jni/libzrtp/sources/bnlib/bn32.c delete mode 100644 jni/libzrtp/sources/bnlib/bn32.h delete mode 100644 jni/libzrtp/sources/bnlib/bn64.c delete mode 100644 jni/libzrtp/sources/bnlib/bn64.h delete mode 100644 jni/libzrtp/sources/bnlib/bnconfig.h.cmake delete mode 100644 jni/libzrtp/sources/bnlib/bninit16.c delete mode 100644 jni/libzrtp/sources/bnlib/bninit32.c delete mode 100644 jni/libzrtp/sources/bnlib/bninit64.c delete mode 100644 jni/libzrtp/sources/bnlib/bnprint.c delete mode 100644 jni/libzrtp/sources/bnlib/bnprint.h delete mode 100644 jni/libzrtp/sources/bnlib/bnsize00.h delete mode 100644 jni/libzrtp/sources/bnlib/ec/curve25519-donna.c delete mode 100644 jni/libzrtp/sources/bnlib/ec/ec.c delete mode 100644 jni/libzrtp/sources/bnlib/ec/ec.h delete mode 100644 jni/libzrtp/sources/bnlib/ec/ecdh.c delete mode 100644 jni/libzrtp/sources/bnlib/ec/ecdh.h delete mode 100644 jni/libzrtp/sources/bnlib/germain.c delete mode 100644 jni/libzrtp/sources/bnlib/germain.h delete mode 100644 jni/libzrtp/sources/bnlib/jacobi.c delete mode 100644 jni/libzrtp/sources/bnlib/jacobi.h delete mode 100644 jni/libzrtp/sources/bnlib/kludge.h delete mode 100644 jni/libzrtp/sources/bnlib/lbn.h delete mode 100644 jni/libzrtp/sources/bnlib/lbn00.c delete mode 100644 jni/libzrtp/sources/bnlib/lbn16.c delete mode 100644 jni/libzrtp/sources/bnlib/lbn16.h delete mode 100644 jni/libzrtp/sources/bnlib/lbn32.c delete mode 100644 jni/libzrtp/sources/bnlib/lbn32.h delete mode 100644 jni/libzrtp/sources/bnlib/lbn64.c delete mode 100644 jni/libzrtp/sources/bnlib/lbn64.h delete mode 100644 jni/libzrtp/sources/bnlib/lbnmem.c delete mode 100644 jni/libzrtp/sources/bnlib/lbnmem.h delete mode 100644 jni/libzrtp/sources/bnlib/legal.c delete mode 100644 jni/libzrtp/sources/bnlib/legal.h delete mode 100644 jni/libzrtp/sources/bnlib/prime.c delete mode 100644 jni/libzrtp/sources/bnlib/prime.h delete mode 100644 jni/libzrtp/sources/bnlib/sieve.c delete mode 100644 jni/libzrtp/sources/bnlib/sieve.h delete mode 100644 jni/libzrtp/sources/common/EventClass.cpp delete mode 100644 jni/libzrtp/sources/common/EventClass.h delete mode 100644 jni/libzrtp/sources/common/MutexClass.cpp delete mode 100644 jni/libzrtp/sources/common/MutexClass.h delete mode 100644 jni/libzrtp/sources/common/Thread.cpp delete mode 100644 jni/libzrtp/sources/common/Thread.h delete mode 100644 jni/libzrtp/sources/common/osSpecifics.c delete mode 100644 jni/libzrtp/sources/common/osSpecifics.h delete mode 100644 jni/libzrtp/sources/cryptcommon/ZrtpRandom.cpp delete mode 100644 jni/libzrtp/sources/cryptcommon/ZrtpRandom.h delete mode 100644 jni/libzrtp/sources/cryptcommon/aes.h delete mode 100644 jni/libzrtp/sources/cryptcommon/aes_modes.c delete mode 100644 jni/libzrtp/sources/cryptcommon/aescpp.h delete mode 100644 jni/libzrtp/sources/cryptcommon/aescrypt.c delete mode 100644 jni/libzrtp/sources/cryptcommon/aeskey.c delete mode 100644 jni/libzrtp/sources/cryptcommon/aesopt.h delete mode 100644 jni/libzrtp/sources/cryptcommon/aestab.c delete mode 100644 jni/libzrtp/sources/cryptcommon/aestab.h delete mode 100644 jni/libzrtp/sources/demo/sdestest.cpp rename jni/libzrtp/sources/{zrtp => src}/Base32.cpp (100%) create mode 100755 jni/libzrtp/sources/src/CMakeLists.txt create mode 100644 jni/libzrtp/sources/src/ZIDFile.cpp rename jni/libzrtp/sources/{zrtp/ZIDRecordFile.cpp => src/ZIDRecord.cpp} (57%) rename jni/libzrtp/sources/{zrtp => src}/ZRtp.cpp (69%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpCWrapper.cpp (94%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpCallbackWrapper.cpp (97%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpConfigure.cpp (82%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpCrc32.cpp (74%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketClearAck.cpp (91%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketCommit.cpp (93%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketConf2Ack.cpp (91%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketConfirm.cpp (84%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketDHPart.cpp (83%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketError.cpp (92%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketErrorAck.cpp (91%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketGoClear.cpp (100%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketHello.cpp (81%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketHelloAck.cpp (91%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketPing.cpp (86%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketPingAck.cpp (87%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketRelayAck.cpp (91%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpPacketSASrelay.cpp (95%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpQueue.cpp (96%) rename jni/libzrtp/sources/{zrtp => src}/ZrtpStateClass.cpp (85%) create mode 100644 jni/libzrtp/sources/src/ZrtpTextData.cpp rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/Base32.h (100%) create mode 100755 jni/libzrtp/sources/src/libzrtpcpp/CMakeLists.txt rename jni/libzrtp/sources/{zrtp/libzrtpcpp/CcrtpTimeoutProvider.h => src/libzrtpcpp/TimeoutProvider.h} (71%) create mode 100644 jni/libzrtp/sources/src/libzrtpcpp/ZIDFile.h rename jni/libzrtp/sources/{zrtp/libzrtpcpp/ZIDRecordFile.h => src/libzrtpcpp/ZIDRecord.h} (81%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZRtp.h (82%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpCWrapper.h (96%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpCallback.h (95%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpCallbackWrapper.h (95%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpCodes.h (90%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpConfigure.h (93%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpCrc32.h (93%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketBase.h (87%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketClearAck.h (92%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketCommit.h (88%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketConf2Ack.h (92%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketConfirm.h (91%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketDHPart.h (93%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketError.h (83%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketErrorAck.h (91%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketGoClear.h (100%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketHello.h (91%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketHelloAck.h (91%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketPing.h (93%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketPingAck.h (87%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketRelayAck.h (91%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpPacketSASrelay.h (86%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpQueue.h (96%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpStateClass.h (97%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpStates.h (94%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpTextData.h (86%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/ZrtpUserCallback.h (95%) rename jni/libzrtp/sources/{zrtp/crypto/twoCFB.cpp => src/libzrtpcpp/crypto/TwoCFB.cpp} (90%) rename jni/libzrtp/sources/{zrtp/crypto/zrtpDH.h => src/libzrtpcpp/crypto/ZrtpDH.h} (95%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/aesCFB.h (91%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/gcrypt/InitializeGcrypt.cpp (96%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/gcrypt/gcryptAesCFB.cpp (89%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/gcrypt/gcryptZrtpDH.cpp (98%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/gcrypt/gcrypthmac256.cpp (92%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/gcrypt/gcrypthmac384.cpp (98%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/gcrypt/gcryptsha256.cpp (93%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/gcrypt/gcryptsha384.cpp (93%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/hmac256.h (100%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/hmac384.h (100%) rename jni/libzrtp/sources/{zrtp/crypto/openssl/aesCFB.cpp => src/libzrtpcpp/crypto/openssl/AesCFB.cpp} (93%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/openssl/InitializeOpenSSL.cpp (97%) rename jni/libzrtp/sources/{zrtp/crypto/openssl/zrtpDH.cpp => src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp} (99%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/openssl/hmac256.cpp (98%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/openssl/hmac384.cpp (92%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/openssl/sha256.cpp (98%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/openssl/sha384.cpp (98%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/sha256.h (97%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/sha384.h (97%) rename jni/libzrtp/sources/{zrtp => src/libzrtpcpp}/crypto/twoCFB.h (88%) rename jni/libzrtp/sources/{cryptcommon => src/libzrtpcpp/crypto}/twofish.c (97%) rename jni/libzrtp/sources/{cryptcommon => src/libzrtpcpp/crypto}/twofish.h (97%) rename jni/libzrtp/sources/{cryptcommon => src/libzrtpcpp/crypto}/twofish_cfb.c (66%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/zrtpPacket.h (98%) rename jni/libzrtp/sources/{zrtp => src}/libzrtpcpp/zrtpccrtp.h (98%) delete mode 100644 jni/libzrtp/sources/srtp/SrtpHandler.cpp delete mode 100644 jni/libzrtp/sources/srtp/SrtpHandler.h delete mode 100644 jni/libzrtp/sources/srtp/crypto/SrtpSymCrypto.cpp rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/brg_endian.h (65%) rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/brg_types.h (55%) delete mode 100644 jni/libzrtp/sources/srtp/crypto/hmac.cpp rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/macSkein.cpp (93%) rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/macSkein.h (96%) delete mode 100644 jni/libzrtp/sources/srtp/crypto/sha1.c delete mode 100644 jni/libzrtp/sources/srtp/crypto/sha1.h rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/skein.c (97%) rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/skein.h (97%) rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/skeinApi.c (99%) rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/skeinApi.h (94%) rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/skein_block.c (97%) rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/skein_iv.h (95%) rename jni/libzrtp/sources/{cryptcommon => srtp/crypto}/skein_port.h (93%) delete mode 100644 jni/libzrtp/sources/zrtp/ZIDCacheDb.cpp delete mode 100644 jni/libzrtp/sources/zrtp/ZIDCacheFile.cpp delete mode 100644 jni/libzrtp/sources/zrtp/ZIDRecordDb.cpp delete mode 100644 jni/libzrtp/sources/zrtp/ZrtpSdesStream.cpp delete mode 100644 jni/libzrtp/sources/zrtp/ZrtpTextData.cpp delete mode 100644 jni/libzrtp/sources/zrtp/crypto/aesCFB.cpp delete mode 100644 jni/libzrtp/sources/zrtp/crypto/hmac256.cpp delete mode 100644 jni/libzrtp/sources/zrtp/crypto/hmac384.cpp delete mode 100644 jni/libzrtp/sources/zrtp/crypto/sha2.c delete mode 100644 jni/libzrtp/sources/zrtp/crypto/sha2.h delete mode 100644 jni/libzrtp/sources/zrtp/crypto/sha256.cpp delete mode 100644 jni/libzrtp/sources/zrtp/crypto/sha384.cpp delete mode 100644 jni/libzrtp/sources/zrtp/crypto/skein256.cpp delete mode 100644 jni/libzrtp/sources/zrtp/crypto/skein256.h delete mode 100644 jni/libzrtp/sources/zrtp/crypto/skein384.cpp delete mode 100644 jni/libzrtp/sources/zrtp/crypto/skein384.h delete mode 100644 jni/libzrtp/sources/zrtp/crypto/skeinMac256.cpp delete mode 100644 jni/libzrtp/sources/zrtp/crypto/skeinMac256.h delete mode 100644 jni/libzrtp/sources/zrtp/crypto/skeinMac384.cpp delete mode 100644 jni/libzrtp/sources/zrtp/crypto/skeinMac384.h delete mode 100644 jni/libzrtp/sources/zrtp/crypto/zrtpDH.cpp delete mode 100644 jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCache.h delete mode 100644 jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheDb.h delete mode 100644 jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheFile.h delete mode 100644 jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecord.h delete mode 100644 jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordDb.h delete mode 100644 jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h delete mode 100644 jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpB64Decode.h delete mode 100644 jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpB64Encode.h delete mode 100644 jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpCacheDbBackend.h delete mode 100644 jni/libzrtp/sources/zrtp/zrtpB64Decode.c delete mode 100644 jni/libzrtp/sources/zrtp/zrtpB64Encode.c delete mode 100644 jni/libzrtp/sources/zrtp/zrtpCacheSqliteBackend.c diff --git a/jni/Android.mk b/jni/Android.mk index d2f25347e..c32c210a9 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -109,6 +109,7 @@ LOCAL_SRC_FILES := \ $(LOCAL_SRC_PATH)/audio/audiortp/audio_rtp_record_handler.cpp \ $(LOCAL_SRC_PATH)/audio/audiortp/audio_rtp_factory.cpp \ $(LOCAL_SRC_PATH)/audio/audiortp/audio_srtp_session.cpp \ + $(LOCAL_SRC_PATH)/audio/audiortp/dtmf_event.cpp \ $(LOCAL_SRC_PATH)/config/sfl_config.cpp \ $(LOCAL_SRC_PATH)/config/yamlemitter.cpp \ $(LOCAL_SRC_PATH)/config/yamlparser.cpp \ @@ -159,8 +160,8 @@ LOCAL_C_INCLUDES += $(LOCAL_SRC_PATH)/.. \ $(MY_SPEEX)/include \ $(MY_LIBYAML)/inc \ $(MY_LIBZRTPCPP) \ - $(MY_LIBZRTPCPP)/zrtp \ - $(MY_LIBZRTPCPP)/zrtp/libzrtpcpp \ + $(MY_LIBZRTPCPP)/src \ + $(MY_LIBZRTPCPP)/src/libzrtpcpp \ $(MY_CCRTP)/src \ $(MY_LIBSAMPLE)/src \ $(MY_OPENSSL)/include \ diff --git a/jni/libzrtp/Android.mk b/jni/libzrtp/Android.mk index 740b64c64..7dc02d21a 100644 --- a/jni/libzrtp/Android.mk +++ b/jni/libzrtp/Android.mk @@ -17,104 +17,62 @@ LOCAL_CPPFLAGS += -fexceptions MY_COMMONCPP = libucommon/sources MY_CCRTP = libccrtp/sources +MY_OPENSSL = libopenssl # include paths for zrtpcpp modules LOCAL_C_INCLUDES += $(ROOT_SRC_PATH) \ $(ROOT_SRC_PATH)/srtp \ - $(ROOT_SRC_PATH)/zrtp \ - $(ROOT_SRC_PATH)/zrtp/libzrtpcpp \ + $(ROOT_SRC_PATH)/src \ + $(ROOT_SRC_PATH)/src/libzrtpcpp \ + $(ROOT_SRC_PATH)/src/libzrtpcpp/openssl \ ${MY_COMMONCPP}/inc \ + $(MY_OPENSSL)/include \ $(MY_CCRTP)/src \ - $(ROOT_SRC_PATH)/bnlib \ - $(ROOT_SRC_PATH)/bnlib/ec -EC_SRCS = $(ROOT_SRC_PATH)/bnlib/ec/ec.c \ - $(ROOT_SRC_PATH)/bnlib/ec/ecdh.c \ - $(ROOT_SRC_PATH)/bnlib/ec/curve25519-donna.c -COMMON_SRCS = $(ROOT_SRC_PATH)/common/osSpecifics.c \ - $(ROOT_SRC_PATH)/common/Thread.cpp \ - $(ROOT_SRC_PATH)/common/MutexClass.cpp \ - $(ROOT_SRC_PATH)/common/EventClass.cpp - -BNLIB_SRCS = $(ROOT_SRC_PATH)/bnlib/bninit64.c \ - $(ROOT_SRC_PATH)/bnlib/legal.c \ - $(ROOT_SRC_PATH)/bnlib/sieve.c \ - $(ROOT_SRC_PATH)/bnlib/bn16.c \ - $(ROOT_SRC_PATH)/bnlib/bn64.c \ - $(ROOT_SRC_PATH)/bnlib/bnprint.c \ - $(ROOT_SRC_PATH)/bnlib/germain.c \ - $(ROOT_SRC_PATH)/bnlib/lbn32.c \ - $(ROOT_SRC_PATH)/bnlib/bninit16.c \ - $(ROOT_SRC_PATH)/bnlib/lbnmem.c \ - $(ROOT_SRC_PATH)/bnlib/prime.c \ - $(ROOT_SRC_PATH)/bnlib/bn32.c \ - $(ROOT_SRC_PATH)/bnlib/bn.c \ - $(ROOT_SRC_PATH)/bnlib/bninit32.c \ - $(ROOT_SRC_PATH)/bnlib/jacobi.c - - -LOCAL_SRC_FILES += $(ROOT_SRC_PATH)/zrtp/ZrtpCallbackWrapper.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZRtp.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpCrc32.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketCommit.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketConf2Ack.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketConfirm.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketDHPart.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketGoClear.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketClearAck.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketHelloAck.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketHello.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketError.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketErrorAck.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketPingAck.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketPing.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketSASrelay.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpPacketRelayAck.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpStateClass.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpTextData.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpConfigure.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpCWrapper.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZrtpQueue.cpp \ - $(ROOT_SRC_PATH)/zrtp/Base32.cpp \ - $(ROOT_SRC_PATH)/zrtp/zrtpB64Encode.c \ - $(ROOT_SRC_PATH)/zrtp/zrtpB64Decode.c \ - $(ROOT_SRC_PATH)/zrtp/ZrtpSdesStream.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZIDRecordDb.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/zrtpDH.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/hmac256.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/sha256.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/hmac384.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/sha384.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/aesCFB.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/twoCFB.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/skein256.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/skeinMac256.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/skein384.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/skeinMac384.cpp \ - $(ROOT_SRC_PATH)/zrtp/crypto/sha2.c \ - $(ROOT_SRC_PATH)/zrtp/ZIDCacheFile.cpp \ - $(ROOT_SRC_PATH)/zrtp/ZIDRecordFile.cpp \ +LOCAL_SRC_FILES += $(ROOT_SRC_PATH)/src/ZrtpCallbackWrapper.cpp \ + $(ROOT_SRC_PATH)/src/ZRtp.cpp \ + $(ROOT_SRC_PATH)/src/ZIDFile.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpCrc32.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketCommit.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketConf2Ack.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketConfirm.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketDHPart.cpp \ + $(ROOT_SRC_PATH)/src/Base32.cpp \ + $(ROOT_SRC_PATH)/src/ZIDRecord.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketGoClear.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketClearAck.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketHelloAck.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketHello.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketError.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketErrorAck.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketPingAck.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketPing.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketSASrelay.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpPacketRelayAck.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpStateClass.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpTextData.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpConfigure.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpCWrapper.cpp \ + $(ROOT_SRC_PATH)/src/ZrtpQueue.cpp \ + $(ROOT_SRC_PATH)/src/libzrtpcpp/crypto/TwoCFB.cpp \ + $(ROOT_SRC_PATH)/src/libzrtpcpp/crypto/twofish_cfb.c \ + $(ROOT_SRC_PATH)/src/libzrtpcpp/crypto/twofish.c \ + $(ROOT_SRC_PATH)/src/libzrtpcpp/crypto/openssl/sha256.cpp \ + $(ROOT_SRC_PATH)/src/libzrtpcpp/crypto/openssl/hmac384.cpp \ + $(ROOT_SRC_PATH)/src/libzrtpcpp/crypto/openssl/hmac256.cpp \ + $(ROOT_SRC_PATH)/src/libzrtpcpp/crypto/openssl/sha384.cpp \ + $(ROOT_SRC_PATH)/src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp \ + $(ROOT_SRC_PATH)/src/libzrtpcpp/crypto/openssl/AesCFB.cpp \ + $(ROOT_SRC_PATH)/srtp/crypto/skein.c \ + $(ROOT_SRC_PATH)/srtp/crypto/skeinApi.c \ + $(ROOT_SRC_PATH)/srtp/crypto/skein_block.c \ + $(ROOT_SRC_PATH)/srtp/crypto/macSkein.cpp \ $(ROOT_SRC_PATH)/srtp/CryptoContext.cpp \ $(ROOT_SRC_PATH)/srtp/CryptoContextCtrl.cpp \ - $(ROOT_SRC_PATH)/srtp/SrtpHandler.cpp \ - $(ROOT_SRC_PATH)/srtp/crypto/hmac.cpp \ - $(ROOT_SRC_PATH)/srtp/crypto/SrtpSymCrypto.cpp \ - $(ROOT_SRC_PATH)/srtp/crypto/sha1.c \ - $(ROOT_SRC_PATH)/cryptcommon/twofish.c \ - $(ROOT_SRC_PATH)/cryptcommon/twofish_cfb.c \ - $(ROOT_SRC_PATH)/cryptcommon/aescrypt.c \ - $(ROOT_SRC_PATH)/cryptcommon/aeskey.c \ - $(ROOT_SRC_PATH)/cryptcommon/aestab.c \ - $(ROOT_SRC_PATH)/cryptcommon/aes_modes.c \ - $(ROOT_SRC_PATH)/cryptcommon/macSkein.cpp \ - $(ROOT_SRC_PATH)/cryptcommon/skein.c \ - $(ROOT_SRC_PATH)/cryptcommon/skein_block.c \ - $(ROOT_SRC_PATH)/cryptcommon/skeinApi.c \ - $(ROOT_SRC_PATH)/cryptcommon/ZrtpRandom.cpp \ - $(EC_SRCS) \ - $(COMMON_SRCS) \ - $(BNLIB_SRCS) + $(ROOT_SRC_PATH)/srtp/crypto/openssl/hmac.cpp \ + $(ROOT_SRC_PATH)/srtp/crypto/openssl/SrtpSymCrypto.cpp \ + LOCAL_STATIC_LIBRARY += libccrtp1 diff --git a/jni/libzrtp/sources/.gitignore b/jni/libzrtp/sources/.gitignore index 4876ff922..ee3d61399 100644 --- a/jni/libzrtp/sources/.gitignore +++ b/jni/libzrtp/sources/.gitignore @@ -1,4 +1,4 @@ -build*/ +build/ autoconf/ doc/html/ configure @@ -16,8 +16,4 @@ aclocal.m4 *.pc *.spec *~ -.DS_Store -._.DS_Store -._buildmac -.directory diff --git a/jni/libzrtp/sources/CMakeLists.txt b/jni/libzrtp/sources/CMakeLists.txt index 8e0bb8031..847717c74 100755 --- a/jni/libzrtp/sources/CMakeLists.txt +++ b/jni/libzrtp/sources/CMakeLists.txt @@ -12,53 +12,13 @@ cmake_minimum_required(VERSION 2.6) PROJECT(libzrtpcpp) -SET(CPACK_PACKAGE_VERSION_MAJOR 4) -SET(CPACK_PACKAGE_VERSION_MINOR 1) -SET(CPACK_PACKAGE_VERSION_PATCH 1) - -set (VERSION 4.1.1) -set (SOVERSION 4) - -# Define supported command line parameters. -# -# Example to build the tivi client: cmake -DTIVI=true .. -# Without any options cmake generates libzrtpcpp for use with GNU ccRTP -# -option(CCRTP "Build library to use with GNU ccRTP." OFF) -option(CORE_LIB "Build core library only, no spcific client support." OFF) -option(CRYPTO_STANDALONE "Use embedded crypto and big number modules." ON) -option(TIVI "Build library for the tivi client, implies '-DCRYPTO_STNDALONE=true'." OFF) -option(SQLITE "Use SQLite DB as backend for ZRTP cache." OFF) -option(SDES "Include SDES when not building for CCRTP." ON) - -option(ANDROID "Generate Android makefiles (Android.mk)" ON) -option(JAVA "Generate Java support files (requires JDK and SWIG)" OFF) - - -# **** Check what and how to build **** -# -if (CCRTP AND TIVI) - MESSAGE(FATAL_ERROR "Cannot build more than one client at once. Use different build directories.") -endif() - -if (CCRTP) - set (PACKAGE libzrtpcpp) - set(zrtplibName zrtpcpp) -elseif (TIVI) - set (PACKAGE libzrtptivi) - set(zrtplibName zrtptivi) - set(CRYPTO_STANDALONE true) - set(SQLITE true) -elseif (CORE_LIB) - set (PACKAGE libzrtpcore) - set(zrtplibName zrtpcppcore) -else() - MESSAGE(WARNING "No client defined, building for GNU ccRTP.") - set (PACKAGE libzrtpcpp) - set(CCRTP true) - set(zrtplibName zrtpcpp) -endif() +SET(CPACK_PACKAGE_VERSION_MAJOR 2) +SET(CPACK_PACKAGE_VERSION_MINOR 3) +SET(CPACK_PACKAGE_VERSION_PATCH 0) +set (VERSION 2.3.0) +set (SOVERSION 2) +set (PACKAGE libzrtpcpp) if(MSVC60) set(BUILD_STATIC ON CACHE BOOL "static linking only" FORCE) @@ -68,18 +28,26 @@ else() endif() # set to true for debug and trace during CMakeLists development -# set(CMAKE_VERBOSE_MAKEFILE TRUE) +set(CMAKE_VERBOSE_MAKEFILE FALSE) -execute_process(COMMAND git rev-parse --short HEAD OUTPUT_VARIABLE GIT_COMMIT) -STRING(REGEX REPLACE "(\r?\n)+$" "" GIT_COMMIT "${GIT_COMMIT}") - -MESSAGE( STATUS "Configuring GNU ${PROJECT_NAME} ${VERSION} for ${PACKAGE}, commit: ${GIT_COMMIT} ...") +MESSAGE( STATUS "Configuring GNU ${PROJECT_NAME} ${VERSION}...") # include most of the fine stuff we need +include(cmake/Modules/FindGcryptConfig.cmake) include(FindPkgConfig) include(CheckLibraryExists) include(CheckIncludeFiles) -include(CheckFunctionExists) +include(cmake/Modules/AutoArgs.cmake) + +if(${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME}) + include(cmake/Modules/GeneratePackage.cmake) + + GENERATE_PACKAGING(${PACKAGE} ${VERSION}) +endif() + +# check the -Denable-ccrtp setting, defaults to true +enable_arg(ccrtp true "Enable GNU ccRTP support for GNU ZRTP") +args_help() if (NOT LIB_SUFFIX) set(LIBDIRNAME "lib") @@ -93,171 +61,107 @@ else() set(LIBDIRNAME "lib${LIB_SUFFIX}") endif() -check_include_files(stdlib.h HAVE_STDLIB_H) -check_include_files(string.h HAVE_STRING_H) +# setup the Thread include and lib +find_package(Threads) +if(CMAKE_HAVE_PTHREAD_H) + set(HAVE_PTHREAD_H TRUE) +endif() +set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT}) + +# define the name of the lib. zrtpcppcore does not include the ccRTP stuff. +set(zrtplib zrtpcppcore) +if(enable_ccrtp) + if (USES_CCRTP_INCLUDE_DIRS) + message(STATUS " Using local commoncpp dependency") + else() + find_package(PkgConfig) + pkg_check_modules(USES_CCRTP libccrtp>=2.0.0) + endif() + include_directories(${USES_CCRTP_INCLUDE_DIRS}) + link_directories(${USES_CRTP_LIBRARY_DIRS}) + add_definitions(${USES_CCRTP_CFLAGS}) + set (LIBS ${LIBS} ${USES_CCRTP_LDFLAGS} ${USES_CCRTP_LIBRARIES}) + set(zrtplib zrtpcpp) +endif() -if (NOT CRYPTO_STANDALONE) - pkg_check_modules(OPENSSL libcrypto>=0.9.8) - if (OPENSSL_FOUND) - set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) #update include files search directory - check_include_files(openssl/bn.h HAVE_OPENSSL_BN_H) - check_include_files(openssl/aes.h HAVE_OPENSSL_AES_H) - check_include_files(openssl/sha.h HAVE_OPENSSL_SHA_H) - check_library_exists(crypto EVP_CipherInit_ex "${OPENSSL_LIBDIR}" HAVE_SSL_CRYPT) #use search lib directory from pkg-config - set(LIBS ${LIBS} -lcrypto) - set(CRYPTOBACKEND "libcrypto >= 0.9.8") - set(BUILD_REQ "libopenssl-devel >= 0.9.8") - set(PACKAGE_REQ "libopenssl >= 0.9.8") - include_directories(${OPENSSL_INCLUDE_DIRS}) #update includes directory from pkg-config +# now get info about crypto libraries +gcr_check(GCRYPT gcrypt) +#if(GCRYPT_FOUND) +# check_include_files(gcrypt.h HAVE_GCRYPT_H) +# set(LIBS ${LIBS} ${GCRYPT_LIBRARIES}) +# set(BUILD_REQ "libgcrypt-devel") +# set(CRYPTOBACKEND="") +# set(PACKAGE_REQ "libgcrypt") +#else() + pkg_check_modules(OPENSSL libcrypto>=0.9.8) + if (OPENSSL_FOUND) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) #update include files search directory + check_include_files(openssl/bn.h HAVE_OPENSSL_BN_H) + check_include_files(openssl/aes.h HAVE_OPENSSL_AES_H) + check_include_files(openssl/sha.h HAVE_OPENSSL_SHA_H) + check_library_exists(crypto EVP_CipherInit_ex "${OPENSSL_LIBDIR}" HAVE_SSL_CRYPT) #use search lib directory from pkg-config + set(LIBS ${LIBS} -lcrypto) + set(CRYPTOBACKEND "libcrypto >= 0.9.8") + set(BUILD_REQ "libopenssl-devel >= 0.9.8") + set(PACKAGE_REQ "libopenssl >= 0.9.8") + include_directories(${OPENSSL_INCLUDE_DIRS}) #update includes directory from pkg-config else() - message(FATAL_ERROR "No crypto library found") + message(FATAL_ERROR "No crypto library found") endif() -else() - # For crypto standalone mode we need to configure the bnlib. In a first step - # without the tests and demos. - check_include_files(stdint.h HAVE_STDINT_H) - check_include_files(stdint.h HAVE_ASSERT_H) - check_include_files(limits.h HAVE_LIMITS_H) - - check_function_exists(memmove HAVE_MEMMOVE) - check_function_exists(memcpy HAVE_MEMCPY) +#endif() - # TODO: check if we compile the tests for bnlib - # - # check_function_exists(clock_gettime HAVE_CLOCK_GETTIME) - # check_function_exists(getrusage HAVE_GETRUSAGE) - # check_function_exists(clock HAVE_CLOCK) - # check_function_exists(time HAVE_TIME) +check_include_files(stdlib.h HAVE_STDLIB_H) +check_include_files(string.h HAVE_STRING_H) - # Check if Solaris-style gethrvtime() is available - # check_function_exists(gethrvtime HAVE_GETHRVTIME) - # - # until here +# necessary and required modules checked, ready to generate config.h +configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) - # necessary and required modules checked, ready to generate config.h - configure_file(${CMAKE_SOURCE_DIR}/bnlib/bnconfig.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/bnconfig.h) -endif() +# the following set(...) commands are only to have backward +# compatibility with autoconf stuff to generate the pc file +set(prefix ${CMAKE_INSTALL_PREFIX}) +set(exec_prefix ${prefix}/bin) +set(libdir ${prefix}/${LIBDIRNAME}) +set(includedir ${prefix}/include) +set(PACKAGE pkgconfig) +configure_file(libzrtpcpp.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/lib${zrtplib}.pc @ONLY) -if (SQLITE) - pkg_check_modules(SQLITE3 sqlite3>=3.7) - if (SQLITE3_FOUND) - check_include_files(sqlite3.h HAVE_SQLITE_H) - set(LIBS ${LIBS} -lsqlite3) - else() - message(FATAL_ERROR "SQLite3 library not found") - endif() -endif() +configure_file(libzrtpcpp.spec.cmake ${CMAKE_CURRENT_BINARY_DIR}/libzrtpcpp.spec @ONLY) -# necessary and required modules checked, ready to generate config.h in top-level build directory -configure_file(config.h.cmake ${CMAKE_BINARY_DIR}/config.h) +#to make sure includes are first taken from those directory +include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) add_definitions(-g -O2 -fno-strict-aliasing) if(CMAKE_COMPILER_IS_GNUCXX) -# add_definitions(-Wno-long-long -Wno-char-subscripts) -# add_definitions(-Wall -ansi -pedantic) -# add_definitions(-Wall -pedantic) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -std=c99") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -std=c++11") - add_definitions(-DNEW_STDCPP) + add_definitions(-Wno-long-long -Wno-char-subscripts) + add_definitions(-Wall -ansi -pedantic) + add_definitions(-DNEW_STDCPP) endif() -include_directories(BEFORE ${CMAKE_BINARY_DIR}) -include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/zrtp) +add_subdirectory(src) -if(CRYPTO_STANDALONE) - add_definitions(-DSUPPORT_NON_NIST) - include_directories (${CMAKE_SOURCE_DIR}/bnlib) +if (enable_ccrtp) + add_subdirectory(demo) endif() -if (SDES AND NOT CCRTP) - set (sdes_src ${CMAKE_SOURCE_DIR}/zrtp/ZrtpSdesStream.cpp) +if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/package/) + MESSAGE(STATUS "package dir not found") + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/package/) endif() -# **** The following source files a common for all clients **** -# -set(zrtp_src_no_cache - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpCallbackWrapper.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZRtp.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpCrc32.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketCommit.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketConf2Ack.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketConfirm.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketDHPart.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketGoClear.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketClearAck.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketHelloAck.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketHello.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketError.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketErrorAck.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketPingAck.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketPing.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketSASrelay.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketRelayAck.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpStateClass.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpTextData.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpConfigure.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZrtpCWrapper.cpp - ${CMAKE_SOURCE_DIR}/zrtp/Base32.cpp - ${CMAKE_SOURCE_DIR}/zrtp/zrtpB64Encode.c - ${CMAKE_SOURCE_DIR}/zrtp/zrtpB64Decode.c - ${CMAKE_SOURCE_DIR}/common/osSpecifics.c ${sdes_src}) - -set(bnlib_src - ${CMAKE_SOURCE_DIR}/bnlib/bn00.c - ${CMAKE_SOURCE_DIR}/bnlib/lbn00.c - ${CMAKE_SOURCE_DIR}/bnlib/bn.c - ${CMAKE_SOURCE_DIR}/bnlib/lbnmem.c - ${CMAKE_SOURCE_DIR}/bnlib/sieve.c - ${CMAKE_SOURCE_DIR}/bnlib/prime.c - ${CMAKE_SOURCE_DIR}/bnlib/bnprint.c - ${CMAKE_SOURCE_DIR}/bnlib/jacobi.c - ${CMAKE_SOURCE_DIR}/bnlib/germain.c - ${CMAKE_SOURCE_DIR}/bnlib/ec/ec.c - ${CMAKE_SOURCE_DIR}/bnlib/ec/ecdh.c - ${CMAKE_SOURCE_DIR}/bnlib/ec/curve25519-donna.c) +########### install files ############### +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${zrtplib}.pc DESTINATION ${LIBDIRNAME}/pkgconfig) -set(zrtp_skein_src - ${CMAKE_SOURCE_DIR}/zrtp/crypto/skeinMac256.cpp - ${CMAKE_SOURCE_DIR}/zrtp/crypto/skein256.cpp - ${CMAKE_SOURCE_DIR}/zrtp/crypto/skeinMac384.cpp - ${CMAKE_SOURCE_DIR}/zrtp/crypto/skein384.cpp) +if(${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME}) -set(zrtp_crypto_src - ${CMAKE_SOURCE_DIR}/zrtp/crypto/zrtpDH.cpp - ${CMAKE_SOURCE_DIR}/zrtp/crypto/hmac256.cpp - ${CMAKE_SOURCE_DIR}/zrtp/crypto/sha256.cpp - ${CMAKE_SOURCE_DIR}/zrtp/crypto/hmac384.cpp - ${CMAKE_SOURCE_DIR}/zrtp/crypto/sha384.cpp + ########### Add uninstall target ############### + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + add_custom_target(uninstall + "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") - ${CMAKE_SOURCE_DIR}/zrtp/crypto/aesCFB.cpp - ${CMAKE_SOURCE_DIR}/zrtp/crypto/twoCFB.cpp - ${CMAKE_SOURCE_DIR}/zrtp/crypto/sha2.c) - -if (NOT SQLITE) - set(zrtp_src ${zrtp_src_no_cache} - ${CMAKE_SOURCE_DIR}/zrtp/ZIDCacheFile.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZIDRecordFile.cpp) -else() - set(zrtp_src ${zrtp_src_no_cache} - ${CMAKE_SOURCE_DIR}/zrtp/ZIDCacheDb.cpp - ${CMAKE_SOURCE_DIR}/zrtp/ZIDRecordDb.cpp - ${CMAKE_SOURCE_DIR}/zrtp/zrtpCacheSqliteBackend.c) - -endif() - -if (CCRTP) - add_subdirectory(clients/ccrtp) - add_subdirectory(demo) endif() - -if (TIVI) - add_subdirectory(clients/tivi) -endif() - -if (CORE_LIB) - add_subdirectory(clients/no_client) -endif() - ##very usefull for macosx, specially when using gtkosx bundler if(APPLE) if (NOT CMAKE_INSTALL_NAME_DIR) diff --git a/jni/libzrtp/sources/COPYING b/jni/libzrtp/sources/COPYING index 02bbb60bc..443254047 100644 --- a/jni/libzrtp/sources/COPYING +++ b/jni/libzrtp/sources/COPYING @@ -1,165 +1,676 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. \ No newline at end of file diff --git a/jni/libzrtp/sources/NEWS b/jni/libzrtp/sources/NEWS index f2b72e684..6224923ad 100755 --- a/jni/libzrtp/sources/NEWS +++ b/jni/libzrtp/sources/NEWS @@ -1,128 +1,3 @@ -== GNU ZRTP 4.1.1 == - -Is a bug fix release that fixes some problems when building a standalone -version of the library, i.e. with embedded crypto algorithms and not using -on openSSL. - -Another fix was necessary for NetBSD thread handling. - - -== GNU ZRTP 4.1.0 == - -Small enhancements when dealing with non-NIST algorithms. An application may -set a ''algorithm selection policy'' to control the selection behaviour. In -addition the the standrad selection policy (as per RFC6189) this version -provides a _non-NIST_ selection policy: if the selected public key algorithm -is a non-NIST ECC algorithm then the other selection functions prefer non-NIST -HASH algorithms (Skein etc). - - -== GNU ZRTP 4.0.0 == - -For this version I added some new algorithms for the DH key agreement -and the Skein Hash for ZRTP. Not further functional enhancments. - -Added a new (old) build parameter -DCORE_LIB that will build a ZRTP core -library. This was available in V2.3 but I somehow lost this for 3.0 -You may add other build parameters, such as SQLITE and CRYPTO_STANDALONE -if you build the core library. - - -== GNU ZRTP 3.2.0 == - -The main ZRTP modules contain fixes for three vulnerabilities found by Mark -Dowd. Thus we advise application developers to use this version of the -library. The vulnerabilities may lead to application crashes during ZRTP -negotiation if an attacker sends prepared ZRTP packets. The fixes remove these -attack vectors. - -Some small other enhancements and cleanup, mainly inside client code. - -Some enhancements in cache handling and the handling of retained shared -secrets. This change was proposed by Phil, is a slight security enhacement and -is fully backward comaptible. - -Because of some API changes clients must be compiled and linked with the new -library. - -For details please refer to the Git logs. - - -== GNU ZRTP 3.1.0 == - -This version adds some new features and code that supports some other -client and this accounts for the most changes inside this release. - -The ZRTP core functionality was not changed as much (bug fixes, cleanup -mainly) and remains fully backward compatible with older library -versions. However, one nice enhancement was done: the addition of a standalone -SDES support module. This module supports basic SDES only without the fancy -stuff like many other SDES implementations. Thus it's pretty interoperable. - -Some other features are: -- add some android support for a client, may serve as template for others -- documentation and code cleanup - -Because of some API changes clients must be compiled and linked with the new -library. - - -== GNU ZRTP 3.0.0 == - -This is a major enhancement and restructuring of the overall ZRTP -distribution. This was necessary because more and more other clients use ZRTP -and add their specific glue code. Also some clients are not prepared to use -openSSL or other crypto libraries to their code and distributions. - -Here a summary of the changes -- a new directory layout to accomodate various clients -- add standalone crypto modules, for example for AES, to have a real - standalone ZRTP/SRTP library that does not require any other crypto library - (optional via CMake configuration) -- Re-structure ZRTP cache and add SQlite3 as optional storage backend - -The default settings for CMake build the normal ZRTP library that use openSSL -as crypto backend, use the normal file based cache and include the GNU ccRTP -modules. This is a librray that is to a large degree compatible with the -earlier builds. - -Please refer to the top level CMakeFile.txt for options how to switch on the -standalone crypto mode or the SQlite3 based cache storage. - - -== GNU ZRTP 2.3.0 == - -Add a "paranoid" mode to ZRTP. If and applications switches to this mode then -the ZRTP stack _always_ asks the user to confirm the SAS thus ZRTP behaves as -if it does not have a cache to store the retained secrets. However, setting -the paranoid mode does not diable the cache, only the GUI behaviour. - -Enhance the CMake scripts to build a ZRTP library that does not contain GNU -ccRTP modules and does not require ccRTP dependencies. - -== GNU ZRTP 2.2.0 == - -Add stubs, callbacks and other provisions to prepare the full implementation -of the SAS signing feature, see RFC6189, section 7.2. This feature needs -support from applications and is rarely used if at all. - -As usual smaller fixes, code clean up etc. - -Because of some API changes clients must be compiled and linked with the new -library. - -== GNU ZRTP 2.1.2 == - -The main topic of this release was to add SRTCP support and some missing -optional features of ZRTP. - -As such I've added some new API and classes that applications may use to add -SRTCP or to use the new ZRTP features. the ZRTP stack now supports PBX -handling, refer to RFC6189 section 7.3ff. - -Because of some API changes clients must be compiled and linked with the new -library. - == GNU ZRTP 2.0.0 == Modify some files to use the new uCommon/commoncpp libraries instead @@ -275,7 +150,7 @@ not support this additional secret anymore. The method ''setOtherSecret(...)'' was renamed to ''setPbxSecret(...)'' to reflect the modification in the draft. -The method ''setSrtpsSecret(...)'' was renamed to ''setAuxSecret(...)'' +The methos ''setSrtpsSecret(...)'' is was renamed to ''setAuxSecret(...)'' to reflect the modification in the draft. diff --git a/jni/libzrtp/sources/README.md b/jni/libzrtp/sources/README.md index f7b996685..cac0592e0 100644 --- a/jni/libzrtp/sources/README.md +++ b/jni/libzrtp/sources/README.md @@ -1,49 +1,29 @@ ## GNU ZRTP C++ This package provides a library that adds ZRTP support to the GNU -ccRTP stack and serves as library for other RTP stacks (PJSIP, GStreamer). -Phil Zimmermann developed ZRTP to allow ad-hoc, easy to +ccRTP stack. Phil Zimmermann developed ZRTP to allow ad-hoc, easy to use key negotiation to setup Secure RTP (SRTP) sessions. GNU ZRTP works together with GNU ccRTP (1.5.0 or later) and provides a ZRTP implementation that can be directly embedded into client and server applications. -The GNU ZRTP implementation is compliant to [RFC 6189][] and adds some more -algorithms. Currently GNU ZRTP C++ supports the following features: +The GNU ZRTP implementation is compliant to [RFC 6189][]. Currently GNU ZRTP +C++ supports the following features: * multi-stream mode -* Finite field Diffie-Hellman with 2048 and 3072 bit primes -* Elliptic curve Diffie-Hellman with 256 and 384 bit curves (NIST curves) -* Elliptic curves Curve25519 and Curve3617 (Dan Bernstein, Tanja Lange) -* Skein Hash and MAC for ZRTP -* AES-128 and AES-256 symmetric ciphers +* Finite field Diffie-Helman with 2048 and 3072 bit primes +* Elliptic curve Diffie-Helman with 256 and 384 bit curves +* AES-128 and AES-256 symmetric cipher * Twofish-128 and Twofish-256 bit symmetric ciphers * The SRTP authentication methods HMAC-SHA1 with 32 bit and 80 bit length and the Skein MAC with 32 bit and 64 bit length * The Short Authentication String (SAS) type with base 32 encoding (4 - characters) and the SAS 256 type using words. - -Some features like preshared mode are not supported but the GNU -ZRTP C++ implementation defines the necessary external interfaces and -functions for these enhanced features. - -**Note:** The Elliptic curves Cure25519 and Curve3617 are available only if you -select the crypto standalone mode during build. - -The newer verisons (starting with 4.1) implement an extensible mechanisms to -define algorithm selection policies that control selection of Hash, symmetric -cipher, and the SRTP authentication. Currently two policies exist: _Standard_ -and _PreferNonNist_. The Standard policy selects algorihms based on the -preferences (order) in the Hello packet, the PreferNonNist policy prefers -non-NIST algorithms, for example Skein and Twofish, if the selected public key -(Diffie-Hellman) algorithm is also one of the non-NIST algorithms. This is -fully backward compatible and in-line with RFC6189. - -### SDES support -This release also provides SDES support. The SDES implementation does not -support all of the fancy stuff but is usable in most cases. This implementation -however supports the new SDES crypto mixing to overcome some security issues -for SIP forking. Please look for `draft-zimmermann-mmusic-sdesc-mix-00`. + characters) + +Enhanced features like PBX SAS relay aka *trusted Man-in-the-Middle* or +preshared mode are not supported but the GNU ZRTP C++ implementation defines +the necessary external interfaces and functions for these enhanced features +(stubs only). ### Interoperability During the development of ZRTP and its sister implementation ZRTP4J (the Java @@ -68,7 +48,7 @@ To enable C based code to use ZRTP C++ I did a C wrapper that offers the same functionality to C based RTP implementations. The first use of the ZRTP C wrapper was for the [PJSIP][] library, actually the RTP part of this library. The ZRTP handler for PJSIP is [here][pjzrtp]. This port enables PJSIP -based clients to use ZRTP. One of the first clients that uses this feature is +based clients to use ZRTP. One of the first clients that use this feature is *[CSipSimple][]*, an very good open source Android SIP client. [pjsip]: http://www.pjsip.org @@ -91,21 +71,13 @@ following versions of Twinkle include GNU ZRTP C++ as well. ### License and further information -I changed the license of the ZRTP core source files from GPL to LGPL. Other -sources files may have own license. Please refer to the copyright notices of -the files. - -Thus most of this library is licensed under the GNU LGPL, version 3 or later. +Please note, this library is licensed under the GNU GPL, version 3 or +later, and has been copyright assigned to the Free Software Foundation. For further information refer to the [ZRTP FAQ][zrtpfaq] and the [GNU ZRTP howto][zrtphow]. Both are part of the GNU Telephony wiki and are located in its documentation category. -Source code in the directory `clients/tivi` and below is not licensed under the -GNU LGPL and is for reference and review only. Refer to the copyright statments -of the source code in these directories, in particular the sqlite3 sources which -have their own license. - [zrtphow]: http://www.gnutelephony.org/index.php/GNU_ZRTP_How_To [zrtpfaq]: http://www.gnutelephony.org/index.php/ZRTP_FAQ [rfc 6189]: http://tools.ietf.org/html/rfc6189 @@ -117,23 +89,11 @@ process. To build GNU ZRTP C++ perform the following steps after you unpacked the source archive or pulled the source from [Github][]: cd <zrtpsrc_dir> - mkdir build - cd build - cmake .. - make - -The CMakeLists.txt supports several options. If you don't specify any options -then `cmake` generates the build that supports GNU ccRTP library and it uses -the standalone cryptographic modules, thus no it's not necessary to install an -cryptographic library on the system. Optionally you may configure ZRTP to use -_sqlite3_ instead of a simple file to store the ZRTP cache data. For example - - cmake -DSQLITE=true .. - -creates the build files that use _sqlite3_. - -Please have a look at the `CMakeLists.txt` for other options. - + mkdir build + cd build + cmake .. + make + Running cmake in a separate `build` directory is the preferred way. Cmake and the following `make` generate all files in or below the build directory. Thus the base directory and the source directories are not polluted with `*.o`, @@ -143,13 +103,3 @@ build directory and create a new one to start from fresh (this is the ultimate different settings without mixing the two builds. [github]: http://github.com/wernerd/ZRTPCPP - - -### Notes when building ZRTP C++ for Android - -The CMake files support creation of an `Android.mk` file for the Tivi client -and may give you an idea how to do it for other clients. The generated -`Android.mk` generates `buildinfo_*.c` files in the root directory. You may -delete these files after the Android static libraries are ready. - -Since version 4.1.1 the example Android build files require NDK r9c. diff --git a/jni/libzrtp/sources/bnlib/bn.c b/jni/libzrtp/sources/bnlib/bn.c deleted file mode 100644 index 36d07fc2d..000000000 --- a/jni/libzrtp/sources/bnlib/bn.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * bn.c - the high-level bignum interface - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - */ - -#include <bn.h> - -/* Functions */ -void -bnBegin(struct BigNum *bn) -{ - static int bninit = 0; - - if (!bninit) { - bnInit(); - bninit = 1; - } - - bn->ptr = 0; - bn->size = 0; - bn->allocated = 0; -} - -void -bnSwap(struct BigNum *a, struct BigNum *b) -{ - void *p; - unsigned t; - - p = a->ptr; - a->ptr = b->ptr; - b->ptr = p; - - t = a->size; - a->size = b->size; - b->size = t; - - t = a->allocated; - a->allocated = b->allocated; - b->allocated = t; -} - -int (*bnYield)(void); - -void (*bnEnd)(struct BigNum *bn); -int (*bnPrealloc)(struct BigNum *bn, unsigned bits); -int (*bnCopy)(struct BigNum *dest, struct BigNum const *src); -void (*bnNorm)(struct BigNum *bn); -void (*bnExtractBigBytes)(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned len); -int (*bnInsertBigBytes)(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len); -void (*bnExtractLittleBytes)(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned len); -int (*bnInsertLittleBytes)(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len); -unsigned (*bnLSWord)(struct BigNum const *src); -int (*bnReadBit)(struct BigNum const *bn, unsigned bit); -unsigned (*bnBits)(struct BigNum const *src); -int (*bnAdd)(struct BigNum *dest, struct BigNum const *src); -int (*bnSub)(struct BigNum *dest, struct BigNum const *src); -int (*bnCmpQ)(struct BigNum const *a, unsigned b); -int (*bnSetQ)(struct BigNum *dest, unsigned src); -int (*bnAddQ)(struct BigNum *dest, unsigned src); -int (*bnSubQ)(struct BigNum *dest, unsigned src); -int (*bnCmp)(struct BigNum const *a, struct BigNum const *b); -int (*bnSquare)(struct BigNum *dest, struct BigNum const *src); -int (*bnMul)(struct BigNum *dest, struct BigNum const *a, - struct BigNum const *b); -int (*bnMulQ)(struct BigNum *dest, struct BigNum const *a, unsigned b); -int (*bnDivMod)(struct BigNum *q, struct BigNum *r, struct BigNum const *n, - struct BigNum const *d); -int (*bnMod)(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *d); -unsigned (*bnModQ)(struct BigNum const *src, unsigned d); -int (*bnExpMod)(struct BigNum *result, struct BigNum const *n, - struct BigNum const *exp, struct BigNum const *mod); -int (*bnDoubleExpMod)(struct BigNum *dest, - struct BigNum const *n1, struct BigNum const *e1, - struct BigNum const *n2, struct BigNum const *e2, - struct BigNum const *mod); -int (*bnTwoExpMod)(struct BigNum *n, struct BigNum const *exp, - struct BigNum const *mod); -int (*bnGcd)(struct BigNum *dest, struct BigNum const *a, - struct BigNum const *b); -int (*bnInv)(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *mod); -int (*bnLShift)(struct BigNum *dest, unsigned amt); -void (*bnRShift)(struct BigNum *dest, unsigned amt); -unsigned (*bnMakeOdd)(struct BigNum *n); -int (*bnBasePrecompBegin)(struct BnBasePrecomp *pre, struct BigNum const *base, - struct BigNum const *mod, unsigned maxebits); -int (*bnBasePrecompCopy)(struct BnBasePrecomp *dst, - struct BnBasePrecomp const *src); -void (*bnBasePrecompEnd)(struct BnBasePrecomp *pre); -int (*bnBasePrecompExpMod)(struct BigNum *dest, - struct BnBasePrecomp const *pre, struct BigNum const *exp, - struct BigNum const *mod); -int (*bnDoubleBasePrecompExpMod)(struct BigNum *dest, - struct BnBasePrecomp const *pre1, struct BigNum const *exp1, - struct BnBasePrecomp const *pre2, struct BigNum const *exp2, - struct BigNum const *mod); diff --git a/jni/libzrtp/sources/bnlib/bn.h b/jni/libzrtp/sources/bnlib/bn.h deleted file mode 100644 index 5cc80f01a..000000000 --- a/jni/libzrtp/sources/bnlib/bn.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * bn.h - the interface to the bignum routines. - * All functions which return ints can potentially allocate memory - * and return -1 if they are unable to. All "const" arguments - * are unmodified. - * - * This is not particularly asymmetric, as some operations are of the - * form a = b @ c, while others do a @= b. In general, outputs may not - * point to the same struct BigNums as inputs, except as specified - * below. This relationship is referred to as "being the same as". - * This is not numerical equivalence. - * - * The "Q" operations take "unsigned" inputs. Higher values of the - * extra input may work on some implementations, but 65535 is the - * highest portable value. Just because UNSIGNED_MAX is larger than - * that, or you know that the word size of the library is larger than that, - * that, does *not* mean it's allowed. - */ -#ifndef BN_H -#define BN_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -struct BigNum { - void *ptr; - unsigned size; /* Note: in (variable-sized) words */ - unsigned allocated; -}; - -#ifndef SWIG -/* - * User-supplied function: if non-NULL, this is called during long-running - * computations. You may put Yield() calls in here to give CPU time to - * other processes. You may also force the computation to be aborted, - * by returning a value < 0, which will be the return value of the - * bnXXX call. (You probably want the value to be someting other than - * -1, to distinguish it from a n out-of-memory error.) - * - * The functions that this is called from, and the intervals at which it - * is called, are not well defined, just "reasonably often". (Currently, - * once per exponent bit in nodular exponentiation, and once per two - * divisions in GCD and inverse computation.) - */ -extern int (*bnYield)(void); - -/* Functions */ - -/* - * You usually never have to call this function explicitly, as - * bnBegin() takes care of it. If the program jumps to address 0, - * this function has bot been called. - */ -void bnInit(void); - -/* - * This initializes an empty struct BigNum to a zero value. - * Do not use this on a BigNum which has had a value stored in it! - */ -void bnBegin(struct BigNum *bn); - -/* Swap two BigNums. Cheap. */ -void bnSwap(struct BigNum *a, struct BigNum *b); - -/* Reset an initialized bigNum to empty, pending deallocation. */ -extern void (*bnEnd)(struct BigNum *bn); - -/* - * If you know you'll need space in the number soon, you can use this function - * to ensure that there is room for at least "bits" bits. Optional. - * Returns <0 on out of memory, but the value is unaffected. - */ -extern int (*bnPrealloc)(struct BigNum *bn, unsigned bits); - -/* Hopefully obvious. dest = src. dest may be the same as src. */ -extern int (*bnCopy)(struct BigNum *dest, struct BigNum const *src); - -/* - * Mostly done automatically, but this removes leading zero words from - * the internal representation of the BigNum. Use is unclear. - */ -extern void (*bnNorm)(struct BigNum *bn); - -/* - * Move bytes between the given buffer and the given BigNum encoded in - * base 256. I.e. after either of these, the buffer will be equal to - * (bn / 256^lsbyte) % 256^len. The difference is which is altered to - * match the other! - */ -extern void (*bnExtractBigBytes)(struct BigNum const *bn, - unsigned char *dest, unsigned lsbyte, unsigned len); -extern int (*bnInsertBigBytes)(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len); - -/* The same, but the buffer is little-endian. */ -extern void (*bnExtractLittleBytes)(struct BigNum const *bn, - unsigned char *dest, unsigned lsbyte, unsigned len); -extern int (*bnInsertLittleBytes)(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len); - -/* Return the least-significant bits (at least 16) of the BigNum */ -extern unsigned (*bnLSWord)(struct BigNum const *src); - -/* Return the selected bit of the BigNum (bit 0 is bn mod 2) */ -extern int (*bnReadBit)(struct BigNum const *bn, unsigned bit); - -/* - * Return the number of significant bits in the BigNum. - * 0 or 1+floor(log2(src)) - */ -extern unsigned (*bnBits)(struct BigNum const *src); -#define bnBytes(bn) ((bnBits(bn)+7)/8) - -/* - * dest += src. dest and src may be the same. Guaranteed not to - * allocate memory unnecessarily, so if you're sure bnBits(dest) - * won't change, you don't need to check the return value. - */ -extern int (*bnAdd)(struct BigNum *dest, struct BigNum const *src); - -/* - * dest -= src. dest and src may be the same, but bnSetQ(dest, 0) is faster. - * if dest < src, returns +1 and sets dest = src-dest. - */ -extern int (*bnSub)(struct BigNum *dest, struct BigNum const *src); - -/* Return sign (-1, 0, +1) of a-b. a <=> b --> bnCmpQ(a, b) <=> 0 */ -extern int (*bnCmpQ)(struct BigNum const *a, unsigned b); - -/* dest = src, where 0 <= src < 2^16. */ -extern int (*bnSetQ)(struct BigNum *dest, unsigned src); - -/* dest += src, where 0 <= src < 2^16 */ -extern int (*bnAddQ)(struct BigNum *dest, unsigned src); - -/* dest -= src, where 0 <= src < 2^16 */ -extern int (*bnSubQ)(struct BigNum *dest, unsigned src); - -/* Return sign (-1, 0, +1) of a-b. a <=> b --> bnCmp(a, b) <=> 0 */ -extern int (*bnCmp)(struct BigNum const *a, struct BigNum const *b); - -/* dest = src^2. dest may be the same as src, but it costs time. */ -extern int (*bnSquare)(struct BigNum *dest, struct BigNum const *src); - -/* dest = a * b. dest may be the same as a or b, but it costs time. */ -extern int (*bnMul)(struct BigNum *dest, struct BigNum const *a, - struct BigNum const *b); - -/* dest = a * b, where 0 <= b < 2^16. dest and a may be the same. */ -extern int (*bnMulQ)(struct BigNum *dest, struct BigNum const *a, unsigned b); - -/* - * q = n/d, r = n%d. r may be the same as n, but not d, - * and q may not be the same as n or d. - * re-entrancy issue: this temporarily modifies d, but restores - * it for return. - */ -extern int (*bnDivMod)(struct BigNum *q, struct BigNum *r, - struct BigNum const *n, struct BigNum const *d); -/* - * dest = src % d. dest and src may be the same, but not dest and d. - * re-entrancy issue: this temporarily modifies d, but restores - * it for return. - */ -extern int (*bnMod)(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *d); - -/* return src % d, where 0 <= d < 2^16. */ -extern unsigned int (*bnModQ)(struct BigNum const *src, unsigned d); - -/* n = n^exp, modulo "mod" "mod" *must* be odd */ -extern int (*bnExpMod)(struct BigNum *result, struct BigNum const *n, - struct BigNum const *exp, struct BigNum const *mod); - -/* - * dest = n1^e1 * n2^e2, modulo "mod". "mod" *must* be odd. - * dest may be the same as n1 or n2. - */ -extern int (*bnDoubleExpMod)(struct BigNum *dest, - struct BigNum const *n1, struct BigNum const *e1, - struct BigNum const *n2, struct BigNum const *e2, - struct BigNum const *mod); - -/* n = 2^exp, modulo "mod" "mod" *must* be odd */ -extern int (*bnTwoExpMod)(struct BigNum *n, struct BigNum const *exp, - struct BigNum const *mod); - -/* dest = gcd(a, b). The inputs may overlap arbitrarily. */ -extern int (*bnGcd)(struct BigNum *dest, struct BigNum const *a, - struct BigNum const *b); - -/* dest = src^-1, modulo "mod". dest may be the same as src. */ -extern int (*bnInv)(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *mod); - -/* Shift dest left "amt" places */ -extern int (*bnLShift)(struct BigNum *dest, unsigned amt); -/* Shift dest right "amt" places, discarding low-order bits */ -extern void (*bnRShift)(struct BigNum *dest, unsigned amt); - -/* For the largest 2^k that divides n, divide n by it and return k. */ -extern unsigned (*bnMakeOdd)(struct BigNum *n); - -/* - * Precomputed data for rapid base^exp (mod mod) computation with fixed - * base and mod. - */ -struct BnBasePrecomp { - void *array; /* Ponter to array of pointers to words */ - unsigned msize; /* Words in modulis (normalized) */ - unsigned bits; /* Bits per array element */ - unsigned maxebits; /* Maximum exponent bits */ - unsigned entries; /* Number of entries */ - unsigned arraysize; -}; - -extern int (*bnBasePrecompBegin)(struct BnBasePrecomp *pre, - struct BigNum const *base, struct BigNum const *mod, - unsigned maxebits); -extern void (*bnBasePrecompEnd)(struct BnBasePrecomp *pre); -extern int (*bnBasePrecompExpMod)(struct BigNum *dest, - struct BnBasePrecomp const *pre, struct BigNum const *exp, - struct BigNum const *mod); -extern int (*bnDoubleBasePrecompExpMod)(struct BigNum *dest, - struct BnBasePrecomp const *pre1, struct BigNum const *exp1, - struct BnBasePrecomp const *pre2, struct BigNum const *exp2, - struct BigNum const *mod); -#endif /* SWIF */ - -#ifdef __cplusplus -} -#endif - -#endif/* !BN_H */ diff --git a/jni/libzrtp/sources/bnlib/bn00.c b/jni/libzrtp/sources/bnlib/bn00.c deleted file mode 100644 index 4bc97973b..000000000 --- a/jni/libzrtp/sources/bnlib/bn00.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * bn00.c - auto-size-detecting bn??.c file. - * - * Written in 1995 by Colin Plumb. - * For licensing and other legal details, see the file legal.c. - */ - -#include "bnsize00.h" - -#if BNSIZE64 - -/* Include all of the C source file by reference */ -#include "bn64.c" -#include "bninit64.c" - -#elif BNSIZE32 - -/* Include all of the C source file by reference */ -#include "bn32.c" -#include "bninit32.c" - -#else /* BNSIZE16 */ - -/* Include all of the C source file by reference */ -#include "bn16.c" -#include "bninit16.c" - -#endif diff --git a/jni/libzrtp/sources/bnlib/bn16.c b/jni/libzrtp/sources/bnlib/bn16.c deleted file mode 100644 index 98e5aa307..000000000 --- a/jni/libzrtp/sources/bnlib/bn16.c +++ /dev/null @@ -1,1188 +0,0 @@ -/* - * bn16.c - the high-level bignum interface - * - * Like lbn16.c, this reserves the string "16" for textual replacement. - * The string must not appear anywhere unless it is intended to be replaced - * to generate other bignum interface functions. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - */ - -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include <bnconfig.h> -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_ASSERT_H -#define NO_ASSERT_H 0 -#endif -#ifndef NO_STRING_H -#define NO_STRING_H 0 -#endif -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 0 -#endif -#ifndef NEED_MEMORY_H -#define NEED_MEMORY_H 0 -#endif - -#if !NO_ASSERT_H -#include <assert.h> -#else -#define assert(x) (void)0 -#endif - -#if !NO_STRING_H -#include <string.h> /* for memmove() in bnMakeOdd */ -#elif HAVE_STRINGS_H -#include <strings.h> -#endif -#if NEED_MEMORY_H -#include <memory.h> -#endif - -/* - * This was useful during debugging, so it's left in here. - * You can ignore it. DBMALLOC is generally undefined. - */ -#ifndef DBMALLOC -#define DBMALLOC 0 -#endif -#if DBMALLOC -#include "../dbmalloc/malloc.h" -#define MALLOCDB malloc_chain_check(1) -#else -#define MALLOCDB (void)0 -#endif - -#include "lbn.h" -#include "lbn16.h" -#include "lbnmem.h" -#include "bn16.h" -#include "bn.h" - -/* Work-arounds for some particularly broken systems */ -#include "kludge.h" /* For memmove() */ - -/* Functions */ -void -bnInit_16(void) -{ - bnEnd = bnEnd_16; - bnPrealloc = bnPrealloc_16; - bnCopy = bnCopy_16; - bnNorm = bnNorm_16; - bnExtractBigBytes = bnExtractBigBytes_16; - bnInsertBigBytes = bnInsertBigBytes_16; - bnExtractLittleBytes = bnExtractLittleBytes_16; - bnInsertLittleBytes = bnInsertLittleBytes_16; - bnLSWord = bnLSWord_16; - bnReadBit = bnReadBit_16; - bnBits = bnBits_16; - bnAdd = bnAdd_16; - bnSub = bnSub_16; - bnCmpQ = bnCmpQ_16; - bnSetQ = bnSetQ_16; - bnAddQ = bnAddQ_16; - bnSubQ = bnSubQ_16; - bnCmp = bnCmp_16; - bnSquare = bnSquare_16; - bnMul = bnMul_16; - bnMulQ = bnMulQ_16; - bnDivMod = bnDivMod_16; - bnMod = bnMod_16; - bnModQ = bnModQ_16; - bnExpMod = bnExpMod_16; - bnDoubleExpMod = bnDoubleExpMod_16; - bnTwoExpMod = bnTwoExpMod_16; - bnGcd = bnGcd_16; - bnInv = bnInv_16; - bnLShift = bnLShift_16; - bnRShift = bnRShift_16; - bnMakeOdd = bnMakeOdd_16; - bnBasePrecompBegin = bnBasePrecompBegin_16; - bnBasePrecompEnd = bnBasePrecompEnd_16; - bnBasePrecompExpMod = bnBasePrecompExpMod_16; - bnDoubleBasePrecompExpMod = bnDoubleBasePrecompExpMod_16; -} - -void -bnEnd_16(struct BigNum *bn) -{ - if (bn->ptr) { - LBNFREE((BNWORD16 *)bn->ptr, bn->allocated); - bn->ptr = 0; - } - bn->size = 0; - bn->allocated = 0; - - MALLOCDB; -} - -/* Internal function. It operates in words. */ -static int -bnResize_16(struct BigNum *bn, unsigned len) -{ - void *p; - - /* Round size up: most mallocs impose 8-byte granularity anyway */ - len = (len + (8/sizeof(BNWORD16) - 1)) & ~(8/sizeof(BNWORD16) - 1); - p = LBNREALLOC((BNWORD16 *)bn->ptr, bn->allocated, len); - if (!p) - return -1; - bn->ptr = p; - bn->allocated = len; - - MALLOCDB; - - return 0; -} - -#define bnSizeCheck(bn, size) \ - if (bn->allocated < size && bnResize_16(bn, size) < 0) \ - return -1 - -/* Preallocate enough space in bn to hold "bits" bits. */ -int -bnPrealloc_16(struct BigNum *bn, unsigned bits) -{ - bits = (bits + 16-1)/16; - bnSizeCheck(bn, bits); - MALLOCDB; - return 0; -} - -int -bnCopy_16(struct BigNum *dest, struct BigNum const *src) -{ - bnSizeCheck(dest, src->size); - dest->size = src->size; - lbnCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, src->size); - MALLOCDB; - return 0; -} - -/* Is this ever needed? Normalize the bn by deleting high-order 0 words */ -void -bnNorm_16(struct BigNum *bn) -{ - bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, bn->size); -} - -/* - * Convert a bignum to big-endian bytes. Returns, in big-endian form, a - * substring of the bignum starting from lsbyte and "len" bytes long. - * Unused high-order (leading) bytes are filled with 0. - */ -void -bnExtractBigBytes_16(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size * (16 / 8); - - /* Fill unused leading bytes with 0 */ - while (s < lsbyte + len) { - *dest++ = 0; - len--; - } - - if (len) - lbnExtractBigBytes_16((BNWORD16 *)bn->ptr, dest, lsbyte, len); - MALLOCDB; -} - -/* The inverse of the above. */ -int -bnInsertBigBytes_16(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size; - unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16); - - /* Pad with zeros as required */ - bnSizeCheck(bn, words); - - if (s < words) { - lbnZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s); - s = words; - } - - lbnInsertBigBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len); - - bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, s); - - MALLOCDB; - return 0; -} - - -/* - * Convert a bignum to little-endian bytes. Returns, in little-endian form, a - * substring of the bignum starting from lsbyte and "len" bytes long. - * Unused high-order (trailing) bytes are filled with 0. - */ -void -bnExtractLittleBytes_16(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size * (16 / 8); - - /* Fill unused leading bytes with 0 */ - while (s < lsbyte + len) - dest[--len] = 0; - - if (len) - lbnExtractLittleBytes_16((BNWORD16 *)bn->ptr, dest, - lsbyte, len); - MALLOCDB; -} - -/* The inverse of the above */ -int -bnInsertLittleBytes_16(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size; - unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16); - - /* Pad with zeros as required */ - bnSizeCheck(bn, words); - - if (s < words) { - lbnZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s); - s = words; - } - - lbnInsertLittleBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len); - - bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, s); - - MALLOCDB; - return 0; -} - -/* Return the least-significant word of the input. */ -unsigned -bnLSWord_16(struct BigNum const *bn) -{ - return bn->size ? (unsigned)((BNWORD16 *)bn->ptr)[BIGLITTLE(-1,0)]: 0; -} - -/* Return a selected bit of the data */ -int -bnReadBit_16(struct BigNum const *bn, unsigned bit) -{ - BNWORD16 word; - if (bit/16 >= bn->size) - return 0; - word = ((BNWORD16 *)bn->ptr)[BIGLITTLE(-1-bit/16,bit/16)]; - return (int)(word >> (bit % 16) & 1); -} - -/* Count the number of significant bits. */ -unsigned -bnBits_16(struct BigNum const *bn) -{ - return lbnBits_16((BNWORD16 *)bn->ptr, bn->size); -} - -/* dest += src */ -int -bnAdd_16(struct BigNum *dest, struct BigNum const *src) -{ - unsigned s = src->size, d = dest->size; - BNWORD16 t; - - if (!s) - return 0; - - bnSizeCheck(dest, s); - - if (d < s) { - lbnZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d); - dest->size = d = s; - MALLOCDB; - } - t = lbnAddN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s); - MALLOCDB; - if (t) { - if (d > s) { - t = lbnAdd1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s), - d-s, t); - MALLOCDB; - } - if (t) { - bnSizeCheck(dest, d+1); - ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t; - dest->size = d+1; - } - } - return 0; -} - -/* - * dest -= src. - * If dest goes negative, this produces the absolute value of - * the difference (the negative of the true value) and returns 1. - * Otherwise, it returls 0. - */ -int -bnSub_16(struct BigNum *dest, struct BigNum const *src) -{ - unsigned s = src->size, d = dest->size; - BNWORD16 t; - - if (d < s && d < (s = lbnNorm_16((BNWORD16 *)src->ptr, s))) { - bnSizeCheck(dest, s); - lbnZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d); - dest->size = d = s; - MALLOCDB; - } - if (!s) - return 0; - t = lbnSubN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s); - MALLOCDB; - if (t) { - if (d > s) { - t = lbnSub1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s), - d-s, t); - MALLOCDB; - } - if (t) { - lbnNeg_16((BNWORD16 *)dest->ptr, d); - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, - dest->size); - MALLOCDB; - return 1; - } - } - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dest->size); - return 0; -} - -/* - * Compare the BigNum to the given value, which must be < 65536. - * Returns -1. 0 or 1 if a<b, a == b or a>b. - * a <=> b --> bnCmpQ(a,b) <=> 0 - */ -int -bnCmpQ_16(struct BigNum const *a, unsigned b) -{ - unsigned t; - BNWORD16 v; - - t = lbnNorm_16((BNWORD16 *)a->ptr, a->size); - /* If a is more than one word long or zero, it's easy... */ - if (t != 1) - return (t > 1) ? 1 : (b ? -1 : 0); - v = (unsigned)((BNWORD16 *)a->ptr)[BIGLITTLE(-1,0)]; - return (v > b) ? 1 : ((v < b) ? -1 : 0); -} - -/* Set dest to a small value */ -int -bnSetQ_16(struct BigNum *dest, unsigned src) -{ - if (src) { - bnSizeCheck(dest, 1); - - ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD16)src; - dest->size = 1; - } else { - dest->size = 0; - } - return 0; -} - -/* dest += src */ -int -bnAddQ_16(struct BigNum *dest, unsigned src) -{ - BNWORD16 t; - - if (!dest->size) - return bnSetQ(dest, src); - - t = lbnAdd1_16((BNWORD16 *)dest->ptr, dest->size, (BNWORD16)src); - MALLOCDB; - if (t) { - src = dest->size; - bnSizeCheck(dest, src+1); - ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t; - dest->size = src+1; - } - return 0; -} - -/* - * Return value as for bnSub: 1 if subtract underflowed, in which - * case the return is the negative of the computed value. - */ -int -bnSubQ_16(struct BigNum *dest, unsigned src) -{ - BNWORD16 t; - - if (!dest->size) - return bnSetQ(dest, src) < 0 ? -1 : (src != 0); - - t = lbnSub1_16((BNWORD16 *)dest->ptr, dest->size, src); - MALLOCDB; - if (t) { - /* Underflow. <= 1 word, so do it simply. */ - lbnNeg_16((BNWORD16 *)dest->ptr, 1); - dest->size = 1; - return 1; - } -/* Try to normalize? Needing this is going to be pretty damn rare. */ -/* dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dest->size); */ - return 0; -} - -/* - * Compare two BigNums. Returns -1. 0 or 1 if a<b, a == b or a>b. - * a <=> b --> bnCmp(a,b) <=> 0 - */ -int -bnCmp_16(struct BigNum const *a, struct BigNum const *b) -{ - unsigned s, t; - - s = lbnNorm_16((BNWORD16 *)a->ptr, a->size); - t = lbnNorm_16((BNWORD16 *)b->ptr, b->size); - - if (s != t) - return s > t ? 1 : -1; - return lbnCmp_16((BNWORD16 *)a->ptr, (BNWORD16 *)b->ptr, s); -} - -/* dest = src*src. This is more efficient than bnMul. */ -int -bnSquare_16(struct BigNum *dest, struct BigNum const *src) -{ - unsigned s; - BNWORD16 *srcbuf; - - s = lbnNorm_16((BNWORD16 *)src->ptr, src->size); - if (!s) { - dest->size = 0; - return 0; - } - bnSizeCheck(dest, 2*s); - - if (src == dest) { - LBNALLOC(srcbuf, BNWORD16, s); - if (!srcbuf) - return -1; - lbnCopy_16(srcbuf, (BNWORD16 *)src->ptr, s); - lbnSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)srcbuf, s); - LBNFREE(srcbuf, s); - } else { - lbnSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s); - } - - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, 2*s); - MALLOCDB; - return 0; -} - -/* dest = a * b. Any overlap between operands is allowed. */ -int -bnMul_16(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) -{ - unsigned s, t; - BNWORD16 *srcbuf; - - s = lbnNorm_16((BNWORD16 *)a->ptr, a->size); - t = lbnNorm_16((BNWORD16 *)b->ptr, b->size); - - if (!s || !t) { - dest->size = 0; - return 0; - } - - if (a == b) - return bnSquare_16(dest, a); - - bnSizeCheck(dest, s+t); - - if (dest == a) { - LBNALLOC(srcbuf, BNWORD16, s); - if (!srcbuf) - return -1; - lbnCopy_16(srcbuf, (BNWORD16 *)a->ptr, s); - lbnMul_16((BNWORD16 *)dest->ptr, srcbuf, s, - (BNWORD16 *)b->ptr, t); - LBNFREE(srcbuf, s); - } else if (dest == b) { - LBNALLOC(srcbuf, BNWORD16, t); - if (!srcbuf) - return -1; - lbnCopy_16(srcbuf, (BNWORD16 *)b->ptr, t); - lbnMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, - srcbuf, t); - LBNFREE(srcbuf, t); - } else { - lbnMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, - (BNWORD16 *)b->ptr, t); - } - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s+t); - MALLOCDB; - return 0; -} - -/* dest = a * b */ -int -bnMulQ_16(struct BigNum *dest, struct BigNum const *a, unsigned b) -{ - unsigned s; - - s = lbnNorm_16((BNWORD16 *)a->ptr, a->size); - if (!s || !b) { - dest->size = 0; - return 0; - } - if (b == 1) - return bnCopy_16(dest, a); - bnSizeCheck(dest, s+1); - lbnMulN1_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, b); - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s+1); - MALLOCDB; - return 0; -} - -/* q = n/d, r = n % d */ -int -bnDivMod_16(struct BigNum *q, struct BigNum *r, struct BigNum const *n, - struct BigNum const *d) -{ - unsigned dsize, nsize; - BNWORD16 qhigh; - - dsize = lbnNorm_16((BNWORD16 *)d->ptr, d->size); - nsize = lbnNorm_16((BNWORD16 *)n->ptr, n->size); - - if (nsize < dsize) { - q->size = 0; /* No quotient */ - r->size = nsize; - return 0; /* Success */ - } - - bnSizeCheck(q, nsize-dsize); - - if (r != n) { /* You are allowed to reduce in place */ - bnSizeCheck(r, nsize); - lbnCopy_16((BNWORD16 *)r->ptr, (BNWORD16 *)n->ptr, nsize); - } - - qhigh = lbnDiv_16((BNWORD16 *)q->ptr, (BNWORD16 *)r->ptr, nsize, - (BNWORD16 *)d->ptr, dsize); - nsize -= dsize; - if (qhigh) { - bnSizeCheck(q, nsize+1); - *((BNWORD16 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh; - q->size = nsize+1; - } else { - q->size = lbnNorm_16((BNWORD16 *)q->ptr, nsize); - } - r->size = lbnNorm_16((BNWORD16 *)r->ptr, dsize); - MALLOCDB; - return 0; -} - -/* det = src % d */ -int -bnMod_16(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d) -{ - unsigned dsize, nsize; - - nsize = lbnNorm_16((BNWORD16 *)src->ptr, src->size); - dsize = lbnNorm_16((BNWORD16 *)d->ptr, d->size); - - - if (dest != src) { - bnSizeCheck(dest, nsize); - lbnCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, nsize); - } - - if (nsize < dsize) { - dest->size = nsize; /* No quotient */ - return 0; - } - - (void)lbnDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-dsize,+dsize), - (BNWORD16 *)dest->ptr, nsize, - (BNWORD16 *)d->ptr, dsize); - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dsize); - MALLOCDB; - return 0; -} - -/* return src % d. */ -unsigned -bnModQ_16(struct BigNum const *src, unsigned d) -{ - unsigned s; - - s = lbnNorm_16((BNWORD16 *)src->ptr, src->size); - if (!s) - return 0; - - if (d & (d-1)) /* Not a power of 2 */ - d = lbnModQ_16((BNWORD16 *)src->ptr, s, d); - else - d = (unsigned)((BNWORD16 *)src->ptr)[BIGLITTLE(-1,0)] & (d-1); - return d; -} - -/* dest = n^exp (mod mod) */ -int -bnExpMod_16(struct BigNum *dest, struct BigNum const *n, - struct BigNum const *exp, struct BigNum const *mod) -{ - unsigned nsize, esize, msize; - - nsize = lbnNorm_16((BNWORD16 *)n->ptr, n->size); - esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size); - msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); - - if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) - return -1; /* Illegal modulus! */ - - bnSizeCheck(dest, msize); - - /* Special-case base of 2 */ - if (nsize == 1 && ((BNWORD16 *)n->ptr)[BIGLITTLE(-1,0)] == 2) { - if (lbnTwoExpMod_16((BNWORD16 *)dest->ptr, - (BNWORD16 *)exp->ptr, esize, - (BNWORD16 *)mod->ptr, msize) < 0) - return -1; - } else { - if (lbnExpMod_16((BNWORD16 *)dest->ptr, - (BNWORD16 *)n->ptr, nsize, - (BNWORD16 *)exp->ptr, esize, - (BNWORD16 *)mod->ptr, msize) < 0) - return -1; - } - - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize); - MALLOCDB; - return 0; -} - -/* - * dest = n1^e1 * n2^e2 (mod mod). This is more efficient than two - * separate modular exponentiations, and in fact asymptotically approaches - * the cost of one. - */ -int -bnDoubleExpMod_16(struct BigNum *dest, - struct BigNum const *n1, struct BigNum const *e1, - struct BigNum const *n2, struct BigNum const *e2, - struct BigNum const *mod) -{ - unsigned n1size, e1size, n2size, e2size, msize; - - n1size = lbnNorm_16((BNWORD16 *)n1->ptr, n1->size); - e1size = lbnNorm_16((BNWORD16 *)e1->ptr, e1->size); - n2size = lbnNorm_16((BNWORD16 *)n2->ptr, n2->size); - e2size = lbnNorm_16((BNWORD16 *)e2->ptr, e2->size); - msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); - - if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) - return -1; /* Illegal modulus! */ - - bnSizeCheck(dest, msize); - - if (lbnDoubleExpMod_16((BNWORD16 *)dest->ptr, - (BNWORD16 *)n1->ptr, n1size, (BNWORD16 *)e1->ptr, e1size, - (BNWORD16 *)n2->ptr, n2size, (BNWORD16 *)e2->ptr, e2size, - (BNWORD16 *)mod->ptr, msize) < 0) - return -1; - - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize); - MALLOCDB; - return 0; -} - -/* n = 2^exp (mod mod) */ -int -bnTwoExpMod_16(struct BigNum *n, struct BigNum const *exp, - struct BigNum const *mod) -{ - unsigned esize, msize; - - esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size); - msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); - - if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) - return -1; /* Illegal modulus! */ - - bnSizeCheck(n, msize); - - if (lbnTwoExpMod_16((BNWORD16 *)n->ptr, (BNWORD16 *)exp->ptr, esize, - (BNWORD16 *)mod->ptr, msize) < 0) - return -1; - - n->size = lbnNorm_16((BNWORD16 *)n->ptr, msize); - MALLOCDB; - return 0; -} - -/* dest = gcd(a, b) */ -int -bnGcd_16(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) -{ - BNWORD16 *tmp; - unsigned asize, bsize; - int i; - - /* Kind of silly, but we might as well permit it... */ - if (a == b) - return dest == a ? 0 : bnCopy(dest, a); - - /* Ensure a is not the same as "dest" */ - if (a == dest) { - a = b; - b = dest; - } - - asize = lbnNorm_16((BNWORD16 *)a->ptr, a->size); - bsize = lbnNorm_16((BNWORD16 *)b->ptr, b->size); - - bnSizeCheck(dest, bsize+1); - - /* Copy a to tmp */ - LBNALLOC(tmp, BNWORD16, asize+1); - if (!tmp) - return -1; - lbnCopy_16(tmp, (BNWORD16 *)a->ptr, asize); - - /* Copy b to dest, if necessary */ - if (dest != b) - lbnCopy_16((BNWORD16 *)dest->ptr, - (BNWORD16 *)b->ptr, bsize); - if (bsize > asize || (bsize == asize && - lbnCmp_16((BNWORD16 *)b->ptr, (BNWORD16 *)a->ptr, asize) > 0)) - { - i = lbnGcd_16((BNWORD16 *)dest->ptr, bsize, tmp, asize, - &dest->size); - if (i > 0) /* Result in tmp, not dest */ - lbnCopy_16((BNWORD16 *)dest->ptr, tmp, dest->size); - } else { - i = lbnGcd_16(tmp, asize, (BNWORD16 *)dest->ptr, bsize, - &dest->size); - if (i == 0) /* Result in tmp, not dest */ - lbnCopy_16((BNWORD16 *)dest->ptr, tmp, dest->size); - } - LBNFREE(tmp, asize+1); - MALLOCDB; - return (i < 0) ? i : 0; -} - -/* - * dest = 1/src (mod mod). Returns >0 if gcd(src, mod) != 1 (in which case - * the inverse does not exist). - */ -int -bnInv_16(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *mod) -{ - unsigned s, m; - int i; - - s = lbnNorm_16((BNWORD16 *)src->ptr, src->size); - m = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); - - /* lbnInv_16 requires that the input be less than the modulus */ - if (m < s || - (m==s && lbnCmp_16((BNWORD16 *)src->ptr, (BNWORD16 *)mod->ptr, s))) - { - bnSizeCheck(dest, s + (m==s)); - if (dest != src) - lbnCopy_16((BNWORD16 *)dest->ptr, - (BNWORD16 *)src->ptr, s); - /* Pre-reduce modulo the modulus */ - (void)lbnDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-m,+m), - (BNWORD16 *)dest->ptr, s, - (BNWORD16 *)mod->ptr, m); - s = lbnNorm_16((BNWORD16 *)dest->ptr, m); - MALLOCDB; - } else { - bnSizeCheck(dest, m+1); - if (dest != src) - lbnCopy_16((BNWORD16 *)dest->ptr, - (BNWORD16 *)src->ptr, s); - } - - i = lbnInv_16((BNWORD16 *)dest->ptr, s, (BNWORD16 *)mod->ptr, m); - if (i == 0) - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, m); - - MALLOCDB; - return i; -} - -/* - * Shift a bignum left the appropriate number of bits, - * multiplying by 2^amt. - */ -int -bnLShift_16(struct BigNum *dest, unsigned amt) -{ - unsigned s = dest->size; - BNWORD16 carry; - - if (amt % 16) { - carry = lbnLshift_16((BNWORD16 *)dest->ptr, s, amt % 16); - if (carry) { - s++; - bnSizeCheck(dest, s); - ((BNWORD16 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry; - } - } - - amt /= 16; - if (amt) { - bnSizeCheck(dest, s+amt); - memmove((BNWORD16 *)dest->ptr BIGLITTLE(-s-amt, +amt), - (BNWORD16 *)dest->ptr BIG(-s), - s * sizeof(BNWORD16)); - lbnZero_16((BNWORD16 *)dest->ptr, amt); - s += amt; - } - dest->size = s; - MALLOCDB; - return 0; -} - -/* - * Shift a bignum right the appropriate number of bits, - * dividing by 2^amt. - */ -void -bnRShift_16(struct BigNum *dest, unsigned amt) -{ - unsigned s = dest->size; - - if (amt >= 16) { - memmove( - (BNWORD16 *)dest->ptr BIG(-s+amt/16), - (BNWORD16 *)dest->ptr BIGLITTLE(-s, +amt/16), - (s-amt/16) * sizeof(BNWORD16)); - s -= amt/16; - amt %= 16; - } - - if (amt) - (void)lbnRshift_16((BNWORD16 *)dest->ptr, s, amt); - - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s); - MALLOCDB; -} - -/* - * Shift a bignum right until it is odd, and return the number of - * bits shifted. n = d * 2^s. Replaces n with d and returns s. - * Returns 0 when given 0. (Another valid answer is infinity.) - */ -unsigned -bnMakeOdd_16(struct BigNum *n) -{ - unsigned size; - unsigned s; /* shift amount */ - BNWORD16 *p; - BNWORD16 t; - - p = (BNWORD16 *)n->ptr; - size = lbnNorm_16(p, n->size); - if (!size) - return 0; - - t = BIGLITTLE(p[-1],p[0]); - s = 0; - - /* See how many words we have to shift */ - if (!t) { - /* Shift by words */ - do { - s++; - BIGLITTLE(--p,p++); - } while ((t = BIGLITTLE(p[-1],p[0])) == 0); - size -= s; - s *= 16; - memmove((BNWORD16 *)n->ptr BIG(-size), p BIG(-size), - size * sizeof(BNWORD16)); - p = (BNWORD16 *)n->ptr; - MALLOCDB; - } - - assert(t); - - if (!(t & 1)) { - /* Now count the bits */ - do { - t >>= 1; - s++; - } while ((t & 1) == 0); - - /* Shift the bits */ - lbnRshift_16(p, size, s & (16-1)); - /* Renormalize */ - if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0) - --size; - } - n->size = size; - - MALLOCDB; - return s; -} - -/* - * Do base- and modulus-dependent precomputation for rapid computation of - * base^exp (mod mod) with various exponents. - * - * See lbn16.c for the details on how the algorithm works. Basically, - * it involves precomputing a table of powers of base, base^(order^k), - * for a suitable range 0 <= k < n detemined by the maximum exponent size - * desired. To do eht exponentiation, the exponent is expressed in base - * "order" (sorry for the confusing terminology) and the precomputed powers - * are combined. - * - * This implementation allows only power-of-2 values for "order". Using - * other numbers can be more efficient, but it's more work and for the - * popular exponent size of 160 bits, an order of 8 is optimal, so it - * hasn't seemed worth it to implement. - * - * Here's a table of the optimal power-of-2 order for various exponent - * sizes and the associated (average) cost for an exponentiation. - * Note that *higher* orders are more memory-efficient; the number - * of precomputed values required is ceil(ebits/order). (Ignore the - * underscores in the middle of numbers; they're harmless.) - * - * At 2 bits, order 2 uses 0.000000 multiplies - * At 4 bits, order 2 uses 1.000000 multiplies - * At 8 bits, order 2 uses 3.000000 multiplies - * At 1_6 bits, order 2 uses 7.000000 multiplies - * At 3_2 bits, order 2 uses 15.000000 multiplies - * At 34 bits, 15.750000 (order 4) < 1_6.000000 (order 2) - * At 6_4 bits, order 4 uses 27.000000 multiplies - * At 99 bits, 39.875000 (order 8) < 40.250000 (order 4) - * At 128 bits, order 8 uses 48.500000 multiplies - * At 256 bits, order 8 uses 85.875000 multiplies - * At 280 bits, 92.625000 (order 1_6) < 92.875000 (order 8) - * At 512 bits, order 1_6 uses 147.000000 multiplies - * At 785 bits, 211.093750 (order 3_2) < 211.250000 (order 1_6) - * At 1024 bits, order 3_2 uses 257.562500 multiplies - * At 2048 bits, order 3_2 uses 456.093750 multiplies - * At 2148 bits, 475.406250 (order 6_4) < 475.468750 (order 3_2) - * At 4096 bits, order 6_4 uses 795.281250 multiplies - * At 5726 bits, 1062.609375 (order 128) < 1062.843750 (order 6_4) - * At 8192 bits, order 128 uses 1412.609375 multiplies - * At 14848 bits, 2355.750000 (order 256) < 2355.929688 (order 128) - * At 37593 bits, 5187.841797 (order 512) < 5188.144531 (order 256) - */ -int -bnBasePrecompBegin_16(struct BnBasePrecomp *pre, struct BigNum const *base, - struct BigNum const *mod, unsigned maxebits) -{ - int i; - BNWORD16 **array; /* Array of precomputed powers of base */ - unsigned n; /* Number of entries in array (needed) */ - unsigned m; /* Number of entries in array (non-NULL) */ - unsigned arraysize; /* Number of entries in array (allocated) */ - unsigned bits; /* log2(order) */ - unsigned msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); - static unsigned const bnBasePrecompThreshTable[] = { - 33, 98, 279, 784, 2147, 5725, 14847, 37592, (unsigned)-1 - }; - - /* Clear pre in case of failure */ - pre->array = 0; - pre->msize = 0; - pre->bits = 0; - pre->maxebits = 0; - pre->arraysize = 0; - pre->entries = 0; - - /* Find the correct bit-window size */ - bits = 0; - do - bits++; - while (maxebits > bnBasePrecompThreshTable[bits]); - - /* Now the number of precomputed values we need */ - n = (maxebits+bits-1)/bits; - assert(n*bits >= maxebits); - - arraysize = n+1; /* Add one trailing NULL for safety */ - array = lbnMemAlloc(arraysize * sizeof(*array)); - if (!array) - return -1; /* Out of memory */ - - /* Now allocate the entries (precomputed powers of base) */ - for (m = 0; m < n; m++) { - BNWORD16 *entry; - - LBNALLOC(entry, BNWORD16, msize); - if (!entry) - break; - array[m] = entry; - } - - /* "m" is the number of successfully allocated entries */ - if (m < n) { - /* Ran out of memory; see if we can use a smaller array */ - BNWORD16 **newarray; - - if (m < 2) { - n = 0; /* Forget it */ - } else { - /* How few bits can we use with what's allocated? */ - bits = (maxebits + m - 1) / m; -retry: - n = (maxebits + bits - 1) / bits; - if (! (n >> bits) ) - n = 0; /* Not enough to amount to anything */ - } - /* Free excess allocated array entries */ - while (m > n) { - BNWORD16 *entry = array[--m]; - LBNFREE(entry, msize); - } - if (!n) { - /* Give it up */ - lbnMemFree(array, arraysize * sizeof(*array)); - return -1; - } - /* - * Try to shrink the pointer array. This might fail, but - * it's not critical. lbnMemRealloc isn't guarnateed to - * exist, so we may have to allocate, copy, and free. - */ -#ifdef lbnMemRealloc - newarray = lbnMemRealloc(array, arraysize * sizeof(*array), - (n+1) * sizeof(*array)); - if (newarray) { - array = newarray; - arraysize = n+1; - } -#else - newarray = lbnMemAlloc((n+1) * sizeof(*array)); - if (newarray) { - memcpy(newarray, array, n * sizeof(*array)); - lbnMemFree(array, arraysize * sizeof(*array)); - array = newarray; - arraysize = n+1; - } -#endif - } - - /* Pad with null pointers */ - while (m < arraysize) - array[m++] = 0; - - /* Okay, we have our array, now initialize it */ - i = lbnBasePrecompBegin_16(array, n, bits, - (BNWORD16 *)base->ptr, base->size, - (BNWORD16 *)mod->ptr, msize); - if (i < 0) { - /* Ack, still out of memory */ - bits++; - m = n; - goto retry; - } - /* Finally, totoal success */ - pre->array = array; - pre->bits = bits; - pre->msize = msize; - pre->maxebits = n * bits; - pre->arraysize = arraysize; - pre->entries = n; - return 0; -} - -/* Free everything preallocated */ -void -bnBasePrecompEnd_16(struct BnBasePrecomp *pre) -{ - BNWORD16 **array = pre->array; - - if (array) { - unsigned entries = pre->entries; - unsigned msize = pre->msize; - unsigned m; - - for (m = 0; m < entries; m++) { - BNWORD16 *entry = array[m]; - if (entry) - LBNFREE(entry, msize); - } - lbnMemFree(array, pre->arraysize * sizeof(array)); - } - pre->array = 0; - pre->bits = 0; - pre->msize = 0; - pre->maxebits = 0; - pre->arraysize = 0; - pre->entries = 0; -} - -int -bnBasePrecompExpMod_16(struct BigNum *dest, struct BnBasePrecomp const *pre, - struct BigNum const *exp, struct BigNum const *mod) -{ - unsigned msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); - unsigned esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size); - BNWORD16 const * const *array = pre->array; - int i; - - assert(msize == pre->msize); - assert(((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1); - assert(lbnBits_16((BNWORD16 *)exp->ptr, esize) <= pre->maxebits); - - bnSizeCheck(dest, msize); - - i = lbnBasePrecompExp_16(dest->ptr, array, pre->bits, - exp->ptr, esize, mod->ptr, msize); - if (i == 0) - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize); - return i; -} - -int -bnDoubleBasePrecompExpMod_16(struct BigNum *dest, - struct BnBasePrecomp const *pre1, struct BigNum const *exp1, - struct BnBasePrecomp const *pre2, struct BigNum const *exp2, - struct BigNum const *mod) -{ - unsigned msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); - unsigned e1size = lbnNorm_16((BNWORD16 *)exp1->ptr, exp1->size); - unsigned e2size = lbnNorm_16((BNWORD16 *)exp1->ptr, exp2->size); - BNWORD16 const * const *array1 = pre1->array; - BNWORD16 const * const *array2 = pre2->array; - int i; - - assert(msize == pre1->msize); - assert(msize == pre2->msize); - assert(((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1); - assert(lbnBits_16((BNWORD16 *)exp1->ptr, e1size) <= pre1->maxebits); - assert(lbnBits_16((BNWORD16 *)exp2->ptr, e2size) <= pre2->maxebits); - assert(pre1->bits == pre2->bits); - - bnSizeCheck(dest, msize); - - i = lbnDoubleBasePrecompExp_16(dest->ptr, pre1->bits, array1, - exp1->ptr, e1size, array2, exp2->ptr, e2size, - mod->ptr, msize); - if (i == 0) - dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize); - return i; -} diff --git a/jni/libzrtp/sources/bnlib/bn16.h b/jni/libzrtp/sources/bnlib/bn16.h deleted file mode 100644 index 967d45aa8..000000000 --- a/jni/libzrtp/sources/bnlib/bn16.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * bn16.h - interface to 16-bit bignum routines. - */ -struct BigNum; -struct BnBasePrecomp; - -void bnInit_16(void); -void bnEnd_16(struct BigNum *bn); -int bnPrealloc_16(struct BigNum *bn, unsigned bits); -int bnCopy_16(struct BigNum *dest, struct BigNum const *src); -int bnSwap_16(struct BigNum *a, struct BigNum *b); -void bnNorm_16(struct BigNum *bn); -void bnExtractBigBytes_16(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned dlen); -int bnInsertBigBytes_16(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len); -void bnExtractLittleBytes_16(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned dlen); -int bnInsertLittleBytes_16(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len); -unsigned bnLSWord_16(struct BigNum const *src); -int bnReadBit_16(struct BigNum const *bn, unsigned bit); -unsigned bnBits_16(struct BigNum const *src); -int bnAdd_16(struct BigNum *dest, struct BigNum const *src); -int bnSub_16(struct BigNum *dest, struct BigNum const *src); -int bnCmpQ_16(struct BigNum const *a, unsigned b); -int bnSetQ_16(struct BigNum *dest, unsigned src); -int bnAddQ_16(struct BigNum *dest, unsigned src); -int bnSubQ_16(struct BigNum *dest, unsigned src); -int bnCmp_16(struct BigNum const *a, struct BigNum const *b); -int bnSquare_16(struct BigNum *dest, struct BigNum const *src); -int bnMul_16(struct BigNum *dest, struct BigNum const *a, - struct BigNum const *b); -int bnMulQ_16(struct BigNum *dest, struct BigNum const *a, unsigned b); -int bnDivMod_16(struct BigNum *q, struct BigNum *r, struct BigNum const *n, - struct BigNum const *d); -int bnMod_16(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *d); -unsigned bnModQ_16(struct BigNum const *src, unsigned d); -int bnExpMod_16(struct BigNum *dest, struct BigNum const *n, - struct BigNum const *exp, struct BigNum const *mod); -int bnDoubleExpMod_16(struct BigNum *dest, - struct BigNum const *n1, struct BigNum const *e1, - struct BigNum const *n2, struct BigNum const *e2, - struct BigNum const *mod); -int bnTwoExpMod_16(struct BigNum *n, struct BigNum const *exp, - struct BigNum const *mod); -int bnGcd_16(struct BigNum *dest, struct BigNum const *a, - struct BigNum const *b); -int bnInv_16(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *mod); -int bnLShift_16(struct BigNum *dest, unsigned amt); -void bnRShift_16(struct BigNum *dest, unsigned amt); -unsigned bnMakeOdd_16(struct BigNum *n); -int bnBasePrecompBegin_16(struct BnBasePrecomp *pre, struct BigNum const *base, - struct BigNum const *mod, unsigned maxebits); -void bnBasePrecompEnd_16(struct BnBasePrecomp *pre); -int bnBasePrecompExpMod_16(struct BigNum *dest, struct BnBasePrecomp const *pre, - struct BigNum const *exp, struct BigNum const *mod); -int bnDoubleBasePrecompExpMod_16(struct BigNum *dest, - struct BnBasePrecomp const *pre1, struct BigNum const *exp1, - struct BnBasePrecomp const *pre2, struct BigNum const *exp2, - struct BigNum const *mod); diff --git a/jni/libzrtp/sources/bnlib/bn32.c b/jni/libzrtp/sources/bnlib/bn32.c deleted file mode 100644 index ee0d257d2..000000000 --- a/jni/libzrtp/sources/bnlib/bn32.c +++ /dev/null @@ -1,1188 +0,0 @@ -/* - * bn32.c - the high-level bignum interface - * - * Like lbn32.c, this reserves the string "32" for textual replacement. - * The string must not appear anywhere unless it is intended to be replaced - * to generate other bignum interface functions. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - */ - -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include <bnconfig.h> -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_ASSERT_H -#define NO_ASSERT_H 0 -#endif -#ifndef NO_STRING_H -#define NO_STRING_H 0 -#endif -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 0 -#endif -#ifndef NEED_MEMORY_H -#define NEED_MEMORY_H 0 -#endif - -#if !NO_ASSERT_H -#include <assert.h> -#else -#define assert(x) (void)0 -#endif - -#if !NO_STRING_H -#include <string.h> /* for memmove() in bnMakeOdd */ -#elif HAVE_STRINGS_H -#include <strings.h> -#endif -#if NEED_MEMORY_H -#include <memory.h> -#endif - -/* - * This was useful during debugging, so it's left in here. - * You can ignore it. DBMALLOC is generally undefined. - */ -#ifndef DBMALLOC -#define DBMALLOC 0 -#endif -#if DBMALLOC -#include "../dbmalloc/malloc.h" -#define MALLOCDB malloc_chain_check(1) -#else -#define MALLOCDB (void)0 -#endif - -#include "lbn.h" -#include "lbn32.h" -#include "lbnmem.h" -#include "bn32.h" -#include "bn.h" - -/* Work-arounds for some particularly broken systems */ -#include "kludge.h" /* For memmove() */ - -/* Functions */ -void -bnInit_32(void) -{ - bnEnd = bnEnd_32; - bnPrealloc = bnPrealloc_32; - bnCopy = bnCopy_32; - bnNorm = bnNorm_32; - bnExtractBigBytes = bnExtractBigBytes_32; - bnInsertBigBytes = bnInsertBigBytes_32; - bnExtractLittleBytes = bnExtractLittleBytes_32; - bnInsertLittleBytes = bnInsertLittleBytes_32; - bnLSWord = bnLSWord_32; - bnReadBit = bnReadBit_32; - bnBits = bnBits_32; - bnAdd = bnAdd_32; - bnSub = bnSub_32; - bnCmpQ = bnCmpQ_32; - bnSetQ = bnSetQ_32; - bnAddQ = bnAddQ_32; - bnSubQ = bnSubQ_32; - bnCmp = bnCmp_32; - bnSquare = bnSquare_32; - bnMul = bnMul_32; - bnMulQ = bnMulQ_32; - bnDivMod = bnDivMod_32; - bnMod = bnMod_32; - bnModQ = bnModQ_32; - bnExpMod = bnExpMod_32; - bnDoubleExpMod = bnDoubleExpMod_32; - bnTwoExpMod = bnTwoExpMod_32; - bnGcd = bnGcd_32; - bnInv = bnInv_32; - bnLShift = bnLShift_32; - bnRShift = bnRShift_32; - bnMakeOdd = bnMakeOdd_32; - bnBasePrecompBegin = bnBasePrecompBegin_32; - bnBasePrecompEnd = bnBasePrecompEnd_32; - bnBasePrecompExpMod = bnBasePrecompExpMod_32; - bnDoubleBasePrecompExpMod = bnDoubleBasePrecompExpMod_32; -} - -void -bnEnd_32(struct BigNum *bn) -{ - if (bn->ptr) { - LBNFREE((BNWORD32 *)bn->ptr, bn->allocated); - bn->ptr = 0; - } - bn->size = 0; - bn->allocated = 0; - - MALLOCDB; -} - -/* Internal function. It operates in words. */ -static int -bnResize_32(struct BigNum *bn, unsigned len) -{ - void *p; - - /* Round size up: most mallocs impose 8-byte granularity anyway */ - len = (len + (8/sizeof(BNWORD32) - 1)) & ~(8/sizeof(BNWORD32) - 1); - p = LBNREALLOC((BNWORD32 *)bn->ptr, bn->allocated, len); - if (!p) - return -1; - bn->ptr = p; - bn->allocated = len; - - MALLOCDB; - - return 0; -} - -#define bnSizeCheck(bn, size) \ - if (bn->allocated < size && bnResize_32(bn, size) < 0) \ - return -1 - -/* Preallocate enough space in bn to hold "bits" bits. */ -int -bnPrealloc_32(struct BigNum *bn, unsigned bits) -{ - bits = (bits + 32-1)/32; - bnSizeCheck(bn, bits); - MALLOCDB; - return 0; -} - -int -bnCopy_32(struct BigNum *dest, struct BigNum const *src) -{ - bnSizeCheck(dest, src->size); - dest->size = src->size; - lbnCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, src->size); - MALLOCDB; - return 0; -} - -/* Is this ever needed? Normalize the bn by deleting high-order 0 words */ -void -bnNorm_32(struct BigNum *bn) -{ - bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, bn->size); -} - -/* - * Convert a bignum to big-endian bytes. Returns, in big-endian form, a - * substring of the bignum starting from lsbyte and "len" bytes long. - * Unused high-order (leading) bytes are filled with 0. - */ -void -bnExtractBigBytes_32(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size * (32 / 8); - - /* Fill unused leading bytes with 0 */ - while (s < lsbyte + len) { - *dest++ = 0; - len--; - } - - if (len) - lbnExtractBigBytes_32((BNWORD32 *)bn->ptr, dest, lsbyte, len); - MALLOCDB; -} - -/* The inverse of the above. */ -int -bnInsertBigBytes_32(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size; - unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32); - - /* Pad with zeros as required */ - bnSizeCheck(bn, words); - - if (s < words) { - lbnZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s); - s = words; - } - - lbnInsertBigBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len); - - bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, s); - - MALLOCDB; - return 0; -} - - -/* - * Convert a bignum to little-endian bytes. Returns, in little-endian form, a - * substring of the bignum starting from lsbyte and "len" bytes long. - * Unused high-order (trailing) bytes are filled with 0. - */ -void -bnExtractLittleBytes_32(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size * (32 / 8); - - /* Fill unused leading bytes with 0 */ - while (s < lsbyte + len) - dest[--len] = 0; - - if (len) - lbnExtractLittleBytes_32((BNWORD32 *)bn->ptr, dest, - lsbyte, len); - MALLOCDB; -} - -/* The inverse of the above */ -int -bnInsertLittleBytes_32(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size; - unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32); - - /* Pad with zeros as required */ - bnSizeCheck(bn, words); - - if (s < words) { - lbnZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s); - s = words; - } - - lbnInsertLittleBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len); - - bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, s); - - MALLOCDB; - return 0; -} - -/* Return the least-significant word of the input. */ -unsigned -bnLSWord_32(struct BigNum const *bn) -{ - return bn->size ? (unsigned)((BNWORD32 *)bn->ptr)[BIGLITTLE(-1,0)]: 0; -} - -/* Return a selected bit of the data */ -int -bnReadBit_32(struct BigNum const *bn, unsigned bit) -{ - BNWORD32 word; - if (bit/32 >= bn->size) - return 0; - word = ((BNWORD32 *)bn->ptr)[BIGLITTLE(-1-bit/32,bit/32)]; - return (int)(word >> (bit % 32) & 1); -} - -/* Count the number of significant bits. */ -unsigned -bnBits_32(struct BigNum const *bn) -{ - return lbnBits_32((BNWORD32 *)bn->ptr, bn->size); -} - -/* dest += src */ -int -bnAdd_32(struct BigNum *dest, struct BigNum const *src) -{ - unsigned s = src->size, d = dest->size; - BNWORD32 t; - - if (!s) - return 0; - - bnSizeCheck(dest, s); - - if (d < s) { - lbnZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d); - dest->size = d = s; - MALLOCDB; - } - t = lbnAddN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s); - MALLOCDB; - if (t) { - if (d > s) { - t = lbnAdd1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s), - d-s, t); - MALLOCDB; - } - if (t) { - bnSizeCheck(dest, d+1); - ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t; - dest->size = d+1; - } - } - return 0; -} - -/* - * dest -= src. - * If dest goes negative, this produces the absolute value of - * the difference (the negative of the true value) and returns 1. - * Otherwise, it returls 0. - */ -int -bnSub_32(struct BigNum *dest, struct BigNum const *src) -{ - unsigned s = src->size, d = dest->size; - BNWORD32 t; - - if (d < s && d < (s = lbnNorm_32((BNWORD32 *)src->ptr, s))) { - bnSizeCheck(dest, s); - lbnZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d); - dest->size = d = s; - MALLOCDB; - } - if (!s) - return 0; - t = lbnSubN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s); - MALLOCDB; - if (t) { - if (d > s) { - t = lbnSub1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s), - d-s, t); - MALLOCDB; - } - if (t) { - lbnNeg_32((BNWORD32 *)dest->ptr, d); - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, - dest->size); - MALLOCDB; - return 1; - } - } - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dest->size); - return 0; -} - -/* - * Compare the BigNum to the given value, which must be < 65536. - * Returns -1. 0 or 1 if a<b, a == b or a>b. - * a <=> b --> bnCmpQ(a,b) <=> 0 - */ -int -bnCmpQ_32(struct BigNum const *a, unsigned b) -{ - unsigned t; - BNWORD32 v; - - t = lbnNorm_32((BNWORD32 *)a->ptr, a->size); - /* If a is more than one word long or zero, it's easy... */ - if (t != 1) - return (t > 1) ? 1 : (b ? -1 : 0); - v = (unsigned)((BNWORD32 *)a->ptr)[BIGLITTLE(-1,0)]; - return (v > b) ? 1 : ((v < b) ? -1 : 0); -} - -/* Set dest to a small value */ -int -bnSetQ_32(struct BigNum *dest, unsigned src) -{ - if (src) { - bnSizeCheck(dest, 1); - - ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD32)src; - dest->size = 1; - } else { - dest->size = 0; - } - return 0; -} - -/* dest += src */ -int -bnAddQ_32(struct BigNum *dest, unsigned src) -{ - BNWORD32 t; - - if (!dest->size) - return bnSetQ(dest, src); - - t = lbnAdd1_32((BNWORD32 *)dest->ptr, dest->size, (BNWORD32)src); - MALLOCDB; - if (t) { - src = dest->size; - bnSizeCheck(dest, src+1); - ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t; - dest->size = src+1; - } - return 0; -} - -/* - * Return value as for bnSub: 1 if subtract underflowed, in which - * case the return is the negative of the computed value. - */ -int -bnSubQ_32(struct BigNum *dest, unsigned src) -{ - BNWORD32 t; - - if (!dest->size) - return bnSetQ(dest, src) < 0 ? -1 : (src != 0); - - t = lbnSub1_32((BNWORD32 *)dest->ptr, dest->size, src); - MALLOCDB; - if (t) { - /* Underflow. <= 1 word, so do it simply. */ - lbnNeg_32((BNWORD32 *)dest->ptr, 1); - dest->size = 1; - return 1; - } -/* Try to normalize? Needing this is going to be pretty damn rare. */ -/* dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dest->size); */ - return 0; -} - -/* - * Compare two BigNums. Returns -1. 0 or 1 if a<b, a == b or a>b. - * a <=> b --> bnCmp(a,b) <=> 0 - */ -int -bnCmp_32(struct BigNum const *a, struct BigNum const *b) -{ - unsigned s, t; - - s = lbnNorm_32((BNWORD32 *)a->ptr, a->size); - t = lbnNorm_32((BNWORD32 *)b->ptr, b->size); - - if (s != t) - return s > t ? 1 : -1; - return lbnCmp_32((BNWORD32 *)a->ptr, (BNWORD32 *)b->ptr, s); -} - -/* dest = src*src. This is more efficient than bnMul. */ -int -bnSquare_32(struct BigNum *dest, struct BigNum const *src) -{ - unsigned s; - BNWORD32 *srcbuf; - - s = lbnNorm_32((BNWORD32 *)src->ptr, src->size); - if (!s) { - dest->size = 0; - return 0; - } - bnSizeCheck(dest, 2*s); - - if (src == dest) { - LBNALLOC(srcbuf, BNWORD32, s); - if (!srcbuf) - return -1; - lbnCopy_32(srcbuf, (BNWORD32 *)src->ptr, s); - lbnSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)srcbuf, s); - LBNFREE(srcbuf, s); - } else { - lbnSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s); - } - - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, 2*s); - MALLOCDB; - return 0; -} - -/* dest = a * b. Any overlap between operands is allowed. */ -int -bnMul_32(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) -{ - unsigned s, t; - BNWORD32 *srcbuf; - - s = lbnNorm_32((BNWORD32 *)a->ptr, a->size); - t = lbnNorm_32((BNWORD32 *)b->ptr, b->size); - - if (!s || !t) { - dest->size = 0; - return 0; - } - - if (a == b) - return bnSquare_32(dest, a); - - bnSizeCheck(dest, s+t); - - if (dest == a) { - LBNALLOC(srcbuf, BNWORD32, s); - if (!srcbuf) - return -1; - lbnCopy_32(srcbuf, (BNWORD32 *)a->ptr, s); - lbnMul_32((BNWORD32 *)dest->ptr, srcbuf, s, - (BNWORD32 *)b->ptr, t); - LBNFREE(srcbuf, s); - } else if (dest == b) { - LBNALLOC(srcbuf, BNWORD32, t); - if (!srcbuf) - return -1; - lbnCopy_32(srcbuf, (BNWORD32 *)b->ptr, t); - lbnMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, - srcbuf, t); - LBNFREE(srcbuf, t); - } else { - lbnMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, - (BNWORD32 *)b->ptr, t); - } - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s+t); - MALLOCDB; - return 0; -} - -/* dest = a * b */ -int -bnMulQ_32(struct BigNum *dest, struct BigNum const *a, unsigned b) -{ - unsigned s; - - s = lbnNorm_32((BNWORD32 *)a->ptr, a->size); - if (!s || !b) { - dest->size = 0; - return 0; - } - if (b == 1) - return bnCopy_32(dest, a); - bnSizeCheck(dest, s+1); - lbnMulN1_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, b); - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s+1); - MALLOCDB; - return 0; -} - -/* q = n/d, r = n % d */ -int -bnDivMod_32(struct BigNum *q, struct BigNum *r, struct BigNum const *n, - struct BigNum const *d) -{ - unsigned dsize, nsize; - BNWORD32 qhigh; - - dsize = lbnNorm_32((BNWORD32 *)d->ptr, d->size); - nsize = lbnNorm_32((BNWORD32 *)n->ptr, n->size); - - if (nsize < dsize) { - q->size = 0; /* No quotient */ - r->size = nsize; - return 0; /* Success */ - } - - bnSizeCheck(q, nsize-dsize); - - if (r != n) { /* You are allowed to reduce in place */ - bnSizeCheck(r, nsize); - lbnCopy_32((BNWORD32 *)r->ptr, (BNWORD32 *)n->ptr, nsize); - } - - qhigh = lbnDiv_32((BNWORD32 *)q->ptr, (BNWORD32 *)r->ptr, nsize, - (BNWORD32 *)d->ptr, dsize); - nsize -= dsize; - if (qhigh) { - bnSizeCheck(q, nsize+1); - *((BNWORD32 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh; - q->size = nsize+1; - } else { - q->size = lbnNorm_32((BNWORD32 *)q->ptr, nsize); - } - r->size = lbnNorm_32((BNWORD32 *)r->ptr, dsize); - MALLOCDB; - return 0; -} - -/* det = src % d */ -int -bnMod_32(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d) -{ - unsigned dsize, nsize; - - nsize = lbnNorm_32((BNWORD32 *)src->ptr, src->size); - dsize = lbnNorm_32((BNWORD32 *)d->ptr, d->size); - - - if (dest != src) { - bnSizeCheck(dest, nsize); - lbnCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, nsize); - } - - if (nsize < dsize) { - dest->size = nsize; /* No quotient */ - return 0; - } - - (void)lbnDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-dsize,+dsize), - (BNWORD32 *)dest->ptr, nsize, - (BNWORD32 *)d->ptr, dsize); - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dsize); - MALLOCDB; - return 0; -} - -/* return src % d. */ -unsigned -bnModQ_32(struct BigNum const *src, unsigned d) -{ - unsigned s; - - s = lbnNorm_32((BNWORD32 *)src->ptr, src->size); - if (!s) - return 0; - - if (d & (d-1)) /* Not a power of 2 */ - d = lbnModQ_32((BNWORD32 *)src->ptr, s, d); - else - d = (unsigned)((BNWORD32 *)src->ptr)[BIGLITTLE(-1,0)] & (d-1); - return d; -} - -/* dest = n^exp (mod mod) */ -int -bnExpMod_32(struct BigNum *dest, struct BigNum const *n, - struct BigNum const *exp, struct BigNum const *mod) -{ - unsigned nsize, esize, msize; - - nsize = lbnNorm_32((BNWORD32 *)n->ptr, n->size); - esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size); - msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); - - if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) - return -1; /* Illegal modulus! */ - - bnSizeCheck(dest, msize); - - /* Special-case base of 2 */ - if (nsize == 1 && ((BNWORD32 *)n->ptr)[BIGLITTLE(-1,0)] == 2) { - if (lbnTwoExpMod_32((BNWORD32 *)dest->ptr, - (BNWORD32 *)exp->ptr, esize, - (BNWORD32 *)mod->ptr, msize) < 0) - return -1; - } else { - if (lbnExpMod_32((BNWORD32 *)dest->ptr, - (BNWORD32 *)n->ptr, nsize, - (BNWORD32 *)exp->ptr, esize, - (BNWORD32 *)mod->ptr, msize) < 0) - return -1; - } - - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize); - MALLOCDB; - return 0; -} - -/* - * dest = n1^e1 * n2^e2 (mod mod). This is more efficient than two - * separate modular exponentiations, and in fact asymptotically approaches - * the cost of one. - */ -int -bnDoubleExpMod_32(struct BigNum *dest, - struct BigNum const *n1, struct BigNum const *e1, - struct BigNum const *n2, struct BigNum const *e2, - struct BigNum const *mod) -{ - unsigned n1size, e1size, n2size, e2size, msize; - - n1size = lbnNorm_32((BNWORD32 *)n1->ptr, n1->size); - e1size = lbnNorm_32((BNWORD32 *)e1->ptr, e1->size); - n2size = lbnNorm_32((BNWORD32 *)n2->ptr, n2->size); - e2size = lbnNorm_32((BNWORD32 *)e2->ptr, e2->size); - msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); - - if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) - return -1; /* Illegal modulus! */ - - bnSizeCheck(dest, msize); - - if (lbnDoubleExpMod_32((BNWORD32 *)dest->ptr, - (BNWORD32 *)n1->ptr, n1size, (BNWORD32 *)e1->ptr, e1size, - (BNWORD32 *)n2->ptr, n2size, (BNWORD32 *)e2->ptr, e2size, - (BNWORD32 *)mod->ptr, msize) < 0) - return -1; - - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize); - MALLOCDB; - return 0; -} - -/* n = 2^exp (mod mod) */ -int -bnTwoExpMod_32(struct BigNum *n, struct BigNum const *exp, - struct BigNum const *mod) -{ - unsigned esize, msize; - - esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size); - msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); - - if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) - return -1; /* Illegal modulus! */ - - bnSizeCheck(n, msize); - - if (lbnTwoExpMod_32((BNWORD32 *)n->ptr, (BNWORD32 *)exp->ptr, esize, - (BNWORD32 *)mod->ptr, msize) < 0) - return -1; - - n->size = lbnNorm_32((BNWORD32 *)n->ptr, msize); - MALLOCDB; - return 0; -} - -/* dest = gcd(a, b) */ -int -bnGcd_32(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) -{ - BNWORD32 *tmp; - unsigned asize, bsize; - int i; - - /* Kind of silly, but we might as well permit it... */ - if (a == b) - return dest == a ? 0 : bnCopy(dest, a); - - /* Ensure a is not the same as "dest" */ - if (a == dest) { - a = b; - b = dest; - } - - asize = lbnNorm_32((BNWORD32 *)a->ptr, a->size); - bsize = lbnNorm_32((BNWORD32 *)b->ptr, b->size); - - bnSizeCheck(dest, bsize+1); - - /* Copy a to tmp */ - LBNALLOC(tmp, BNWORD32, asize+1); - if (!tmp) - return -1; - lbnCopy_32(tmp, (BNWORD32 *)a->ptr, asize); - - /* Copy b to dest, if necessary */ - if (dest != b) - lbnCopy_32((BNWORD32 *)dest->ptr, - (BNWORD32 *)b->ptr, bsize); - if (bsize > asize || (bsize == asize && - lbnCmp_32((BNWORD32 *)b->ptr, (BNWORD32 *)a->ptr, asize) > 0)) - { - i = lbnGcd_32((BNWORD32 *)dest->ptr, bsize, tmp, asize, - &dest->size); - if (i > 0) /* Result in tmp, not dest */ - lbnCopy_32((BNWORD32 *)dest->ptr, tmp, dest->size); - } else { - i = lbnGcd_32(tmp, asize, (BNWORD32 *)dest->ptr, bsize, - &dest->size); - if (i == 0) /* Result in tmp, not dest */ - lbnCopy_32((BNWORD32 *)dest->ptr, tmp, dest->size); - } - LBNFREE(tmp, asize+1); - MALLOCDB; - return (i < 0) ? i : 0; -} - -/* - * dest = 1/src (mod mod). Returns >0 if gcd(src, mod) != 1 (in which case - * the inverse does not exist). - */ -int -bnInv_32(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *mod) -{ - unsigned s, m; - int i; - - s = lbnNorm_32((BNWORD32 *)src->ptr, src->size); - m = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); - - /* lbnInv_32 requires that the input be less than the modulus */ - if (m < s || - (m==s && lbnCmp_32((BNWORD32 *)src->ptr, (BNWORD32 *)mod->ptr, s))) - { - bnSizeCheck(dest, s + (m==s)); - if (dest != src) - lbnCopy_32((BNWORD32 *)dest->ptr, - (BNWORD32 *)src->ptr, s); - /* Pre-reduce modulo the modulus */ - (void)lbnDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-m,+m), - (BNWORD32 *)dest->ptr, s, - (BNWORD32 *)mod->ptr, m); - s = lbnNorm_32((BNWORD32 *)dest->ptr, m); - MALLOCDB; - } else { - bnSizeCheck(dest, m+1); - if (dest != src) - lbnCopy_32((BNWORD32 *)dest->ptr, - (BNWORD32 *)src->ptr, s); - } - - i = lbnInv_32((BNWORD32 *)dest->ptr, s, (BNWORD32 *)mod->ptr, m); - if (i == 0) - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, m); - - MALLOCDB; - return i; -} - -/* - * Shift a bignum left the appropriate number of bits, - * multiplying by 2^amt. - */ -int -bnLShift_32(struct BigNum *dest, unsigned amt) -{ - unsigned s = dest->size; - BNWORD32 carry; - - if (amt % 32) { - carry = lbnLshift_32((BNWORD32 *)dest->ptr, s, amt % 32); - if (carry) { - s++; - bnSizeCheck(dest, s); - ((BNWORD32 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry; - } - } - - amt /= 32; - if (amt) { - bnSizeCheck(dest, s+amt); - memmove((BNWORD32 *)dest->ptr BIGLITTLE(-s-amt, +amt), - (BNWORD32 *)dest->ptr BIG(-s), - s * sizeof(BNWORD32)); - lbnZero_32((BNWORD32 *)dest->ptr, amt); - s += amt; - } - dest->size = s; - MALLOCDB; - return 0; -} - -/* - * Shift a bignum right the appropriate number of bits, - * dividing by 2^amt. - */ -void -bnRShift_32(struct BigNum *dest, unsigned amt) -{ - unsigned s = dest->size; - - if (amt >= 32) { - memmove( - (BNWORD32 *)dest->ptr BIG(-s+amt/32), - (BNWORD32 *)dest->ptr BIGLITTLE(-s, +amt/32), - (s-amt/32) * sizeof(BNWORD32)); - s -= amt/32; - amt %= 32; - } - - if (amt) - (void)lbnRshift_32((BNWORD32 *)dest->ptr, s, amt); - - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s); - MALLOCDB; -} - -/* - * Shift a bignum right until it is odd, and return the number of - * bits shifted. n = d * 2^s. Replaces n with d and returns s. - * Returns 0 when given 0. (Another valid answer is infinity.) - */ -unsigned -bnMakeOdd_32(struct BigNum *n) -{ - unsigned size; - unsigned s; /* shift amount */ - BNWORD32 *p; - BNWORD32 t; - - p = (BNWORD32 *)n->ptr; - size = lbnNorm_32(p, n->size); - if (!size) - return 0; - - t = BIGLITTLE(p[-1],p[0]); - s = 0; - - /* See how many words we have to shift */ - if (!t) { - /* Shift by words */ - do { - s++; - BIGLITTLE(--p,p++); - } while ((t = BIGLITTLE(p[-1],p[0])) == 0); - size -= s; - s *= 32; - memmove((BNWORD32 *)n->ptr BIG(-size), p BIG(-size), - size * sizeof(BNWORD32)); - p = (BNWORD32 *)n->ptr; - MALLOCDB; - } - - assert(t); - - if (!(t & 1)) { - /* Now count the bits */ - do { - t >>= 1; - s++; - } while ((t & 1) == 0); - - /* Shift the bits */ - lbnRshift_32(p, size, s & (32-1)); - /* Renormalize */ - if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0) - --size; - } - n->size = size; - - MALLOCDB; - return s; -} - -/* - * Do base- and modulus-dependent precomputation for rapid computation of - * base^exp (mod mod) with various exponents. - * - * See lbn32.c for the details on how the algorithm works. Basically, - * it involves precomputing a table of powers of base, base^(order^k), - * for a suitable range 0 <= k < n detemined by the maximum exponent size - * desired. To do eht exponentiation, the exponent is expressed in base - * "order" (sorry for the confusing terminology) and the precomputed powers - * are combined. - * - * This implementation allows only power-of-2 values for "order". Using - * other numbers can be more efficient, but it's more work and for the - * popular exponent size of 320 bits, an order of 8 is optimal, so it - * hasn't seemed worth it to implement. - * - * Here's a table of the optimal power-of-2 order for various exponent - * sizes and the associated (average) cost for an exponentiation. - * Note that *higher* orders are more memory-efficient; the number - * of precomputed values required is ceil(ebits/order). (Ignore the - * underscores in the middle of numbers; they're harmless.) - * - * At 2 bits, order 2 uses 0.000000 multiplies - * At 4 bits, order 2 uses 1.000000 multiplies - * At 8 bits, order 2 uses 3.000000 multiplies - * At 1_6 bits, order 2 uses 7.000000 multiplies - * At 3_2 bits, order 2 uses 15.000000 multiplies - * At 34 bits, 15.750000 (order 4) < 1_6.000000 (order 2) - * At 6_4 bits, order 4 uses 27.000000 multiplies - * At 99 bits, 39.875000 (order 8) < 40.250000 (order 4) - * At 128 bits, order 8 uses 48.500000 multiplies - * At 256 bits, order 8 uses 85.875000 multiplies - * At 280 bits, 92.625000 (order 1_6) < 92.875000 (order 8) - * At 512 bits, order 1_6 uses 147.000000 multiplies - * At 785 bits, 211.093750 (order 3_2) < 211.250000 (order 1_6) - * At 1024 bits, order 3_2 uses 257.562500 multiplies - * At 2048 bits, order 3_2 uses 456.093750 multiplies - * At 2148 bits, 475.406250 (order 6_4) < 475.468750 (order 3_2) - * At 4096 bits, order 6_4 uses 795.281250 multiplies - * At 5726 bits, 1062.609375 (order 128) < 1062.843750 (order 6_4) - * At 8192 bits, order 128 uses 1412.609375 multiplies - * At 14848 bits, 2355.750000 (order 256) < 2355.929688 (order 128) - * At 37593 bits, 5187.841797 (order 512) < 5188.144531 (order 256) - */ -int -bnBasePrecompBegin_32(struct BnBasePrecomp *pre, struct BigNum const *base, - struct BigNum const *mod, unsigned maxebits) -{ - int i; - BNWORD32 **array; /* Array of precomputed powers of base */ - unsigned n; /* Number of entries in array (needed) */ - unsigned m; /* Number of entries in array (non-NULL) */ - unsigned arraysize; /* Number of entries in array (allocated) */ - unsigned bits; /* log2(order) */ - unsigned msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); - static unsigned const bnBasePrecompThreshTable[] = { - 33, 98, 279, 784, 2147, 5725, 14847, 37592, (unsigned)-1 - }; - - /* Clear pre in case of failure */ - pre->array = 0; - pre->msize = 0; - pre->bits = 0; - pre->maxebits = 0; - pre->arraysize = 0; - pre->entries = 0; - - /* Find the correct bit-window size */ - bits = 0; - do - bits++; - while (maxebits > bnBasePrecompThreshTable[bits]); - - /* Now the number of precomputed values we need */ - n = (maxebits+bits-1)/bits; - assert(n*bits >= maxebits); - - arraysize = n+1; /* Add one trailing NULL for safety */ - array = lbnMemAlloc(arraysize * sizeof(*array)); - if (!array) - return -1; /* Out of memory */ - - /* Now allocate the entries (precomputed powers of base) */ - for (m = 0; m < n; m++) { - BNWORD32 *entry; - - LBNALLOC(entry, BNWORD32, msize); - if (!entry) - break; - array[m] = entry; - } - - /* "m" is the number of successfully allocated entries */ - if (m < n) { - /* Ran out of memory; see if we can use a smaller array */ - BNWORD32 **newarray; - - if (m < 2) { - n = 0; /* Forget it */ - } else { - /* How few bits can we use with what's allocated? */ - bits = (maxebits + m - 1) / m; -retry: - n = (maxebits + bits - 1) / bits; - if (! (n >> bits) ) - n = 0; /* Not enough to amount to anything */ - } - /* Free excess allocated array entries */ - while (m > n) { - BNWORD32 *entry = array[--m]; - LBNFREE(entry, msize); - } - if (!n) { - /* Give it up */ - lbnMemFree(array, arraysize * sizeof(*array)); - return -1; - } - /* - * Try to shrink the pointer array. This might fail, but - * it's not critical. lbnMemRealloc isn't guarnateed to - * exist, so we may have to allocate, copy, and free. - */ -#ifdef lbnMemRealloc - newarray = lbnMemRealloc(array, arraysize * sizeof(*array), - (n+1) * sizeof(*array)); - if (newarray) { - array = newarray; - arraysize = n+1; - } -#else - newarray = lbnMemAlloc((n+1) * sizeof(*array)); - if (newarray) { - memcpy(newarray, array, n * sizeof(*array)); - lbnMemFree(array, arraysize * sizeof(*array)); - array = newarray; - arraysize = n+1; - } -#endif - } - - /* Pad with null pointers */ - while (m < arraysize) - array[m++] = 0; - - /* Okay, we have our array, now initialize it */ - i = lbnBasePrecompBegin_32(array, n, bits, - (BNWORD32 *)base->ptr, base->size, - (BNWORD32 *)mod->ptr, msize); - if (i < 0) { - /* Ack, still out of memory */ - bits++; - m = n; - goto retry; - } - /* Finally, totoal success */ - pre->array = array; - pre->bits = bits; - pre->msize = msize; - pre->maxebits = n * bits; - pre->arraysize = arraysize; - pre->entries = n; - return 0; -} - -/* Free everything preallocated */ -void -bnBasePrecompEnd_32(struct BnBasePrecomp *pre) -{ - BNWORD32 **array = pre->array; - - if (array) { - unsigned entries = pre->entries; - unsigned msize = pre->msize; - unsigned m; - - for (m = 0; m < entries; m++) { - BNWORD32 *entry = array[m]; - if (entry) - LBNFREE(entry, msize); - } - lbnMemFree(array, pre->arraysize * sizeof(array)); - } - pre->array = 0; - pre->bits = 0; - pre->msize = 0; - pre->maxebits = 0; - pre->arraysize = 0; - pre->entries = 0; -} - -int -bnBasePrecompExpMod_32(struct BigNum *dest, struct BnBasePrecomp const *pre, - struct BigNum const *exp, struct BigNum const *mod) -{ - unsigned msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); - unsigned esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size); - BNWORD32 const * const *array = pre->array; - int i; - - assert(msize == pre->msize); - assert(((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1); - assert(lbnBits_32((BNWORD32 *)exp->ptr, esize) <= pre->maxebits); - - bnSizeCheck(dest, msize); - - i = lbnBasePrecompExp_32(dest->ptr, array, pre->bits, - exp->ptr, esize, mod->ptr, msize); - if (i == 0) - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize); - return i; -} - -int -bnDoubleBasePrecompExpMod_32(struct BigNum *dest, - struct BnBasePrecomp const *pre1, struct BigNum const *exp1, - struct BnBasePrecomp const *pre2, struct BigNum const *exp2, - struct BigNum const *mod) -{ - unsigned msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); - unsigned e1size = lbnNorm_32((BNWORD32 *)exp1->ptr, exp1->size); - unsigned e2size = lbnNorm_32((BNWORD32 *)exp1->ptr, exp2->size); - BNWORD32 const * const *array1 = pre1->array; - BNWORD32 const * const *array2 = pre2->array; - int i; - - assert(msize == pre1->msize); - assert(msize == pre2->msize); - assert(((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1); - assert(lbnBits_32((BNWORD32 *)exp1->ptr, e1size) <= pre1->maxebits); - assert(lbnBits_32((BNWORD32 *)exp2->ptr, e2size) <= pre2->maxebits); - assert(pre1->bits == pre2->bits); - - bnSizeCheck(dest, msize); - - i = lbnDoubleBasePrecompExp_32(dest->ptr, pre1->bits, array1, - exp1->ptr, e1size, array2, exp2->ptr, e2size, - mod->ptr, msize); - if (i == 0) - dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize); - return i; -} diff --git a/jni/libzrtp/sources/bnlib/bn32.h b/jni/libzrtp/sources/bnlib/bn32.h deleted file mode 100644 index 7beba6182..000000000 --- a/jni/libzrtp/sources/bnlib/bn32.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * bn32.h - interface to 32-bit bignum routines. - */ -struct BigNum; -struct BnBasePrecomp; - -void bnInit_32(void); -void bnEnd_32(struct BigNum *bn); -int bnPrealloc_32(struct BigNum *bn, unsigned bits); -int bnCopy_32(struct BigNum *dest, struct BigNum const *src); -int bnSwap_32(struct BigNum *a, struct BigNum *b); -void bnNorm_32(struct BigNum *bn); -void bnExtractBigBytes_32(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned dlen); -int bnInsertBigBytes_32(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len); -void bnExtractLittleBytes_32(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned dlen); -int bnInsertLittleBytes_32(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len); -unsigned bnLSWord_32(struct BigNum const *src); -int bnReadBit_32(struct BigNum const *bn, unsigned bit); -unsigned bnBits_32(struct BigNum const *src); -int bnAdd_32(struct BigNum *dest, struct BigNum const *src); -int bnSub_32(struct BigNum *dest, struct BigNum const *src); -int bnCmpQ_32(struct BigNum const *a, unsigned b); -int bnSetQ_32(struct BigNum *dest, unsigned src); -int bnAddQ_32(struct BigNum *dest, unsigned src); -int bnSubQ_32(struct BigNum *dest, unsigned src); -int bnCmp_32(struct BigNum const *a, struct BigNum const *b); -int bnSquare_32(struct BigNum *dest, struct BigNum const *src); -int bnMul_32(struct BigNum *dest, struct BigNum const *a, - struct BigNum const *b); -int bnMulQ_32(struct BigNum *dest, struct BigNum const *a, unsigned b); -int bnDivMod_32(struct BigNum *q, struct BigNum *r, struct BigNum const *n, - struct BigNum const *d); -int bnMod_32(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *d); -unsigned bnModQ_32(struct BigNum const *src, unsigned d); -int bnExpMod_32(struct BigNum *dest, struct BigNum const *n, - struct BigNum const *exp, struct BigNum const *mod); -int bnDoubleExpMod_32(struct BigNum *dest, - struct BigNum const *n1, struct BigNum const *e1, - struct BigNum const *n2, struct BigNum const *e2, - struct BigNum const *mod); -int bnTwoExpMod_32(struct BigNum *n, struct BigNum const *exp, - struct BigNum const *mod); -int bnGcd_32(struct BigNum *dest, struct BigNum const *a, - struct BigNum const *b); -int bnInv_32(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *mod); -int bnLShift_32(struct BigNum *dest, unsigned amt); -void bnRShift_32(struct BigNum *dest, unsigned amt); -unsigned bnMakeOdd_32(struct BigNum *n); -int bnBasePrecompBegin_32(struct BnBasePrecomp *pre, struct BigNum const *base, - struct BigNum const *mod, unsigned maxebits); -void bnBasePrecompEnd_32(struct BnBasePrecomp *pre); -int bnBasePrecompExpMod_32(struct BigNum *dest, struct BnBasePrecomp const *pre, - struct BigNum const *exp, struct BigNum const *mod); -int bnDoubleBasePrecompExpMod_32(struct BigNum *dest, - struct BnBasePrecomp const *pre1, struct BigNum const *exp1, - struct BnBasePrecomp const *pre2, struct BigNum const *exp2, - struct BigNum const *mod); diff --git a/jni/libzrtp/sources/bnlib/bn64.c b/jni/libzrtp/sources/bnlib/bn64.c deleted file mode 100644 index 23cf18555..000000000 --- a/jni/libzrtp/sources/bnlib/bn64.c +++ /dev/null @@ -1,1188 +0,0 @@ -/* - * bn64.c - the high-level bignum interface - * - * Like lbn64.c, this reserves the string "64" for textual replacement. - * The string must not appear anywhere unless it is intended to be replaced - * to generate other bignum interface functions. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - */ - -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include <bnconfig.h> -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_ASSERT_H -#define NO_ASSERT_H 0 -#endif -#ifndef NO_STRING_H -#define NO_STRING_H 0 -#endif -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 0 -#endif -#ifndef NEED_MEMORY_H -#define NEED_MEMORY_H 0 -#endif - -#if !NO_ASSERT_H -#include <assert.h> -#else -#define assert(x) (void)0 -#endif - -#if !NO_STRING_H -#include <string.h> /* for memmove() in bnMakeOdd */ -#elif HAVE_STRINGS_H -#include <strings.h> -#endif -#if NEED_MEMORY_H -#include <memory.h> -#endif - -/* - * This was useful during debugging, so it's left in here. - * You can ignore it. DBMALLOC is generally undefined. - */ -#ifndef DBMALLOC -#define DBMALLOC 0 -#endif -#if DBMALLOC -#include "../dbmalloc/malloc.h" -#define MALLOCDB malloc_chain_check(1) -#else -#define MALLOCDB (void)0 -#endif - -#include "lbn.h" -#include "lbn64.h" -#include "lbnmem.h" -#include "bn64.h" -#include "bn.h" - -/* Work-arounds for some particularly broken systems */ -#include "kludge.h" /* For memmove() */ - -/* Functions */ -void -bnInit_64(void) -{ - bnEnd = bnEnd_64; - bnPrealloc = bnPrealloc_64; - bnCopy = bnCopy_64; - bnNorm = bnNorm_64; - bnExtractBigBytes = bnExtractBigBytes_64; - bnInsertBigBytes = bnInsertBigBytes_64; - bnExtractLittleBytes = bnExtractLittleBytes_64; - bnInsertLittleBytes = bnInsertLittleBytes_64; - bnLSWord = bnLSWord_64; - bnReadBit = bnReadBit_64; - bnBits = bnBits_64; - bnAdd = bnAdd_64; - bnSub = bnSub_64; - bnCmpQ = bnCmpQ_64; - bnSetQ = bnSetQ_64; - bnAddQ = bnAddQ_64; - bnSubQ = bnSubQ_64; - bnCmp = bnCmp_64; - bnSquare = bnSquare_64; - bnMul = bnMul_64; - bnMulQ = bnMulQ_64; - bnDivMod = bnDivMod_64; - bnMod = bnMod_64; - bnModQ = bnModQ_64; - bnExpMod = bnExpMod_64; - bnDoubleExpMod = bnDoubleExpMod_64; - bnTwoExpMod = bnTwoExpMod_64; - bnGcd = bnGcd_64; - bnInv = bnInv_64; - bnLShift = bnLShift_64; - bnRShift = bnRShift_64; - bnMakeOdd = bnMakeOdd_64; - bnBasePrecompBegin = bnBasePrecompBegin_64; - bnBasePrecompEnd = bnBasePrecompEnd_64; - bnBasePrecompExpMod = bnBasePrecompExpMod_64; - bnDoubleBasePrecompExpMod = bnDoubleBasePrecompExpMod_64; -} - -void -bnEnd_64(struct BigNum *bn) -{ - if (bn->ptr) { - LBNFREE((BNWORD64 *)bn->ptr, bn->allocated); - bn->ptr = 0; - } - bn->size = 0; - bn->allocated = 0; - - MALLOCDB; -} - -/* Internal function. It operates in words. */ -static int -bnResize_64(struct BigNum *bn, unsigned len) -{ - void *p; - - /* Round size up: most mallocs impose 8-byte granularity anyway */ - len = (len + (8/sizeof(BNWORD64) - 1)) & ~(8/sizeof(BNWORD64) - 1); - p = LBNREALLOC((BNWORD64 *)bn->ptr, bn->allocated, len); - if (!p) - return -1; - bn->ptr = p; - bn->allocated = len; - - MALLOCDB; - - return 0; -} - -#define bnSizeCheck(bn, size) \ - if (bn->allocated < size && bnResize_64(bn, size) < 0) \ - return -1 - -/* Preallocate enough space in bn to hold "bits" bits. */ -int -bnPrealloc_64(struct BigNum *bn, unsigned bits) -{ - bits = (bits + 64-1)/64; - bnSizeCheck(bn, bits); - MALLOCDB; - return 0; -} - -int -bnCopy_64(struct BigNum *dest, struct BigNum const *src) -{ - bnSizeCheck(dest, src->size); - dest->size = src->size; - lbnCopy_64((BNWORD64 *)dest->ptr, (BNWORD64 *)src->ptr, src->size); - MALLOCDB; - return 0; -} - -/* Is this ever needed? Normalize the bn by deleting high-order 0 words */ -void -bnNorm_64(struct BigNum *bn) -{ - bn->size = lbnNorm_64((BNWORD64 *)bn->ptr, bn->size); -} - -/* - * Convert a bignum to big-endian bytes. Returns, in big-endian form, a - * substring of the bignum starting from lsbyte and "len" bytes long. - * Unused high-order (leading) bytes are filled with 0. - */ -void -bnExtractBigBytes_64(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size * (64 / 8); - - /* Fill unused leading bytes with 0 */ - while (s < lsbyte + len) { - *dest++ = 0; - len--; - } - - if (len) - lbnExtractBigBytes_64((BNWORD64 *)bn->ptr, dest, lsbyte, len); - MALLOCDB; -} - -/* The inverse of the above. */ -int -bnInsertBigBytes_64(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size; - unsigned words = (len+lsbyte+sizeof(BNWORD64)-1) / sizeof(BNWORD64); - - /* Pad with zeros as required */ - bnSizeCheck(bn, words); - - if (s < words) { - lbnZero_64((BNWORD64 *)bn->ptr BIGLITTLE(-s,+s), words-s); - s = words; - } - - lbnInsertBigBytes_64((BNWORD64 *)bn->ptr, src, lsbyte, len); - - bn->size = lbnNorm_64((BNWORD64 *)bn->ptr, s); - - MALLOCDB; - return 0; -} - - -/* - * Convert a bignum to little-endian bytes. Returns, in little-endian form, a - * substring of the bignum starting from lsbyte and "len" bytes long. - * Unused high-order (trailing) bytes are filled with 0. - */ -void -bnExtractLittleBytes_64(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size * (64 / 8); - - /* Fill unused leading bytes with 0 */ - while (s < lsbyte + len) - dest[--len] = 0; - - if (len) - lbnExtractLittleBytes_64((BNWORD64 *)bn->ptr, dest, - lsbyte, len); - MALLOCDB; -} - -/* The inverse of the above */ -int -bnInsertLittleBytes_64(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len) -{ - unsigned s = bn->size; - unsigned words = (len+lsbyte+sizeof(BNWORD64)-1) / sizeof(BNWORD64); - - /* Pad with zeros as required */ - bnSizeCheck(bn, words); - - if (s < words) { - lbnZero_64((BNWORD64 *)bn->ptr BIGLITTLE(-s,+s), words-s); - s = words; - } - - lbnInsertLittleBytes_64((BNWORD64 *)bn->ptr, src, lsbyte, len); - - bn->size = lbnNorm_64((BNWORD64 *)bn->ptr, s); - - MALLOCDB; - return 0; -} - -/* Return the least-significant word of the input. */ -unsigned -bnLSWord_64(struct BigNum const *bn) -{ - return bn->size ? (unsigned)((BNWORD64 *)bn->ptr)[BIGLITTLE(-1,0)]: 0; -} - -/* Return a selected bit of the data */ -int -bnReadBit_64(struct BigNum const *bn, unsigned bit) -{ - BNWORD64 word; - if (bit/64 >= bn->size) - return 0; - word = ((BNWORD64 *)bn->ptr)[BIGLITTLE(-1-bit/64,bit/64)]; - return (int)(word >> (bit % 64) & 1); -} - -/* Count the number of significant bits. */ -unsigned -bnBits_64(struct BigNum const *bn) -{ - return lbnBits_64((BNWORD64 *)bn->ptr, bn->size); -} - -/* dest += src */ -int -bnAdd_64(struct BigNum *dest, struct BigNum const *src) -{ - unsigned s = src->size, d = dest->size; - BNWORD64 t; - - if (!s) - return 0; - - bnSizeCheck(dest, s); - - if (d < s) { - lbnZero_64((BNWORD64 *)dest->ptr BIGLITTLE(-d,+d), s-d); - dest->size = d = s; - MALLOCDB; - } - t = lbnAddN_64((BNWORD64 *)dest->ptr, (BNWORD64 *)src->ptr, s); - MALLOCDB; - if (t) { - if (d > s) { - t = lbnAdd1_64((BNWORD64 *)dest->ptr BIGLITTLE(-s,+s), - d-s, t); - MALLOCDB; - } - if (t) { - bnSizeCheck(dest, d+1); - ((BNWORD64 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t; - dest->size = d+1; - } - } - return 0; -} - -/* - * dest -= src. - * If dest goes negative, this produces the absolute value of - * the difference (the negative of the true value) and returns 1. - * Otherwise, it returls 0. - */ -int -bnSub_64(struct BigNum *dest, struct BigNum const *src) -{ - unsigned s = src->size, d = dest->size; - BNWORD64 t; - - if (d < s && d < (s = lbnNorm_64((BNWORD64 *)src->ptr, s))) { - bnSizeCheck(dest, s); - lbnZero_64((BNWORD64 *)dest->ptr BIGLITTLE(-d,+d), s-d); - dest->size = d = s; - MALLOCDB; - } - if (!s) - return 0; - t = lbnSubN_64((BNWORD64 *)dest->ptr, (BNWORD64 *)src->ptr, s); - MALLOCDB; - if (t) { - if (d > s) { - t = lbnSub1_64((BNWORD64 *)dest->ptr BIGLITTLE(-s,+s), - d-s, t); - MALLOCDB; - } - if (t) { - lbnNeg_64((BNWORD64 *)dest->ptr, d); - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, - dest->size); - MALLOCDB; - return 1; - } - } - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, dest->size); - return 0; -} - -/* - * Compare the BigNum to the given value, which must be < 65536. - * Returns -1. 0 or 1 if a<b, a == b or a>b. - * a <=> b --> bnCmpQ(a,b) <=> 0 - */ -int -bnCmpQ_64(struct BigNum const *a, unsigned b) -{ - unsigned t; - BNWORD64 v; - - t = lbnNorm_64((BNWORD64 *)a->ptr, a->size); - /* If a is more than one word long or zero, it's easy... */ - if (t != 1) - return (t > 1) ? 1 : (b ? -1 : 0); - v = (unsigned)((BNWORD64 *)a->ptr)[BIGLITTLE(-1,0)]; - return (v > b) ? 1 : ((v < b) ? -1 : 0); -} - -/* Set dest to a small value */ -int -bnSetQ_64(struct BigNum *dest, unsigned src) -{ - if (src) { - bnSizeCheck(dest, 1); - - ((BNWORD64 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD64)src; - dest->size = 1; - } else { - dest->size = 0; - } - return 0; -} - -/* dest += src */ -int -bnAddQ_64(struct BigNum *dest, unsigned src) -{ - BNWORD64 t; - - if (!dest->size) - return bnSetQ(dest, src); - - t = lbnAdd1_64((BNWORD64 *)dest->ptr, dest->size, (BNWORD64)src); - MALLOCDB; - if (t) { - src = dest->size; - bnSizeCheck(dest, src+1); - ((BNWORD64 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t; - dest->size = src+1; - } - return 0; -} - -/* - * Return value as for bnSub: 1 if subtract underflowed, in which - * case the return is the negative of the computed value. - */ -int -bnSubQ_64(struct BigNum *dest, unsigned src) -{ - BNWORD64 t; - - if (!dest->size) - return bnSetQ(dest, src) < 0 ? -1 : (src != 0); - - t = lbnSub1_64((BNWORD64 *)dest->ptr, dest->size, src); - MALLOCDB; - if (t) { - /* Underflow. <= 1 word, so do it simply. */ - lbnNeg_64((BNWORD64 *)dest->ptr, 1); - dest->size = 1; - return 1; - } -/* Try to normalize? Needing this is going to be pretty damn rare. */ -/* dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, dest->size); */ - return 0; -} - -/* - * Compare two BigNums. Returns -1. 0 or 1 if a<b, a == b or a>b. - * a <=> b --> bnCmp(a,b) <=> 0 - */ -int -bnCmp_64(struct BigNum const *a, struct BigNum const *b) -{ - unsigned s, t; - - s = lbnNorm_64((BNWORD64 *)a->ptr, a->size); - t = lbnNorm_64((BNWORD64 *)b->ptr, b->size); - - if (s != t) - return s > t ? 1 : -1; - return lbnCmp_64((BNWORD64 *)a->ptr, (BNWORD64 *)b->ptr, s); -} - -/* dest = src*src. This is more efficient than bnMul. */ -int -bnSquare_64(struct BigNum *dest, struct BigNum const *src) -{ - unsigned s; - BNWORD64 *srcbuf; - - s = lbnNorm_64((BNWORD64 *)src->ptr, src->size); - if (!s) { - dest->size = 0; - return 0; - } - bnSizeCheck(dest, 2*s); - - if (src == dest) { - LBNALLOC(srcbuf, BNWORD64, s); - if (!srcbuf) - return -1; - lbnCopy_64(srcbuf, (BNWORD64 *)src->ptr, s); - lbnSquare_64((BNWORD64 *)dest->ptr, (BNWORD64 *)srcbuf, s); - LBNFREE(srcbuf, s); - } else { - lbnSquare_64((BNWORD64 *)dest->ptr, (BNWORD64 *)src->ptr, s); - } - - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, 2*s); - MALLOCDB; - return 0; -} - -/* dest = a * b. Any overlap between operands is allowed. */ -int -bnMul_64(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) -{ - unsigned s, t; - BNWORD64 *srcbuf; - - s = lbnNorm_64((BNWORD64 *)a->ptr, a->size); - t = lbnNorm_64((BNWORD64 *)b->ptr, b->size); - - if (!s || !t) { - dest->size = 0; - return 0; - } - - if (a == b) - return bnSquare_64(dest, a); - - bnSizeCheck(dest, s+t); - - if (dest == a) { - LBNALLOC(srcbuf, BNWORD64, s); - if (!srcbuf) - return -1; - lbnCopy_64(srcbuf, (BNWORD64 *)a->ptr, s); - lbnMul_64((BNWORD64 *)dest->ptr, srcbuf, s, - (BNWORD64 *)b->ptr, t); - LBNFREE(srcbuf, s); - } else if (dest == b) { - LBNALLOC(srcbuf, BNWORD64, t); - if (!srcbuf) - return -1; - lbnCopy_64(srcbuf, (BNWORD64 *)b->ptr, t); - lbnMul_64((BNWORD64 *)dest->ptr, (BNWORD64 *)a->ptr, s, - srcbuf, t); - LBNFREE(srcbuf, t); - } else { - lbnMul_64((BNWORD64 *)dest->ptr, (BNWORD64 *)a->ptr, s, - (BNWORD64 *)b->ptr, t); - } - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, s+t); - MALLOCDB; - return 0; -} - -/* dest = a * b */ -int -bnMulQ_64(struct BigNum *dest, struct BigNum const *a, unsigned b) -{ - unsigned s; - - s = lbnNorm_64((BNWORD64 *)a->ptr, a->size); - if (!s || !b) { - dest->size = 0; - return 0; - } - if (b == 1) - return bnCopy_64(dest, a); - bnSizeCheck(dest, s+1); - lbnMulN1_64((BNWORD64 *)dest->ptr, (BNWORD64 *)a->ptr, s, b); - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, s+1); - MALLOCDB; - return 0; -} - -/* q = n/d, r = n % d */ -int -bnDivMod_64(struct BigNum *q, struct BigNum *r, struct BigNum const *n, - struct BigNum const *d) -{ - unsigned dsize, nsize; - BNWORD64 qhigh; - - dsize = lbnNorm_64((BNWORD64 *)d->ptr, d->size); - nsize = lbnNorm_64((BNWORD64 *)n->ptr, n->size); - - if (nsize < dsize) { - q->size = 0; /* No quotient */ - r->size = nsize; - return 0; /* Success */ - } - - bnSizeCheck(q, nsize-dsize); - - if (r != n) { /* You are allowed to reduce in place */ - bnSizeCheck(r, nsize); - lbnCopy_64((BNWORD64 *)r->ptr, (BNWORD64 *)n->ptr, nsize); - } - - qhigh = lbnDiv_64((BNWORD64 *)q->ptr, (BNWORD64 *)r->ptr, nsize, - (BNWORD64 *)d->ptr, dsize); - nsize -= dsize; - if (qhigh) { - bnSizeCheck(q, nsize+1); - *((BNWORD64 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh; - q->size = nsize+1; - } else { - q->size = lbnNorm_64((BNWORD64 *)q->ptr, nsize); - } - r->size = lbnNorm_64((BNWORD64 *)r->ptr, dsize); - MALLOCDB; - return 0; -} - -/* det = src % d */ -int -bnMod_64(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d) -{ - unsigned dsize, nsize; - - nsize = lbnNorm_64((BNWORD64 *)src->ptr, src->size); - dsize = lbnNorm_64((BNWORD64 *)d->ptr, d->size); - - - if (dest != src) { - bnSizeCheck(dest, nsize); - lbnCopy_64((BNWORD64 *)dest->ptr, (BNWORD64 *)src->ptr, nsize); - } - - if (nsize < dsize) { - dest->size = nsize; /* No quotient */ - return 0; - } - - (void)lbnDiv_64((BNWORD64 *)dest->ptr BIGLITTLE(-dsize,+dsize), - (BNWORD64 *)dest->ptr, nsize, - (BNWORD64 *)d->ptr, dsize); - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, dsize); - MALLOCDB; - return 0; -} - -/* return src % d. */ -unsigned -bnModQ_64(struct BigNum const *src, unsigned d) -{ - unsigned s; - - s = lbnNorm_64((BNWORD64 *)src->ptr, src->size); - if (!s) - return 0; - - if (d & (d-1)) /* Not a power of 2 */ - d = lbnModQ_64((BNWORD64 *)src->ptr, s, d); - else - d = (unsigned)((BNWORD64 *)src->ptr)[BIGLITTLE(-1,0)] & (d-1); - return d; -} - -/* dest = n^exp (mod mod) */ -int -bnExpMod_64(struct BigNum *dest, struct BigNum const *n, - struct BigNum const *exp, struct BigNum const *mod) -{ - unsigned nsize, esize, msize; - - nsize = lbnNorm_64((BNWORD64 *)n->ptr, n->size); - esize = lbnNorm_64((BNWORD64 *)exp->ptr, exp->size); - msize = lbnNorm_64((BNWORD64 *)mod->ptr, mod->size); - - if (!msize || (((BNWORD64 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) - return -1; /* Illegal modulus! */ - - bnSizeCheck(dest, msize); - - /* Special-case base of 2 */ - if (nsize == 1 && ((BNWORD64 *)n->ptr)[BIGLITTLE(-1,0)] == 2) { - if (lbnTwoExpMod_64((BNWORD64 *)dest->ptr, - (BNWORD64 *)exp->ptr, esize, - (BNWORD64 *)mod->ptr, msize) < 0) - return -1; - } else { - if (lbnExpMod_64((BNWORD64 *)dest->ptr, - (BNWORD64 *)n->ptr, nsize, - (BNWORD64 *)exp->ptr, esize, - (BNWORD64 *)mod->ptr, msize) < 0) - return -1; - } - - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, msize); - MALLOCDB; - return 0; -} - -/* - * dest = n1^e1 * n2^e2 (mod mod). This is more efficient than two - * separate modular exponentiations, and in fact asymptotically approaches - * the cost of one. - */ -int -bnDoubleExpMod_64(struct BigNum *dest, - struct BigNum const *n1, struct BigNum const *e1, - struct BigNum const *n2, struct BigNum const *e2, - struct BigNum const *mod) -{ - unsigned n1size, e1size, n2size, e2size, msize; - - n1size = lbnNorm_64((BNWORD64 *)n1->ptr, n1->size); - e1size = lbnNorm_64((BNWORD64 *)e1->ptr, e1->size); - n2size = lbnNorm_64((BNWORD64 *)n2->ptr, n2->size); - e2size = lbnNorm_64((BNWORD64 *)e2->ptr, e2->size); - msize = lbnNorm_64((BNWORD64 *)mod->ptr, mod->size); - - if (!msize || (((BNWORD64 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) - return -1; /* Illegal modulus! */ - - bnSizeCheck(dest, msize); - - if (lbnDoubleExpMod_64((BNWORD64 *)dest->ptr, - (BNWORD64 *)n1->ptr, n1size, (BNWORD64 *)e1->ptr, e1size, - (BNWORD64 *)n2->ptr, n2size, (BNWORD64 *)e2->ptr, e2size, - (BNWORD64 *)mod->ptr, msize) < 0) - return -1; - - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, msize); - MALLOCDB; - return 0; -} - -/* n = 2^exp (mod mod) */ -int -bnTwoExpMod_64(struct BigNum *n, struct BigNum const *exp, - struct BigNum const *mod) -{ - unsigned esize, msize; - - esize = lbnNorm_64((BNWORD64 *)exp->ptr, exp->size); - msize = lbnNorm_64((BNWORD64 *)mod->ptr, mod->size); - - if (!msize || (((BNWORD64 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) - return -1; /* Illegal modulus! */ - - bnSizeCheck(n, msize); - - if (lbnTwoExpMod_64((BNWORD64 *)n->ptr, (BNWORD64 *)exp->ptr, esize, - (BNWORD64 *)mod->ptr, msize) < 0) - return -1; - - n->size = lbnNorm_64((BNWORD64 *)n->ptr, msize); - MALLOCDB; - return 0; -} - -/* dest = gcd(a, b) */ -int -bnGcd_64(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) -{ - BNWORD64 *tmp; - unsigned asize, bsize; - int i; - - /* Kind of silly, but we might as well permit it... */ - if (a == b) - return dest == a ? 0 : bnCopy(dest, a); - - /* Ensure a is not the same as "dest" */ - if (a == dest) { - a = b; - b = dest; - } - - asize = lbnNorm_64((BNWORD64 *)a->ptr, a->size); - bsize = lbnNorm_64((BNWORD64 *)b->ptr, b->size); - - bnSizeCheck(dest, bsize+1); - - /* Copy a to tmp */ - LBNALLOC(tmp, BNWORD64, asize+1); - if (!tmp) - return -1; - lbnCopy_64(tmp, (BNWORD64 *)a->ptr, asize); - - /* Copy b to dest, if necessary */ - if (dest != b) - lbnCopy_64((BNWORD64 *)dest->ptr, - (BNWORD64 *)b->ptr, bsize); - if (bsize > asize || (bsize == asize && - lbnCmp_64((BNWORD64 *)b->ptr, (BNWORD64 *)a->ptr, asize) > 0)) - { - i = lbnGcd_64((BNWORD64 *)dest->ptr, bsize, tmp, asize, - &dest->size); - if (i > 0) /* Result in tmp, not dest */ - lbnCopy_64((BNWORD64 *)dest->ptr, tmp, dest->size); - } else { - i = lbnGcd_64(tmp, asize, (BNWORD64 *)dest->ptr, bsize, - &dest->size); - if (i == 0) /* Result in tmp, not dest */ - lbnCopy_64((BNWORD64 *)dest->ptr, tmp, dest->size); - } - LBNFREE(tmp, asize+1); - MALLOCDB; - return (i < 0) ? i : 0; -} - -/* - * dest = 1/src (mod mod). Returns >0 if gcd(src, mod) != 1 (in which case - * the inverse does not exist). - */ -int -bnInv_64(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *mod) -{ - unsigned s, m; - int i; - - s = lbnNorm_64((BNWORD64 *)src->ptr, src->size); - m = lbnNorm_64((BNWORD64 *)mod->ptr, mod->size); - - /* lbnInv_64 requires that the input be less than the modulus */ - if (m < s || - (m==s && lbnCmp_64((BNWORD64 *)src->ptr, (BNWORD64 *)mod->ptr, s))) - { - bnSizeCheck(dest, s + (m==s)); - if (dest != src) - lbnCopy_64((BNWORD64 *)dest->ptr, - (BNWORD64 *)src->ptr, s); - /* Pre-reduce modulo the modulus */ - (void)lbnDiv_64((BNWORD64 *)dest->ptr BIGLITTLE(-m,+m), - (BNWORD64 *)dest->ptr, s, - (BNWORD64 *)mod->ptr, m); - s = lbnNorm_64((BNWORD64 *)dest->ptr, m); - MALLOCDB; - } else { - bnSizeCheck(dest, m+1); - if (dest != src) - lbnCopy_64((BNWORD64 *)dest->ptr, - (BNWORD64 *)src->ptr, s); - } - - i = lbnInv_64((BNWORD64 *)dest->ptr, s, (BNWORD64 *)mod->ptr, m); - if (i == 0) - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, m); - - MALLOCDB; - return i; -} - -/* - * Shift a bignum left the appropriate number of bits, - * multiplying by 2^amt. - */ -int -bnLShift_64(struct BigNum *dest, unsigned amt) -{ - unsigned s = dest->size; - BNWORD64 carry; - - if (amt % 64) { - carry = lbnLshift_64((BNWORD64 *)dest->ptr, s, amt % 64); - if (carry) { - s++; - bnSizeCheck(dest, s); - ((BNWORD64 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry; - } - } - - amt /= 64; - if (amt) { - bnSizeCheck(dest, s+amt); - memmove((BNWORD64 *)dest->ptr BIGLITTLE(-s-amt, +amt), - (BNWORD64 *)dest->ptr BIG(-s), - s * sizeof(BNWORD64)); - lbnZero_64((BNWORD64 *)dest->ptr, amt); - s += amt; - } - dest->size = s; - MALLOCDB; - return 0; -} - -/* - * Shift a bignum right the appropriate number of bits, - * dividing by 2^amt. - */ -void -bnRShift_64(struct BigNum *dest, unsigned amt) -{ - unsigned s = dest->size; - - if (amt >= 64) { - memmove( - (BNWORD64 *)dest->ptr BIG(-s+amt/64), - (BNWORD64 *)dest->ptr BIGLITTLE(-s, +amt/64), - (s-amt/64) * sizeof(BNWORD64)); - s -= amt/64; - amt %= 64; - } - - if (amt) - (void)lbnRshift_64((BNWORD64 *)dest->ptr, s, amt); - - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, s); - MALLOCDB; -} - -/* - * Shift a bignum right until it is odd, and return the number of - * bits shifted. n = d * 2^s. Replaces n with d and returns s. - * Returns 0 when given 0. (Another valid answer is infinity.) - */ -unsigned -bnMakeOdd_64(struct BigNum *n) -{ - unsigned size; - unsigned s; /* shift amount */ - BNWORD64 *p; - BNWORD64 t; - - p = (BNWORD64 *)n->ptr; - size = lbnNorm_64(p, n->size); - if (!size) - return 0; - - t = BIGLITTLE(p[-1],p[0]); - s = 0; - - /* See how many words we have to shift */ - if (!t) { - /* Shift by words */ - do { - s++; - BIGLITTLE(--p,p++); - } while ((t = BIGLITTLE(p[-1],p[0])) == 0); - size -= s; - s *= 64; - memmove((BNWORD64 *)n->ptr BIG(-size), p BIG(-size), - size * sizeof(BNWORD64)); - p = (BNWORD64 *)n->ptr; - MALLOCDB; - } - - assert(t); - - if (!(t & 1)) { - /* Now count the bits */ - do { - t >>= 1; - s++; - } while ((t & 1) == 0); - - /* Shift the bits */ - lbnRshift_64(p, size, s & (64-1)); - /* Renormalize */ - if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0) - --size; - } - n->size = size; - - MALLOCDB; - return s; -} - -/* - * Do base- and modulus-dependent precomputation for rapid computation of - * base^exp (mod mod) with various exponents. - * - * See lbn64.c for the details on how the algorithm works. Basically, - * it involves precomputing a table of powers of base, base^(order^k), - * for a suitable range 0 <= k < n detemined by the maximum exponent size - * desired. To do eht exponentiation, the exponent is expressed in base - * "order" (sorry for the confusing terminology) and the precomputed powers - * are combined. - * - * This implementation allows only power-of-2 values for "order". Using - * other numbers can be more efficient, but it's more work and for the - * popular exponent size of 640 bits, an order of 8 is optimal, so it - * hasn't seemed worth it to implement. - * - * Here's a table of the optimal power-of-2 order for various exponent - * sizes and the associated (average) cost for an exponentiation. - * Note that *higher* orders are more memory-efficient; the number - * of precomputed values required is ceil(ebits/order). (Ignore the - * underscores in the middle of numbers; they're harmless.) - * - * At 2 bits, order 2 uses 0.000000 multiplies - * At 4 bits, order 2 uses 1.000000 multiplies - * At 8 bits, order 2 uses 3.000000 multiplies - * At 1_6 bits, order 2 uses 7.000000 multiplies - * At 3_2 bits, order 2 uses 15.000000 multiplies - * At 34 bits, 15.750000 (order 4) < 1_6.000000 (order 2) - * At 6_4 bits, order 4 uses 27.000000 multiplies - * At 99 bits, 39.875000 (order 8) < 40.250000 (order 4) - * At 128 bits, order 8 uses 48.500000 multiplies - * At 256 bits, order 8 uses 85.875000 multiplies - * At 280 bits, 92.625000 (order 1_6) < 92.875000 (order 8) - * At 512 bits, order 1_6 uses 147.000000 multiplies - * At 785 bits, 211.093750 (order 3_2) < 211.250000 (order 1_6) - * At 1024 bits, order 3_2 uses 257.562500 multiplies - * At 2048 bits, order 3_2 uses 456.093750 multiplies - * At 2148 bits, 475.406250 (order 6_4) < 475.468750 (order 3_2) - * At 4096 bits, order 6_4 uses 795.281250 multiplies - * At 5726 bits, 1062.609375 (order 128) < 1062.843750 (order 6_4) - * At 8192 bits, order 128 uses 1412.609375 multiplies - * At 14848 bits, 2355.750000 (order 256) < 2355.929688 (order 128) - * At 37593 bits, 5187.841797 (order 512) < 5188.144531 (order 256) - */ -int -bnBasePrecompBegin_64(struct BnBasePrecomp *pre, struct BigNum const *base, - struct BigNum const *mod, unsigned maxebits) -{ - int i; - BNWORD64 **array; /* Array of precomputed powers of base */ - unsigned n; /* Number of entries in array (needed) */ - unsigned m; /* Number of entries in array (non-NULL) */ - unsigned arraysize; /* Number of entries in array (allocated) */ - unsigned bits; /* log2(order) */ - unsigned msize = lbnNorm_64((BNWORD64 *)mod->ptr, mod->size); - static unsigned const bnBasePrecompThreshTable[] = { - 33, 98, 279, 784, 2147, 5725, 14847, 37592, (unsigned)-1 - }; - - /* Clear pre in case of failure */ - pre->array = 0; - pre->msize = 0; - pre->bits = 0; - pre->maxebits = 0; - pre->arraysize = 0; - pre->entries = 0; - - /* Find the correct bit-window size */ - bits = 0; - do - bits++; - while (maxebits > bnBasePrecompThreshTable[bits]); - - /* Now the number of precomputed values we need */ - n = (maxebits+bits-1)/bits; - assert(n*bits >= maxebits); - - arraysize = n+1; /* Add one trailing NULL for safety */ - array = lbnMemAlloc(arraysize * sizeof(*array)); - if (!array) - return -1; /* Out of memory */ - - /* Now allocate the entries (precomputed powers of base) */ - for (m = 0; m < n; m++) { - BNWORD64 *entry; - - LBNALLOC(entry, BNWORD64, msize); - if (!entry) - break; - array[m] = entry; - } - - /* "m" is the number of successfully allocated entries */ - if (m < n) { - /* Ran out of memory; see if we can use a smaller array */ - BNWORD64 **newarray; - - if (m < 2) { - n = 0; /* Forget it */ - } else { - /* How few bits can we use with what's allocated? */ - bits = (maxebits + m - 1) / m; -retry: - n = (maxebits + bits - 1) / bits; - if (! (n >> bits) ) - n = 0; /* Not enough to amount to anything */ - } - /* Free excess allocated array entries */ - while (m > n) { - BNWORD64 *entry = array[--m]; - LBNFREE(entry, msize); - } - if (!n) { - /* Give it up */ - lbnMemFree(array, arraysize * sizeof(*array)); - return -1; - } - /* - * Try to shrink the pointer array. This might fail, but - * it's not critical. lbnMemRealloc isn't guarnateed to - * exist, so we may have to allocate, copy, and free. - */ -#ifdef lbnMemRealloc - newarray = lbnMemRealloc(array, arraysize * sizeof(*array), - (n+1) * sizeof(*array)); - if (newarray) { - array = newarray; - arraysize = n+1; - } -#else - newarray = lbnMemAlloc((n+1) * sizeof(*array)); - if (newarray) { - memcpy(newarray, array, n * sizeof(*array)); - lbnMemFree(array, arraysize * sizeof(*array)); - array = newarray; - arraysize = n+1; - } -#endif - } - - /* Pad with null pointers */ - while (m < arraysize) - array[m++] = 0; - - /* Okay, we have our array, now initialize it */ - i = lbnBasePrecompBegin_64(array, n, bits, - (BNWORD64 *)base->ptr, base->size, - (BNWORD64 *)mod->ptr, msize); - if (i < 0) { - /* Ack, still out of memory */ - bits++; - m = n; - goto retry; - } - /* Finally, totoal success */ - pre->array = array; - pre->bits = bits; - pre->msize = msize; - pre->maxebits = n * bits; - pre->arraysize = arraysize; - pre->entries = n; - return 0; -} - -/* Free everything preallocated */ -void -bnBasePrecompEnd_64(struct BnBasePrecomp *pre) -{ - BNWORD64 **array = pre->array; - - if (array) { - unsigned entries = pre->entries; - unsigned msize = pre->msize; - unsigned m; - - for (m = 0; m < entries; m++) { - BNWORD64 *entry = array[m]; - if (entry) - LBNFREE(entry, msize); - } - lbnMemFree(array, pre->arraysize * sizeof(array)); - } - pre->array = 0; - pre->bits = 0; - pre->msize = 0; - pre->maxebits = 0; - pre->arraysize = 0; - pre->entries = 0; -} - -int -bnBasePrecompExpMod_64(struct BigNum *dest, struct BnBasePrecomp const *pre, - struct BigNum const *exp, struct BigNum const *mod) -{ - unsigned msize = lbnNorm_64((BNWORD64 *)mod->ptr, mod->size); - unsigned esize = lbnNorm_64((BNWORD64 *)exp->ptr, exp->size); - BNWORD64 const * const *array = pre->array; - int i; - - assert(msize == pre->msize); - assert(((BNWORD64 *)mod->ptr)[BIGLITTLE(-1,0)] & 1); - assert(lbnBits_64((BNWORD64 *)exp->ptr, esize) <= pre->maxebits); - - bnSizeCheck(dest, msize); - - i = lbnBasePrecompExp_64(dest->ptr, array, pre->bits, - exp->ptr, esize, mod->ptr, msize); - if (i == 0) - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, msize); - return i; -} - -int -bnDoubleBasePrecompExpMod_64(struct BigNum *dest, - struct BnBasePrecomp const *pre1, struct BigNum const *exp1, - struct BnBasePrecomp const *pre2, struct BigNum const *exp2, - struct BigNum const *mod) -{ - unsigned msize = lbnNorm_64((BNWORD64 *)mod->ptr, mod->size); - unsigned e1size = lbnNorm_64((BNWORD64 *)exp1->ptr, exp1->size); - unsigned e2size = lbnNorm_64((BNWORD64 *)exp1->ptr, exp2->size); - BNWORD64 const * const *array1 = pre1->array; - BNWORD64 const * const *array2 = pre2->array; - int i; - - assert(msize == pre1->msize); - assert(msize == pre2->msize); - assert(((BNWORD64 *)mod->ptr)[BIGLITTLE(-1,0)] & 1); - assert(lbnBits_64((BNWORD64 *)exp1->ptr, e1size) <= pre1->maxebits); - assert(lbnBits_64((BNWORD64 *)exp2->ptr, e2size) <= pre2->maxebits); - assert(pre1->bits == pre2->bits); - - bnSizeCheck(dest, msize); - - i = lbnDoubleBasePrecompExp_64(dest->ptr, pre1->bits, array1, - exp1->ptr, e1size, array2, exp2->ptr, e2size, - mod->ptr, msize); - if (i == 0) - dest->size = lbnNorm_64((BNWORD64 *)dest->ptr, msize); - return i; -} diff --git a/jni/libzrtp/sources/bnlib/bn64.h b/jni/libzrtp/sources/bnlib/bn64.h deleted file mode 100644 index 1c23721ec..000000000 --- a/jni/libzrtp/sources/bnlib/bn64.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * bn64.h - interface to 64-bit bignum routines. - */ -struct BigNum; -struct BnBasePrecomp; - -void bnInit_64(void); -void bnEnd_64(struct BigNum *bn); -int bnPrealloc_64(struct BigNum *bn, unsigned bits); -int bnCopy_64(struct BigNum *dest, struct BigNum const *src); -int bnSwap_64(struct BigNum *a, struct BigNum *b); -void bnNorm_64(struct BigNum *bn); -void bnExtractBigBytes_64(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned dlen); -int bnInsertBigBytes_64(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len); -void bnExtractLittleBytes_64(struct BigNum const *bn, unsigned char *dest, - unsigned lsbyte, unsigned dlen); -int bnInsertLittleBytes_64(struct BigNum *bn, unsigned char const *src, - unsigned lsbyte, unsigned len); -unsigned bnLSWord_64(struct BigNum const *src); -int bnReadBit_64(struct BigNum const *bn, unsigned bit); -unsigned bnBits_64(struct BigNum const *src); -int bnAdd_64(struct BigNum *dest, struct BigNum const *src); -int bnSub_64(struct BigNum *dest, struct BigNum const *src); -int bnCmpQ_64(struct BigNum const *a, unsigned b); -int bnSetQ_64(struct BigNum *dest, unsigned src); -int bnAddQ_64(struct BigNum *dest, unsigned src); -int bnSubQ_64(struct BigNum *dest, unsigned src); -int bnCmp_64(struct BigNum const *a, struct BigNum const *b); -int bnSquare_64(struct BigNum *dest, struct BigNum const *src); -int bnMul_64(struct BigNum *dest, struct BigNum const *a, - struct BigNum const *b); -int bnMulQ_64(struct BigNum *dest, struct BigNum const *a, unsigned b); -int bnDivMod_64(struct BigNum *q, struct BigNum *r, struct BigNum const *n, - struct BigNum const *d); -int bnMod_64(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *d); -unsigned bnModQ_64(struct BigNum const *src, unsigned d); -int bnExpMod_64(struct BigNum *dest, struct BigNum const *n, - struct BigNum const *exp, struct BigNum const *mod); -int bnDoubleExpMod_64(struct BigNum *dest, - struct BigNum const *n1, struct BigNum const *e1, - struct BigNum const *n2, struct BigNum const *e2, - struct BigNum const *mod); -int bnTwoExpMod_64(struct BigNum *n, struct BigNum const *exp, - struct BigNum const *mod); -int bnGcd_64(struct BigNum *dest, struct BigNum const *a, - struct BigNum const *b); -int bnInv_64(struct BigNum *dest, struct BigNum const *src, - struct BigNum const *mod); -int bnLShift_64(struct BigNum *dest, unsigned amt); -void bnRShift_64(struct BigNum *dest, unsigned amt); -unsigned bnMakeOdd_64(struct BigNum *n); -int bnBasePrecompBegin_64(struct BnBasePrecomp *pre, struct BigNum const *base, - struct BigNum const *mod, unsigned maxebits); -void bnBasePrecompEnd_64(struct BnBasePrecomp *pre); -int bnBasePrecompExpMod_64(struct BigNum *dest, struct BnBasePrecomp const *pre, - struct BigNum const *exp, struct BigNum const *mod); -int bnDoubleBasePrecompExpMod_64(struct BigNum *dest, - struct BnBasePrecomp const *pre1, struct BigNum const *exp1, - struct BnBasePrecomp const *pre2, struct BigNum const *exp2, - struct BigNum const *mod); diff --git a/jni/libzrtp/sources/bnlib/bnconfig.h.cmake b/jni/libzrtp/sources/bnlib/bnconfig.h.cmake deleted file mode 100644 index 2571de117..000000000 --- a/jni/libzrtp/sources/bnlib/bnconfig.h.cmake +++ /dev/null @@ -1,68 +0,0 @@ -/* - * bnconfig.h.cmake -- Configuration file for BigNum library. - * - * cmake processes this file. - */ -#ifndef _BNCONFIG_H -#define _BNCONFIG_H - -/* Checks for the presence and absence of various header files */ -#cmakedefine HAVE_ASSERT_H 1 -#define NO_ASSERT_H !HAVE_ASSERT_H - -#cmakedefine HAVE_LIMITS_H 1 -#define NO_LIMITS_H !HAVE_LIMITS_H - -#cmakedefine HAVE_STDLIB_H 1 -#define NO_STDLIB_H !HAVE_STDLIB_H - -#cmakedefine HAVE_STRING_H 1 -#define NO_STRING_H !HAVE_STRING_H - -#cmakedefine HAVE_STRINGS_H 1 - -#cmakedefine NEED_MEMORY_H 1 - -/* We go to some trouble to find accurate times... */ - -/* Define if you have Posix.4 glock_gettime() */ -#cmakedefine HAVE_CLOCK_GETTIME 1 -/* Define if you have Solaris-style gethrvtime() */ -#cmakedefine HAVE_GETHRVTIME 1 -/* Define if you have getrusage() */ -#cmakedefine HAVE_GETRUSAGE 1 -/* Define if you have clock() */ -#cmakedefine HAVE_CLOCK 1 -/* Define if you have time() */ -#cmakedefine HAVE_TIME 1 - -/* - * Define as 0 if #including <sys/time.h> automatically - * #includes <time.h>, and doing so explicitly causes an - * error. - */ -#define TIME_WITH_SYS_TIME 0 - -/* Defines for various kinds of library brokenness */ - -/* Define if <stdio.h> is missing prototypes (= lots of warnings!) */ -#cmakedefine NO_STDIO_PROTOS 1 - -/* Define if <assert.h> depends on <stdio.h> and breaks without it */ -#cmakedefine ASSERT_NEEDS_STDIO 1 -/* Define if <assert.h> depends on <stdlib.h> and complains without it */ -#cmakedefine ASSERT_NEEDS_STDLIB 1 - -/* - * Define if <string.h> delcares the mem* functions to take char * - * instead of void * parameters (= lots of warnings) - */ -#cmakedefine MEM_PROTOS_BROKEN 1 - -/* If not available, bcopy() is substituted */ -#cmakedefine HAVE_MEMMOVE 1 -#define NO_MEMMOVE !HAVE_MEMMOVE -#cmakedefine HAVE_MEMCPY 1 -#define NO_MEMCPY !HAVE_MEMCPY - -#endif /* _BNCONFIG_H */ diff --git a/jni/libzrtp/sources/bnlib/bninit16.c b/jni/libzrtp/sources/bnlib/bninit16.c deleted file mode 100644 index 16c6f3ec4..000000000 --- a/jni/libzrtp/sources/bnlib/bninit16.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * bninit16.c - Provide an init function that sets things up for 16-bit - * operation. This is a seaparate tiny file so you can compile two bn - * packages into the library and write a custom init routine. - * - * Written in 1995 by Colin Plumb. - */ - -#include "bn.h" -#include "bn16.h" - -void -bnInit(void) -{ - bnInit_16(); -} diff --git a/jni/libzrtp/sources/bnlib/bninit32.c b/jni/libzrtp/sources/bnlib/bninit32.c deleted file mode 100644 index b27d36371..000000000 --- a/jni/libzrtp/sources/bnlib/bninit32.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * bninit32.c - Provide an init function that sets things up for 32-bit - * operation. This is a seaparate tiny file so you can compile two bn - * packages into the library and write a custom init routine. - * - * Written in 1995 by Colin Plumb. - */ - -#include "bn.h" -#include "bn32.h" - -void -bnInit(void) -{ - bnInit_32(); -} diff --git a/jni/libzrtp/sources/bnlib/bninit64.c b/jni/libzrtp/sources/bnlib/bninit64.c deleted file mode 100644 index 4abe67300..000000000 --- a/jni/libzrtp/sources/bnlib/bninit64.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * bninit64.c - Provide an init function that sets things up for 64-bit - * operation. This is a seaparate tiny file so you can compile two bn - * packages into the library and write a custom init routine. - * - * Written in 1995 by Colin Plumb. - */ - -#include "bn.h" -#include "bn64.h" - -void -bnInit(void) -{ - bnInit_64(); -} diff --git a/jni/libzrtp/sources/bnlib/bnprint.c b/jni/libzrtp/sources/bnlib/bnprint.c deleted file mode 100644 index a40724840..000000000 --- a/jni/libzrtp/sources/bnlib/bnprint.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * bnprint.c - Print a bignum, for debugging purposes. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - */ -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include "bnconfig.h" -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_STRING_H -#define NO_STRING_H 0 -#endif -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 0 -#endif - -#include <stdio.h> -#include <stdint.h> - -#if !NO_STRING_H -#include <string.h> -#elif HAVE_STRINGS_H -#include <strings.h> -#endif - -#include "bn.h" -#include "bnprint.h" - -#include "kludge.h" - -int -bnPrint(FILE *f, char const *prefix, struct BigNum const *bn, - char const *suffix) -{ - unsigned char temp[32]; /* How much to print on one line */ - unsigned len; - size_t i; - - if (prefix && fputs(prefix, f) < 0) - return EOF; - - len = (bnBits(bn) + 7)/ 8; - - if (!len) { - if (putc('0', f) < 0) - return EOF; - } else { - while (len > sizeof(temp)) { - len -= sizeof(temp); - bnExtractBigBytes(bn, temp, len, sizeof(temp)); - for (i = 0; i < sizeof(temp); i++) - if (fprintf(f, "%02X", temp[i]) < 0) - return EOF; - if (putc('\\', f) < 0 || putc('\n', f) < 0) - return EOF; - if (prefix) { - i = strlen(prefix); - while (i--) - if (putc(' ', f) < 0) - return EOF; - } - } - bnExtractBigBytes(bn, temp, 0, len); - for (i = 0; i < len; i++) - if (fprintf(f, "%02X", temp[i]) < 0) - return EOF; - } - return suffix ? fputs(suffix, f) : 0; -} - -/* - * Convert an ASCII character to digit value - */ -static int getAsciiDigit( uint32_t *d, int radix, char c ) -{ - *d = 255; - - if( c >= 0x30 && c <= 0x39 ) - *d = c - 0x30; - if( c >= 0x41 && c <= 0x46 ) - *d = c - 0x37; - if( c >= 0x61 && c <= 0x66 ) - *d = c - 0x57; - - if( *d >= (uint32_t)radix ) - return( -1 ); - - return( 0 ); -} - -int -bnReadAscii(struct BigNum *X, char *s, int radix) -{ - int slen = strlen(s); - int i, neg = 0; - uint32_t d; - - bnSetQ(X, 0); - for( i = 0; i < slen; i++ ) { - if(i == 0 && s[i] == '-') { - neg = 1; - continue; - } - getAsciiDigit(&d, radix, s[i]); - bnMulQ(X, X, radix); - - bnAddQ(X, d); - } - return(neg); -} diff --git a/jni/libzrtp/sources/bnlib/bnprint.h b/jni/libzrtp/sources/bnlib/bnprint.h deleted file mode 100644 index b10393a4d..000000000 --- a/jni/libzrtp/sources/bnlib/bnprint.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef BNPRINT_H -#define BNPRINT_H - -#include <stdio.h> - -#ifdef __cplusplus -extern "C" -{ -#endif - -struct BigNum; - -#ifndef SWIG -int bnPrint(FILE *f, char const *prefix, struct BigNum const *bn, - char const *suffix); -#endif - -/** - * Convert an ASCII string into a BigNum. - * - * This function converts an ASCII string into a Big number. If the first - * character of the string is a minus sign the big number is a negative number. - * - * @param X the BigNum that stores the result - * - * @param s the ASCII string in big-endian format (first digit is most significant) - * - * @param radix the function can use radix between 2 and 16 - */ -int bnReadAscii(struct BigNum *X, char *s, int radix); -#ifdef __cplusplus -} -#endif - -#endif /* BNPRINT_H */ diff --git a/jni/libzrtp/sources/bnlib/bnsize00.h b/jni/libzrtp/sources/bnlib/bnsize00.h deleted file mode 100644 index 962f486d3..000000000 --- a/jni/libzrtp/sources/bnlib/bnsize00.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * bnsize00.h - pick the correct machine word size to use. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - */ -#include "lbn.h" /* Get basic information */ - -#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD64) -# if defined(BNWORD128) || (defined(lbnMulAdd1_64) && defined(lbnMulSub1_64)) -# define BNSIZE64 1 -# elif defined(mul64_ppmm) || defined(mul64_ppmma) || defined(mul64_ppmmaa) -# define BNSIZE64 1 -# endif -#endif - -#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD32) -# if defined(BNWORD64) || (defined(lbnMulAdd1_32) && defined(lbnMulSub1_32)) -# define BNSIZE32 1 -# elif defined(mul32_ppmm) || defined(mul32_ppmma) || defined(mul32_ppmmaa) -# define BNSIZE32 1 -# endif -#endif - -#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD16) -# if defined(BNWORD32) || (defined(lbnMulAdd1_16) && defined(lbnMulSub1_16)) -# define BNSIZE16 1 -# elif defined(mul16_ppmm) || defined(mul16_ppmma) || defined(mul16_ppmmaa) -# define BNSIZE16 1 -# endif -#endif - -#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 -#error Unable to find a viable word size to compile bignum library. -#endif diff --git a/jni/libzrtp/sources/bnlib/ec/curve25519-donna.c b/jni/libzrtp/sources/bnlib/ec/curve25519-donna.c deleted file mode 100644 index de11280c0..000000000 --- a/jni/libzrtp/sources/bnlib/ec/curve25519-donna.c +++ /dev/null @@ -1,731 +0,0 @@ -/* Copyright 2008, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * curve25519-donna: Curve25519 elliptic curve, public key function - * - * http://code.google.com/p/curve25519-donna/ - * - * Adam Langley <agl@imperialviolet.org> - * - * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to> - * - * More information about curve25519 can be found here - * http://cr.yp.to/ecdh.html - * - * djb's sample implementation of curve25519 is written in a special assembly - * language called qhasm and uses the floating point registers. - * - * This is, almost, a clean room reimplementation from the curve25519 paper. It - * uses many of the tricks described therein. Only the crecip function is taken - * from the sample implementation. - */ - -#include <string.h> -#include <stdint.h> - -#ifdef _MSC_VER -#define inline __inline -#endif - -typedef uint8_t u8; -typedef int32_t s32; -typedef int64_t limb; - -/* Field element representation: - * - * Field elements are written as an array of signed, 64-bit limbs, least - * significant first. The value of the field element is: - * x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ... - * - * i.e. the limbs are 26, 25, 26, 25, ... bits wide. - */ - -/* Sum two numbers: output += in */ -static void fsum(limb *output, const limb *in) { - unsigned i; - for (i = 0; i < 10; i += 2) { - output[0+i] = (output[0+i] + in[0+i]); - output[1+i] = (output[1+i] + in[1+i]); - } -} - -/* Find the difference of two numbers: output = in - output - * (note the order of the arguments!) - */ -static void fdifference(limb *output, const limb *in) { - unsigned i; - for (i = 0; i < 10; ++i) { - output[i] = (in[i] - output[i]); - } -} - -/* Multiply a number by a scalar: output = in * scalar */ -static void fscalar_product(limb *output, const limb *in, const limb scalar) { - unsigned i; - for (i = 0; i < 10; ++i) { - output[i] = in[i] * scalar; - } -} - -/* Multiply two numbers: output = in2 * in - * - * output must be distinct to both inputs. The inputs are reduced coefficient - * form, the output is not. - */ -static void fproduct(limb *output, const limb *in2, const limb *in) { - output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]); - output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) + - ((limb) ((s32) in2[1])) * ((s32) in[0]); - output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) + - ((limb) ((s32) in2[0])) * ((s32) in[2]) + - ((limb) ((s32) in2[2])) * ((s32) in[0]); - output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) + - ((limb) ((s32) in2[2])) * ((s32) in[1]) + - ((limb) ((s32) in2[0])) * ((s32) in[3]) + - ((limb) ((s32) in2[3])) * ((s32) in[0]); - output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) + - 2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) + - ((limb) ((s32) in2[3])) * ((s32) in[1])) + - ((limb) ((s32) in2[0])) * ((s32) in[4]) + - ((limb) ((s32) in2[4])) * ((s32) in[0]); - output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) + - ((limb) ((s32) in2[3])) * ((s32) in[2]) + - ((limb) ((s32) in2[1])) * ((s32) in[4]) + - ((limb) ((s32) in2[4])) * ((s32) in[1]) + - ((limb) ((s32) in2[0])) * ((s32) in[5]) + - ((limb) ((s32) in2[5])) * ((s32) in[0]); - output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) + - ((limb) ((s32) in2[1])) * ((s32) in[5]) + - ((limb) ((s32) in2[5])) * ((s32) in[1])) + - ((limb) ((s32) in2[2])) * ((s32) in[4]) + - ((limb) ((s32) in2[4])) * ((s32) in[2]) + - ((limb) ((s32) in2[0])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[0]); - output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) + - ((limb) ((s32) in2[4])) * ((s32) in[3]) + - ((limb) ((s32) in2[2])) * ((s32) in[5]) + - ((limb) ((s32) in2[5])) * ((s32) in[2]) + - ((limb) ((s32) in2[1])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[1]) + - ((limb) ((s32) in2[0])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[0]); - output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) + - 2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) + - ((limb) ((s32) in2[5])) * ((s32) in[3]) + - ((limb) ((s32) in2[1])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[1])) + - ((limb) ((s32) in2[2])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[2]) + - ((limb) ((s32) in2[0])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[0]); - output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) + - ((limb) ((s32) in2[5])) * ((s32) in[4]) + - ((limb) ((s32) in2[3])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[3]) + - ((limb) ((s32) in2[2])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[2]) + - ((limb) ((s32) in2[1])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[1]) + - ((limb) ((s32) in2[0])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[0]); - output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) + - ((limb) ((s32) in2[3])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[3]) + - ((limb) ((s32) in2[1])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[1])) + - ((limb) ((s32) in2[4])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[4]) + - ((limb) ((s32) in2[2])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[2]); - output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) + - ((limb) ((s32) in2[6])) * ((s32) in[5]) + - ((limb) ((s32) in2[4])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[4]) + - ((limb) ((s32) in2[3])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[3]) + - ((limb) ((s32) in2[2])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[2]); - output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) + - 2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[5]) + - ((limb) ((s32) in2[3])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[3])) + - ((limb) ((s32) in2[4])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[4]); - output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) + - ((limb) ((s32) in2[7])) * ((s32) in[6]) + - ((limb) ((s32) in2[5])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[5]) + - ((limb) ((s32) in2[4])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[4]); - output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) + - ((limb) ((s32) in2[5])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[5])) + - ((limb) ((s32) in2[6])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[6]); - output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) + - ((limb) ((s32) in2[8])) * ((s32) in[7]) + - ((limb) ((s32) in2[6])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[6]); - output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) + - 2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[7])); - output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) + - ((limb) ((s32) in2[9])) * ((s32) in[8]); - output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]); -} - -/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */ -static void freduce_degree(limb *output) { - /* Each of these shifts and adds ends up multiplying the value by 19. */ - output[8] += output[18] << 4; - output[8] += output[18] << 1; - output[8] += output[18]; - output[7] += output[17] << 4; - output[7] += output[17] << 1; - output[7] += output[17]; - output[6] += output[16] << 4; - output[6] += output[16] << 1; - output[6] += output[16]; - output[5] += output[15] << 4; - output[5] += output[15] << 1; - output[5] += output[15]; - output[4] += output[14] << 4; - output[4] += output[14] << 1; - output[4] += output[14]; - output[3] += output[13] << 4; - output[3] += output[13] << 1; - output[3] += output[13]; - output[2] += output[12] << 4; - output[2] += output[12] << 1; - output[2] += output[12]; - output[1] += output[11] << 4; - output[1] += output[11] << 1; - output[1] += output[11]; - output[0] += output[10] << 4; - output[0] += output[10] << 1; - output[0] += output[10]; -} - -#if (-1 & 3) != 3 -#error "This code only works on a two's complement system" -#endif - -/* return v / 2^26, using only shifts and adds. */ -static limb div_by_2_26(const limb v) -{ - /* High word of v; no shift needed*/ - const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); - /* Set to all 1s if v was negative; else set to 0s. */ - const int32_t sign = ((int32_t) highword) >> 31; - /* Set to 0x3ffffff if v was negative; else set to 0. */ - const int32_t roundoff = ((uint32_t) sign) >> 6; - /* Should return v / (1<<26) */ - return (v + roundoff) >> 26; -} - -/* return v / (2^25), using only shifts and adds. */ -static limb div_by_2_25(const limb v) -{ - /* High word of v; no shift needed*/ - const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); - /* Set to all 1s if v was negative; else set to 0s. */ - const int32_t sign = ((int32_t) highword) >> 31; - /* Set to 0x1ffffff if v was negative; else set to 0. */ - const int32_t roundoff = ((uint32_t) sign) >> 7; - /* Should return v / (1<<25) */ - return (v + roundoff) >> 25; -} - -static s32 div_s32_by_2_25(const s32 v) -{ - const s32 roundoff = ((uint32_t)(v >> 31)) >> 7; - return (v + roundoff) >> 25; -} - -/* Reduce all coefficients of the short form input so that |x| < 2^26. - * - * On entry: |output[i]| < 2^62 - */ -static void freduce_coefficients(limb *output) { - unsigned i; - - output[10] = 0; - - for (i = 0; i < 10; i += 2) { - limb over = div_by_2_26(output[i]); - output[i] -= over << 26; - output[i+1] += over; - - over = div_by_2_25(output[i+1]); - output[i+1] -= over << 25; - output[i+2] += over; - } - /* Now |output[10]| < 2 ^ 38 and all other coefficients are reduced. */ - output[0] += output[10] << 4; - output[0] += output[10] << 1; - output[0] += output[10]; - - output[10] = 0; - - /* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19 * 2^38 - * So |over| will be no more than 77825 */ - { - limb over = div_by_2_26(output[0]); - output[0] -= over << 26; - output[1] += over; - } - - /* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 77825 - * So |over| will be no more than 1. */ - { - /* output[1] fits in 32 bits, so we can use div_s32_by_2_25 here. */ - s32 over32 = div_s32_by_2_25((s32) output[1]); - output[1] -= over32 << 25; - output[2] += over32; - } - - /* Finally, output[0,1,3..9] are reduced, and output[2] is "nearly reduced": - * we have |output[2]| <= 2^26. This is good enough for all of our math, - * but it will require an extra freduce_coefficients before fcontract. */ -} - -/* A helpful wrapper around fproduct: output = in * in2. - * - * output must be distinct to both inputs. The output is reduced degree and - * reduced coefficient. - */ -static void -fmul(limb *output, const limb *in, const limb *in2) { - limb t[19]; - fproduct(t, in, in2); - freduce_degree(t); - freduce_coefficients(t); - memcpy(output, t, sizeof(limb) * 10); -} - -static void fsquare_inner(limb *output, const limb *in) { - output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]); - output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]); - output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) + - ((limb) ((s32) in[0])) * ((s32) in[2])); - output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) + - ((limb) ((s32) in[0])) * ((s32) in[3])); - output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) + - 4 * ((limb) ((s32) in[1])) * ((s32) in[3]) + - 2 * ((limb) ((s32) in[0])) * ((s32) in[4]); - output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) + - ((limb) ((s32) in[1])) * ((s32) in[4]) + - ((limb) ((s32) in[0])) * ((s32) in[5])); - output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) + - ((limb) ((s32) in[2])) * ((s32) in[4]) + - ((limb) ((s32) in[0])) * ((s32) in[6]) + - 2 * ((limb) ((s32) in[1])) * ((s32) in[5])); - output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) + - ((limb) ((s32) in[2])) * ((s32) in[5]) + - ((limb) ((s32) in[1])) * ((s32) in[6]) + - ((limb) ((s32) in[0])) * ((s32) in[7])); - output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) + - 2 * (((limb) ((s32) in[2])) * ((s32) in[6]) + - ((limb) ((s32) in[0])) * ((s32) in[8]) + - 2 * (((limb) ((s32) in[1])) * ((s32) in[7]) + - ((limb) ((s32) in[3])) * ((s32) in[5]))); - output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) + - ((limb) ((s32) in[3])) * ((s32) in[6]) + - ((limb) ((s32) in[2])) * ((s32) in[7]) + - ((limb) ((s32) in[1])) * ((s32) in[8]) + - ((limb) ((s32) in[0])) * ((s32) in[9])); - output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) + - ((limb) ((s32) in[4])) * ((s32) in[6]) + - ((limb) ((s32) in[2])) * ((s32) in[8]) + - 2 * (((limb) ((s32) in[3])) * ((s32) in[7]) + - ((limb) ((s32) in[1])) * ((s32) in[9]))); - output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) + - ((limb) ((s32) in[4])) * ((s32) in[7]) + - ((limb) ((s32) in[3])) * ((s32) in[8]) + - ((limb) ((s32) in[2])) * ((s32) in[9])); - output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) + - 2 * (((limb) ((s32) in[4])) * ((s32) in[8]) + - 2 * (((limb) ((s32) in[5])) * ((s32) in[7]) + - ((limb) ((s32) in[3])) * ((s32) in[9]))); - output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) + - ((limb) ((s32) in[5])) * ((s32) in[8]) + - ((limb) ((s32) in[4])) * ((s32) in[9])); - output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) + - ((limb) ((s32) in[6])) * ((s32) in[8]) + - 2 * ((limb) ((s32) in[5])) * ((s32) in[9])); - output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) + - ((limb) ((s32) in[6])) * ((s32) in[9])); - output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) + - 4 * ((limb) ((s32) in[7])) * ((s32) in[9]); - output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]); - output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]); -} - -static void -fsquare(limb *output, const limb *in) { - limb t[19]; - fsquare_inner(t, in); - freduce_degree(t); - freduce_coefficients(t); - memcpy(output, t, sizeof(limb) * 10); -} - -/* Take a little-endian, 32-byte number and expand it into polynomial form */ -static void -fexpand(limb *output, const u8 *input) { -#define F(n,start,shift,mask) \ - output[n] = ((((limb) input[start + 0]) | \ - ((limb) input[start + 1]) << 8 | \ - ((limb) input[start + 2]) << 16 | \ - ((limb) input[start + 3]) << 24) >> shift) & mask; - F(0, 0, 0, 0x3ffffff); - F(1, 3, 2, 0x1ffffff); - F(2, 6, 3, 0x3ffffff); - F(3, 9, 5, 0x1ffffff); - F(4, 12, 6, 0x3ffffff); - F(5, 16, 0, 0x1ffffff); - F(6, 19, 1, 0x3ffffff); - F(7, 22, 3, 0x1ffffff); - F(8, 25, 4, 0x3ffffff); - F(9, 28, 6, 0x1ffffff); -#undef F -} - -#if (-32 >> 1) != -16 -#error "This code only works when >> does sign-extension on negative numbers" -#endif - -/* Take a fully reduced polynomial form number and contract it into a - * little-endian, 32-byte array - */ -static void -fcontract(u8 *output, limb *input) { - int i; - int j; - - for (j = 0; j < 2; ++j) { - for (i = 0; i < 9; ++i) { - if ((i & 1) == 1) { - /* This calculation is a time-invariant way to make input[i] positive - by borrowing from the next-larger limb. - */ - const s32 mask = (s32)(input[i]) >> 31; - const s32 carry = -(((s32)(input[i]) & mask) >> 25); - input[i] = (s32)(input[i]) + (carry << 25); - input[i+1] = (s32)(input[i+1]) - carry; - } else { - const s32 mask = (s32)(input[i]) >> 31; - const s32 carry = -(((s32)(input[i]) & mask) >> 26); - input[i] = (s32)(input[i]) + (carry << 26); - input[i+1] = (s32)(input[i+1]) - carry; - } - } - { - const s32 mask = (s32)(input[9]) >> 31; - const s32 carry = -(((s32)(input[9]) & mask) >> 25); - input[9] = (s32)(input[9]) + (carry << 25); - input[0] = (s32)(input[0]) - (carry * 19); - } - } - - /* The first borrow-propagation pass above ended with every limb - except (possibly) input[0] non-negative. - - Since each input limb except input[0] is decreased by at most 1 - by a borrow-propagation pass, the second borrow-propagation pass - could only have wrapped around to decrease input[0] again if the - first pass left input[0] negative *and* input[1] through input[9] - were all zero. In that case, input[1] is now 2^25 - 1, and this - last borrow-propagation step will leave input[1] non-negative. - */ - { - const s32 mask = (s32)(input[0]) >> 31; - const s32 carry = -(((s32)(input[0]) & mask) >> 26); - input[0] = (s32)(input[0]) + (carry << 26); - input[1] = (s32)(input[1]) - carry; - } - - /* Both passes through the above loop, plus the last 0-to-1 step, are - necessary: if input[9] is -1 and input[0] through input[8] are 0, - negative values will remain in the array until the end. - */ - - input[1] <<= 2; - input[2] <<= 3; - input[3] <<= 5; - input[4] <<= 6; - input[6] <<= 1; - input[7] <<= 3; - input[8] <<= 4; - input[9] <<= 6; -#define F(i, s) \ - output[s+0] |= input[i] & 0xff; \ - output[s+1] = (input[i] >> 8) & 0xff; \ - output[s+2] = (input[i] >> 16) & 0xff; \ - output[s+3] = (input[i] >> 24) & 0xff; - output[0] = 0; - output[16] = 0; - F(0,0); - F(1,3); - F(2,6); - F(3,9); - F(4,12); - F(5,16); - F(6,19); - F(7,22); - F(8,25); - F(9,28); -#undef F -} - -/* Input: Q, Q', Q-Q' - * Output: 2Q, Q+Q' - * - * x2 z3: long form - * x3 z3: long form - * x z: short form, destroyed - * xprime zprime: short form, destroyed - * qmqp: short form, preserved - */ -static void fmonty(limb *x2, limb *z2, /* output 2Q */ - limb *x3, limb *z3, /* output Q + Q' */ - limb *x, limb *z, /* input Q */ - limb *xprime, limb *zprime, /* input Q' */ - const limb *qmqp /* input Q - Q' */) { - limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19], - zzprime[19], zzzprime[19], xxxprime[19]; - - memcpy(origx, x, 10 * sizeof(limb)); - fsum(x, z); - fdifference(z, origx); /* does x - z */ - - memcpy(origxprime, xprime, sizeof(limb) * 10); - fsum(xprime, zprime); - fdifference(zprime, origxprime); - fproduct(xxprime, xprime, z); - fproduct(zzprime, x, zprime); - freduce_degree(xxprime); - freduce_coefficients(xxprime); - freduce_degree(zzprime); - freduce_coefficients(zzprime); - memcpy(origxprime, xxprime, sizeof(limb) * 10); - fsum(xxprime, zzprime); - fdifference(zzprime, origxprime); - fsquare(xxxprime, xxprime); - fsquare(zzzprime, zzprime); - fproduct(zzprime, zzzprime, qmqp); - freduce_degree(zzprime); - freduce_coefficients(zzprime); - memcpy(x3, xxxprime, sizeof(limb) * 10); - memcpy(z3, zzprime, sizeof(limb) * 10); - - fsquare(xx, x); - fsquare(zz, z); - fproduct(x2, xx, zz); - freduce_degree(x2); - freduce_coefficients(x2); - fdifference(zz, xx); /* does zz = xx - zz */ - memset(zzz + 10, 0, sizeof(limb) * 9); - fscalar_product(zzz, zz, 121665); - /* No need to call freduce_degree here: - fscalar_product doesn't increase the degree of its input. - */ - freduce_coefficients(zzz); - fsum(zzz, xx); - fproduct(z2, zz, zzz); - freduce_degree(z2); - freduce_coefficients(z2); -} - -/* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave - * them unchanged if 'iswap' is 0. Runs in data-invariant time to avoid - * side-channel attacks. - * - * NOTE that this function requires that 'iswap' be 1 or 0; other values give - * wrong results. Also, the two limb arrays must be in reduced-coefficient, - * reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped, - * and all all values in a[0..9],b[0..9] must have magnitude less than - * INT32_MAX. - */ -static void -swap_conditional(limb a[19], limb b[19], limb iswap) { - unsigned i; - const s32 swap = (s32) -iswap; - - for (i = 0; i < 10; ++i) { - const s32 x = swap & ( ((s32)a[i]) ^ ((s32)b[i]) ); - a[i] = ((s32)a[i]) ^ x; - b[i] = ((s32)b[i]) ^ x; - } -} - -/* Calculates nQ where Q is the x-coordinate of a point on the curve - * - * resultx/resultz: the x coordinate of the resulting curve point (short form) - * n: a little endian, 32-byte number - * q: a point of the curve (short form) - */ -static void -cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { - limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0}; - limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; - limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1}; - limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; - - unsigned i, j; - - memcpy(nqpqx, q, sizeof(limb) * 10); - - for (i = 0; i < 32; ++i) { - u8 byte = n[31 - i]; - for (j = 0; j < 8; ++j) { - const limb bit = byte >> 7; - - swap_conditional(nqx, nqpqx, bit); - swap_conditional(nqz, nqpqz, bit); - fmonty(nqx2, nqz2, - nqpqx2, nqpqz2, - nqx, nqz, - nqpqx, nqpqz, - q); - swap_conditional(nqx2, nqpqx2, bit); - swap_conditional(nqz2, nqpqz2, bit); - - t = nqx; - nqx = nqx2; - nqx2 = t; - t = nqz; - nqz = nqz2; - nqz2 = t; - t = nqpqx; - nqpqx = nqpqx2; - nqpqx2 = t; - t = nqpqz; - nqpqz = nqpqz2; - nqpqz2 = t; - - byte <<= 1; - } - } - - memcpy(resultx, nqx, sizeof(limb) * 10); - memcpy(resultz, nqz, sizeof(limb) * 10); -} - -/* ----------------------------------------------------------------------------- - * Shamelessly copied from djb's code - * ----------------------------------------------------------------------------- */ -static void -crecip(limb *out, const limb *z) { - limb z2[10]; - limb z9[10]; - limb z11[10]; - limb z2_5_0[10]; - limb z2_10_0[10]; - limb z2_20_0[10]; - limb z2_50_0[10]; - limb z2_100_0[10]; - limb t0[10]; - limb t1[10]; - int i; - - /* 2 */ fsquare(z2,z); - /* 4 */ fsquare(t1,z2); - /* 8 */ fsquare(t0,t1); - /* 9 */ fmul(z9,t0,z); - /* 11 */ fmul(z11,z9,z2); - /* 22 */ fsquare(t0,z11); - /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9); - - /* 2^6 - 2^1 */ fsquare(t0,z2_5_0); - /* 2^7 - 2^2 */ fsquare(t1,t0); - /* 2^8 - 2^3 */ fsquare(t0,t1); - /* 2^9 - 2^4 */ fsquare(t1,t0); - /* 2^10 - 2^5 */ fsquare(t0,t1); - /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0); - - /* 2^11 - 2^1 */ fsquare(t0,z2_10_0); - /* 2^12 - 2^2 */ fsquare(t1,t0); - /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } - /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0); - - /* 2^21 - 2^1 */ fsquare(t0,z2_20_0); - /* 2^22 - 2^2 */ fsquare(t1,t0); - /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } - /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0); - - /* 2^41 - 2^1 */ fsquare(t1,t0); - /* 2^42 - 2^2 */ fsquare(t0,t1); - /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } - /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0); - - /* 2^51 - 2^1 */ fsquare(t0,z2_50_0); - /* 2^52 - 2^2 */ fsquare(t1,t0); - /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } - /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0); - - /* 2^101 - 2^1 */ fsquare(t1,z2_100_0); - /* 2^102 - 2^2 */ fsquare(t0,t1); - /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); } - /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0); - - /* 2^201 - 2^1 */ fsquare(t0,t1); - /* 2^202 - 2^2 */ fsquare(t1,t0); - /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); } - /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0); - - /* 2^251 - 2^1 */ fsquare(t1,t0); - /* 2^252 - 2^2 */ fsquare(t0,t1); - /* 2^253 - 2^3 */ fsquare(t1,t0); - /* 2^254 - 2^4 */ fsquare(t0,t1); - /* 2^255 - 2^5 */ fsquare(t1,t0); - /* 2^255 - 21 */ fmul(out,t1,z11); -} - -int curve25519_donna(u8 *, const u8 *, const u8 *); - -int curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) { - limb bp[10], x[10], z[11], zmone[10]; - uint8_t e[32]; - int i; - - for (i = 0; i < 32; ++i) e[i] = secret[i]; - e[0] &= 248; - e[31] &= 127; - e[31] |= 64; - - fexpand(bp, basepoint); - cmult(x, z, e, bp); - crecip(zmone, z); - fmul(z, x, zmone); - freduce_coefficients(z); - fcontract(mypublic, z); - return 0; -} diff --git a/jni/libzrtp/sources/bnlib/ec/ec.c b/jni/libzrtp/sources/bnlib/ec/ec.c deleted file mode 100644 index 18e612f82..000000000 --- a/jni/libzrtp/sources/bnlib/ec/ec.c +++ /dev/null @@ -1,1695 +0,0 @@ -/* - * Copyright (C) 2012-2013 Werner Dittmann - * All rights reserved. For licensing and other legal details, see the file legal.c. - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - * - */ -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> - -#include <bn.h> -#include <bnprint.h> - -#include <ec/ec.h> - -static BigNum _mpiZero; -static BigNum _mpiOne; -static BigNum _mpiTwo; -static BigNum _mpiThree; -static BigNum _mpiFour; -static BigNum _mpiEight; - -static BigNum* mpiZero = &_mpiZero; -static BigNum* mpiOne = &_mpiOne; -static BigNum* mpiTwo = &_mpiTwo; -static BigNum* mpiThree = &_mpiThree; -static BigNum* mpiFour = &_mpiFour; -static BigNum* mpiEight = &_mpiEight; -static int initialized = 0; - - -/* The following parameters are given: - - The prime modulus p - - The order n - - The 160-bit input seed SEED to the SHA-1 based algorithm (i.e., the domain parameter seed) - - The output c of the SHA-1 based algorithm - - The coefficient b (satisfying b2 c ≡ –27 (mod p)) - - The base point x coordinate Gx - - The base point y coordinate Gy -*/ - -typedef struct _curveData { - char *p; - char *n; - char *SEED; - char *c; - char *b; - char *Gx; - char *Gy; -} curveData; - -static curveData nist192 = { - "6277101735386680763835789423207666416083908700390324961279", - "6277101735386680763835789423176059013767194773182842284081", - "3045ae6fc8422f64ed579528d38120eae12196d5", - "3099d2bbbfcb2538542dcd5fb078b6ef5f3d6fe2c745de65", - "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", - "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", - "07192b95ffc8da78631011ed6b24cdd573f977a11e794811", -}; - -static curveData nist224 = { - "26959946667150639794667015087019630673557916260026308143510066298881", - "26959946667150639794667015087019625940457807714424391721682722368061", - "bd71344799d5c7fcdc45b59fa3b9ab8f6a948bc5", - "5b056c7e11dd68f40469ee7f3c7a7d74f7d121116506d031218291fb", - "b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", - "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", - "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", -}; - -static curveData nist256 = { - "115792089210356248762697446949407573530086143415290314195533631308867097853951", - "115792089210356248762697446949407573529996955224135760342422259061068512044369", - "c49d360886e704936a6678e1139d26b7819f7e90", - "7efba1662985be9403cb055c75d4f7e0ce8d84a9c5114abcaf3177680104fa0d", - "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", - "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", - "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", -}; - -static curveData nist384 = { - "39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", - "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643", - "a335926aa319a27a1d00896a6773a4827acdac73", - "79d1e655f868f02fff48dcdee14151ddb80643c1406d0ca10dfe6fc52009540a495e8042ea5f744f6e184667cc722483", - "b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", - "aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", - "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", -}; - -static curveData nist521 = { - "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", - "6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", - "d09e8800291cb85396cc6717393284aaa0da64ba", - "0b48bfa5f420a34949539d2bdfc264eeeeb077688e44fbf0ad8f6d0edb37bd6b533281000518e19f1b9ffbe0fe9ed8a3c2200b8f875e523868c70c1e5bf55bad637", - "051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", - "c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", - "11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", -}; - - -/* - * The data for curve3617 copied from: - * http://safecurves.cr.yp.to/field.html - * http://safecurves.cr.yp.to/base.html - */ -static curveData curve3617 = { - "3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef", /* Prime */ - "7ffffffffffffffffffffffffffffffffffffffffffffffffffeb3cc92414cf706022b36f1c0338ad63cf181b0e71a5e106af79", /* order */ - "", /* SEED */ - "", /* c */ - "", /* b */ - "1a334905141443300218c0631c326e5fcd46369f44c03ec7f57ff35498a4ab4d6d6ba111301a73faa8537c64c4fd3812f3cbc595", /* Gx*/ - "22", /* Gy (radix 16) */ -}; - -/* - * The data for curve25519 copied from: - * http://safecurves.cr.yp.to/field.html - * http://safecurves.cr.yp.to/base.html - * - * Note: - * The data for Curve25519 is here for the sake of completeness and to have the same - * set of initialization. One exception if the base point X coordinate (Gx) that we use to - * compute the DH public value, refer to function ecdhGeneratePublic(...) in ecdh.c. - * - * Otherwise the functions use EcCurve structure only to get the pointers to the Curve25519 - * wrapper functions. - * - */ -static curveData curve25519 = { - "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", /* Prime */ - "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", /* order */ - "", /* SEED */ - "", /* c */ - "", /* b */ - "9", /* Gx */ - "20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9", /* Gy */ -}; - -/*============================================================================*/ -/* Bignum Shorthand Functions */ -/*============================================================================*/ - -int bnAddMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod) -{ - bnAdd (rslt, n1); - if (bnCmp (rslt, mod) >= 0) { - bnSub (rslt, mod); - } - return 0; -} - -int bnAddQMod_ (struct BigNum *rslt, unsigned n1, struct BigNum *mod) -{ - bnAddQ (rslt, n1); - if (bnCmp (rslt, mod) >= 0) { - bnSub (rslt, mod); - } - return 0; -} - -int bnSubMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod) -{ - if (bnCmp (rslt, n1) < 0) { - bnAdd (rslt, mod); - } - bnSub (rslt, n1); - return 0; -} - -int bnSubQMod_ (struct BigNum *rslt, unsigned n1, struct BigNum *mod) -{ - if (bnCmpQ (rslt, n1) < 0) { - bnAdd (rslt, mod); - } - bnSubQ (rslt, n1); - return 0; -} - -int bnMulMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *n2, struct BigNum *mod, const EcCurve *curve) -{ - bnMul (rslt, n1, n2); - if (curve) - curve->modOp(rslt, rslt, mod); - else - bnMod(rslt, rslt, mod); - return 0; -} - -int bnMulQMod_ (struct BigNum *rslt, struct BigNum *n1, unsigned n2, struct BigNum *mod, const EcCurve *curve) -{ - bnMulQ (rslt, n1, n2); - if (curve) - curve->modOp(rslt, rslt, mod); - else - bnMod(rslt, rslt, mod); - return 0; -} - -int bnSquareMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod, const EcCurve *curve) -{ - bnSquare (rslt, n1); - if (curve) - curve->modOp(rslt, rslt, mod); - else - bnMod(rslt, rslt, mod); - return 0; -} - -/* - * Note on the Curve25519 functions and usage of BigNumber: - * In most cases the functions to compute Curve25519 data are small wrapper functions - * that implement the same API as for the other curve functions. The wrapper functions - * then call the very specific, high-efficient function in curve25519-donna.c . - * - * For Curve25519 we don't have a real implementation for point add, point doubling, modulo - * and check public key. Please refer to the actual implementations below. - */ - -static int ecGetAffineNist(const EcCurve *curve, EcPoint *R, const EcPoint *P); -static int ecGetAffineEd(const EcCurve *curve, EcPoint *R, const EcPoint *P); -static int ecGetAffine25519(const EcCurve *curve, EcPoint *R, const EcPoint *P); - -static int ecDoublePointNist(const EcCurve *curve, EcPoint *R, const EcPoint *P); -static int ecDoublePointEd(const EcCurve *curve, EcPoint *R, const EcPoint *P); -static int ecDoublePoint25519(const EcCurve *curve, EcPoint *R, const EcPoint *P); - -static int ecAddPointNist(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q); -static int ecAddPointEd(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q); -static int ecAddPoint25519(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q); - -static int ecCheckPubKeyNist(const EcCurve *curve, const EcPoint *pub); -static int ecCheckPubKey3617(const EcCurve *curve, const EcPoint *pub); -static int ecCheckPubKey25519(const EcCurve *curve, const EcPoint *pub); - -static int ecGenerateRandomNumberNist(const EcCurve *curve, BigNum *d); -static int ecGenerateRandomNumber3617(const EcCurve *curve, BigNum *d); -static int ecGenerateRandomNumber25519(const EcCurve *curve, BigNum *d); - -static int ecMulPointScalarNormal(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar); -static int ecMulPointScalar25519(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar); - -/* Forward declaration of new modulo functions for the EC curves */ -static int newMod192(BigNum *r, const BigNum *a, const BigNum *modulo); -static int newMod256(BigNum *r, const BigNum *a, const BigNum *modulo); -static int newMod384(BigNum *r, const BigNum *a, const BigNum *modulo); -static int newMod521(BigNum *r, const BigNum *a, const BigNum *modulo); - -static int mod3617(BigNum *r, const BigNum *a, const BigNum *modulo); -static int mod25519(BigNum *r, const BigNum *a, const BigNum *modulo); - -static void commonInit() -{ - bnBegin(mpiZero); bnSetQ(mpiZero, 0); - bnBegin(mpiOne); bnSetQ(mpiOne, 1); - bnBegin(mpiTwo); bnSetQ(mpiTwo, 2); - bnBegin(mpiThree); bnSetQ(mpiThree, 3); - bnBegin(mpiFour); bnSetQ(mpiFour, 4); - bnBegin(mpiEight); bnSetQ(mpiEight, 8); -} - -static void curveCommonInit(EcCurve *curve) -{ - /* Initialize scratchpad variables and their pointers */ - bnBegin(&curve->_S1); curve->S1 = &curve->_S1; - bnBegin(&curve->_U1); curve->U1 = &curve->_U1; - bnBegin(&curve->_H); curve->H = &curve->_H; - bnBegin(&curve->_R); curve->R = &curve->_R; - bnBegin(&curve->_t0); curve->t0 = &curve->_t0; - bnBegin(&curve->_t1); curve->t1 = &curve->_t1; - bnBegin(&curve->_t2); curve->t2 = &curve->_t2; - bnBegin(&curve->_t3); curve->t3 = &curve->_t3; -} - -static void curveCommonPrealloc(EcCurve *curve) -{ - size_t maxBits; - - /* variables must be able to hold p^2, plus one nimb (min. 15 bits) for overflow */ - maxBits = bnBits(curve->p) * 2 + 15; - - /* The set_bit allocates enough memory to hold maximum values */ - /* Initialize scratchpad variables before use */ - bnPrealloc(curve->S1, maxBits); - bnPrealloc(curve->U1, maxBits); - bnPrealloc(curve->H, maxBits); - bnPrealloc(curve->R, maxBits); - bnPrealloc(curve->S1, maxBits); - bnPrealloc(curve->t1, maxBits); - bnPrealloc(curve->t2, maxBits); - bnPrealloc(curve->t3, maxBits); -} - -int ecGetCurveNistECp(Curves curveId, EcCurve *curve) -{ - curveData *cd; - - if (curveId >= Curve25519 && curveId <= Curve3617) - return ecGetCurvesCurve(curveId, curve); - - if (!initialized) { - commonInit(); - initialized = 1; - } - if (curve == NULL) - return -2; - - bnBegin(&curve->_p); curve->p = &curve->_p; - bnBegin(&curve->_n); curve->n = &curve->_n; - bnBegin(&curve->_SEED); curve->SEED = &curve->_SEED; - bnBegin(&curve->_c); curve->c = &curve->_c; - bnBegin(&curve->_a); curve->a = &curve->_a; - bnBegin(&curve->_b); curve->b = &curve->_b; - bnBegin(&curve->_Gx); curve->Gx = &curve->_Gx; - bnBegin(&curve->_Gy); curve->Gy = &curve->_Gy; - - curveCommonInit(curve); - - switch (curveId) { - case NIST192P: - cd = &nist192; - curve->modOp = newMod192; - break; - - case NIST224P: - cd = &nist224; - curve->modOp = bnMod; - break; - - case NIST256P: - cd = &nist256; - curve->modOp = bnMod; - break; - - case NIST384P: - cd = &nist384; - curve->modOp = newMod384; - break; - - case NIST521P: - cd = &nist521; - curve->modOp = newMod521; - break; - - default: - return -2; - } - - curve->affineOp = ecGetAffineNist; - curve->doubleOp = ecDoublePointNist; - curve->addOp = ecAddPointNist; - curve->checkPubOp = ecCheckPubKeyNist; - curve->randomOp = ecGenerateRandomNumberNist; - curve->mulScalar = ecMulPointScalarNormal; - - bnReadAscii(curve->p, cd->p, 10); - bnReadAscii(curve->n, cd->n, 10); - bnReadAscii(curve->SEED, cd->SEED, 16); - bnReadAscii(curve->c, cd->c, 16); - bnCopy(curve->a, curve->p); - bnSub(curve->a, mpiThree); - bnReadAscii(curve->b, cd->b, 16); - bnReadAscii(curve->Gx, cd->Gx, 16); - bnReadAscii(curve->Gy, cd->Gy, 16); - - curveCommonPrealloc(curve); - curve->id = curveId; - - return 0; -} - -int ecGetCurvesCurve(Curves curveId, EcCurve *curve) -{ - curveData *cd; - - if (!initialized) { - commonInit(); - initialized = 1; - } - if (curve == NULL) - return -2; - - /* set-up all bignum structures, simplifies "free" handling */ - bnBegin(&curve->_p); curve->p = &curve->_p; - bnBegin(&curve->_n); curve->n = &curve->_n; - bnBegin(&curve->_SEED); curve->SEED = &curve->_SEED; - bnBegin(&curve->_c); curve->c = &curve->_c; - bnBegin(&curve->_a); curve->a = &curve->_a; - bnBegin(&curve->_b); curve->b = &curve->_b; - bnBegin(&curve->_Gx); curve->Gx = &curve->_Gx; - bnBegin(&curve->_Gy); curve->Gy = &curve->_Gy; - - curveCommonInit(curve); - - switch (curveId) { - case Curve3617: - cd = &curve3617; - curve->modOp = mod3617; - curve->affineOp = ecGetAffineEd; - curve->doubleOp = ecDoublePointEd; - curve->addOp = ecAddPointEd; - curve->checkPubOp = ecCheckPubKey3617; - curve->randomOp = ecGenerateRandomNumber3617; - curve->mulScalar = ecMulPointScalarNormal; - - bnReadAscii(curve->a, "3617", 10); - break; - - case Curve25519: - cd = &curve25519; - curve->modOp = mod25519; - curve->affineOp = ecGetAffine25519; - curve->doubleOp = ecDoublePoint25519; - curve->addOp = ecAddPoint25519; - curve->checkPubOp = ecCheckPubKey25519; - curve->randomOp = ecGenerateRandomNumber25519; - curve->mulScalar = ecMulPointScalar25519; - - bnReadAscii(curve->a, "486662", 10); - break; - - default: - return -2; - } - bnReadAscii(curve->p, cd->p, 16); - bnReadAscii(curve->n, cd->n, 16); - - bnReadAscii(curve->Gx, cd->Gx, 16); - bnReadAscii(curve->Gy, cd->Gy, 16); - - curveCommonPrealloc(curve); - curve->id = curveId; - return 0; -} - -void ecFreeCurveNistECp(EcCurve *curve) -{ - if (curve == NULL) - return; - - bnEnd(curve->p); - bnEnd(curve->n); - bnEnd(curve->SEED); - bnEnd(curve->c); - bnEnd(curve->b); - bnEnd(curve->Gx); - bnEnd(curve->Gy); - - bnEnd(curve->S1); - bnEnd(curve->U1); - bnEnd(curve->H); - bnEnd(curve->R); - bnEnd(curve->t0); - bnEnd(curve->t1); - bnEnd(curve->t2); - bnEnd(curve->t3); -} - -/* - * EC point helper functions - */ - -void ecInitPoint(EcPoint *P) -{ - INIT_EC_POINT(P); -} - -void ecFreePoint(EcPoint *P) -{ - FREE_EC_POINT(P); -} - -void ecSetBasePoint(EcCurve *C, EcPoint *P) -{ - SET_EC_BASE_POINT(C, P); -} - -void ecFreeCurvesCurve(EcCurve *curve) -{ - ecFreeCurveNistECp(curve); -} - -/*============================================================================*/ -/* Elliptic Curve arithmetic */ -/*============================================================================*/ - -int ecGetAffine(const EcCurve *curve, EcPoint *R, const EcPoint *P) -{ - return curve->affineOp(curve, R, P); -} - -static int ecGetAffineNist(const EcCurve *curve, EcPoint *R, const EcPoint *P) -{ - int ret = 0; - - struct BigNum z_1, z_2; - - bnBegin(&z_1); - bnBegin(&z_2); - - /* affine x = X / Z^2 */ - bnInv (&z_1, P->z, curve->p); /* z_1 = Z^(-1) */ - bnMulMod_(&z_2, &z_1, &z_1, curve->p, curve); /* z_2 = Z^(-2) */ - bnMulMod_(R->x, P->x, &z_2, curve->p, curve); - - /* affine y = Y / Z^3 */ - bnMulMod_(&z_2, &z_2, &z_1, curve->p, curve); /* z_2 = Z^(-3) */ - bnMulMod_(R->y, P->y, &z_2, curve->p, curve); - - bnSetQ(R->z, 1); - - bnEnd(&z_1); - bnEnd(&z_2); - return ret; -} - -static int ecGetAffineEd(const EcCurve *curve, EcPoint *R, const EcPoint *P) -{ - int ret = 0; - - struct BigNum z_1; - - bnBegin(&z_1); - - /* affine x = X / Z */ - bnInv (&z_1, P->z, curve->p); /* z_1 = Z^(-1) */ - bnMulMod_(R->x, P->x, &z_1, curve->p, curve); - - /* affine y = Y / Z */ - bnMulMod_(R->y, P->y, &z_1, curve->p, curve); - - bnSetQ(R->z, 1); - - bnEnd(&z_1); - return ret; - -} - -/* - * If the arguments do not point to the same EcPoint then copy P to result. - * Curve25519 has no specific GetAffine function, it's all inside curve25519-donna - */ -static int ecGetAffine25519(const EcCurve *curve, EcPoint *R, const EcPoint *P) -{ - if (R != P) { - bnCopy(R->x, P->x); - bnCopy(R->y, P->y); - bnCopy(R->z, P->z); - } - return 0; -} - -int ecDoublePoint(const EcCurve *curve, EcPoint *R, const EcPoint *P) -{ - return curve->doubleOp(curve, R, P); -} - -static int ecDoublePointNist(const EcCurve *curve, EcPoint *R, const EcPoint *P) -{ - int ret = 0; - - EcPoint tP; - const EcPoint *ptP = 0; - - if (!bnCmp(P->y, mpiZero) || !bnCmp(P->z, mpiZero)) { - bnSetQ(R->x, 1); - bnSetQ(R->y, 1); - bnSetQ(R->z, 0); - return 0; - } - - /* Check for overlapping arguments, copy if necessary and set pointer */ - if (P == R) { - INIT_EC_POINT(&tP); - ptP = &tP; - bnCopy(tP.x, P->x); - bnCopy(tP.y, P->y); - bnCopy(tP.z, P->z); - } - else - ptP = P; - - /* S = 4*X*Y^2, save Y^2 in t1 for later use */ - bnMulMod_(curve->t1, ptP->y, ptP->y, curve->p, curve); /* t1 = Y^2 */ - bnMulMod_(curve->t0, ptP->x, mpiFour, curve->p, curve); /* t0 = 4 * X */ - bnMulMod_(curve->S1, curve->t0, curve->t1, curve->p, curve); /* S1 = t0 * t1 */ - - /* M = 3*(X + Z^2)*(X - Z^2), use scratch variable U1 to store M value */ - bnMulMod_(curve->t2, ptP->z, ptP->z, curve->p, curve); /* t2 = Z^2 */ - bnCopy(curve->t0, ptP->x); - bnAddMod_(curve->t0, curve->t2, curve->p); /* t0 = X + t2 */ - bnMulMod_(curve->t3, curve->t0, mpiThree, curve->p, curve); /* t3 = 3 * t0 */ - bnCopy(curve->t0, ptP->x); - bnSubMod_(curve->t0, curve->t2, curve->p); /* t0 = X - t2 */ - bnMulMod_(curve->U1, curve->t3, curve->t0, curve->p, curve); /* M = t3 * t0 */ - - /* X' = M^2 - 2*S */ - bnMulMod_(curve->t2, curve->U1, curve->U1, curve->p, curve); /* t2 = M^2 */ - bnMulMod_(curve->t0, curve->S1, mpiTwo, curve->p, curve); /* t0 = S * 2 */ - bnCopy(R->x, curve->t2); - bnSubMod_(R->x, curve->t0, curve->p); /* X' = t2 - t0 */ - - /* Y' = M*(S - X') - 8*Y^4 */ - bnMulMod_(curve->t3, curve->t1, curve->t1, curve->p, curve); /* t3 = Y^4 (t1 saved above) */ - bnMulMod_(curve->t2, curve->t3, mpiEight, curve->p, curve); /* t2 = t3 * 8 */ - bnCopy(curve->t3, curve->S1); - bnSubMod_(curve->t3, R->x, curve->p); /* t3 = S - X' */ - bnMulMod_(curve->t0, curve->U1, curve->t3, curve->p, curve); /* t0 = M * t3 */ - bnCopy(R->y, curve->t0); - bnSubMod_(R->y, curve->t2, curve->p); /* Y' = t0 - t2 */ - - /* Z' = 2*Y*Z */ - bnMulMod_(curve->t0, ptP->y, mpiTwo, curve->p, curve); /* t0 = 2 * Y */ - bnMulMod_(R->z, curve->t0, ptP->z, curve->p, curve); /* Z' = to * Z */ - - if (P == R) - FREE_EC_POINT(&tP); - - return ret; -} - -static int ecDoublePointEd(const EcCurve *curve, EcPoint *R, const EcPoint *P) -{ - EcPoint tP; - const EcPoint *ptP = 0; - - /* Check for overlapping arguments, copy if necessary and set pointer */ - if (P == R) { - INIT_EC_POINT(&tP); - ptP = &tP; - bnCopy(tP.x, P->x); - bnCopy(tP.y, P->y); - bnCopy(tP.z, P->z); - } - else - ptP = P; - - /* Compute B, C, D, H, E */ - bnCopy(curve->t1, ptP->x); - bnAddMod_(curve->t1, ptP->y, curve->p); - bnSquareMod_(curve->t0, curve->t1, curve->p, curve); /* t0 -> B */ - - bnSquareMod_(R->x, ptP->x, curve->p, curve); /* Rx -> C */ - - bnSquareMod_(R->y, ptP->y, curve->p, curve); /* Ry -> D */ - - bnSquareMod_(R->z, ptP->z, curve->p, curve); /* Rz -> H */ - bnAddMod_(R->z, R->z, curve->p); /* Rz -> 2H */ - - bnCopy(curve->t1, R->x); - bnAddMod_(curve->t1, R->y, curve->p); /* t1 -> E */ - - /* Compute Ry */ - bnCopy(curve->t2, R->x); - bnSubMod_(curve->t2, R->y, curve->p); /* C - D */ - bnMulMod_(R->y, curve->t1, curve->t2, curve->p, curve); /* E * t3; Ry */ - - /* Compute Rx */ - bnSubMod_(curve->t0, curve->t1, curve->p); /* B - E; sub result */ - bnCopy(curve->t2, curve->t1); - bnSubMod_(curve->t2, R->z, curve->p); /* t2 -> J; (E - 2H) */ - bnMulMod_(R->x, curve->t2, curve->t0, curve->p, curve); /* J * t0 */ - - /* Compute Rz */ - bnMulMod_(R->z, curve->t2, curve->t1, curve->p, curve); /* J * E */ - - if (P == R) - FREE_EC_POINT(&tP); - - return 0; -} - -/* - * Curve25519 has no specific Double Point function, all inside curve25519-donna - */ -static int ecDoublePoint25519(const EcCurve *curve, EcPoint *R, const EcPoint *P) -{ - return -2; -} - -/* Add two elliptic curve points. Any of them may be the same object. */ -int ecAddPoint(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q) -{ - return curve->addOp(curve, R, P, Q); -} - -static int ecAddPointNist(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q) -{ - int ret = 0; - - EcPoint tP, tQ; - const EcPoint *ptP = 0; - const EcPoint *ptQ = 0; - - - /* Fast check if application called add(R, P, P) */ - if (!bnCmp(P->x, Q->x) && !bnCmp(P->y, Q->y) && !bnCmp(P->z, Q->z)) { - return ecDoublePoint(curve, R, P); - } - - /* if P is (@,@), R = Q */ - if (!bnCmp(P->z, mpiZero)) { - bnCopy(R->x, Q->x); - bnCopy(R->y, Q->y); - bnCopy(R->z, Q->z); - return 0; - } - - /* if Q is (@,@), R = P */ - if (!bnCmp(Q->z, mpiZero)) { - bnCopy(R->x, P->x); - bnCopy(R->y, P->y); - bnCopy(R->z, P->z); - return 0; - } - - /* Check for overlapping arguments, copy if necessary and set pointers */ - if (P == R) { - INIT_EC_POINT(&tP); - ptP = &tP; - bnCopy(tP.x, P->x); - bnCopy(tP.y, P->y); - bnCopy(tP.z, P->z); - } - else - ptP = P; - - if (Q == R) { - INIT_EC_POINT(&tQ); - ptQ = &tQ; - bnCopy(tQ.x, Q->x); - bnCopy(tQ.y, Q->y); - bnCopy(tQ.z, Q->z); - } - else - ptQ = Q; - - /* U1 = X1*Z2^2, where X1: P->x, Z2: Q->z */ - bnMulMod_(curve->t1, ptQ->z, ptQ->z, curve->p, curve); /* t1 = Z2^2 */ - bnMulMod_(curve->U1, ptP->x, curve->t1, curve->p, curve); /* U1 = X1 * z_2 */ - - /* S1 = Y1*Z2^3, where Y1: P->y */ - bnMulMod_(curve->t1, curve->t1, ptQ->z, curve->p, curve); /* t1 = Z2^3 */ - bnMulMod_(curve->S1, ptP->y, curve->t1, curve->p, curve); /* S1 = Y1 * z_2 */ - - /* U2 = X2*Z1^2, where X2: Q->x, Z1: P->z */ - bnMulMod_(curve->t1, ptP->z, ptP->z, curve->p, curve); /* t1 = Z1^2 */ - bnMulMod_(curve->H, ptQ->x, curve->t1, curve->p, curve); /* H = X2 * t1 (store U2 in H) */ - - /* H = U2 - U1 */ - bnSubMod_(curve->H, curve->U1, curve->p); - - /* S2 = Y2*Z1^3, where Y2: Q->y */ - bnMulMod_(curve->t1, curve->t1, ptP->z, curve->p, curve); /* t1 = Z1^3 */ - bnMulMod_(curve->R, ptQ->y, curve->t1, curve->p, curve); /* R = Y2 * t1 (store S2 in R) */ - - /* R = S2 - S1 */ - bnSubMod_(curve->R, curve->S1, curve->p); - - /* if (U1 == U2), i.e H is zero */ - if (!bnCmp(curve->H, mpiZero)) { - - /* if (S1 != S2), i.e. R is _not_ zero: return infinity*/ - if (bnCmp(curve->R, mpiZero)) { - bnSetQ(R->x, 1); - bnSetQ(R->y, 1); - bnSetQ(R->z, 0); - return 0; - } - return ecDoublePoint(curve, R, P); - } - /* X3 = R^2 - H^3 - 2*U1*H^2, where X3: R->x */ - bnMulMod_(curve->t0, curve->H, curve->H, curve->p, curve); /* t0 = H^2 */ - bnMulMod_(curve->t1, curve->U1, curve->t0, curve->p, curve); /* t1 = U1 * t0, (hold t1) */ - bnMulMod_(curve->t0, curve->t0, curve->H, curve->p, curve); /* t0 = H^3, (hold t0) */ - bnMulMod_(curve->t2, curve->R, curve->R, curve->p, curve); /* t2 = R^2 */ - bnCopy(curve->t3, curve->t2); - bnSubMod_(curve->t3, curve->t0, curve->p); /* t3 = t2 - t0, (-H^3)*/ - bnMulMod_(curve->t2, mpiTwo, curve->t1, curve->p, curve); /* t2 = 2 * t1 */ - bnCopy(R->x, curve->t3); - bnSubMod_(R->x, curve->t2, curve->p); /* X3 = t3 - t2 */ - - /* Y3 = R*(U1*H^2 - X3) - S1*H^3, where Y3: R->y */ - bnSubMod_(curve->t1, R->x, curve->p); /* t1 = t1 - X3, overwrites t1 now */ - bnMulMod_(curve->t2, curve->R, curve->t1, curve->p, curve); /* t2 = R * z_2 */ - bnMulMod_(curve->S1, curve->S1, curve->t0, curve->p, curve); /* S1 = S1 * t0, (t0 has H^3) */ - bnCopy(R->y, curve->t2); - bnSubMod_(R->y, curve->S1, curve->p); /* Y3 = t2 - S1 */ - - /* Z3 = H*Z1*Z2, where Z1: P->z, Z2: Q->z, Z3: R->z */ - bnMulMod_(curve->t2, curve->H, P->z, curve->p, curve); /* t2 = H * Z1 */ - bnMulMod_(R->z, curve->t2, Q->z, curve->p, curve); /* Z3 = t2 * Z2 */ - - if (P == R) - FREE_EC_POINT(&tP); - if (Q == R) - FREE_EC_POINT(&tQ); - return ret; -} - -/* - * Refer to the document: Faster addition and doubling on elliptic curves; Daniel J. Bernstein and Tanja Lange - * section 4. - * - * This function is a variant of the 'addition'. The function returns the result in an own curve point - * and does not overwrite its input parameters. - */ -static int ecAddPointEd(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q) -{ - EcPoint tP, tQ; - const EcPoint *ptP = 0; - const EcPoint *ptQ = 0; - - /* if P is (@,@), R = Q */ - if (!bnCmp(P->z, mpiZero)) { - bnCopy(R->x, Q->x); - bnCopy(R->y, Q->y); - bnCopy(R->z, Q->z); - return 0; - } - - /* if Q is (@,@), R = P */ - if (!bnCmp(Q->z, mpiZero)) { - bnCopy(R->x, P->x); - bnCopy(R->y, P->y); - bnCopy(R->z, P->z); - return 0; - } - - /* Check for overlapping arguments, copy if necessary and set pointers */ - if (P == R) { - INIT_EC_POINT(&tP); - ptP = &tP; - bnCopy(tP.x, P->x); - bnCopy(tP.y, P->y); - bnCopy(tP.z, P->z); - } - else - ptP = P; - - if (Q == R) { - INIT_EC_POINT(&tQ); - ptQ = &tQ; - bnCopy(tQ.x, Q->x); - bnCopy(tQ.y, Q->y); - bnCopy(tQ.z, Q->z); - } - else - ptQ = Q; - - /* Compute A, C, D first */ - bnMulMod_(R->z, ptP->z, ptQ->z, curve->p, curve); /* Rz -> A; (Z1 * z2); Rz becomes R3 */ - bnMulMod_(R->x, ptP->x, ptQ->x, curve->p, curve); /* Rx -> C; (X1 * X2); Rx becomes R1 */ - bnMulMod_(R->y, ptP->y, ptQ->y, curve->p, curve); /* Ry -> D; (Y1 * Y2); Ry becomes R2 */ - - /* Compute large parts of X3 equation, sub result in t0 */ - bnCopy(curve->t0, ptP->x); - bnAddMod_(curve->t0, ptP->y, curve->p); /* t0 -> X1 + Y1 */ - bnCopy(curve->t1, ptQ->x); - bnAddMod_(curve->t1, ptQ->y, curve->p); /* t1 -> X2 + Y2 */ - bnMulMod_(curve->t2, curve->t0, curve->t1, curve->p, curve); /* t2 = t0 * t1 */ - bnSubMod_(curve->t2, R->x, curve->p); /* t2 - C */ - bnSubMod_(curve->t2, R->y, curve->p); /* t2 - D */ - bnMulMod_(curve->t0, curve->t2, R->z, curve->p, curve); /* t0 -> R7; (t2 * A); sub result */ - - /* Compute E */ - bnMulMod_(curve->t2, R->x, R->y, curve->p, curve); /* t2 = C * D */ - bnMulMod_(curve->t1, curve->t2, curve->a, curve->p, curve); /* t1 -> E; t1 new R8 */ - - /* Compute part of Y3 equation, sub result in t2 */ - bnSubMod_(R->y, R->x, curve->p); /* Ry = D - C; sub result */ - bnMulMod_(curve->t2, R->y, R->z, curve->p, curve); /* t2 = Ry * A; sub result */ - - /* Compute B */ - bnSquareMod_(R->z, R->z, curve->p, curve); /* Rz -> B; (A^2) */ - - /* Compute F */ - bnCopy(curve->t3, R->z); - bnSubMod_(curve->t3, curve->t1, curve->p); /* t3 -> F; (B - E) */ - - /* Compute G */ - bnAddMod_(R->z, curve->t1, curve->p); /* Rz -> G; (B + E) */ - - /* Compute, X, Y, Z results */ - bnMulMod_(R->x, curve->t3, curve->t0, curve->p, curve); /* Rx = F * t0 */ - bnMulMod_(R->y, curve->t2, R->z, curve->p, curve); /* Ry = t2 * G */ - bnMulMod_(R->z, curve->t3, R->z, curve->p, curve); /* Rz = F * G */ - - if (P == R) - FREE_EC_POINT(&tP); - if (Q == R) - FREE_EC_POINT(&tQ); - - return 0; -} - -/* - * Curve25519 has no specific Add Point function, all inside curve25519-donna - */ -static int ecAddPoint25519(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q) -{ - return -2; -} - -int ecMulPointScalar(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar) -{ - return curve->mulScalar(curve, R, P, scalar); -} - -static int ecMulPointScalarNormal(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar) -{ - int ret = 0; - int i; - int bits = bnBits(scalar); - EcPoint n; - - INIT_EC_POINT(&n); - bnCopy(n.x, P->x); - bnCopy(n.y, P->y); - bnCopy(n.z, P->z); - - bnSetQ(R->x, 0); - bnSetQ(R->y, 0); - bnSetQ(R->z, 0); - - for (i = 0; i < bits; i++) { - if (bnReadBit(scalar, i)) - ecAddPoint(curve, R, R, &n); - - /* ecAddPoint(curve, &n, &n, &n); */ - ecDoublePoint(curve, &n, &n); - } - FREE_EC_POINT(&n); - return ret; -} - -/* - * This function uses BigNumber only as containers to transport the 32 byte data. - * This makes it compliant to the other functions and thus higher-level API does not change. - * - * curve25519_donna function uses data in little endian format. - */ -static int ecMulPointScalar25519(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar) -{ - uint8_t basepoint[32], secret[32], result[32]; - - bnExtractLittleBytes(P->x, basepoint, 0, 32); /* 25519 function requires the X coordinate only (compressed) */ - bnExtractLittleBytes(scalar, secret, 0, 32); - curve25519_donna(result, secret, basepoint); - bnInsertLittleBytes(R->x, result, 0, 32); - return 0; -} - -#ifdef WEAKRANDOM -#include <fcntl.h> - -/* - * A standard random number generator that uses the portable random() system function. - * - * This should be enhanced to use a better random generator - */ -static int _random(unsigned char *output, size_t len) -{ - size_t num = 0; - - int rnd = open("/dev/urandom", O_RDONLY); - if (rnd >= 0) { - num = read(rnd, output, len); - close(rnd); - } - else - return num; - - return( 0 ); -} -#else -#include <cryptcommon/ZrtpRandom.h> -static int _random(unsigned char *output, size_t len) -{ - return zrtp_getRandomData(output, len); -} -#endif - -int ecGenerateRandomNumber(const EcCurve *curve, BigNum *d) -{ - return curve->randomOp(curve, d); -} - -static int ecGenerateRandomNumberNist(const EcCurve *curve, BigNum *d) -{ - BigNum c, nMinusOne; - - size_t randomBytes = ((bnBits(curve->n) + 64) + 7) / 8; - - uint8_t *ran = malloc(randomBytes); - - bnBegin(&c); - bnBegin(&nMinusOne); - - bnCopy(&nMinusOne, curve->n); - bnSubMod_(&nMinusOne, mpiOne, curve->p); - - bnSetQ(d, 0); - - while (!bnCmpQ(d, 0)) { - /* use _random function */ - _random(ran, randomBytes); - bnInsertBigBytes(&c, ran, 0, randomBytes); - bnMod(d, &c, &nMinusOne); - bnAddMod_(d, mpiOne, curve->p); - } - - bnEnd(&c); - bnEnd(&nMinusOne); - free(ran); - - return 0; -} - -static int ecGenerateRandomNumber3617(const EcCurve *curve, BigNum *d) -{ - unsigned char random[52]; - _random(random, 52); - - /* prepare the secret random data: clear bottom 3 bits. Clearing top 2 bits - * makes is a 414 bit value - */ - random[51] &= ~0x7; - random[0] &= 0x3f; - /* convert the random data into big numbers */ - bnInsertBigBytes(d, random, 0, 52); - return 0; -} - -static int ecGenerateRandomNumber25519(const EcCurve *curve, BigNum *d) -{ - unsigned char random[32]; - _random(random, 32); - - /* No specific preparation. The curve25519_donna functions prepares the data. - * - * convert the random data into big numbers. the bigNumber is a container only. - * we don not use the big number for any arithmetic - */ - bnInsertLittleBytes(d, random, 0, 32); - return 0; - -} - -int ecCheckPubKey(const EcCurve *curve, const EcPoint *pub) -{ - return curve->checkPubOp(curve, pub); -} - -static int ecCheckPubKeyNist(const NistECpCurve *curve, const EcPoint *pub) -{ - /* Represent point at infinity by (0, 0), make sure it's not that */ - if (bnCmpQ(pub->x, 0) == 0 && bnCmpQ(pub->y, 0) == 0) { - return 0; - } - /* Check that coordinates are within range */ - if (bnCmpQ(pub->x, 0) < 0 || bnCmp(pub->x, curve->p) >= 0) { - return 0; - } - if (bnCmpQ(pub->y, 0) < 0 || bnCmp(pub->y, curve->p) >= 0) { - return 0; - } - /* Check that point satisfies EC equation y^2 = x^3 - 3x + b, mod P */ - bnSquareMod_(curve->t1, pub->y, curve->p, curve); - bnSquareMod_(curve->t2, pub->x, curve->p, curve); - bnSubQMod_(curve->t2, 3, curve->p); - bnMulMod_(curve->t2, curve->t2, pub->x, curve->p, curve); - bnAddMod_(curve->t2, curve->b, curve->p); - if (bnCmp (curve->t1, curve->t2) != 0) { - return 0; - } - return 1; - -} - -static int ecCheckPubKey3617(const EcCurve *curve, const EcPoint *pub) -{ - /* Represent point at infinity by (0, 0), make sure it's not that */ - if (bnCmpQ(pub->x, 0) == 0 && bnCmpQ(pub->y, 0) == 0) { - return 0; - } - /* Check that coordinates are within range */ - if (bnCmpQ(pub->x, 0) < 0 || bnCmp(pub->x, curve->p) >= 0) { - return 0; - } - if (bnCmpQ(pub->y, 0) < 0 || bnCmp(pub->y, curve->p) >= 0) { - return 0; - } - /* Check that point satisfies EC equation x^2+y^2 = 1+3617x^2y^2, mod P */ - bnSquareMod_(curve->t1, pub->y, curve->p, curve); - bnSquareMod_(curve->t2, pub->x, curve->p, curve); - bnCopy(curve->t3, curve->t1); /* Load t3 */ - bnAddMod_(curve->t3, curve->t2, curve->p); /* t3 = t1 + t2, (x^2+y^2)*/ - - bnMulMod_(curve->t0, curve->a, curve->t1, curve->p, curve); /* t0 = a * t1, (3617 * x^2) */ - bnMulMod_(curve->t0, curve->t0, curve->t2, curve->p, curve); /* t0 = t0 * t1, (3617 * x^2 * y^2) */ - bnAddMod_(curve->t0, mpiOne, curve->p); /* t0 = t0 + 1, (3617 * x^2 * y^2 + 1) */ - - if (bnCmp (curve->t0, curve->t3) != 0) { - return 0; - } - return 1; -} - -/** - * According to http://cr.yp.to/ecdh.html#validate no validation is required if used for Diffie-Hellman - * thus always return success. - */ -static int ecCheckPubKey25519(const EcCurve *curve, const EcPoint *pub) -{ - return 1; -} - -static int mod3617(BigNum *r, const BigNum *a, const BigNum *modulo) -{ - unsigned char buffer[52] = {0}; - int cmp; - BigNum tmp; - - bnBegin(&tmp); - cmp = bnCmp(modulo, a); - if (cmp == 0) { /* a is equal modulo, set resul to zero */ - bnSetQ(r, 0); - return 0; - } - if (cmp > 0) { /* modulo is greater than a - copy a to r and return it */ - bnCopy(r, a); - return 0; - } - bnExtractLittleBytes(a, buffer, 0, 52); - buffer[51] &= 0x3f; - - bnCopy(&tmp, a); - bnRShift(&tmp, 414); - bnCopy(r, &tmp); - bnLShift(r, 4); - bnAdd(r, &tmp); - - bnInsertLittleBytes(&tmp, buffer, 0, 52); - - bnAdd(r, &tmp); - while (bnCmp(r, modulo) >= 0) { - bnSub(r, modulo); - } - bnEnd(&tmp); - return 0; -} - -/* - * Curve25519 has no specific modulo function, all inside curve25519-donna - */ -static int mod25519(BigNum *r, const BigNum *a, const BigNum *modulo) -{ - return -2; -} - -/* - * Beware: Here are the dragons. - * - * The modulo implementations for the NIST curves. For more detailled information see - * FIPS 186-3, chapter D.2 and other papers about Generailzed Mersenne numbers. - * - * I use byte operations to perfom the additions with carry. On a little endian machine - * this saves conversion from/to big endian format if I would use integers for example. Also - * using byte addition into a short carry accumulator works on every word size and avoids - * complex testing and handling of wordsizes and big/little endian stuff. - * - */ - -/* new modulo for 192bit curve */ -static int newMod192(BigNum *r, const BigNum *a, const BigNum *modulo) -{ - unsigned char buffer[200] = {0}; - unsigned char *pt; - unsigned char *ps1; - unsigned char *ps2; - unsigned char *ps3; - short ac; - int cmp; - - /* Binary big number representation in PolarSSL is always big endian - * - * the least significant 64bit large word starts at byte offset 40, - * the least significant 32bit word starts at byte offset 44 - * the least significant byte starts at byte offset 47 - * - * S3 S2 S1 T - * /-----^------\ - * A5 A4 A3 A2 A1 A0 - * 64bit 0 1 2 3 4 5 - * |--+--|--+--|--+--|--+--|--+--|--+--| - * 32bit 0 1 2 3 4 5 6 7 8 9 10 11 - * - * perform T + S1 + S2 + S3 mod p - - * where T = (A2 || A1 || A0) - * + S1 = ( 0 || A3 || A3) - * + S2 = (A4 || A4 || 0) - * + S3 = (A5 || A5 || A5) - * - * TODO: error check if input variable is > modulo^2 (do normal mpi_mod_mpi), - */ - - /* TODO: check if a is > modulo^2 */ - cmp = bnCmp(modulo, a); - if (cmp == 0) { /* a is equal modulo, set resul to zero */ - bnSetQ(r, 0); - return 0; - } - if (cmp > 0) { /* modulo is greater than a - copy a to r and return it */ - bnCopy(r, a); - return 0; - } - bnExtractBigBytes(a, buffer, 0, bnBytes(modulo)*2); - - /* 6 'A' words, each word is 8 byte. Compute offset to least significant byte of word X */ -#define A(X) buffer + (((6-X)*8)-1) - - ac = 0; - - pt = A(0); /* pt points to least significant byte of A0 */ - - /* Add up first 8 byte word, no need to add ps2 */ - ps1 = A(3); /* ps1 points to least significant byte of S1 (A3) */ - ps3 = A(5); /* ps3 points to least significant byte of S3 (A5)*/ - - /* Each block processes one 32 bit word, big endian, using byte operations */ - ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8; - - ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8; - - /* Add up second 8 byte word, all three S words are used here */ - ps1 = A(3); ps2 = A(4); ps3 = A(5); - - ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - - ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - - /* Add up third 8 byte word, no need to add S1 word */ - ps2 = A(4); ps3 = A(5); - - ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - - ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8; - - /* In this function we cannot have a negative carry and at most a carry of 2 - * thus just subtract the modulo until we are less than modulo - */ - bnSetQ(r, 0); - - *(A(3)) = ac; /* Store the carry */ - bnInsertBigBytes(r, A(3), 0, 25); /* 25: 3 * 8 byte words + 1 carry byte */ - while (bnCmp(r, modulo) >= 0) { - bnSub(r, modulo); - } - return 0; -} -#undef A - -/* new modulo for 256bit curve */ -static int newMod256(BigNum *r, const BigNum *a, const BigNum *modulo) -{ - unsigned char buffer[200] = {0}; - unsigned char *pt; - unsigned char *ps1; - unsigned char *ps2; - unsigned char *ps3; - unsigned char *ps4; - - unsigned char *pd1; - unsigned char *pd2; - unsigned char *pd3; - unsigned char *pd4; - short ac; - int cmp; - - /* Binary big number representation in PolarSSL is always big endian - * - * the least significant byte starts at byte offset 63 - * - * T - * /-----------------^------------------\ - * A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 - * |----+----|----+----|----+----|----+----|----+----|----+----|----+----|----+----| - * offset 0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 - * - * T = ( A7 || A6 || A5 || A4 || A3 || A2 || A1 || A0 ) - * - * S1 = ( A15 || A14 || A13 || A12 || A11 || 00 || 00 || 00 ) - * S2 = ( 00 || A15 || A14 || A13 || A12 || 00 || 00 || 00 ) - * S3 = ( A15 || A14 || 00 || 00 || 00 || A10 || A9 || A8 ) - * S4 = ( A8 || A13 || A15 || A14 || A13 || A11 || A10 || A9 ) - * D1 = ( A10 || A8 || 00 || 00 || 00 || A13 || A12 || A11 ) - * D2 = ( A11 || A9 || 00 || 00 || A15 || A14 || A13 || A12 ) - * D3 = ( A12 || 00 || A10 || A9 || A8 || A15 || A14 || A13 ) - * D4 = ( A13 || 00 || A11 || A10 || A9 || 00 || A15 || A14 ) - * - * perform B = T + 2*S1 + 2*S2 + S3 + S4 - D1 - D2 - D3 - D4 mod p - * - * TODO: error check if input variable is > modulo^2 (do normal mpi_mod_mpi), - */ - - cmp = bnCmp(modulo, a); - if (cmp == 0) { /* a is equal modulo, set resul to zero */ - bnSetQ(r, 0); - return 0; - } - if (cmp > 0) { /* modulo is greater than a - copya to r and return it */ - bnCopy(r, a); - return 0; - } - bnExtractBigBytes(a, buffer, 0, bnBytes(modulo)*2); - - /* 16 'A' words, each word is 4 byte. Compute offset to least significant byte of word X */ -#define A(X) buffer + (((16-X)*4)-1) - - ac = 0; - - pt = A(0); /* pt points to least significant byte of A0 */ - - /* Set up to add up data that goes into A0 (right-most column abover); S1, S2 not used */ - ps3 = A(8); /* ps3 points to least significant byte of S3 */ - ps4 = A(9); /* ps4 points to least significant byte of S4 */ - pd1 = A(11); /* pd1 points to least significant byte of D1 */ - pd2 = A(12); /* pd2 points to least significant byte of D2 */ - pd3 = A(13); /* pd3 points to least significant byte of D3 */ - pd4 = A(14); /* pd4 points to least significant byte of D4 */ - - /* Each block processes one 32 bit word, big endian, using byte operations */ - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - - /* Set up to add up data that goes into A1; S1, S2 not used */ - ps3 = A(9); ps4 = A(10); pd1 = A(12); pd2 = A(13); pd3 = A(14); pd4 = A(15); - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - - /* Set up to add up data that goes into A2; S1, S2, D4 not used */ - ps3 = A(10); ps4 = A(11); pd1 = A(13); pd2 = A(14); pd3 = A(15); - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - - /* Set up to add up data that goes into A3; S3, D1 not used */ - ps1 = A(11); ps2 = A(12); ps4 = A(13); pd2 = A(15); pd3 = A(8); pd4 = A(9); - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - - /* Set up to add up data that goes into A4; S3, D1, D2 not used */ - ps1 = A(12); ps2 = A(13); ps4 = A(14); pd3 = A(9); pd4 = A(10); - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - - /* Set up to add up data that goes into A5; S3, D1, D2 not used */ - ps1 = A(13); ps2 = A(14); ps4 = A(15); pd3 = A(10); pd4 = A(11); - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - - /* Set up to add up data that goes into A6; D3, D4 not used */ - ps1 = A(14); ps2 = A(15); ps3 = A(14); ps4 = A(13); pd1 = A(8); pd2 = A(9); - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2;ac += *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - - /* Set up to add up data that goes into A7; S2 not used */ - ps1 = A(15); ps3 = A(15); ps4 = A(8); pd1 = A(10); pd2 = A(11); pd3 = A(12); pd4 = A(13); - ac += *pt + *ps1;ac += *ps1--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8; - - bnSetQ(r, 0); - if (ac > 0) { - *(A(8)) = ac; /* Store the carry */ - bnInsertBigBytes(r, A(8), 0, 33); /* 33: 8 * 4 byte words + 1 carry byte */ - } - /* Negative carry requires that we add the modulo (carry * -1) times to make - * the result positive. Then get the result mod(256). - */ - else if (ac < 0) { - int msb, maxMsb; - - *(A(8)) = 0; - bnInsertBigBytes(r, A(8), 0, 33); /* 33: 8 * 4 byte words + 1 carry byte */ - ac *= -1; - while (ac--) { - bnAdd(r, modulo); - } - maxMsb = bnBits(modulo); - msb = bnBits(r) - maxMsb; - /* clear all bits above bit length of modulo. This length is 256 here, thus - * we effectiviely doing a mod(256) - */ - if (msb > 0) { - BigNum tmp; - bnBegin(&tmp); - bnSetQ (&tmp, 1); - bnLShift (&tmp, maxMsb); - bnMod(r, r, &tmp); - bnEnd(&tmp); - } - } - else { - *(A(8)) = 0; - bnInsertBigBytes(r, A(8), 0, 33); /* 33: 8 * 4 byte words + 1 carry byte */ - } - while (bnCmp(r, modulo) >= 0) { - bnSub(r, modulo); - } - return 0; -} -#undef A - - -/* new modulo for 384bit curve */ -static int newMod384(BigNum *r, const BigNum *a, const BigNum *modulo) -{ - unsigned char buffer[200] = {0}; - unsigned char *pt; - unsigned char *ps1; - unsigned char *ps2; - unsigned char *ps3; - unsigned char *ps4; - unsigned char *ps5; - unsigned char *ps6; - - unsigned char *pd1; - unsigned char *pd2; - unsigned char *pd3; - short ac; - int cmp; - - /* - * - * the least significant byte starts at byte offset 97 - * - * T - * /---------------------------^----------------------------\ - * A23 ......... A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 - * |----+ ...... |----+----|----+----|----+----|----+----|----+----|----+----|----+----|----+----| - * - * T = (A11 || A10 || A9 || A8 || A7 || A6 || A5 || A4 || A3 || A2 || A1 || A0) - - * S1 = ( 00 || 00 || 00 || 00 || 00 || A23 || A22 || A21 || 00 || 00 || 00 || 00) - * S2 = (A23 || A22 || A21 || A20 || A19 || A18 || A17 || A16 || A15 || A14 || A13 || A12) - * S3 = (A20 || A19 || A18 || A17 || A16 || A15 || A14 || A13 || A12 || A23 || A22 || A21) - * S4 = (A19 || A18 || A17 || A16 || A15 || A14 || A13 || A12 || A20 || 00 || A23 || 00) - * S5 = ( 00 || 00 || 00 || 00 || A23 || A22 || A21 || A20 || 00 || 00 || 00 || 00) - * S6 = ( 00 || 00 || 00 || 00 || 00 || 00 || A23 || A22 || A21 || 00 || 00 || A20) - * D1 = (A22 || A21 || A20 || A19 || A18 || A17 || A16 || A15 || A14 || A13 || A12 || A23) - * D2 = ( 00 || 00 || 00 || 00 || 00 || 00 || 00 || A23 || A22 || A21 || A20 || 00) - * D3 = ( 00 || 00 || 00 || 00 || 00 || 00 || 00 || A23 || A23 || 00 || 00 || 00) - * - * perform B = T + 2S1 + S2 + S3 + S4 + S5 + S6 – D1 – D2 – D3 mod p - * - * TODO: error check if input variable is > modulo^2 (do normal mpi_mod_mpi), - * optimize if input is already < modulo (just copy over in this case). - */ - - cmp = bnCmp(modulo, a); - if (cmp == 0) { /* a is equal modulo, set resul to zero */ - bnSetQ(r, 0); - return 0; - } - if (cmp > 0) { /* modulo is greater than a - copy a to r and return it */ - bnCopy(r, a); - return 0; - } - - bnExtractBigBytes(a, buffer, 0, bnBytes(modulo)*2); - - /* 24 'A' words, each word is 4 byte. Compute offset to least significant byte of word X */ -#define A(X) buffer + (((24-X)*4)-1) - - ac = 0; - - pt = A(0); /* pt points to least significant byte of A0 */ - - /* Set up to add data that goes into A0; S1, S4, S5, D2, D3 not used */ - ps2 = A(12); ps3 = A(21); ps6 = A(20); pd1 = A(23); - - /* Each block processes one 32 bit word, big endian, using byte operations */ - ac += *pt + *ps2--; ac += *ps3--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A1; S1, S5, S6, D3 not used */ - ps2 = A(13); ps3 = A(22); ps4 = A(23); pd1= A(12); pd2 = A(20); - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A2; S1, S4, S5, S6, D3 not used */ - ps2 = A(14); ps3 = A(23); pd1 = A(13); pd2 = A(21); - ac += *pt + *ps2--; ac += *ps3--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A3; S1, S5, S6 not used */ - ps2 = A(15); ps3 = A(12); ps4 = A(20); ps6 = A(21); pd1 = A(14); pd2 = A(22); pd3 = A(23); - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps6--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps6--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps6--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps6--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A4 */ - ps1 = A(21); ps2 = A(16); ps3 = A(13); ps4 = A(12); ps5 = A(20); ps6 = A(22); pd1 = A(15); pd2 = A(23), pd3 = A(23); - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A5; D2, D3 not used */ - ps1 = A(22); ps2 = A(17); ps3 = A(14); ps4 = A(13); ps5 = A(21); ps6 = A(23); pd1 = A(16); - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A6; S6, D2, D3 not used */ - ps1 = A(23); ps2 = A(18); ps3 = A(15); ps4 = A(14); ps5 = A(22); pd1 = A(17); - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A7; S1, S6, D2, D3 not used */ - ps2 = A(19); ps3 = A(16); ps4 = A(15); ps5 = A(23); pd1 = A(18); - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A8; S1, S5, S6, D2, D3 not used */ - ps2 = A(20); ps3 = A(17); ps4 = A(16); pd1 = A(19); - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A9; S1, S5, S6, D2, D3 not used */ - ps2 = A(21); ps3 = A(18); ps4 = A(17); pd1 = A(20); - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A10; S1, S5, S6, D2, D3 not used */ - ps2 = A(22); ps3 = A(19); ps4 = A(18); pd1 = A(21); - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - - /* Set up to add data that goes into A10; S1, S5, S6, D2, D3 not used */ - ps2 = A(23); ps3 = A(20); ps4 = A(19); pd1 = A(22); - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8; - - bnSetQ(r, 0); - if (ac > 0) { - *(A(12)) = ac; /* Store the carry */ - bnInsertBigBytes(r, A(12), 0, 49); /* 49: 12 * 4 byte words + 1 carry byte */ - } - /* Negative carry requires that we add the modulo (carry * -1) times to make - * the result positive. Then get the result mod(256). - */ - else if (ac < 0) { - int msb, maxMsb; - - *(A(12)) = 0; - bnInsertBigBytes(r, A(12), 0, 49); /* 49: 12 * 4 byte words + 1 carry byte */ - ac *= -1; - while (ac--) { - bnAdd(r, modulo); - } - maxMsb = bnBits(modulo); - msb = bnBits(r) - maxMsb; - /* clear all bits above bit length of modulo. This length is 384 here, thus - * we effectiviely doing a mod(384) - */ - if (msb > 0) { - BigNum tmp; - bnBegin(&tmp); - bnSetQ (&tmp, 1); - bnLShift (&tmp, maxMsb); - bnMod(r, r, &tmp); - bnEnd(&tmp); - } - } - else { - *(A(12)) = 0; - bnInsertBigBytes(r, A(12), 0, 49); /* 49: 12 * 4 byte words + 1 carry byte */ - } - while (bnCmp(r, modulo) >= 0) { - bnSub(r, modulo); - } - return 0; -} -#undef A - - -/* new modulo for 521bit curve, much easier because the prime for 521 is a real Mersenne prime */ -static int newMod521(BigNum *r, const BigNum *a, const BigNum *modulo) -{ - unsigned char buf1[200] = {0}; - unsigned char buf2[200] = {0}; - unsigned char *p1; - unsigned char *p2; - size_t modSize; - short ac = 0; - unsigned int i; - int cmp; - - /* TODO: check if a is > modulo^2 */ -#if 0 - if (a->s < 0) /* is it a negative value? */ - return bnMod(r, a, modulo); -#endif - cmp = bnCmp(modulo, a); - if (cmp == 0) { /* a is equal modulo, set resul to zero */ - bnSetQ(r, 0); - return 0; - } - bnCopy(r, a); - if (cmp > 0) { /* modulo is greater than a - return the prepared r */ - return 0; - } - modSize = bnBytes(modulo); - - bnExtractBigBytes(a, buf1, 0, modSize*2); /* a must be less modulo^2 */ - buf1[modSize] &= 1; /* clear all bits except least significat */ - - bnRShift(r, 521); - bnExtractBigBytes(r, buf2, 0, modSize*2); - buf2[modSize] &= 1; - - p1 = &buf2[131]; /* p1 is pointer to A0 */ - p2 = &buf1[131]; /* p2 is pointer to A1 */ - - for (i = 0; i < modSize; i++) { - ac += *p1 + *p2--; *p1-- = ac; ac >>= 8; - } - bnSetQ(r, 0); - bnInsertBigBytes(r, p1+1, 0, modSize); - - while (bnCmp(r, modulo) >= 0) { - bnSub(r, modulo); - } - return 0; -} - diff --git a/jni/libzrtp/sources/bnlib/ec/ec.h b/jni/libzrtp/sources/bnlib/ec/ec.h deleted file mode 100644 index 172ffd861..000000000 --- a/jni/libzrtp/sources/bnlib/ec/ec.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (C) 2012 Werner Dittmann - * All rights reserved. For licensing and other legal details, see the file legal.c. - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - * - */ -#ifndef _EC_H_ -#define _EC_H_ - -#include <bn.h> - -/** - * @file ec.h - * @brief Elliptic curve functions for bnlib - * @defgroup BNLIB_EC Elliptic curve functions - * @{ - */ - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef struct BigNum BigNum; - -typedef enum { - NIST192P = 1, - NIST224P = 2, - NIST256P = 3, - NIST384P = 4, - NIST521P = 5, - Curve25519 = 10, - Curve3617 = 11 -} Curves; - -/** - * \brief This structure contains the x, y affine coordinates and the z value if we - * use projective coordinates during EC point arithmetic. - */ -typedef struct _EcPoint { - BigNum *x, *y, *z; - BigNum tx, ty, tz; -} EcPoint; - -/** - * @brief This structure contains the value of EC curves over Prime Fields. - * - * The for NIST curves the field names correspond to the variable names defined in - * NIST FIPS 186-3, E.1.2. The <b>a</b> curve parameter is the constant -3 and is - * computed during initialization of the curve structure. - * - * For other curves, for example curve3917 we have less parameters to fill in, mostly - * the prime number, the base point, etc. Refer to the curve's initialization function - * about the use of the fileds. - */ -struct EcCurve; -struct EcCurve { - Curves id; - BigNum _p; - BigNum _n; - BigNum _SEED; - BigNum _c; - BigNum _a; - BigNum _b; - BigNum _Gx; - BigNum _Gy; - /* Pointers to the BigNum structures, for better readability mainly */ - BigNum *p; - BigNum *n; - BigNum *SEED; - BigNum *c; - BigNum *a; - BigNum *b; - BigNum *Gx; - BigNum *Gy; - /* some scratch pad variables, the EC algorithms use them to - avoid to much memory allocation/deallocatio0n overhead */ - BigNum _S1, _U1, _H, _R, _t0, _t1, _t2, _t3; - BigNum *S1, *U1, *H, *R, *t0, *t1, *t2, *t3; - int (*affineOp)(const struct EcCurve *curve, EcPoint *R, const EcPoint *P); - int (*doubleOp)(const struct EcCurve *curve, EcPoint *R, const EcPoint *P); - int (*addOp)(const struct EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q); - int (*modOp)(BigNum *, const BigNum *, const BigNum *); - int (*checkPubOp)(const struct EcCurve *curve, const EcPoint *pub); - int (*randomOp)(const struct EcCurve *curve, BigNum *d); - int (*mulScalar)(const struct EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar); - -}; - -typedef struct EcCurve EcCurve; -typedef EcCurve NistECpCurve; - -/** - * \brief Marco to initialize a EC point structure. - * - * \param P Address of the EC point structure - */ -#define INIT_EC_POINT(P) {EcPoint *e = P; e->x = &e->tx; e->y = &e->ty; e->z = &e->tz; bnBegin(e->x); bnBegin(e->y); bnBegin(e->z);} - -/** - * \brief Marco to free a EC point structure. - * - * \param P Address of the EC point structure - */ -#define FREE_EC_POINT(P) {EcPoint *e = P; bnEnd(e->x); bnEnd(e->y); bnEnd(e->z);} - -/** - * \brief Marco to set a EC point structure to the curve's base point. - * - * \param C Address of the NistECpCurve structure. - * - * \param P Address of the EC point structure. - */ -#define SET_EC_BASE_POINT(C, P) {EcPoint *e = P; const EcCurve *c = C; bnCopy(e->x, c->Gx); bnCopy(e->y, c->Gy); bnSetQ(e->z, 1);} - -/* - * EC point helper functions - */ -extern void ecInitPoint(EcPoint *P); - -extern void ecFreePoint(EcPoint *P); - -extern void ecSetBasePoint(EcCurve *C, EcPoint *P); - -/** - * \brief Get NIST EC curve parameters. - * - * Before reusing a EC curve structure make sure to call ecFreeCurveNistECp - * to return memory. - * - * \param curveId Which curve to initialize - * - * \param curve Pointer to a EcCurve structure - * - * \return 0 if successful - * - * \note Call ecFreeCurveNistECp to return allocated memory. - */ -int ecGetCurveNistECp(Curves curveId, NistECpCurve *curve); - - -/** - * \brief Free EC curve parameters. - * - * \param curve Pointer to a EcCurve structure - * - * \note Curve parameters must be initialized calling ecGetCurveNistECp. - */ -void ecFreeCurveNistECp(EcCurve *curve); - -/** - * \brief Double an EC point. - * - * This function uses affine coordinates to perform the computations. For - * further reference see RFC 6090 or the standard work <i>Guide to Elliptic - * Curve Cryptography</i>. - * - * \param curve Address of EC curve structure - * \param R Address of resulting EC point structure - * \param P Address of the EC point structure - * - * \return 0 if successful - */ -int ecDoublePoint(const EcCurve *curve, EcPoint *R, const EcPoint *P); - -/** - * \brief Add two EC points. - * - * This function uses affine coordinates to perform the computations. For - * further reference see RFC 6090 or the standard work <i>Guide to Elliptic - * Curve Cryptography</i>. - * - * \param curve Address of EC curve structure - * \param R Address of resulting EC point structure - * \param P Address of the first EC point structure - * \param Q Address of the second EC point structure - * - * \return 0 if successful - */ -int ecAddPoint(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q); - -/** - * \brief Mulitply an EC point with a scalar value. - * - * \param curve Address of EC curve structure - * \param R Address of resulting EC point structure - * \param P Address of the EC point structure - * \param scalar Address of the scalar multi-precision integer value - * - * \return 0 if successful - */ -int ecMulPointScalar(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar); - -/** - * \brief Convert an EC point from Jacobian projective coordinates to normal affine x/y coordinates. - * - * \param curve Address of EC curve structure - * \param R Address of EC point structure that receives the x/y coordinates - * \param P Address of the EC point structure that contains the jacobian x/y/z coordinates. - * - * \return 0 if successful - */ -int ecGetAffine(const EcCurve *curve, EcPoint *R, const EcPoint *P); - -/** - * @brief Generate a random number. - * - * The method generates a random number and checks if it matches the curve restricitions. - * Use this number as ECDH private key. - * - * @param curve the NIST curve to use. - * - * @param d receives the generated random number. - */ -int ecGenerateRandomNumber(const NistECpCurve *curve, BigNum *d); - -/** - * @brief Check a public key. - * - * The method checks if a public key is valid. For NIST curves it uses the - * ECC Partial Validation, NIST SP800-56A section 5.6.2.6 - * - * For other curves it computes the equation and compares the left hand and - * the right handresults. If they are equal the point is on the curve. - * - * @param curve the curve to use. - * - * @param pub the public key to check. - * - * @returns true (!0) if the check was ok, false (0) otherwise. - * - * @note The function uses some scratch pad variable of the NistECpCurve structure. - */ -int ecCheckPubKey(const EcCurve *curve, const EcPoint *pub); - -int ecGetCurvesCurve(Curves curveId, EcCurve *curve); - -void ecFreeCurvesCurve(EcCurve *curve); - -/** - * This is a special function for DJB's curve 25519. Actually it's the scalar multiplication - * mypublic = basepoint * secret - */ -int curve25519_donna(unsigned char *mypublic, const unsigned char *secret, const unsigned char *basepoint); - -/* - * Some additional functions that are not available in bnlib - */ -int bnAddMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod); - -int bnAddQMod_ (struct BigNum *rslt, unsigned n1, struct BigNum *mod); - -int bnSubMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod); - -int bnSubQMod_ (struct BigNum *rslt, unsigned n1, struct BigNum *mod); - -int bnMulMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *n2, struct BigNum *mod, const EcCurve *curve); - -int bnMulQMod_ (struct BigNum *rslt, struct BigNum *n1, unsigned n2, struct BigNum *mod, const EcCurve *curve); - -int bnSquareMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod, const EcCurve *curve); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif diff --git a/jni/libzrtp/sources/bnlib/ec/ecdh.c b/jni/libzrtp/sources/bnlib/ec/ecdh.c deleted file mode 100644 index 8d1bc23c2..000000000 --- a/jni/libzrtp/sources/bnlib/ec/ecdh.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2012 Werner Dittmann - * All rights reserved. For licensing and other legal details, see the file legal.c. - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - * - */ - -#include <ec/ec.h> -#include <ec/ecdh.h> - -int ecdhGeneratePublic(const EcCurve *curve, EcPoint *Q, const BigNum *d) -{ - EcPoint G; - - INIT_EC_POINT(&G); - SET_EC_BASE_POINT(curve, &G); - - ecMulPointScalar(curve, Q, &G, d); - ecGetAffine(curve, Q, Q); - - FREE_EC_POINT(&G); - - return ecCheckPubKey(curve, Q); -} - -int ecdhComputeAgreement(const EcCurve *curve, BigNum *agreement, const EcPoint *Q, const BigNum *d) -{ - EcPoint t0; - - INIT_EC_POINT(&t0); - - ecMulPointScalar(curve, &t0, Q, d); - ecGetAffine(curve, &t0, &t0); - /* TODO: check for infinity here */ - - bnCopy(agreement, t0.x); - - FREE_EC_POINT(&t0); - - return 0; -} diff --git a/jni/libzrtp/sources/bnlib/ec/ecdh.h b/jni/libzrtp/sources/bnlib/ec/ecdh.h deleted file mode 100644 index 7ec32ad62..000000000 --- a/jni/libzrtp/sources/bnlib/ec/ecdh.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2012 Werner Dittmann - * All rights reserved. For licensing and other legal details, see the file legal.c. - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - * - */ -#ifndef _ECDH_H_ -#define _ECDH_H_ -/** - * @file ec.h - * @brief Elliptic Diffie-Hellman functions for bnlib - * @defgroup BNLIB_EC Elliptic curve functions - * @{ - */ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * @brief Takes a secret large random number and computes the public EC point. - * - * @param curve is the curve to use. - * - * @param Q the functions writes the computed public point in this parameter. - * - * @param d is the secret random number. - * - * @return @c true (!0) if public key was computed, @c false otherwise. - * - * @sa ecGenerateRandomNumber - */ -int ecdhGeneratePublic(const EcCurve *curve, EcPoint *Q, const BigNum *d); - -/** - * @brief Computes the key agreement value. - * - * Takes the public EC point of the other party and applies the EC DH algorithm - * to compute the agreed value. - * - * @param curve is the curve to use, must be the same curve as used in - * @c ecdhGeneratePublic. - * - * @param agreemtn the functions writes the computed agreed value in this parameter. - * - * @param Q is the other party's public point. - * - * @param d is the secret random number. - */ -int ecdhComputeAgreement(const EcCurve *curve, BigNum *agreement, const EcPoint *Q, const BigNum *d); - -#ifdef __cplusplus -} -#endif -/** - * @} - */ - -#endif \ No newline at end of file diff --git a/jni/libzrtp/sources/bnlib/germain.c b/jni/libzrtp/sources/bnlib/germain.c deleted file mode 100644 index 52dbb50cf..000000000 --- a/jni/libzrtp/sources/bnlib/germain.c +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Sophie Germain prime generation using the bignum library and sieving. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - */ -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include "bnconfig.h" -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_ASSERT_H -#define NO_ASSERT_H 0 -#endif -#if !NO_ASSERT_H -#include <assert.h> -#else -#define assert(x) (void)0 -#endif - -#define BNDEBUG 1 -#ifndef BNDEBUG -#define BNDEBUG 0 -#endif -#if BNDEBUG -#include <stdio.h> -#endif - -#include "bn.h" -#include "germain.h" -#include "jacobi.h" -#include "lbnmem.h" /* For lbnMemWipe */ -#include "sieve.h" - -#include "kludge.h" - -/* Size of the sieve area (can be up to 65536/8 = 8192) */ -#define SIEVE 8192 - -static unsigned const confirm[] = {2, 3, 5, 7, 11, 13, 17}; -#define CONFIRMTESTS (sizeof(confirm)/sizeof(*confirm)) - -#if BNDEBUG -/* - * For sanity checking the sieve, we check for small divisors of the numbers - * we get back. This takes "rem", a partially reduced form of the prime, - * "div" a divisor to check for, and "order", a parameter of the "order" - * of Sophie Germain primes (0 = normal primes, 1 = Sophie Germain primes, - * 2 = 4*p+3 is also prime, etc.) and does the check. It just complains - * to stdout if the check fails. - */ -static void -germainSanity(unsigned rem, unsigned div, unsigned order) -{ - unsigned mul = 1; - - rem %= div; - if (!rem) - printf("bn div by %u!\n", div); - while (order--) { - rem += rem+1; - if (rem >= div) - rem -= div; - mul += mul; - if (!rem) - printf("%u*bn+%u div by %u!\n", mul, mul-1, div); - } -} -#endif /* BNDEBUG */ - -/* - * Helper function that does the slow primality test. - * bn is the input bignum; a, e and bn2 are temporary buffers that are - * allocated by the caller to save overhead. bn2 is filled with - * a copy of 2^order*bn+2^order-1 if bn is found to be prime. - * - * Returns 0 if both bn and bn2 are prime, >0 if not prime, and -1 on - * error (out of memory). If not prime, the return value is the number - * of modular exponentiations performed. Prints a '+' or '-' on the - * given FILE (if any) for each test that is passed by bn, and a '*' - * for each test that is passed by bn2. - * - * The testing consists of strong pseudoprimality tests, to the bases given - * in the confirm[] array above. (Also called Miller-Rabin, although that's - * not technically correct if we're using fixed bases.) Some people worry - * that this might not be enough. Number theorists may wish to generate - * primality proofs, but for random inputs, this returns non-primes with - * a probability which is quite negligible, which is good enough. - * - * It has been proved (see Carl Pomerance, "On the Distribution of - * Pseudoprimes", Math. Comp. v.37 (1981) pp. 587-593) that the number of - * pseudoprimes (composite numbers that pass a Fermat test to the base 2) - * less than x is bounded by: - * exp(ln(x)^(5/14)) <= P_2(x) ### CHECK THIS FORMULA - it looks wrong! ### - * P_2(x) <= x * exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))). - * Thus, the local density of Pseudoprimes near x is at most - * exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))), and at least - * exp(ln(x)^(5/14) - ln(x)). Here are some values of this function - * for various k-bit numbers x = 2^k: - * Bits Density <= Bit equivalent Density >= Bit equivalent - * 128 3.577869e-07 21.414396 4.202213e-37 120.840190 - * 192 4.175629e-10 31.157288 4.936250e-56 183.724558 - * 256 5.804314e-13 40.647940 4.977813e-75 246.829095 - * 384 1.578039e-18 59.136573 3.938861e-113 373.400096 - * 512 5.858255e-24 77.175803 2.563353e-151 500.253110 - * 768 1.489276e-34 112.370944 7.872825e-228 754.422724 - * 1024 6.633188e-45 146.757062 1.882404e-304 1008.953565 - * - * As you can see, there's quite a bit of slop between these estimates. - * In fact, the density of pseudoprimes is conjectured to be closer to the - * square of that upper bound. E.g. the density of pseudoprimes of size - * 256 is around 3 * 10^-27. The density of primes is very high, from - * 0.005636 at 256 bits to 0.001409 at 1024 bits, i.e. more than 10^-3. - * - * For those people used to cryptographic levels of security where the - * 56 bits of DES key space is too small because it's exhaustible with - * custom hardware searching engines, note that you are not generating - * 50,000,000 primes per second on each of 56,000 custom hardware chips - * for several hours. The chances that another Dinosaur Killer asteroid - * will land today is about 10^-11 or 2^-36, so it would be better to - * spend your time worrying about *that*. Well, okay, there should be - * some derating for the chance that astronomers haven't seen it yet, - * but I think you get the idea. For a good feel about the probability - * of various events, I have heard that a good book is by E'mile Borel, - * "Les Probabilite's et la vie". (The 's are accents, not apostrophes.) - * - * For more on the subject, try "Finding Four Million Large Random Primes", - * by Ronald Rivest, in Advancess in Cryptology: Proceedings of Crypto - * '90. He used a small-divisor test, then a Fermat test to the base 2, - * and then 8 iterations of a Miller-Rabin test. About 718 million random - * 256-bit integers were generated, 43,741,404 passed the small divisor - * test, 4,058,000 passed the Fermat test, and all 4,058,000 passed all - * 8 iterations of the Miller-Rabin test, proving their primality beyond - * most reasonable doubts. - * - * If the probability of getting a pseudoprime is some small p, then the - * probability of not getting it in t trials is (1-p)^t. Remember that, - * for small p, (1-p)^(1/p) ~ 1/e, the base of natural logarithms. - * (This is more commonly expressed as e = lim_{x\to\infty} (1+1/x)^x.) - * Thus, (1-p)^t ~ e^(-p*t) = exp(-p*t). So the odds of being able to - * do this many tests without seeing a pseudoprime if you assume that - * p = 10^-6 (one in a million) is one in 57.86. If you assume that - * p = 2*10^-6, it's one in 3347.6. So it's implausible that the density - * of pseudoprimes is much more than one millionth the density of primes. - * - * He also gives a theoretical argument that the chance of finding a - * 256-bit non-prime which satisfies one Fermat test to the base 2 is - * less than 10^-22. The small divisor test improves this number, and - * if the numbers are 512 bits (as needed for a 1024-bit key) the odds - * of failure shrink to about 10^-44. Thus, he concludes, for practical - * purposes *one* Fermat test to the base 2 is sufficient. - */ -static int -germainPrimeTest(struct BigNum const *bn, struct BigNum *bn2, struct BigNum *e, - struct BigNum *a, unsigned order, int (*f)(void *arg, int c), void *arg) -{ - int err; - unsigned i; - int j; - unsigned k, l, n; - -#if BNDEBUG /* Debugging */ - /* - * This is debugging code to test the sieving stage. - * If the sieving is wrong, it will let past numbers with - * small divisors. The prime test here will still work, and - * weed them out, but you'll be doing a lot more slow tests, - * and presumably excluding from consideration some other numbers - * which might be prime. This check just verifies that none - * of the candidates have any small divisors. If this - * code is enabled and never triggers, you can feel quite - * confident that the sieving is doing its job. - */ - i = bnLSWord(bn); - if (!(i % 2)) printf("bn div by 2!"); - i = bnModQ(bn, 51051); /* 51051 = 3 * 7 * 11 * 13 * 17 */ - germainSanity(i, 3, order); - germainSanity(i, 7, order); - germainSanity(i, 11, order); - germainSanity(i, 13, order); - germainSanity(i, 17, order); - i = bnModQ(bn, 63365); /* 63365 = 5 * 19 * 23 * 29 */ - germainSanity(i, 5, order); - germainSanity(i, 19, order); - germainSanity(i, 23, order); - germainSanity(i, 29, order); - i = bnModQ(bn, 47027); /* 47027 = 31 * 37 * 41 */ - germainSanity(i, 31, order); - germainSanity(i, 37, order); - germainSanity(i, 41, order); -#endif - /* - * First, check whether bn is prime. This uses a fast primality - * test which usually obviates the need to do one of the - * confirmation tests later. See prime.c for a full explanation. - * We check bn first because it's one bit smaller, saving one - * modular squaring, and because we might be able to save another - * when testing it. (1/4 of the time.) A small speed hack, - * but finding big Sophie Germain primes is *slow*. - */ - if (bnCopy(e, bn) < 0) - return -1; - (void)bnSubQ(e, 1); - l = bnLSWord(e); - - j = 1; /* Where to start in prime array for strong prime tests */ - - if (l & 7) { - bnRShift(e, 1); - if (bnTwoExpMod(a, e, bn) < 0) - return -1; - if ((l & 7) == 6) { - /* bn == 7 mod 8, expect +1 */ - if (bnBits(a) != 1) - return 1; /* Not prime */ - k = 1; - } else { - /* bn == 3 or 5 mod 8, expect -1 == bn-1 */ - if (bnAddQ(a, 1) < 0) - return -1; - if (bnCmp(a, bn) != 0) - return 1; /* Not prime */ - k = 1; - if (l & 4) { - /* bn == 5 mod 8, make odd for strong tests */ - bnRShift(e, 1); - k = 2; - } - } - } else { - /* bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn */ - bnRShift(e, 2); - if (bnTwoExpMod(a, e, bn) < 0) - return -1; - if (bnBits(a) == 1) { - j = 0; /* Re-do strong prime test to base 2 */ - } else { - if (bnAddQ(a, 1) < 0) - return -1; - if (bnCmp(a, bn) != 0) - return 1; /* Not prime */ - } - k = 2 + bnMakeOdd(e); - } - - - /* - * It's prime! Now check higher-order forms bn2 = 2*bn+1, 4*bn+3, - * etc. Since bn2 == 3 mod 4, a strong pseudoprimality test boils - * down to looking at a^((bn2-1)/2) mod bn and seeing if it's +/-1. - * (+1 if bn2 is == 7 mod 8, -1 if it's == 3) - * Of course, that exponent is just the previous bn2 or bn... - */ - if (bnCopy(bn2, bn) < 0) - return -1; - for (n = 0; n < order; n++) { - /* - * Print a success indicator: the sign of Jacobi(2,bn2), - * which is available to us in l. bn2 = 2*bn + 1. Since bn - * is odd, bn2 must be == 3 mod 4, so the options modulo 8 - * are 3 and 7. 3 if l == 1 mod 4, 7 if l == 3 mod 4. - * The sign of the Jacobi symbol is - and + for these cases, - * respectively. - */ - if (f && (err = f(arg, "-+"[(l >> 1) & 1])) < 0) - return err; - /* Exponent is previous bn2 */ - if (bnCopy(e, bn2) < 0 || bnLShift(bn2, 1) < 0) - return -1; - (void)bnAddQ(bn2, 1); /* Can't overflow */ - if (bnTwoExpMod(a, e, bn2) < 0) - return -1; - if (n | l) { /* Expect + */ - if (bnBits(a) != 1) - return 2+n; /* Not prime */ - } else { - if (bnAddQ(a, 1) < 0) - return -1; - if (bnCmp(a, bn2) != 0) - return 2+n; /* Not prime */ - } - l = bnLSWord(bn2); - } - - /* Final success indicator - it's in the bag. */ - if (f && (err = f(arg, '*')) < 0) - return err; - - /* - * Success! We have found a prime! Now go on to confirmation - * tests... k is an amount by which we know it's safe to shift - * down e. j = 1 unless the test to the base 2 could stand to be - * re-done (it wasn't *quite* a strong test), in which case it's 0. - * - * Here, we do the full strong pseudoprimality test. This proves - * that a number is composite, or says that it's probably prime. - * - * For the given base a, find bn-1 = 2^k * e, then find - * x == a^e (mod bn). - * If x == +1 -> strong pseudoprime to base a - * Otherwise, repeat k times: - * If x == -1, -> strong pseudoprime - * x = x^2 (mod bn) - * If x = +1 -> composite - * If we reach the end of the iteration and x is *not* +1, at the - * end, it is composite. But it's also composite if the result - * *is* +1. Which means that the squaring actually only has to - * proceed k-1 times. If x is not -1 by then, it's composite - * no matter what the result of the squaring is. - * - * For the multiples 2*bn+1, 4*bn+3, etc. then k = 1 (and e is - * the previous multiple of bn) so the squaring loop is never - * actually executed at all. - */ - for (i = j; i < CONFIRMTESTS; i++) { - if (bnCopy(e, bn) < 0) - return -1; - bnRShift(e, k); - k += bnMakeOdd(e); - (void)bnSetQ(a, confirm[i]); - if (bnExpMod(a, a, e, bn) < 0) - return -1; - - if (bnBits(a) != 1) { - l = k; - for (;;) { - if (bnAddQ(a, 1) < 0) - return -1; - if (bnCmp(a, bn) == 0) /* Was result bn-1? */ - break; /* Prime */ - if (!--l) - return (1+order)*i+2; /* Fail */ - /* This part is executed once, on average. */ - (void)bnSubQ(a, 1); /* Restore a */ - if (bnSquare(a, a) < 0 || bnMod(a, a, bn) < 0) - return -1; - if (bnBits(a) == 1) - return (1+order)*i+1; /* Fail */ - } - } - - if (bnCopy(bn2, bn) < 0) - return -1; - - /* Only do the following if we're not re-doing base 2 */ - if (i) for (n = 0; n < order; n++) { - if (bnCopy(e, bn2) < 0 || bnLShift(bn2, 1) < 0) - return -1; - (void)bnAddQ(bn2, 1); - - /* Print success indicator for previous test */ - j = bnJacobiQ(confirm[i], bn2); - if (f && (err = f(arg, j < 0 ? '-' : '+')) < 0) - return err; - - /* Check that p^e == Jacobi(p,bn2) (mod bn2) */ - (void)bnSetQ(a, confirm[i]); - if (bnExpMod(a, a, e, bn2) < 0) - return -1; - /* - * FIXME: Actually, we don't need to compute the - * Jacobi symbol externally... it never happens that - * a = +/-1 but it's the wrong one. So we can just - * look at a and use its sign. Find a proof somewhere. - */ - if (j < 0) { - /* Not a Q.R., should have a = bn2-1 */ - if (bnAddQ(a, 1) < 0) - return -1; - if (bnCmp(a, bn2) != 0) /* Was result bn2-1? */ - return (1+order)*i+n+2; /* Fail */ - } else { - /* Quadratic residue, should have a = 1 */ - if (bnBits(a) != 1) - return (1+order)*i+n+2; /* Fail */ - } - } - /* Final success indicator for the base confirm[i]. */ - if (f && (err = f(arg, '*')) < 0) - return err; - } - - return 0; /* Prime! */ -} - -/* - * Add x*y to bn, which is usually (but not always) < 65536. - * Do it in a simple linear manner. - */ -static int -bnAddMult(struct BigNum *bn, unsigned long x, unsigned y) -{ - unsigned long z = (unsigned long)x * y; - - while (z > 65535) { - if (bnAddQ(bn, 65535) < 0) - return -1; - z -= 65535; - } - return bnAddQ(bn, (unsigned)z); -} - -/* - * Modifies the bignum to return the next Sophie Germain prime >= the - * input value. Sohpie Germain primes are number such that p is - * prime and 2*p+1 is also prime. - * - * This is actually parameterized: it generates primes p such that "order" - * multiples-plus-two are also prime, 2*p+1, 2*(2*p+1)+1 = 4*p+3, etc. - * - * Returns >=0 on success or -1 on failure (out of memory). On success, - * the return value is the number of modular exponentiations performed - * (excluding the final confirmations). This never gives up searching. - * - * The FILE *f argument, if non-NULL, has progress indicators written - * to it. A dot (.) is written every time a primeality test is failed, - * a plus (+) or minus (-) when the smaller prime of the pair passes a - * test, and a star (*) when the larger one does. Finally, a slash (/) - * is printed when the sieve was emptied without finding a prime and is - * being refilled. - * - * Apologies to structured programmers for all the GOTOs. - */ -int -germainPrimeGen(struct BigNum *bn, unsigned order, - int (*f)(void *arg, int c), void *arg) -{ - int retval; - unsigned p, prev; - unsigned inc; - struct BigNum a, e, bn2; - int modexps = 0; -#ifdef MSDOS - unsigned char *sieve; -#else - unsigned char sieve[SIEVE]; -#endif - -#ifdef MSDOS - sieve = lbnMemAlloc(SIEVE); - if (!sieve) - return -1; -#endif - - bnBegin(&a); - bnBegin(&e); - bnBegin(&bn2); - - /* - * Obviously, the prime we find must be odd. Further, if 2*p+1 - * is also to be prime (order > 0) then p != 1 (mod 3), lest - * 2*p+1 == 3 (mod 3). Added to p != 3 (mod 3), p == 2 (mod 3) - * and p == 5 (mod 6). - * If order > 2 and we care about 4*p+3 and 8*p+7, then similarly - * p == 4 (mod 5), so p == 29 (mod 30). - * So pick the step size for searching based on the order - * and increse bn until it's == -1 (mod inc). - * - * mod 7 doesn't have a unique value for p because 2 -> 5 -> 4 -> 2, - * nor does mod 11, and I don't want to think about things past - * that. The required order would be impractically high, in any case. - */ - inc = order ? ((order > 2) ? 30 : 6) : 2; - if (bnAddQ(bn, inc-1 - bnModQ(bn, inc)) < 0) - goto failed; - - for (;;) { - if (sieveBuild(sieve, SIEVE, bn, inc, order) < 0) - goto failed; - - p = prev = 0; - if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) { - do { - /* Adjust bn to have the right value. */ - assert(p >= prev); - if (bnAddMult(bn, p-prev, inc) < 0) - goto failed; - prev = p; - - /* Okay, do the strong tests. */ - retval = germainPrimeTest(bn, &bn2, &e, &a, - order, f, arg); - if (retval <= 0) - goto done; - modexps += retval; - if (f && (retval = f(arg, '.')) < 0) - goto done; - - /* And try again */ - p = sieveSearch(sieve, SIEVE, p); - } while (p); - } - - /* Ran out of sieve space - increase bn and keep trying. */ - if (bnAddMult(bn, (unsigned long)SIEVE*8-prev, inc) < 0) - goto failed; - if (f && (retval = f(arg, '/')) < 0) - goto done; - } /* for (;;) */ - -failed: - retval = -1; -done: - bnEnd(&bn2); - bnEnd(&e); - bnEnd(&a); -#ifdef MSDOS - lbnMemFree(sieve, SIEVE); -#else - lbnMemWipe(sieve, sizeof(sieve)); -#endif - return retval < 0 ? retval : modexps+(order+1)*CONFIRMTESTS; -} - -int -germainPrimeGenStrong(struct BigNum *bn, struct BigNum const *step, - unsigned order, int (*f)(void *arg, int c), void *arg) -{ - int retval; - unsigned p, prev; - struct BigNum a, e, bn2; - int modexps = 0; -#ifdef MSDOS - unsigned char *sieve; -#else - unsigned char sieve[SIEVE]; -#endif - -#ifdef MSDOS - sieve = lbnMemAlloc(SIEVE); - if (!sieve) - return -1; -#endif - bnBegin(&a); - bnBegin(&e); - bnBegin(&bn2); - - for (;;) { - if (sieveBuildBig(sieve, SIEVE, bn, step, order) < 0) - goto failed; - - p = prev = 0; - if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) { - do { - /* - * Adjust bn to have the right value, - * adding (p-prev) * 2*step. - */ - assert(p >= prev); - /* Compute delta into a */ - if (bnMulQ(&a, step, p-prev) < 0) - goto failed; - if (bnAdd(bn, &a) < 0) - goto failed; - prev = p; - - /* Okay, do the strong tests. */ - retval = germainPrimeTest(bn, &bn2, &e, &a, - order, f, arg); - if (retval <= 0) - goto done; - modexps += retval; - if (f && (retval = f(arg, '.')) < 0) - goto done; - - /* And try again */ - p = sieveSearch(sieve, SIEVE, p); - } while (p); - } - - /* Ran out of sieve space - increase bn and keep trying. */ -#if SIEVE*8 == 65536 - /* Corner case that will never actually happen */ - if (!prev) { - if (bnAdd(bn, step) < 0) - goto failed; - p = 65535; - } else { - p = (unsigned)(SIEVE*8 - prev); - } -#else - p = SIEVE*8 - prev; -#endif - if (bnMulQ(&a, step, p) < 0 || bnAdd(bn, &a) < 0) - goto failed; - if (f && (retval = f(arg, '/')) < 0) - goto done; - } /* for (;;) */ - -failed: - retval = -1; -done: - bnEnd(&bn2); - bnEnd(&e); - bnEnd(&a); -#ifdef MSDOS - lbnMemFree(sieve, SIEVE); -#else - lbnMemWipe(sieve, sizeof(sieve)); -#endif - return retval < 0 ? retval : modexps+(order+1)*CONFIRMTESTS; -} diff --git a/jni/libzrtp/sources/bnlib/germain.h b/jni/libzrtp/sources/bnlib/germain.h deleted file mode 100644 index f1e018a0b..000000000 --- a/jni/libzrtp/sources/bnlib/germain.h +++ /dev/null @@ -1,8 +0,0 @@ -struct BigNum; - -/* Generate a Sophie Germain prime */ -int germainPrimeGen(struct BigNum *bn, unsigned order, - int (*f)(void *arg, int c), void *arg); -/* The same, but search for using the given step size */ -int germainPrimeGenStrong(struct BigNum *bn, struct BigNum const *step, - unsigned order, int (*f)(void *arg, int c), void *arg); diff --git a/jni/libzrtp/sources/bnlib/jacobi.c b/jni/libzrtp/sources/bnlib/jacobi.c deleted file mode 100644 index 24b73137a..000000000 --- a/jni/libzrtp/sources/bnlib/jacobi.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Compute the Jacobi symbol (small prime case only). - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - */ -#include "bn.h" -#include "jacobi.h" - -/* - * For a small (usually prime, but not necessarily) prime p, - * compute Jacobi(p,bn), which is -1, 0 or +1, using the following rules: - * Jacobi(x, y) = Jacobi(x mod y, y) - * Jacobi(0, y) = 0 - * Jacobi(1, y) = 1 - * Jacobi(2, y) = 0 if y is even, +1 if y is +/-1 mod 8, -1 if y = +/-3 mod 8 - * Jacobi(x1*x2, y) = Jacobi(x1, y) * Jacobi(x2, y) (used with x1 = 2 & x1 = 4) - * If x and y are both odd, then - * Jacobi(x, y) = Jacobi(y, x) * (-1 if x = y = 3 mod 4, +1 otherwise) - */ -int -bnJacobiQ(unsigned p, struct BigNum const *bn) -{ - int j = 1; - unsigned u = bnLSWord(bn); - - if (!(u & 1)) - return 0; /* Don't *do* that */ - - /* First, get rid of factors of 2 in p */ - while ((p & 3) == 0) - p >>= 2; - if ((p & 1) == 0) { - p >>= 1; - if ((u ^ u>>1) & 2) - j = -j; /* 3 (011) or 5 (101) mod 8 */ - } - if (p == 1) - return j; - /* Then, apply quadratic reciprocity */ - if (p & u & 2) /* p = u = 3 (mod 4? */ - j = -j; - /* And reduce u mod p */ - u = bnModQ(bn, p); - - /* Now compute Jacobi(u,p), u < p */ - while (u) { - while ((u & 3) == 0) - u >>= 2; - if ((u & 1) == 0) { - u >>= 1; - if ((p ^ p>>1) & 2) - j = -j; /* 3 (011) or 5 (101) mod 8 */ - } - if (u == 1) - return j; - /* Now both u and p are odd, so use quadratic reciprocity */ - if (u < p) { - unsigned t = u; u = p; p = t; - if (u & p & 2) /* u = p = 3 (mod 4? */ - j = -j; - } - /* Now u >= p, so it can be reduced */ - u %= p; - } - return 0; -} diff --git a/jni/libzrtp/sources/bnlib/jacobi.h b/jni/libzrtp/sources/bnlib/jacobi.h deleted file mode 100644 index 4dfd1e2ad..000000000 --- a/jni/libzrtp/sources/bnlib/jacobi.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * For a small (usually prime, but not necessarily) prime p, - * Return Jacobi(p,bn), which is -1, 0 or +1. - * bn must be odd. - */ -struct BigNum; -int bnJacobiQ(unsigned p, struct BigNum const *bn); diff --git a/jni/libzrtp/sources/bnlib/kludge.h b/jni/libzrtp/sources/bnlib/kludge.h deleted file mode 100644 index 023c8905d..000000000 --- a/jni/libzrtp/sources/bnlib/kludge.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef KLUDGE_H -#define KLUDGE_H - -/* - * Kludges for not-quite-ANSI systems. - * This should always be the last file included, because it may - * mess up some system header files. - */ - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef ASSERT_NEEDS_STDIO -#define ASSERT_NEEDS_STDIO 0 -#endif -#ifndef ASSERT_NEEDS_STDLIB -#define ASSERT_NEEDS_STDLIB 0 -#endif -#ifndef NO_STDLIB_H -#define NO_STDLIB_H 0 -#endif - -/* SunOS 4.1.x <assert.h> needs "stderr" defined, and "exit" declared... */ -#ifdef assert -#if ASSERT_NEEDS_STDIO -#include <stdio.h> -#endif -#if ASSERT_NEEDS_STDLIB -#if !NO_STDLIB_H -#include <stdlib.h> -#endif -#endif -#endif - -#ifndef NO_MEMMOVE -#define NO_MEMMOVE 0 -#endif -#if NO_MEMMOVE /* memove() not in libraries */ -#define memmove(dest,src,len) bcopy(src,dest,len) -#endif - -#ifndef NO_MEMCPY -#define NO_MEMCPY 0 -#endif -#if NO_MEMCPY /* memcpy() not in libraries */ -#define memcpy(dest,src,len) bcopy(src,dest,len) -#endif - -#ifndef MEM_PROTOS_BROKEN -#define MEM_PROTOS_BROKEN 0 -#endif -#if MEM_PROTOS_BROKEN -#define memcpy(d,s,l) memcpy((void *)(d), (void const *)(s), l) -#define memmove(d,s,l) memmove((void *)(d), (void const *)(s), l) -#define memcmp(d,s,l) memcmp((void const *)(d), (void const *)(s), l) -#define memset(d,v,l) memset((void *)(d), v, l) -#endif - -/* - * If there are no prototypes for the stdio functions, use these to - * reduce compiler warnings. Uses EOF as a giveaway to indicate - * that <stdio.h> was #included. - */ -#ifndef NO_STDIO_PROTOS -#define NO_STDIO_PROTOS 0 -#endif -#if NO_STDIO_PROTOS /* Missing prototypes for "simple" functions */ -#ifdef EOF -#ifdef __cplusplus -extern "C" { -#endif -int (puts)(char const *); -int (fputs)(char const *, FILE *); -int (fflush)(FILE *); -int (printf)(char const *, ...); -int (fprintf)(FILE *, char const *, ...); -/* If we have a sufficiently old-fashioned stdio, it probably uses these... */ -int (_flsbuf)(int, FILE *); -int (_filbuf)(FILE *); -#ifdef __cplusplus -} -#endif -#endif /* EOF */ -#endif /* NO_STDIO_PROTOS */ - -/* - * Borland C seems to think that it's a bad idea to decleare a - * structure tag and not declare the contents. I happen to think - * it's a *good* idea to use such "opaque" structures wherever - * possible. So shut up. - */ -#ifdef __BORLANDC__ -#pragma warn -stu -#ifndef MSDOS -#define MSDOS 1 -#endif -#endif - -/* Turn off warning about negation of unsigned values */ -#ifdef _MSC_VER -#pragma warning(disable:4146) -#endif - -/* Cope with people forgetting to define the OS, if possible... */ -#ifndef MSDOS -#ifdef __MSDOS -#define MSDOS 1 -#endif -#endif -#ifndef MSDOS -#ifdef __MSDOS__ -#define MSDOS 1 -#endif -#endif - -/* By MS-DOS, we mean 16-bit brain-dead MS-DOS. Not GCC & GO32 */ -#ifdef __GO32 -#undef MSDOS -#endif -#ifdef __GO32__ -#undef MSDOS -#endif - -#endif /* KLUDGE_H */ diff --git a/jni/libzrtp/sources/bnlib/lbn.h b/jni/libzrtp/sources/bnlib/lbn.h deleted file mode 100644 index 25f378408..000000000 --- a/jni/libzrtp/sources/bnlib/lbn.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * lbn.h - Low-level bignum header. - * Defines various word sizes and useful macros. - * TODO: Rewrite this to use <stdint.h> and/or <inttypes.h> - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - */ -#ifndef LBN_H -#define LBN_H - -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include <bnconfig.h> -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_LIMITS_H -#define NO_LIMITS_H 0 -#endif - -#include <stdint.h> /* TODO: protect by configuration ifdef */ - -/* Make sure we have 8-bit bytes */ -#if !NO_LIMITS_H -#include <limits.h> -#if UCHAR_MAX != 0xff || CHAR_BIT != 8 -#error The bignum library requires 8-bit unsigned characters. -#endif -#endif /* !NO_LIMITS_H */ - -#ifdef BNINCLUDE /* If this is defined as, say, foo.h */ -#define STR(x) #x /* STR(BNINCLUDE) -> "BNINCLUDE" */ -#define XSTR(x) STR(x) /* XSTR(BNINCLUDE) -> STR(foo.h) -> "foo.h" */ -#include XSTR(BNINCLUDE) /* #include "foo.h" */ -#undef XSTR -#undef STR -#endif - -/* Do we want bnYield()? */ -#ifndef BNYIELD -#define BNYIELD 0 -#endif - -/* Figure out the endianness */ -/* Error if more than one is defined */ -#if defined(BN_BIG_ENDIAN) && defined(BN_LITTLE_ENDIAN) -#error Only one of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN may be defined -#endif - -/* - * If no preference is stated, little-endian C code is slightly more - * efficient, so prefer that. (The endianness here does NOT have to - * match the machine's native byte sex; the library's C code will work - * either way. The flexibility is allowed for assembly routines - * that do care. - */ -#if !defined(BN_BIG_ENDIAN) && !defined(BN_LITTLE_ENDIAN) -#define BN_LITTLE_ENDIAN 1 -#endif /* !BN_BIG_ENDIAN && !BN_LITTLE_ENDIAN */ - -/* Macros to choose between big and little endian */ -#if defined(BN_BIG_ENDIAN) -#define BIG(b) b -#define LITTLE(l) /*nothing*/ -#define BIGLITTLE(b,l) b -#elif BN_LITTLE_ENDIAN -#define BIG(b) /*nothing*/ -#define LITTLE(l) l -#define BIGLITTLE(b,l) l -#else -#error One of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN must be defined as 1 -#endif - - -/* - * Define a 16-bit unsigned type if available. - * Unsigned short is preferred over unsigned int to make the type chosen - * by this file more stable on platforms (such as many 68000 compilers) - * which support both 16- and 32-bit ints. - */ -#ifndef BNWORD16 -#if !defined USHRT_MAX || USHRT_MAX == 0xffff || UINT_MAX == 0xffff -#define BNWORD16 uint16_t -#endif -#endif /* BNWORD16 */ - -/* - * Define a 32-bit unsigned type if available. - * Unsigned long is preferred over unsigned int to make the type chosen - * by this file more stable on platforms (such as many 68000 compilers) - * which support both 16- and 32-bit ints. - */ -#ifndef BNWORD32 -#if !defined ULONG_MAX || ULONG_MAX == 0xfffffffful || UINT_MAX == 0xffffffff || USHRT_MAX == 0xffffffff -#define BNWORD32 uint32_t -#endif -#endif /* BNWORD32 */ - -/* - * Find a 64-bit unsigned type. - * The conditions here are more complicated to avoid using numbers that - * will choke lesser preprocessors (like 0xffffffffffffffff) unless - * we're reasonably certain that they'll be acceptable. - */ -#if !defined(BNWORD64) && ULONG_MAX > 0xffffffffUL -#if ULONG_MAX == 0xffffffffffffffff -#define BNWORD64 uint64_t -#endif -#endif - -/* - * I would test the value of unsigned long long, but some *preprocessors* - * don't constants that long even if the compiler can accept them, so it - * doesn't work reliably. So cross our fingers and hope that it's a 64-bit - * type. - * - * GCC uses ULONG_LONG_MAX. Solaris uses ULLONG_MAX. IRIX uses ULONGLONG_MAX. - * Are there any other names for this? - */ -#if !defined(BNWORD64) && \ - (defined(ULONG_LONG_MAX) || defined (ULLONG_MAX) || defined(ULONGLONG_MAX)) -#define BNWORD64 uint64_t -#endif - -/* We don't even try to find a 128-bit type at the moment */ - -#endif /* !LBN_H */ diff --git a/jni/libzrtp/sources/bnlib/lbn00.c b/jni/libzrtp/sources/bnlib/lbn00.c deleted file mode 100644 index 228ff07ec..000000000 --- a/jni/libzrtp/sources/bnlib/lbn00.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * lbn00.c - auto-size-detecting lbn??.c file. - * - * Written in 1995 by Colin Plumb. - */ - -#include "bnsize00.h" - -#if BNSIZE64 - -/* Include all of the C source file by reference */ -#include "lbn64.c" - -#elif BNSIZE32 - -/* Include all of the C source file by reference */ -#include "lbn32.c" - -#else /* BNSIZE16 */ - -/* Include all of the C source file by reference */ -#include "lbn16.c" - -#endif diff --git a/jni/libzrtp/sources/bnlib/lbn16.c b/jni/libzrtp/sources/bnlib/lbn16.c deleted file mode 100644 index 313094a3a..000000000 --- a/jni/libzrtp/sources/bnlib/lbn16.c +++ /dev/null @@ -1,4073 +0,0 @@ -/* - * lbn16.c - Low-level bignum routines, 16-bit version. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - * - * NOTE: the magic constants "16" and "32" appear in many places in this - * file, including inside identifiers. Because it is not possible to - * ask "#ifdef" of a macro expansion, it is not possible to use the - * preprocessor to conditionalize these properly. Thus, this file is - * intended to be edited with textual search and replace to produce - * alternate word size versions. Any reference to the number of bits - * in a word must be the string "16", and that string must not appear - * otherwise. Any reference to twice this number must appear as "32", - * which likewise must not appear otherwise. Is that clear? - * - * Remember, when doubling the bit size replace the larger number (32) - * first, then the smaller (16). When halving the bit size, do the - * opposite. Otherwise, things will get wierd. Also, be sure to replace - * every instance that appears. (:%s/foo/bar/g in vi) - * - * These routines work with a pointer to the least-significant end of - * an array of WORD16s. The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros - * defined in lbn.h (which expand to x on a big-edian machine and y on a - * little-endian machine) are used to conditionalize the code to work - * either way. If you have no assembly primitives, it doesn't matter. - * Note that on a big-endian machine, the least-significant-end pointer - * is ONE PAST THE END. The bytes are ptr[-1] through ptr[-len]. - * On little-endian, they are ptr[0] through ptr[len-1]. This makes - * perfect sense if you consider pointers to point *between* bytes rather - * than at them. - * - * Because the array index values are unsigned integers, ptr[-i] - * may not work properly, since the index -i is evaluated as an unsigned, - * and if pointers are wider, zero-extension will produce a positive - * number rahter than the needed negative. The expression used in this - * code, *(ptr-i) will, however, work. (The array syntax is equivalent - * to *(ptr+-i), which is a pretty subtle difference.) - * - * Many of these routines will get very unhappy if fed zero-length inputs. - * They use assert() to enforce this. An higher layer of code must make - * sure that these aren't called with zero-length inputs. - * - * Any of these routines can be replaced with more efficient versions - * elsewhere, by just #defining their names. If one of the names - * is #defined, the C code is not compiled in and no declaration is - * made. Use the BNINCLUDE file to do that. Typically, you compile - * asm subroutines with the same name and just, e.g. - * #define lbnMulAdd1_16 lbnMulAdd1_16 - * - * If you want to write asm routines, start with lbnMulAdd1_16(). - * This is the workhorse of modular exponentiation. lbnMulN1_16() is - * also used a fair bit, although not as much and it's defined in terms - * of lbnMulAdd1_16 if that has a custom version. lbnMulSub1_16 and - * lbnDiv21_16 are used in the usual division and remainder finding. - * (Not the Montgomery reduction used in modular exponentiation, though.) - * Once you have lbnMulAdd1_16 defined, writing the other two should - * be pretty easy. (Just make sure you get the sign of the subtraction - * in lbnMulSub1_16 right - it's dest = dest - source * k.) - * - * The only definitions that absolutely need a double-word (BNWORD32) - * type are lbnMulAdd1_16 and lbnMulSub1_16; if those are provided, - * the rest follows. lbnDiv21_16, however, is a lot slower unless you - * have them, and lbnModQ_16 takes after it. That one is used quite a - * bit for prime sieving. - */ - -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include <bnconfig.h> -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_ASSERT_H -#define NO_ASSERT_H 0 -#endif -#ifndef NO_STRING_H -#define NO_STRING_H 0 -#endif -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 0 -#endif -#ifndef NEED_MEMORY_H -#define NEED_MEMORY_H 0 -#endif - -#if !NO_ASSERT_H -#include <assert.h> -#else -#define assert(x) (void)0 -#endif - -#if !NO_STRING_H -#include <string.h> /* For memcpy */ -#elif HAVE_STRINGS_H -#include <strings.h> -#endif -#if NEED_MEMORY_H -#include <memory.h> -#endif - -#include "lbn.h" -#include "lbn16.h" -#include "lbnmem.h" - -#include "kludge.h" - -#ifndef BNWORD16 -#error 16-bit bignum library requires a 16-bit data type -#endif - -/* If this is defined, include bnYield() calls */ -#if BNYIELD -extern int (*bnYield)(void); /* From bn.c */ -#endif - -/* - * Most of the multiply (and Montgomery reduce) routines use an outer - * loop that iterates over one of the operands - a so-called operand - * scanning approach. One big advantage of this is that the assembly - * support routines are simpler. The loops can be rearranged to have - * an outer loop that iterates over the product, a so-called product - * scanning approach. This has the advantage of writing less data - * and doing fewer adds to memory, so is supposedly faster. Some - * code has been written using a product-scanning approach, but - * it appears to be slower, so it is turned off by default. Some - * experimentation would be appreciated. - * - * (The code is also annoying to get right and not very well commented, - * one of my pet peeves about math libraries. I'm sorry.) - */ -#ifndef PRODUCT_SCAN -#define PRODUCT_SCAN 0 -#endif - -/* - * Copy an array of words. <Marvin mode on> Thrilling, isn't it? </Marvin> - * This is a good example of how the byte offsets and BIGLITTLE() macros work. - * Another alternative would have been - * memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD16)), but I find that - * putting operators into conditional macros is confusing. - */ -#ifndef lbnCopy_16 -void -lbnCopy_16(BNWORD16 *dest, BNWORD16 const *src, unsigned len) -{ - memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src), - len * sizeof(*src)); -} -#endif /* !lbnCopy_16 */ - -/* - * Fill n words with zero. This does it manually rather than calling - * memset because it can assume alignment to make things faster while - * memset can't. Note how big-endian numbers are naturally addressed - * using predecrement, while little-endian is postincrement. - */ -#ifndef lbnZero_16 -void -lbnZero_16(BNWORD16 *num, unsigned len) -{ - while (len--) - BIGLITTLE(*--num,*num++) = 0; -} -#endif /* !lbnZero_16 */ - -/* - * Negate an array of words. - * Negation is subtraction from zero. Negating low-order words - * entails doing nothing until a non-zero word is hit. Once that - * is negated, a borrow is generated and never dies until the end - * of the number is hit. Negation with borrow, -x-1, is the same as ~x. - * Repeat that until the end of the number. - * - * Doesn't return borrow out because that's pretty useless - it's - * always set unless the input is 0, which is easy to notice in - * normalized form. - */ -#ifndef lbnNeg_16 -void -lbnNeg_16(BNWORD16 *num, unsigned len) -{ - assert(len); - - /* Skip low-order zero words */ - while (BIGLITTLE(*--num,*num) == 0) { - if (!--len) - return; - LITTLE(num++;) - } - /* Negate the lowest-order non-zero word */ - *num = -*num; - /* Complement all the higher-order words */ - while (--len) { - BIGLITTLE(--num,++num); - *num = ~*num; - } -} -#endif /* !lbnNeg_16 */ - - -/* - * lbnAdd1_16: add the single-word "carry" to the given number. - * Used for minor increments and propagating the carry after - * adding in a shorter bignum. - * - * Technique: If we have a double-width word, presumably the compiler - * can add using its carry in inline code, so we just use a larger - * accumulator to compute the carry from the first addition. - * If not, it's more complex. After adding the first carry, which may - * be > 1, compare the sum and the carry. If the sum wraps (causing a - * carry out from the addition), the result will be less than each of the - * inputs, since the wrap subtracts a number (2^16) which is larger than - * the other input can possibly be. If the sum is >= the carry input, - * return success immediately. - * In either case, if there is a carry, enter a loop incrementing words - * until one does not wrap. Since we are adding 1 each time, the wrap - * will be to 0 and we can test for equality. - */ -#ifndef lbnAdd1_16 /* If defined, it's provided as an asm subroutine */ -#ifdef BNWORD32 -BNWORD16 -lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry) -{ - BNWORD32 t; - assert(len > 0); /* Alternative: if (!len) return carry */ - - t = (BNWORD32)BIGLITTLE(*--num,*num) + carry; - BIGLITTLE(*num,*num++) = (BNWORD16)t; - if ((t >> 16) == 0) - return 0; - while (--len) { - if (++BIGLITTLE(*--num,*num++) != 0) - return 0; - } - return 1; -} -#else /* no BNWORD32 */ -BNWORD16 -lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry) -{ - assert(len > 0); /* Alternative: if (!len) return carry */ - - if ((BIGLITTLE(*--num,*num++) += carry) >= carry) - return 0; - while (--len) { - if (++BIGLITTLE(*--num,*num++) != 0) - return 0; - } - return 1; -} -#endif -#endif/* !lbnAdd1_16 */ - -/* - * lbnSub1_16: subtract the single-word "borrow" from the given number. - * Used for minor decrements and propagating the borrow after - * subtracting a shorter bignum. - * - * Technique: Similar to the add, above. If there is a double-length type, - * use that to generate the first borrow. - * If not, after subtracting the first borrow, which may be > 1, compare - * the difference and the *negative* of the carry. If the subtract wraps - * (causing a borrow out from the subtraction), the result will be at least - * as large as -borrow. If the result < -borrow, then no borrow out has - * appeared and we may return immediately, except when borrow == 0. To - * deal with that case, use the identity that -x = ~x+1, and instead of - * comparing < -borrow, compare for <= ~borrow. - * Either way, if there is a borrow out, enter a loop decrementing words - * until a non-zero word is reached. - * - * Note the cast of ~borrow to (BNWORD16). If the size of an int is larger - * than BNWORD16, C rules say the number is expanded for the arithmetic, so - * the inversion will be done on an int and the value won't be quite what - * is expected. - */ -#ifndef lbnSub1_16 /* If defined, it's provided as an asm subroutine */ -#ifdef BNWORD32 -BNWORD16 -lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow) -{ - BNWORD32 t; - assert(len > 0); /* Alternative: if (!len) return borrow */ - - t = (BNWORD32)BIGLITTLE(*--num,*num) - borrow; - BIGLITTLE(*num,*num++) = (BNWORD16)t; - if ((t >> 16) == 0) - return 0; - while (--len) { - if ((BIGLITTLE(*--num,*num++))-- != 0) - return 0; - } - return 1; -} -#else /* no BNWORD32 */ -BNWORD16 -lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow) -{ - assert(len > 0); /* Alternative: if (!len) return borrow */ - - if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD16)~borrow) - return 0; - while (--len) { - if ((BIGLITTLE(*--num,*num++))-- != 0) - return 0; - } - return 1; -} -#endif -#endif /* !lbnSub1_16 */ - -/* - * lbnAddN_16: add two bignums of the same length, returning the carry (0 or 1). - * One of the building blocks, along with lbnAdd1, of adding two bignums of - * differing lengths. - * - * Technique: Maintain a word of carry. If there is no double-width type, - * use the same technique as in lbnAdd1, above, to maintain the carry by - * comparing the inputs. Adding the carry sources is used as an OR operator; - * at most one of the two comparisons can possibly be true. The first can - * only be true if carry == 1 and x, the result, is 0. In that case the - * second can't possibly be true. - */ -#ifndef lbnAddN_16 -#ifdef BNWORD32 -BNWORD16 -lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) -{ - BNWORD32 t; - - assert(len > 0); - - t = (BNWORD32)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++); - BIGLITTLE(*num1,*num1++) = (BNWORD16)t; - while (--len) { - t = (BNWORD32)BIGLITTLE(*--num1,*num1) + - (BNWORD32)BIGLITTLE(*--num2,*num2++) + (t >> 16); - BIGLITTLE(*num1,*num1++) = (BNWORD16)t; - } - - return (BNWORD16)(t>>16); -} -#else /* no BNWORD32 */ -BNWORD16 -lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) -{ - BNWORD16 x, carry = 0; - - assert(len > 0); /* Alternative: change loop to test at start */ - - do { - x = BIGLITTLE(*--num2,*num2++); - carry = (x += carry) < carry; - carry += (BIGLITTLE(*--num1,*num1++) += x) < x; - } while (--len); - - return carry; -} -#endif -#endif /* !lbnAddN_16 */ - -/* - * lbnSubN_16: add two bignums of the same length, returning the carry (0 or 1). - * One of the building blocks, along with subn1, of subtracting two bignums of - * differing lengths. - * - * Technique: If no double-width type is availble, maintain a word of borrow. - * First, add the borrow to the subtrahend (did you have to learn all those - * awful words in elementary school, too?), and if it overflows, set the - * borrow again. Then subtract the modified subtrahend from the next word - * of input, using the same technique as in subn1, above. - * Adding the borrows is used as an OR operator; at most one of the two - * comparisons can possibly be true. The first can only be true if - * borrow == 1 and x, the result, is 0. In that case the second can't - * possibly be true. - * - * In the double-word case, (BNWORD16)-(t>>16) is subtracted, rather than - * adding t>>16, because the shift would need to sign-extend and that's - * not guaranteed to happen in ANSI C, even with signed types. - */ -#ifndef lbnSubN_16 -#ifdef BNWORD32 -BNWORD16 -lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) -{ - BNWORD32 t; - - assert(len > 0); - - t = (BNWORD32)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++); - BIGLITTLE(*num1,*num1++) = (BNWORD16)t; - - while (--len) { - t = (BNWORD32)BIGLITTLE(*--num1,*num1) - - (BNWORD32)BIGLITTLE(*--num2,*num2++) - (BNWORD16)-(t >> 16); - BIGLITTLE(*num1,*num1++) = (BNWORD16)t; - } - - return -(BNWORD16)(t>>16); -} -#else -BNWORD16 -lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) -{ - BNWORD16 x, borrow = 0; - - assert(len > 0); /* Alternative: change loop to test at start */ - - do { - x = BIGLITTLE(*--num2,*num2++); - borrow = (x += borrow) < borrow; - borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD16)~x; - } while (--len); - - return borrow; -} -#endif -#endif /* !lbnSubN_16 */ - -#ifndef lbnCmp_16 -/* - * lbnCmp_16: compare two bignums of equal length, returning the sign of - * num1 - num2. (-1, 0 or +1). - * - * Technique: Change the little-endian pointers to big-endian pointers - * and compare from the most-significant end until a difference if found. - * When it is, figure out the sign of the difference and return it. - */ -int -lbnCmp_16(BNWORD16 const *num1, BNWORD16 const *num2, unsigned len) -{ - BIGLITTLE(num1 -= len, num1 += len); - BIGLITTLE(num2 -= len, num2 += len); - - while (len--) { - if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) { - if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2)) - return -1; - else - return 1; - } - } - return 0; -} -#endif /* !lbnCmp_16 */ - -/* - * mul16_ppmmaa(ph,pl,x,y,a,b) is an optional routine that - * computes (ph,pl) = x * y + a + b. mul16_ppmma and mul16_ppmm - * are simpler versions. If you want to be lazy, all of these - * can be defined in terms of the others, so here we create any - * that have not been defined in terms of the ones that have been. - */ - -/* Define ones with fewer a's in terms of ones with more a's */ -#if !defined(mul16_ppmma) && defined(mul16_ppmmaa) -#define mul16_ppmma(ph,pl,x,y,a) mul16_ppmmaa(ph,pl,x,y,a,0) -#endif - -#if !defined(mul16_ppmm) && defined(mul16_ppmma) -#define mul16_ppmm(ph,pl,x,y) mul16_ppmma(ph,pl,x,y,0) -#endif - -/* - * Use this definition to test the mul16_ppmm-based operations on machines - * that do not provide mul16_ppmm. Change the final "0" to a "1" to - * enable it. - */ -#if !defined(mul16_ppmm) && defined(BNWORD32) && 0 /* Debugging */ -#define mul16_ppmm(ph,pl,x,y) \ - ({BNWORD32 _ = (BNWORD32)(x)*(y); (pl) = _; (ph) = _>>16;}) -#endif - -#if defined(mul16_ppmm) && !defined(mul16_ppmma) -#define mul16_ppmma(ph,pl,x,y,a) \ - (mul16_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a)) -#endif - -#if defined(mul16_ppmma) && !defined(mul16_ppmmaa) -#define mul16_ppmmaa(ph,pl,x,y,a,b) \ - (mul16_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b)) -#endif - -/* - * lbnMulN1_16: Multiply an n-word input by a 1-word input and store the - * n+1-word product. This uses either the mul16_ppmm and mul16_ppmma - * macros, or C multiplication with the BNWORD32 type. This uses mul16_ppmma - * if available, assuming you won't bother defining it unless you can do - * better than the normal multiplication. - */ -#ifndef lbnMulN1_16 -#ifdef lbnMulAdd1_16 /* If we have this asm primitive, use it. */ -void -lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) -{ - lbnZero_16(out, len); - BIGLITTLE(*(out-len-1),*(out+len)) = lbnMulAdd1_16(out, in, len, k); -} -#elif defined(mul16_ppmm) -void -lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) -{ - BNWORD16 carry, carryin; - - assert(len > 0); - - BIG(--out;--in;); - mul16_ppmm(carry, *out, *in, k); - LITTLE(out++;in++;) - - while (--len) { - BIG(--out;--in;) - carryin = carry; - mul16_ppmma(carry, *out, *in, k, carryin); - LITTLE(out++;in++;) - } - BIGLITTLE(*--out,*out) = carry; -} -#elif defined(BNWORD32) -void -lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) -{ - BNWORD32 p; - - assert(len > 0); - - p = (BNWORD32)BIGLITTLE(*--in,*in++) * k; - BIGLITTLE(*--out,*out++) = (BNWORD16)p; - - while (--len) { - p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + (BNWORD16)(p >> 16); - BIGLITTLE(*--out,*out++) = (BNWORD16)p; - } - BIGLITTLE(*--out,*out) = (BNWORD16)(p >> 16); -} -#else -#error No 16x16 -> 32 multiply available for 16-bit bignum package -#endif -#endif /* lbnMulN1_16 */ - -/* - * lbnMulAdd1_16: Multiply an n-word input by a 1-word input and add the - * low n words of the product to the destination. *Returns the n+1st word - * of the product.* (That turns out to be more convenient than adding - * it into the destination and dealing with a possible unit carry out - * of *that*.) This uses either the mul16_ppmma and mul16_ppmmaa macros, - * or C multiplication with the BNWORD32 type. - * - * If you're going to write assembly primitives, this is the one to - * start with. It is by far the most commonly called function. - */ -#ifndef lbnMulAdd1_16 -#if defined(mul16_ppmm) -BNWORD16 -lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) -{ - BNWORD16 prod, carry, carryin; - - assert(len > 0); - - BIG(--out;--in;); - carryin = *out; - mul16_ppmma(carry, *out, *in, k, carryin); - LITTLE(out++;in++;) - - while (--len) { - BIG(--out;--in;); - carryin = carry; - mul16_ppmmaa(carry, prod, *in, k, carryin, *out); - *out = prod; - LITTLE(out++;in++;) - } - - return carry; -} -#elif defined(BNWORD32) -BNWORD16 -lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) -{ - BNWORD32 p; - - assert(len > 0); - - p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out); - BIGLITTLE(*out,*out++) = (BNWORD16)p; - - while (--len) { - p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + - (BNWORD16)(p >> 16) + BIGLITTLE(*--out,*out); - BIGLITTLE(*out,*out++) = (BNWORD16)p; - } - - return (BNWORD16)(p >> 16); -} -#else -#error No 16x16 -> 32 multiply available for 16-bit bignum package -#endif -#endif /* lbnMulAdd1_16 */ - -/* - * lbnMulSub1_16: Multiply an n-word input by a 1-word input and subtract the - * n-word product from the destination. Returns the n+1st word of the product. - * This uses either the mul16_ppmm and mul16_ppmma macros, or - * C multiplication with the BNWORD32 type. - * - * This is rather uglier than adding, but fortunately it's only used in - * division which is not used too heavily. - */ -#ifndef lbnMulSub1_16 -#if defined(mul16_ppmm) -BNWORD16 -lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) -{ - BNWORD16 prod, carry, carryin; - - assert(len > 0); - - BIG(--in;) - mul16_ppmm(carry, prod, *in, k); - LITTLE(in++;) - carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD16)~prod; - - while (--len) { - BIG(--in;); - carryin = carry; - mul16_ppmma(carry, prod, *in, k, carryin); - LITTLE(in++;) - carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD16)~prod; - } - - return carry; -} -#elif defined(BNWORD32) -BNWORD16 -lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) -{ - BNWORD32 p; - BNWORD16 carry, t; - - assert(len > 0); - - p = (BNWORD32)BIGLITTLE(*--in,*in++) * k; - t = BIGLITTLE(*--out,*out); - carry = (BNWORD16)(p>>16) + ((BIGLITTLE(*out,*out++)=t-(BNWORD16)p) > t); - - while (--len) { - p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + carry; - t = BIGLITTLE(*--out,*out); - carry = (BNWORD16)(p>>16) + - ( (BIGLITTLE(*out,*out++)=t-(BNWORD16)p) > t ); - } - - return carry; -} -#else -#error No 16x16 -> 32 multiply available for 16-bit bignum package -#endif -#endif /* !lbnMulSub1_16 */ - -/* - * Shift n words left "shift" bits. 0 < shift < 16. Returns the - * carry, any bits shifted off the left-hand side (0 <= carry < 2^shift). - */ -#ifndef lbnLshift_16 -BNWORD16 -lbnLshift_16(BNWORD16 *num, unsigned len, unsigned shift) -{ - BNWORD16 x, carry; - - assert(shift > 0); - assert(shift < 16); - - carry = 0; - while (len--) { - BIG(--num;) - x = *num; - *num = (x<<shift) | carry; - LITTLE(num++;) - carry = x >> (16-shift); - } - return carry; -} -#endif /* !lbnLshift_16 */ - -/* - * An optimized version of the above, for shifts of 1. - * Some machines can use add-with-carry tricks for this. - */ -#ifndef lbnDouble_16 -BNWORD16 -lbnDouble_16(BNWORD16 *num, unsigned len) -{ - BNWORD16 x, carry; - - carry = 0; - while (len--) { - BIG(--num;) - x = *num; - *num = (x<<1) | carry; - LITTLE(num++;) - carry = x >> (16-1); - } - return carry; -} -#endif /* !lbnDouble_16 */ - -/* - * Shift n words right "shift" bits. 0 < shift < 16. Returns the - * carry, any bits shifted off the right-hand side (0 <= carry < 2^shift). - */ -#ifndef lbnRshift_16 -BNWORD16 -lbnRshift_16(BNWORD16 *num, unsigned len, unsigned shift) -{ - BNWORD16 x, carry = 0; - - assert(shift > 0); - assert(shift < 16); - - BIGLITTLE(num -= len, num += len); - - while (len--) { - LITTLE(--num;) - x = *num; - *num = (x>>shift) | carry; - BIG(num++;) - carry = x << (16-shift); - } - return carry >> (16-shift); -} -#endif /* !lbnRshift_16 */ - -/* - * Multiply two numbers of the given lengths. prod and num2 may overlap, - * provided that the low len1 bits of prod are free. (This corresponds - * nicely to the place the result is returned from lbnMontReduce_16.) - * - * TODO: Use Karatsuba multiply. The overlap constraints may have - * to get rewhacked. - */ -#ifndef lbnMul_16 -void -lbnMul_16(BNWORD16 *prod, BNWORD16 const *num1, unsigned len1, - BNWORD16 const *num2, unsigned len2) -{ - /* Special case of zero */ - if (!len1 || !len2) { - lbnZero_16(prod, len1+len2); - return; - } - - /* Multiply first word */ - lbnMulN1_16(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); - - /* - * Add in subsequent words, storing the most significant word, - * which is new each time. - */ - while (--len2) { - BIGLITTLE(--prod,prod++); - BIGLITTLE(*(prod-len1-1),*(prod+len1)) = - lbnMulAdd1_16(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); - } -} -#endif /* !lbnMul_16 */ - -/* - * lbnMulX_16 is a square multiply - both inputs are the same length. - * It's normally just a macro wrapper around the general multiply, - * but might be implementable in assembly more efficiently (such as - * when product scanning). - */ -#ifndef lbnMulX_16 -#if defined(BNWORD32) && PRODUCT_SCAN -/* - * Test code to see whether product scanning is any faster. It seems - * to make the C code slower, so PRODUCT_SCAN is not defined. - */ -static void -lbnMulX_16(BNWORD16 *prod, BNWORD16 const *num1, BNWORD16 const *num2, - unsigned len) -{ - BNWORD32 x, y; - BNWORD16 const *p1, *p2; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!len) - return; - - x = (BNWORD32)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); - BIGLITTLE(*--prod, *prod++) = (BNWORD16)x; - x >>= 16; - - for (i = 1; i < len; i++) { - carry = 0; - p1 = num1; - p2 = BIGLITTLE(num2-i-1,num2+i+1); - for (j = 0; j <= i; j++) { - BIG(y = (BNWORD32)*--p1 * *p2++;) - LITTLE(y = (BNWORD32)*p1++ * *--p2;) - x += y; - carry += (x < y); - } - BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; - x = (x >> 16) | (BNWORD32)carry << 16; - } - for (i = 1; i < len; i++) { - carry = 0; - p1 = BIGLITTLE(num1-i,num1+i); - p2 = BIGLITTLE(num2-len,num2+len); - for (j = i; j < len; j++) { - BIG(y = (BNWORD32)*--p1 * *p2++;) - LITTLE(y = (BNWORD32)*p1++ * *--p2;) - x += y; - carry += (x < y); - } - BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; - x = (x >> 16) | (BNWORD32)carry << 16; - } - - BIGLITTLE(*--prod,*prod) = (BNWORD16)x; -} -#else /* !defined(BNWORD32) || !PRODUCT_SCAN */ -/* Default trivial macro definition */ -#define lbnMulX_16(prod, num1, num2, len) lbnMul_16(prod, num1, len, num2, len) -#endif /* !defined(BNWORD32) || !PRODUCT_SCAN */ -#endif /* !lbmMulX_16 */ - -#if !defined(lbnMontMul_16) && defined(BNWORD32) && PRODUCT_SCAN -/* - * Test code for product-scanning multiply. This seems to slow the C - * code down rather than speed it up. - * This does a multiply and Montgomery reduction together, using the - * same loops. The outer loop scans across the product, twice. - * The first pass computes the low half of the product and the - * Montgomery multipliers. These are stored in the product array, - * which contains no data as of yet. x and carry add up the columns - * and propagate carries forward. - * - * The second half multiplies the upper half, adding in the modulus - * times the Montgomery multipliers. The results of this multiply - * are stored. - */ -static void -lbnMontMul_16(BNWORD16 *prod, BNWORD16 const *num1, BNWORD16 const *num2, - BNWORD16 const *mod, unsigned len, BNWORD16 inv) -{ - BNWORD32 x, y; - BNWORD16 const *p1, *p2, *pm; - BNWORD16 *pp; - BNWORD16 t; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!len) - return; - - /* - * This computes directly into the high half of prod, so just - * shift the pointer and consider prod only "len" elements long - * for the rest of the code. - */ - BIGLITTLE(prod -= len, prod += len); - - /* Pass 1 - compute Montgomery multipliers */ - /* First iteration can have certain simplifications. */ - x = (BNWORD32)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); - BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD16)x; - y = (BNWORD32)t * BIGLITTLE(mod[-1],mod[0]); - x += y; - /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */ - carry = (x < y); - assert((BNWORD16)x == 0); - x = x >> 16 | (BNWORD32)carry << 16; - - for (i = 1; i < len; i++) { - carry = 0; - p1 = num1; - p2 = BIGLITTLE(num2-i-1,num2+i+1); - pp = prod; - pm = BIGLITTLE(mod-i-1,mod+i+1); - for (j = 0; j < i; j++) { - y = (BNWORD32)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); - x += y; - carry += (x < y); - y = (BNWORD32)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm); - x += y; - carry += (x < y); - } - y = (BNWORD32)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]); - x += y; - carry += (x < y); - assert(BIGLITTLE(pp == prod-i, pp == prod+i)); - BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD16)x; - assert(BIGLITTLE(pm == mod-1, pm == mod+1)); - y = (BNWORD32)t * BIGLITTLE(pm[0],pm[-1]); - x += y; - carry += (x < y); - assert((BNWORD16)x == 0); - x = x >> 16 | (BNWORD32)carry << 16; - } - - /* Pass 2 - compute reduced product and store */ - for (i = 1; i < len; i++) { - carry = 0; - p1 = BIGLITTLE(num1-i,num1+i); - p2 = BIGLITTLE(num2-len,num2+len); - pm = BIGLITTLE(mod-i,mod+i); - pp = BIGLITTLE(prod-len,prod+len); - for (j = i; j < len; j++) { - y = (BNWORD32)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); - x += y; - carry += (x < y); - y = (BNWORD32)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp); - x += y; - carry += (x < y); - } - assert(BIGLITTLE(pm == mod-len, pm == mod+len)); - assert(BIGLITTLE(pp == prod-i, pp == prod+i)); - BIGLITTLE(pp[0],pp[-1]) = (BNWORD16)x; - x = (x >> 16) | (BNWORD32)carry << 16; - } - - /* Last round of second half, simplified. */ - BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD16)x; - carry = (x >> 16); - - while (carry) - carry -= lbnSubN_16(prod, mod, len); - while (lbnCmp_16(prod, mod, len) >= 0) - (void)lbnSubN_16(prod, mod, len); -} -/* Suppress later definition */ -#define lbnMontMul_16 lbnMontMul_16 -#endif - -#if !defined(lbnSquare_16) && defined(BNWORD32) && PRODUCT_SCAN -/* - * Trial code for product-scanning squaring. This seems to slow the C - * code down rather than speed it up. - */ -void -lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len) -{ - BNWORD32 x, y, z; - BNWORD16 const *p1, *p2; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!len) - return; - - /* Word 0 of product */ - x = (BNWORD32)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]); - BIGLITTLE(*--prod, *prod++) = (BNWORD16)x; - x >>= 16; - - /* Words 1 through len-1 */ - for (i = 1; i < len; i++) { - carry = 0; - y = 0; - p1 = num; - p2 = BIGLITTLE(num-i-1,num+i+1); - for (j = 0; j < (i+1)/2; j++) { - BIG(z = (BNWORD32)*--p1 * *p2++;) - LITTLE(z = (BNWORD32)*p1++ * *--p2;) - y += z; - carry += (y < z); - } - y += z = y; - carry += carry + (y < z); - if ((i & 1) == 0) { - assert(BIGLITTLE(--p1 == p2, p1 == --p2)); - BIG(z = (BNWORD32)*p2 * *p2;) - LITTLE(z = (BNWORD32)*p1 * *p1;) - y += z; - carry += (y < z); - } - x += y; - carry += (x < y); - BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; - x = (x >> 16) | (BNWORD32)carry << 16; - } - /* Words len through 2*len-2 */ - for (i = 1; i < len; i++) { - carry = 0; - y = 0; - p1 = BIGLITTLE(num-i,num+i); - p2 = BIGLITTLE(num-len,num+len); - for (j = 0; j < (len-i)/2; j++) { - BIG(z = (BNWORD32)*--p1 * *p2++;) - LITTLE(z = (BNWORD32)*p1++ * *--p2;) - y += z; - carry += (y < z); - } - y += z = y; - carry += carry + (y < z); - if ((len-i) & 1) { - assert(BIGLITTLE(--p1 == p2, p1 == --p2)); - BIG(z = (BNWORD32)*p2 * *p2;) - LITTLE(z = (BNWORD32)*p1 * *p1;) - y += z; - carry += (y < z); - } - x += y; - carry += (x < y); - BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; - x = (x >> 16) | (BNWORD32)carry << 16; - } - - /* Word 2*len-1 */ - BIGLITTLE(*--prod,*prod) = (BNWORD16)x; -} -/* Suppress later definition */ -#define lbnSquare_16 lbnSquare_16 -#endif - -/* - * Square a number, using optimized squaring to reduce the number of - * primitive multiples that are executed. There may not be any - * overlap of the input and output. - * - * Technique: Consider the partial products in the multiplication - * of "abcde" by itself: - * - * a b c d e - * * a b c d e - * ================== - * ae be ce de ee - * ad bd cd dd de - * ac bc cc cd ce - * ab bb bc bd be - * aa ab ac ad ae - * - * Note that everything above the main diagonal: - * ae be ce de = (abcd) * e - * ad bd cd = (abc) * d - * ac bc = (ab) * c - * ab = (a) * b - * - * is a copy of everything below the main diagonal: - * de - * cd ce - * bc bd be - * ab ac ad ae - * - * Thus, the sum is 2 * (off the diagonal) + diagonal. - * - * This is accumulated beginning with the diagonal (which - * consist of the squares of the digits of the input), which is then - * divided by two, the off-diagonal added, and multiplied by two - * again. The low bit is simply a copy of the low bit of the - * input, so it doesn't need special care. - * - * TODO: Merge the shift by 1 with the squaring loop. - * TODO: Use Karatsuba. (a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W. - */ -#ifndef lbnSquare_16 -void -lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len) -{ - BNWORD16 t; - BNWORD16 *prodx = prod; /* Working copy of the argument */ - BNWORD16 const *numx = num; /* Working copy of the argument */ - unsigned lenx = len; /* Working copy of the argument */ - - if (!len) - return; - - /* First, store all the squares */ - while (lenx--) { -#ifdef mul16_ppmm - BNWORD16 ph, pl; - t = BIGLITTLE(*--numx,*numx++); - mul16_ppmm(ph,pl,t,t); - BIGLITTLE(*--prodx,*prodx++) = pl; - BIGLITTLE(*--prodx,*prodx++) = ph; -#elif defined(BNWORD32) /* use BNWORD32 */ - BNWORD32 p; - t = BIGLITTLE(*--numx,*numx++); - p = (BNWORD32)t * t; - BIGLITTLE(*--prodx,*prodx++) = (BNWORD16)p; - BIGLITTLE(*--prodx,*prodx++) = (BNWORD16)(p>>16); -#else /* Use lbnMulN1_16 */ - t = BIGLITTLE(numx[-1],*numx); - lbnMulN1_16(prodx, numx, 1, t); - BIGLITTLE(--numx,numx++); - BIGLITTLE(prodx -= 2, prodx += 2); -#endif - } - /* Then, shift right 1 bit */ - (void)lbnRshift_16(prod, 2*len, 1); - - /* Then, add in the off-diagonal sums */ - lenx = len; - numx = num; - prodx = prod; - while (--lenx) { - t = BIGLITTLE(*--numx,*numx++); - BIGLITTLE(--prodx,prodx++); - t = lbnMulAdd1_16(prodx, numx, lenx, t); - lbnAdd1_16(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t); - BIGLITTLE(--prodx,prodx++); - } - - /* Shift it back up */ - lbnDouble_16(prod, 2*len); - - /* And set the low bit appropriately */ - BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1; -} -#endif /* !lbnSquare_16 */ - -/* - * lbnNorm_16 - given a number, return a modified length such that the - * most significant digit is non-zero. Zero-length input is okay. - */ -#ifndef lbnNorm_16 -unsigned -lbnNorm_16(BNWORD16 const *num, unsigned len) -{ - BIGLITTLE(num -= len,num += len); - while (len && BIGLITTLE(*num++,*--num) == 0) - --len; - return len; -} -#endif /* lbnNorm_16 */ - -/* - * lbnBits_16 - return the number of significant bits in the array. - * It starts by normalizing the array. Zero-length input is okay. - * Then assuming there's anything to it, it fetches the high word, - * generates a bit length by multiplying the word length by 16, and - * subtracts off 16/2, 16/4, 16/8, ... bits if the high bits are clear. - */ -#ifndef lbnBits_16 -unsigned -lbnBits_16(BNWORD16 const *num, unsigned len) -{ - BNWORD16 t; - unsigned i; - - len = lbnNorm_16(num, len); - if (len) { - t = BIGLITTLE(*(num-len),*(num+(len-1))); - assert(t); - len *= 16; - i = 16/2; - do { - if (t >> i) - t >>= i; - else - len -= i; - } while ((i /= 2) != 0); - } - return len; -} -#endif /* lbnBits_16 */ - -/* - * If defined, use hand-rolled divide rather than compiler's native. - * If the machine doesn't do it in line, the manual code is probably - * faster, since it can assume normalization and the fact that the - * quotient will fit into 16 bits, which a general 32-bit divide - * in a compiler's run-time library can't do. - */ -#ifndef BN_SLOW_DIVIDE_32 -/* Assume that divisors of more than thirty-two bits are slow */ -#define BN_SLOW_DIVIDE_32 (32 > 0x20) -#endif - -/* - * Return (nh<<16|nl) % d, and place the quotient digit into *q. - * It is guaranteed that nh < d, and that d is normalized (with its high - * bit set). If we have a double-width type, it's easy. If not, ooh, - * yuk! - */ -#ifndef lbnDiv21_16 -#if defined(BNWORD32) && !BN_SLOW_DIVIDE_32 -BNWORD16 -lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d) -{ - BNWORD32 n = (BNWORD32)nh << 16 | nl; - - /* Divisor must be normalized */ - assert(d >> (16-1) == 1); - - *q = n / d; - return n % d; -} -#else -/* - * This is where it gets ugly. - * - * Do the division in two halves, using Algorithm D from section 4.3.1 - * of Knuth. Note Theorem B from that section, that the quotient estimate - * is never more than the true quotient, and is never more than two - * too low. - * - * The mapping onto conventional long division is (everything a half word): - * _____________qh___ql_ - * dh dl ) nh.h nh.l nl.h nl.l - * - (qh * d) - * ----------- - * rrrr rrrr nl.l - * - (ql * d) - * ----------- - * rrrr rrrr - * - * The implicit 3/2-digit d*qh and d*ql subtractors are computed this way: - * First, estimate a q digit so that nh/dh works. Subtracting qh*dh from - * the (nh.h nh.l) list leaves a 1/2-word remainder r. Then compute the - * low part of the subtractor, qh * dl. This also needs to be subtracted - * from (nh.h nh.l nl.h) to get the final remainder. So we take the - * remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and - * try to subtract qh * dl from that. Since the remainder is 1/2-word - * long, shifting and adding nl.h results in a single word r. - * It is possible that the remainder we're working with, r, is less than - * the product qh * dl, if we estimated qh too high. The estimation - * technique can produce a qh that is too large (never too small), leading - * to r which is too small. In that case, decrement the digit qh, add - * shifted dh to r (to correct for that error), and subtract dl from the - * product we're comparing r with. That's the "correct" way to do it, but - * just adding dl to r instead of subtracting it from the product is - * equivalent and a lot simpler. You just have to watch out for overflow. - * - * The process is repeated with (rrrr rrrr nl.l) for the low digit of the - * quotient ql. - * - * The various uses of 16/2 for shifts are because of the note about - * automatic editing of this file at the very top of the file. - */ -#define highhalf(x) ( (x) >> 16/2 ) -#define lowhalf(x) ( (x) & (((BNWORD16)1 << 16/2)-1) ) -BNWORD16 -lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d) -{ - BNWORD16 dh = highhalf(d), dl = lowhalf(d); - BNWORD16 qh, ql, prod, r; - - /* Divisor must be normalized */ - assert((d >> (16-1)) == 1); - - /* Do first half-word of division */ - qh = nh / dh; - r = nh % dh; - prod = qh * dl; - - /* - * Add next half-word of numerator to remainder and correct. - * qh may be up to two too large. - */ - r = (r << (16/2)) | highhalf(nl); - if (r < prod) { - --qh; r += d; - if (r >= d && r < prod) { - --qh; r += d; - } - } - r -= prod; - - /* Do second half-word of division */ - ql = r / dh; - r = r % dh; - prod = ql * dl; - - r = (r << (16/2)) | lowhalf(nl); - if (r < prod) { - --ql; r += d; - if (r >= d && r < prod) { - --ql; r += d; - } - } - r -= prod; - - *q = (qh << (16/2)) | ql; - - return r; -} -#endif -#endif /* lbnDiv21_16 */ - - -/* - * In the division functions, the dividend and divisor are referred to - * as "n" and "d", which stand for "numerator" and "denominator". - * - * The quotient is (nlen-dlen+1) digits long. It may be overlapped with - * the high (nlen-dlen) words of the dividend, but one extra word is needed - * on top to hold the top word. - */ - -/* - * Divide an n-word number by a 1-word number, storing the remainder - * and n-1 words of the n-word quotient. The high word is returned. - * It IS legal for rem to point to the same address as n, and for - * q to point one word higher. - * - * TODO: If BN_SLOW_DIVIDE_32, add a divnhalf_16 which uses 16-bit - * dividends if the divisor is half that long. - * TODO: Shift the dividend on the fly to avoid the last division and - * instead have a remainder that needs shifting. - * TODO: Use reciprocals rather than dividing. - */ -#ifndef lbnDiv1_16 -BNWORD16 -lbnDiv1_16(BNWORD16 *q, BNWORD16 *rem, BNWORD16 const *n, unsigned len, - BNWORD16 d) -{ - unsigned shift; - unsigned xlen; - BNWORD16 r; - BNWORD16 qhigh; - - assert(len > 0); - assert(d); - - if (len == 1) { - r = *n; - *rem = r%d; - return r/d; - } - - shift = 0; - r = d; - xlen = 16/2; - do { - if (r >> xlen) - r >>= xlen; - else - shift += xlen; - } while ((xlen /= 2) != 0); - assert((d >> (16-1-shift)) == 1); - d <<= shift; - - BIGLITTLE(q -= len-1,q += len-1); - BIGLITTLE(n -= len,n += len); - - r = BIGLITTLE(*n++,*--n); - if (r < d) { - qhigh = 0; - } else { - qhigh = r/d; - r %= d; - } - - xlen = len; - while (--xlen) - r = lbnDiv21_16(BIGLITTLE(q++,--q), r, BIGLITTLE(*n++,*--n), d); - - /* - * Final correction for shift - shift the quotient up "shift" - * bits, and merge in the extra bits of quotient. Then reduce - * the final remainder mod the real d. - */ - if (shift) { - d >>= shift; - qhigh = (qhigh << shift) | lbnLshift_16(q, len-1, shift); - BIGLITTLE(q[-1],*q) |= r/d; - r %= d; - } - *rem = r; - - return qhigh; -} -#endif - -/* - * This function performs a "quick" modulus of a number with a divisor - * d which is guaranteed to be at most sixteen bits, i.e. less than 65536. - * This applies regardless of the word size the library is compiled with. - * - * This function is important to prime generation, for sieving. - */ -#ifndef lbnModQ_16 -/* If there's a custom lbnMod21_16, no normalization needed */ -#ifdef lbnMod21_16 -unsigned -lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) -{ - unsigned i, shift; - BNWORD16 r; - - assert(len > 0); - - BIGLITTLE(n -= len,n += len); - - /* Try using a compare to avoid the first divide */ - r = BIGLITTLE(*n++,*--n); - if (r >= d) - r %= d; - while (--len) - r = lbnMod21_16(r, BIGLITTLE(*n++,*--n), d); - - return r; -} -#elif defined(BNWORD32) && !BN_SLOW_DIVIDE_32 -unsigned -lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) -{ - BNWORD16 r; - - if (!--len) - return BIGLITTLE(n[-1],n[0]) % d; - - BIGLITTLE(n -= len,n += len); - r = BIGLITTLE(n[-1],n[0]); - - do { - r = (BNWORD16)((((BNWORD32)r<<16) | BIGLITTLE(*n++,*--n)) % d); - } while (--len); - - return r; -} -#elif 16 >= 0x20 -/* - * If the single word size can hold 65535*65536, then this function - * is avilable. - */ -#ifndef highhalf -#define highhalf(x) ( (x) >> 16/2 ) -#define lowhalf(x) ( (x) & ((1 << 16/2)-1) ) -#endif -unsigned -lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) -{ - BNWORD16 r, x; - - BIGLITTLE(n -= len,n += len); - - r = BIGLITTLE(*n++,*--n); - while (--len) { - x = BIGLITTLE(*n++,*--n); - r = (r%d << 16/2) | highhalf(x); - r = (r%d << 16/2) | lowhalf(x); - } - - return r%d; -} -#else -/* Default case - use lbnDiv21_16 */ -unsigned -lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) -{ - unsigned i, shift; - BNWORD16 r; - BNWORD16 q; - - assert(len > 0); - - shift = 0; - r = d; - i = 16; - while (i /= 2) { - if (r >> i) - r >>= i; - else - shift += i; - } - assert(d >> (16-1-shift) == 1); - d <<= shift; - - BIGLITTLE(n -= len,n += len); - - r = BIGLITTLE(*n++,*--n); - if (r >= d) - r %= d; - - while (--len) - r = lbnDiv21_16(&q, r, BIGLITTLE(*n++,*--n), d); - - /* - * Final correction for shift - shift the quotient up "shift" - * bits, and merge in the extra bits of quotient. Then reduce - * the final remainder mod the real d. - */ - if (shift) - r %= d >> shift; - - return r; -} -#endif -#endif /* lbnModQ_16 */ - -/* - * Reduce n mod d and return the quotient. That is, find: - * q = n / d; - * n = n % d; - * d is altered during the execution of this subroutine by normalizing it. - * It must already have its most significant word non-zero; it is shifted - * so its most significant bit is non-zero. - * - * The quotient q is nlen-dlen+1 words long. To make it possible to - * overlap the quptient with the input (you can store it in the high dlen - * words), the high word of the quotient is *not* stored, but is returned. - * (If all you want is the remainder, you don't care about it, anyway.) - * - * This uses algorithm D from Knuth (4.3.1), except that we do binary - * (shift) normalization of the divisor. WARNING: This is hairy! - * - * This function is used for some modular reduction, but it is not used in - * the modular exponentiation loops; they use Montgomery form and the - * corresponding, more efficient, Montgomery reduction. This code - * is needed for the conversion to Montgomery form, however, so it - * has to be here and it might as well be reasonably efficient. - * - * The overall operation is as follows ("top" and "up" refer to the - * most significant end of the number; "bottom" and "down", the least): - * - * - Shift the divisor up until the most significant bit is set. - * - Shift the dividend up the same amount. This will produce the - * correct quotient, and the remainder can be recovered by shifting - * it back down the same number of bits. This may produce an overflow - * word, but the word is always strictly less than the most significant - * divisor word. - * - Estimate the first quotient digit qhat: - * - First take the top two words (one of which is the overflow) of the - * dividend and divide by the top word of the divisor: - * qhat = (nh,nm)/dh. This qhat is >= the correct quotient digit - * and, since dh is normalized, it is at most two over. - * - Second, correct by comparing the top three words. If - * (dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again. - * The second iteration can be simpler because there can't be a third. - * The computation can be simplified by subtracting dh*qhat from - * both sides, suitably shifted. This reduces the left side to - * dl*qhat. On the right, (nh,nm)-dh*qhat is simply the - * remainder r from (nh,nm)%dh, so the right is (r,nl). - * This produces qhat that is almost always correct and at - * most (prob ~ 2/2^16) one too high. - * - Subtract qhat times the divisor (suitably shifted) from the dividend. - * If there is a borrow, qhat was wrong, so decrement it - * and add the divisor back in (once). - * - Store the final quotient digit qhat in the quotient array q. - * - * Repeat the quotient digit computation for successive digits of the - * quotient until the whole quotient has been computed. Then shift the - * divisor and the remainder down to correct for the normalization. - * - * TODO: Special case 2-word divisors. - * TODO: Use reciprocals rather than dividing. - */ -#ifndef divn_16 -BNWORD16 -lbnDiv_16(BNWORD16 *q, BNWORD16 *n, unsigned nlen, BNWORD16 *d, unsigned dlen) -{ - BNWORD16 nh,nm,nl; /* Top three words of the dividend */ - BNWORD16 dh,dl; /* Top two words of the divisor */ - BNWORD16 qhat; /* Extimate of quotient word */ - BNWORD16 r; /* Remainder from quotient estimate division */ - BNWORD16 qhigh; /* High word of quotient */ - unsigned i; /* Temp */ - unsigned shift; /* Bits shifted by normalization */ - unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */ -#ifdef mul16_ppmm - BNWORD16 t16; -#elif defined(BNWORD32) - BNWORD32 t32; -#else /* use lbnMulN1_16 */ - BNWORD16 t2[2]; -#define t2high BIGLITTLE(t2[0],t2[1]) -#define t2low BIGLITTLE(t2[1],t2[0]) -#endif - - assert(dlen); - assert(nlen >= dlen); - - /* - * Special cases for short divisors. The general case uses the - * top top 2 digits of the divisor (d) to estimate a quotient digit, - * so it breaks if there are fewer digits available. Thus, we need - * special cases for a divisor of length 1. A divisor of length - * 2 can have a *lot* of administrivia overhead removed removed, - * so it's probably worth special-casing that case, too. - */ - if (dlen == 1) - return lbnDiv1_16(q, BIGLITTLE(n-1,n), n, nlen, - BIGLITTLE(d[-1],d[0])); - -#if 0 - /* - * @@@ This is not yet written... The general loop will do, - * albeit less efficiently - */ - if (dlen == 2) { - /* - * divisor two digits long: - * use the 3/2 technique from Knuth, but we know - * it's exact. - */ - dh = BIGLITTLE(d[-1],d[0]); - dl = BIGLITTLE(d[-2],d[1]); - shift = 0; - if ((sh & ((BNWORD16)1 << 16-1-shift)) == 0) { - do { - shift++; - } while (dh & (BNWORD16)1<<16-1-shift) == 0); - dh = dh << shift | dl >> (16-shift); - dl <<= shift; - - - } - - - for (shift = 0; (dh & (BNWORD16)1 << 16-1-shift)) == 0; shift++) - ; - if (shift) { - } - dh = dh << shift | dl >> (16-shift); - shift = 0; - while (dh - } -#endif - - dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); - assert(dh); - - /* Normalize the divisor */ - shift = 0; - r = dh; - i = 16/2; - do { - if (r >> i) - r >>= i; - else - shift += i; - } while ((i /= 2) != 0); - - nh = 0; - if (shift) { - lbnLshift_16(d, dlen, shift); - dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); - nh = lbnLshift_16(n, nlen, shift); - } - - /* Assert that dh is now normalized */ - assert(dh >> (16-1)); - - /* Also get the second-most significant word of the divisor */ - dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2))); - - /* - * Adjust pointers: n to point to least significant end of first - * first subtract, and q to one the most-significant end of the - * quotient array. - */ - BIGLITTLE(n -= qlen,n += qlen); - BIGLITTLE(q -= qlen,q += qlen); - - /* Fetch the most significant stored word of the dividend */ - nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); - - /* - * Compute the first digit of the quotient, based on the - * first two words of the dividend (the most significant of which - * is the overflow word h). - */ - if (nh) { - assert(nh < dh); - r = lbnDiv21_16(&qhat, nh, nm, dh); - } else if (nm >= dh) { - qhat = nm/dh; - r = nm % dh; - } else { /* Quotient is zero */ - qhigh = 0; - goto divloop; - } - - /* Now get the third most significant word of the dividend */ - nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); - - /* - * Correct qhat, the estimate of quotient digit. - * qhat can only be high, and at most two words high, - * so the loop can be unrolled and abbreviated. - */ -#ifdef mul16_ppmm - mul16_ppmm(nm, t16, qhat, dl); - if (nm > r || (nm == r && t16 > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - nm -= (t16 < dl); - t16 -= dl; - if (nm > r || (nm == r && t16 > nl)) - qhat--; - } - } -#elif defined(BNWORD32) - t32 = (BNWORD32)qhat * dl; - if (t32 > ((BNWORD32)r << 16) + nl) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) > dh) { - t32 -= dl; - if (t32 > ((BNWORD32)r << 16) + nl) - qhat--; - } - } -#else /* Use lbnMulN1_16 */ - lbnMulN1_16(BIGLITTLE(t2+2,t2), &dl, 1, qhat); - if (t2high > r || (t2high == r && t2low > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - t2high -= (t2low < dl); - t2low -= dl; - if (t2high > r || (t2high == r && t2low > nl)) - qhat--; - } - } -#endif - - /* Do the multiply and subtract */ - r = lbnMulSub1_16(n, d, dlen, qhat); - /* If there was a borrow, add back once. */ - if (r > nh) { /* Borrow? */ - (void)lbnAddN_16(n, d, dlen); - qhat--; - } - - /* Remember the first quotient digit. */ - qhigh = qhat; - - /* Now, the main division loop: */ -divloop: - while (qlen--) { - - /* Advance n */ - nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); - BIGLITTLE(++n,--n); - nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); - - if (nh == dh) { - qhat = ~(BNWORD16)0; - /* Optimized computation of r = (nh,nm) - qhat * dh */ - r = nh + nm; - if (r < nh) - goto subtract; - } else { - assert(nh < dh); - r = lbnDiv21_16(&qhat, nh, nm, dh); - } - - nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); -#ifdef mul16_ppmm - mul16_ppmm(nm, t16, qhat, dl); - if (nm > r || (nm == r && t16 > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - nm -= (t16 < dl); - t16 -= dl; - if (nm > r || (nm == r && t16 > nl)) - qhat--; - } - } -#elif defined(BNWORD32) - t32 = (BNWORD32)qhat * dl; - if (t32 > ((BNWORD32)r<<16) + nl) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - t32 -= dl; - if (t32 > ((BNWORD32)r << 16) + nl) - qhat--; - } - } -#else /* Use lbnMulN1_16 */ - lbnMulN1_16(BIGLITTLE(t2+2,t2), &dl, 1, qhat); - if (t2high > r || (t2high == r && t2low > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - t2high -= (t2low < dl); - t2low -= dl; - if (t2high > r || (t2high == r && t2low > nl)) - qhat--; - } - } -#endif - - /* - * As a point of interest, note that it is not worth checking - * for qhat of 0 or 1 and installing special-case code. These - * occur with probability 2^-16, so spending 1 cycle to check - * for them is only worth it if we save more than 2^15 cycles, - * and a multiply-and-subtract for numbers in the 1024-bit - * range just doesn't take that long. - */ -subtract: - /* - * n points to the least significant end of the substring - * of n to be subtracted from. qhat is either exact or - * one too large. If the subtract gets a borrow, it was - * one too large and the divisor is added back in. It's - * a dlen+1 word add which is guaranteed to produce a - * carry out, so it can be done very simply. - */ - r = lbnMulSub1_16(n, d, dlen, qhat); - if (r > nh) { /* Borrow? */ - (void)lbnAddN_16(n, d, dlen); - qhat--; - } - /* Store the quotient digit */ - BIGLITTLE(*q++,*--q) = qhat; - } - /* Tah dah! */ - - if (shift) { - lbnRshift_16(d, dlen, shift); - lbnRshift_16(n, dlen, shift); - } - - return qhigh; -} -#endif - -/* - * Find the negative multiplicative inverse of x (x must be odd!) modulo 2^16. - * - * This just performs Newton's iteration until it gets the - * inverse. The initial estimate is always correct to 3 bits, and - * sometimes 4. The number of valid bits doubles each iteration. - * (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable - * for the error mod 2^2n. x * y == 1 + k*2^n (mod 2^2n) and follow - * the iteration through.) - */ -#ifndef lbnMontInv1_16 -BNWORD16 -lbnMontInv1_16(BNWORD16 const x) -{ - BNWORD16 y = x, z; - - assert(x & 1); - - while ((z = x*y) != 1) - y *= 2 - z; - return -y; -} -#endif /* !lbnMontInv1_16 */ - -#if defined(BNWORD32) && PRODUCT_SCAN -/* - * Test code for product-scanning Montgomery reduction. - * This seems to slow the C code down rather than speed it up. - * - * The first loop computes the Montgomery multipliers, storing them over - * the low half of the number n. - * - * The second half multiplies the upper half, adding in the modulus - * times the Montgomery multipliers. The results of this multiply - * are stored. - */ -void -lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned mlen, BNWORD16 inv) -{ - BNWORD32 x, y; - BNWORD16 const *pm; - BNWORD16 *pn; - BNWORD16 t; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!mlen) - return; - - /* Pass 1 - compute Montgomery multipliers */ - /* First iteration can have certain simplifications. */ - t = BIGLITTLE(n[-1],n[0]); - x = t; - t *= inv; - BIGLITTLE(n[-1], n[0]) = t; - x += (BNWORD32)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */ - assert((BNWORD16)x == 0); - x = x >> 16; - - for (i = 1; i < mlen; i++) { - carry = 0; - pn = n; - pm = BIGLITTLE(mod-i-1,mod+i+1); - for (j = 0; j < i; j++) { - y = (BNWORD32)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm); - x += y; - carry += (x < y); - } - assert(BIGLITTLE(pn == n-i, pn == n+i)); - y = t = BIGLITTLE(pn[-1], pn[0]); - x += y; - carry += (x < y); - BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD16)x; - assert(BIGLITTLE(pm == mod-1, pm == mod+1)); - y = (BNWORD32)t * BIGLITTLE(pm[0],pm[-1]); - x += y; - carry += (x < y); - assert((BNWORD16)x == 0); - x = x >> 16 | (BNWORD32)carry << 16; - } - - BIGLITTLE(n -= mlen, n += mlen); - - /* Pass 2 - compute upper words and add to n */ - for (i = 1; i < mlen; i++) { - carry = 0; - pm = BIGLITTLE(mod-i,mod+i); - pn = n; - for (j = i; j < mlen; j++) { - y = (BNWORD32)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn); - x += y; - carry += (x < y); - } - assert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen)); - assert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i)); - y = t = BIGLITTLE(*(n-i),*(n+i-1)); - x += y; - carry += (x < y); - BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD16)x; - x = (x >> 16) | (BNWORD32)carry << 16; - } - - /* Last round of second half, simplified. */ - t = BIGLITTLE(*(n-mlen),*(n+mlen-1)); - x += t; - BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD16)x; - carry = (unsigned)(x >> 16); - - while (carry) - carry -= lbnSubN_16(n, mod, mlen); - while (lbnCmp_16(n, mod, mlen) >= 0) - (void)lbnSubN_16(n, mod, mlen); -} -#define lbnMontReduce_16 lbnMontReduce_16 -#endif - -/* - * Montgomery reduce n, modulo mod. This reduces modulo mod and divides by - * 2^(16*mlen). Returns the result in the *top* mlen words of the argument n. - * This is ready for another multiplication using lbnMul_16. - * - * Montgomery representation is a very useful way to encode numbers when - * you're doing lots of modular reduction. What you do is pick a multiplier - * R which is relatively prime to the modulus and very easy to divide by. - * Since the modulus is odd, R is closen as a power of 2, so the division - * is a shift. In fact, it's a shift of an integral number of words, - * so the shift can be implicit - just drop the low-order words. - * - * Now, choose R *larger* than the modulus m, 2^(16*mlen). Then convert - * all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the - * relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. Note that: - * - The Montgomery form of a number depends on the modulus m. - * A fixed modulus m is assumed throughout this discussion. - * - Since R is relaitvely prime to m, multiplication by R is invertible; - * no information about the numbers is lost, they're just scrambled. - * - Adding (and subtracting) numbers in this form works just as usual. - * M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m - * - Multiplying numbers in this form produces a*b*R*R. The problem - * is to divide out the excess factor of R, modulo m as well as to - * reduce to the given length mlen. It turns out that this can be - * done *faster* than a normal divide, which is where the speedup - * in Montgomery division comes from. - * - * Normal reduction chooses a most-significant quotient digit q and then - * subtracts q*m from the number to be reduced. Choosing q is tricky - * and involved (just look at lbnDiv_16 to see!) and is usually - * imperfect, requiring a check for correction after the subtraction. - * - * Montgomery reduction *adds* a multiple of m to the *low-order* part - * of the number to be reduced. This multiple is chosen to make the - * low-order part of the number come out to zero. This can be done - * with no trickery or error using a precomputed inverse of the modulus. - * In this code, the "part" is one word, but any width can be used. - * - * Repeating this step sufficiently often results in a value which - * is a multiple of R (a power of two, remember) but is still (since - * the additions were to the low-order part and thus did not increase - * the value of the number being reduced very much) still not much - * larger than m*R. Then implicitly divide by R and subtract off - * m until the result is in the correct range. - * - * Since the low-order part being cancelled is less than R, the - * multiple of m added must have a multiplier which is at most R-1. - * Assuming that the input is at most m*R-1, the final number is - * at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from - * the high-order part, equivalent to subtracting m*R from the - * while number, produces a result which is at most m*R - m - 1, - * which divided by R is at most m-1. - * - * To convert *to* Montgomery form, you need a regular remainder - * routine, although you can just compute R*R (mod m) and do the - * conversion using Montgomery multiplication. To convert *from* - * Montgomery form, just Montgomery reduce the number to - * remove the extra factor of R. - * - * TODO: Change to a full inverse and use Karatsuba's multiplication - * rather than this word-at-a-time. - */ -#ifndef lbnMontReduce_16 -void -lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned const mlen, - BNWORD16 inv) -{ - BNWORD16 t; - BNWORD16 c = 0; - unsigned len = mlen; - - /* inv must be the negative inverse of mod's least significant word */ - assert((BNWORD16)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD16)-1); - - assert(len); - - do { - t = lbnMulAdd1_16(n, mod, mlen, inv * BIGLITTLE(n[-1],n[0])); - c += lbnAdd1_16(BIGLITTLE(n-mlen,n+mlen), len, t); - BIGLITTLE(--n,++n); - } while (--len); - - /* - * All that adding can cause an overflow past the modulus size, - * but it's unusual, and never by much, so a subtraction loop - * is the right way to deal with it. - * This subtraction happens infrequently - I've only ever seen it - * invoked once per reduction, and then just under 22.5% of the time. - */ - while (c) - c -= lbnSubN_16(n, mod, mlen); - while (lbnCmp_16(n, mod, mlen) >= 0) - (void)lbnSubN_16(n, mod, mlen); -} -#endif /* !lbnMontReduce_16 */ - -/* - * A couple of helpers that you might want to implement atomically - * in asm sometime. - */ -#ifndef lbnMontMul_16 -/* - * Multiply "num1" by "num2", modulo "mod", all of length "len", and - * place the result in the high half of "prod". "inv" is the inverse - * of the least-significant word of the modulus, modulo 2^16. - * This uses numbers in Montgomery form. Reduce using "len" and "inv". - * - * This is implemented as a macro to win on compilers that don't do - * inlining, since it's so trivial. - */ -#define lbnMontMul_16(prod, n1, n2, mod, len, inv) \ - (lbnMulX_16(prod, n1, n2, len), lbnMontReduce_16(prod, mod, len, inv)) -#endif /* !lbnMontMul_16 */ - -#ifndef lbnMontSquare_16 -/* - * Square "n", modulo "mod", both of length "len", and place the result - * in the high half of "prod". "inv" is the inverse of the least-significant - * word of the modulus, modulo 2^16. - * This uses numbers in Montgomery form. Reduce using "len" and "inv". - * - * This is implemented as a macro to win on compilers that don't do - * inlining, since it's so trivial. - */ -#define lbnMontSquare_16(prod, n, mod, len, inv) \ - (lbnSquare_16(prod, n, len), lbnMontReduce_16(prod, mod, len, inv)) - -#endif /* !lbnMontSquare_16 */ - -/* - * Convert a number to Montgomery form - requires mlen + nlen words - * of memory in "n". - */ -void -lbnToMont_16(BNWORD16 *n, unsigned nlen, BNWORD16 *mod, unsigned mlen) -{ - /* Move n up "mlen" words */ - lbnCopy_16(BIGLITTLE(n-mlen,n+mlen), n, nlen); - lbnZero_16(n, mlen); - /* Do the division - dump the quotient in the high-order words */ - (void)lbnDiv_16(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen); -} - -/* - * Convert from Montgomery form. Montgomery reduction is all that is - * needed. - */ -void -lbnFromMont_16(BNWORD16 *n, BNWORD16 *mod, unsigned len) -{ - /* Zero the high words of n */ - lbnZero_16(BIGLITTLE(n-len,n+len), len); - lbnMontReduce_16(n, mod, len, lbnMontInv1_16(mod[BIGLITTLE(-1,0)])); - /* Move n down len words */ - lbnCopy_16(n, BIGLITTLE(n-len,n+len), len); -} - -/* - * The windowed exponentiation algorithm, precomputes a table of odd - * powers of n up to 2^k. See the comment in bnExpMod_16 below for - * an explanation of how it actually works works. - * - * It takes 2^(k-1)-1 multiplies to compute the table, and (e-1)/(k+1) - * multiplies (on average) to perform the exponentiation. To minimize - * the sum, k must vary with e. The optimal window sizes vary with the - * exponent length. Here are some selected values and the boundary cases. - * (An underscore _ has been inserted into some of the numbers to ensure - * that magic strings like 16 do not appear in this table. It should be - * ignored.) - * - * At e = 1 bits, k=1 (0.000000) is best - * At e = 2 bits, k=1 (0.500000) is best - * At e = 4 bits, k=1 (1.500000) is best - * At e = 8 bits, k=2 (3.333333) < k=1 (3.500000) - * At e = 1_6 bits, k=2 (6.000000) is best - * At e = 26 bits, k=3 (9.250000) < k=2 (9.333333) - * At e = 3_2 bits, k=3 (10.750000) is best - * At e = 6_4 bits, k=3 (18.750000) is best - * At e = 82 bits, k=4 (23.200000) < k=3 (23.250000) - * At e = 128 bits, k=4 (3_2.400000) is best - * At e = 242 bits, k=5 (55.1_66667) < k=4 (55.200000) - * At e = 256 bits, k=5 (57.500000) is best - * At e = 512 bits, k=5 (100.1_66667) is best - * At e = 674 bits, k=6 (127.142857) < k=5 (127.1_66667) - * At e = 1024 bits, k=6 (177.142857) is best - * At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857) - * At e = 2048 bits, k=7 (318.875000) is best - * At e = 4096 bits, k=7 (574.875000) is best - * - * The numbers in parentheses are the expected number of multiplications - * needed to do the computation. The normal russian-peasant modular - * exponentiation technique always uses (e-1)/2. For exponents as - * small as 192 bits (below the range of current factoring algorithms), - * half of the multiplies are eliminated, 45.2 as opposed to the naive - * 95.5. Counting the 191 squarings as 3/4 a multiply each (squaring - * proper is just over half of multiplying, but the Montgomery - * reduction in each case is also a multiply), that's 143.25 - * multiplies, for totals of 188.45 vs. 238.75 - a 21% savings. - * For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a - * 24.3% savings. It asymptotically approaches 25%. - * - * Um, actually there's a slightly more accurate way to count, which - * really is the average number of multiplies required, averaged - * uniformly over all 2^(e-1) e-bit numbers, from 2^(e-1) to (2^e)-1. - * It's based on the recurrence that for the last b bits, b <= k, at - * most one multiply is needed (and none at all 1/2^b of the time), - * while when b > k, the odds are 1/2 each way that the bit will be - * 0 (meaning no multiplies to reduce it to the b-1-bit case) and - * 1/2 that the bit will be 1, starting a k-bit window and requiring - * 1 multiply beyond the b-k-bit case. Since the most significant - * bit is always 1, a k-bit window always starts there, and that - * multiply is by 1, so it isn't a multiply at all. Thus, the - * number of multiplies is simply that needed for the last e-k bits. - * This recurrence produces: - * - * At e = 1 bits, k=1 (0.000000) is best - * At e = 2 bits, k=1 (0.500000) is best - * At e = 4 bits, k=1 (1.500000) is best - * At e = 6 bits, k=2 (2.437500) < k=1 (2.500000) - * At e = 8 bits, k=2 (3.109375) is best - * At e = 1_6 bits, k=2 (5.777771) is best - * At e = 24 bits, k=3 (8.437629) < k=2 (8.444444) - * At e = 3_2 bits, k=3 (10.437492) is best - * At e = 6_4 bits, k=3 (18.437500) is best - * At e = 81 bits, k=4 (22.6_40000) < k=3 (22.687500) - * At e = 128 bits, k=4 (3_2.040000) is best - * At e = 241 bits, k=5 (54.611111) < k=4 (54.6_40000) - * At e = 256 bits, k=5 (57.111111) is best - * At e = 512 bits, k=5 (99.777778) is best - * At e = 673 bits, k=6 (126.591837) < k=5 (126.611111) - * At e = 1024 bits, k=6 (176.734694) is best - * At e = 1793 bits, k=7 (286.578125) < k=6 (286.591837) - * At e = 2048 bits, k=7 (318.453125) is best - * At e = 4096 bits, k=7 (574.453125) is best - * - * This has the rollover points at 6, 24, 81, 241, 673 and 1793 instead - * of 8, 26, 82, 242, 674, and 1794. Not a very big difference. - * (The numbers past that are k=8 at 4609 and k=9 at 11521, - * vs. one more in each case for the approximation.) - * - * Given that exponents for which k>7 are useful are uncommon, - * a fixed size table for k <= 7 is used for simplicity. - * - * The basic number of squarings needed is e-1, although a k-bit - * window (for k > 1) can save, on average, k-2 of those, too. - * That savings currently isn't counted here. It would drive the - * crossover points slightly lower. - * (Actually, this win is also reduced in the DoubleExpMod case, - * meaning we'd have to split the tables. Except for that, the - * multiplies by powers of the two bases are independent, so - * the same logic applies to each as the single case.) - * - * Table entry i is the largest number of bits in an exponent to - * process with a window size of i+1. Entry 6 is the largest - * possible unsigned number, so the window will never be more - * than 7 bits, requiring 2^6 = 0x40 slots. - */ -#define BNEXPMOD_MAX_WINDOW 7 -static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = { - 5, 23, 80, 240, 672, 1792, (unsigned)-1 -/* 7, 25, 81, 241, 673, 1793, (unsigned)-1 ### The old approximations */ -}; - -/* - * Perform modular exponentiation, as fast as possible! This uses - * Montgomery reduction, optimized squaring, and windowed exponentiation. - * The modulus "mod" MUST be odd! - * - * This returns 0 on success, -1 on out of memory. - * - * The window algorithm: - * The idea is to keep a running product of b1 = n^(high-order bits of exp), - * and then keep appending exponent bits to it. The following patterns - * apply to a 3-bit window (k = 3): - * To append 0: square - * To append 1: square, multiply by n^1 - * To append 10: square, multiply by n^1, square - * To append 11: square, square, multiply by n^3 - * To append 100: square, multiply by n^1, square, square - * To append 101: square, square, square, multiply by n^5 - * To append 110: square, square, multiply by n^3, square - * To append 111: square, square, square, multiply by n^7 - * - * Since each pattern involves only one multiply, the longer the pattern - * the better, except that a 0 (no multiplies) can be appended directly. - * We precompute a table of odd powers of n, up to 2^k, and can then - * multiply k bits of exponent at a time. Actually, assuming random - * exponents, there is on average one zero bit between needs to - * multiply (1/2 of the time there's none, 1/4 of the time there's 1, - * 1/8 of the time, there's 2, 1/16 of the time, there's 3, etc.), so - * you have to do one multiply per k+1 bits of exponent. - * - * The loop walks down the exponent, squaring the result buffer as - * it goes. There is a wbits+1 bit lookahead buffer, buf, that is - * filled with the upcoming exponent bits. (What is read after the - * end of the exponent is unimportant, but it is filled with zero here.) - * When the most-significant bit of this buffer becomes set, i.e. - * (buf & tblmask) != 0, we have to decide what pattern to multiply - * by, and when to do it. We decide, remember to do it in future - * after a suitable number of squarings have passed (e.g. a pattern - * of "100" in the buffer requires that we multiply by n^1 immediately; - * a pattern of "110" calls for multiplying by n^3 after one more - * squaring), clear the buffer, and continue. - * - * When we start, there is one more optimization: the result buffer - * is implcitly one, so squaring it or multiplying by it can be - * optimized away. Further, if we start with a pattern like "100" - * in the lookahead window, rather than placing n into the buffer - * and then starting to square it, we have already computed n^2 - * to compute the odd-powers table, so we can place that into - * the buffer and save a squaring. - * - * This means that if you have a k-bit window, to compute n^z, - * where z is the high k bits of the exponent, 1/2 of the time - * it requires no squarings. 1/4 of the time, it requires 1 - * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings. - * And the remaining 1/2^(k-1) of the time, the top k bits are a - * 1 followed by k-1 0 bits, so it again only requires k-2 - * squarings, not k-1. The average of these is 1. Add that - * to the one squaring we have to do to compute the table, - * and you'll see that a k-bit window saves k-2 squarings - * as well as reducing the multiplies. (It actually doesn't - * hurt in the case k = 1, either.) - * - * n must have mlen words allocated. Although fewer may be in use - * when n is passed in, all are in use on exit. - */ -int -lbnExpMod_16(BNWORD16 *result, BNWORD16 const *n, unsigned nlen, - BNWORD16 const *e, unsigned elen, BNWORD16 *mod, unsigned mlen) -{ - BNWORD16 *table[1 << (BNEXPMOD_MAX_WINDOW-1)]; - /* Table of odd powers of n */ - unsigned ebits; /* Exponent bits */ - unsigned wbits; /* Window size */ - unsigned tblmask; /* Mask of exponentiation window */ - BNWORD16 bitpos; /* Mask of current look-ahead bit */ - unsigned buf; /* Buffer of exponent bits */ - unsigned multpos; /* Where to do pending multiply */ - BNWORD16 const *mult; /* What to multiply by */ - unsigned i; /* Loop counter */ - int isone; /* Flag: accum. is implicitly one */ - BNWORD16 *a, *b; /* Working buffers/accumulators */ - BNWORD16 *t; /* Pointer into the working buffers */ - BNWORD16 inv; /* mod^-1 modulo 2^16 */ - int y; /* bnYield() result */ - - assert(mlen); - assert(nlen <= mlen); - - /* First, a couple of trivial cases. */ - elen = lbnNorm_16(e, elen); - if (!elen) { - /* x ^ 0 == 1 */ - lbnZero_16(result, mlen); - BIGLITTLE(result[-1],result[0]) = 1; - return 0; - } - ebits = lbnBits_16(e, elen); - if (ebits == 1) { - /* x ^ 1 == x */ - if (n != result) - lbnCopy_16(result, n, nlen); - if (mlen > nlen) - lbnZero_16(BIGLITTLE(result-nlen,result+nlen), - mlen-nlen); - return 0; - } - - /* Okay, now move the exponent pointer to the most-significant word */ - e = BIGLITTLE(e-elen, e+elen-1); - - /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ - wbits = 0; - while (ebits > bnExpModThreshTable[wbits]) - wbits++; - - /* Allocate working storage: two product buffers and the tables. */ - LBNALLOC(a, BNWORD16, 2*mlen); - if (!a) - return -1; - LBNALLOC(b, BNWORD16, 2*mlen); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ - tblmask = 1u << wbits; - - /* We have the result buffer available, so use it. */ - table[0] = result; - - /* - * Okay, we now have a minimal-sized table - expand it. - * This is allowed to fail! If so, scale back the table size - * and proceed. - */ - for (i = 1; i < tblmask; i++) { - LBNALLOC(t, BNWORD16, mlen); - if (!t) /* Out of memory! Quit the loop. */ - break; - table[i] = t; - } - - /* If we stopped, with i < tblmask, shrink the tables appropriately */ - while (tblmask > i) { - wbits--; - tblmask >>= 1; - } - /* Free up our overallocations */ - while (--i > tblmask) - LBNFREE(table[i], mlen); - - /* Okay, fill in the table */ - - /* Compute the necessary modular inverse */ - inv = lbnMontInv1_16(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - /* Convert n to Montgomery form */ - - /* Move n up "mlen" words into a */ - t = BIGLITTLE(a-mlen, a+mlen); - lbnCopy_16(t, n, nlen); - lbnZero_16(a, mlen); - /* Do the division - lose the quotient into the high-order words */ - (void)lbnDiv_16(t, a, mlen+nlen, mod, mlen); - /* Copy into first table entry */ - lbnCopy_16(table[0], a, mlen); - - /* Square a into b */ - lbnMontSquare_16(b, a, mod, mlen, inv); - - /* Use high half of b to initialize the table */ - t = BIGLITTLE(b-mlen, b+mlen); - for (i = 1; i < tblmask; i++) { - lbnMontMul_16(a, t, table[i-1], mod, mlen, inv); - lbnCopy_16(table[i], BIGLITTLE(a-mlen, a+mlen), mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* We might use b = n^2 later... */ - - /* Initialze the fetch pointer */ - bitpos = (BNWORD16)1 << ((ebits-1) & (16-1)); /* Initialize mask */ - - /* This should point to the msbit of e */ - assert((*e & bitpos) != 0); - - /* - * Pre-load the window. Becuase the window size is - * never larger than the exponent size, there is no need to - * detect running off the end of e in here. - * - * The read-ahead is controlled by elen and the bitpos mask. - * Note that this is *ahead* of ebits, which tracks the - * most significant end of the window. The purpose of this - * initialization is to get the two wbits+1 bits apart, - * like they should be. - * - * Note that bitpos and e1len together keep track of the - * lookahead read pointer in the exponent that is used here. - */ - buf = 0; - for (i = 0; i <= wbits; i++) { - buf = (buf << 1) | ((*e & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e++,e--); - bitpos = (BNWORD16)1 << (16-1); - elen--; - } - } - assert(buf & tblmask); - - /* - * Set the pending multiply positions to a location that will - * never be encountered, thus ensuring that nothing will happen - * until the need for a multiply appears and one is scheduled. - */ - multpos = ebits; /* A NULL value */ - mult = 0; /* Force a crash if we use these */ - - /* - * Okay, now begins the real work. The first step is - * slightly magic, so it's done outside the main loop, - * but it's very similar to what's inside. - */ - ebits--; /* Start processing the first bit... */ - isone = 1; - - /* - * This is just like the multiply in the loop, except that - * - We know the msbit of buf is set, and - * - We have the extra value n^2 floating around. - * So, do the usual computation, and if the result is that - * the buffer should be multiplied by n^1 immediately - * (which we'd normally then square), we multiply it - * (which reduces to a copy, which reduces to setting a flag) - * by n^2 and skip the squaring. Thus, we do the - * multiply and the squaring in one step. - */ - assert(buf & tblmask); - multpos = ebits - wbits; - while ((buf & 1) == 0) { - buf >>= 1; - multpos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(multpos <= ebits); - mult = table[buf>>1]; - buf = 0; - - /* Special case: use already-computed value sitting in buffer */ - if (multpos == ebits) - isone = 0; - - /* - * At this point, the buffer (which is the high half of b) holds - * either 1 (implicitly, as the "isone" flag is set), or n^2. - */ - - /* - * The main loop. The procedure is: - * - Advance the window - * - If the most-significant bit of the window is set, - * schedule a multiply for the appropriate time in the - * future (may be immediately) - * - Perform any pending multiples - * - Check for termination - * - Square the buffer - * - * At any given time, the acumulated product is held in - * the high half of b. - */ - for (;;) { - ebits--; - - /* Advance the window */ - assert(buf < tblmask); - buf <<= 1; - /* - * This reads ahead of the current exponent position - * (controlled by ebits), so we have to be able to read - * past the lsb of the exponents without error. - */ - if (elen) { - buf |= ((*e & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e++,e--); - bitpos = (BNWORD16)1 << (16-1); - elen--; - } - } - - /* Examine the window for pending multiplies */ - if (buf & tblmask) { - multpos = ebits - wbits; - while ((buf & 1) == 0) { - buf >>= 1; - multpos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(multpos <= ebits); - mult = table[buf>>1]; - buf = 0; - } - - /* If we have a pending multiply, do it */ - if (ebits == multpos) { - /* Multiply by the table entry remembered previously */ - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - /* Multiply by 1 is a trivial case */ - lbnCopy_16(t, mult, mlen); - isone = 0; - } else { - lbnMontMul_16(a, t, mult, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } - } - - /* Are we done? */ - if (!ebits) - break; - - /* Square the input */ - if (!isone) { - t = BIGLITTLE(b-mlen, b+mlen); - lbnMontSquare_16(a, t, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } /* for (;;) */ - - assert(!isone); - assert(!buf); - - /* DONE! */ - - /* Convert result out of Montgomery form */ - t = BIGLITTLE(b-mlen, b+mlen); - lbnCopy_16(b, t, mlen); - lbnZero_16(t, mlen); - lbnMontReduce_16(b, mod, mlen, inv); - lbnCopy_16(result, t, mlen); - /* - * Clean up - free intermediate storage. - * Do NOT free table[0], which is the result - * buffer. - */ - y = 0; -#if BNYIELD -yield: -#endif - while (--tblmask) - LBNFREE(table[tblmask], mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; /* Success */ -} - -/* - * Compute and return n1^e1 * n2^e2 mod "mod". - * result may be either input buffer, or something separate. - * It must be "mlen" words long. - * - * There is a current position in the exponents, which is kept in e1bits. - * (The exponents are swapped if necessary so e1 is the longer of the two.) - * At any given time, the value in the accumulator is - * n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod". - * As e1bits is counted down, this is updated, by squaring it and doing - * any necessary multiplies. - * To decide on the necessary multiplies, two windows, each w1bits+1 bits - * wide, are maintained in buf1 and buf2, which read *ahead* of the - * e1bits position (with appropriate handling of the case when e1bits - * drops below w1bits+1). When the most-significant bit of either window - * becomes set, indicating that something needs to be multiplied by - * the accumulator or it will get out of sync, the window is examined - * to see which power of n1 or n2 to multiply by, and when (possibly - * later, if the power is greater than 1) the multiply should take - * place. Then the multiply and its location are remembered and the - * window is cleared. - * - * If we had every power of n1 in the table, the multiply would always - * be w1bits steps in the future. But we only keep the odd powers, - * so instead of waiting w1bits squarings and then multiplying - * by n1^k, we wait w1bits-k squarings and multiply by n1. - * - * Actually, w2bits can be less than w1bits, but the window is the same - * size, to make it easier to keep track of where we're reading. The - * appropriate number of low-order bits of the window are just ignored. - */ -int -lbnDoubleExpMod_16(BNWORD16 *result, - BNWORD16 const *n1, unsigned n1len, - BNWORD16 const *e1, unsigned e1len, - BNWORD16 const *n2, unsigned n2len, - BNWORD16 const *e2, unsigned e2len, - BNWORD16 *mod, unsigned mlen) -{ - BNWORD16 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)]; - /* Table of odd powers of n1 */ - BNWORD16 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)]; - /* Table of odd powers of n2 */ - unsigned e1bits, e2bits; /* Exponent bits */ - unsigned w1bits, w2bits; /* Window sizes */ - unsigned tblmask; /* Mask of exponentiation window */ - BNWORD16 bitpos; /* Mask of current look-ahead bit */ - unsigned buf1, buf2; /* Buffer of exponent bits */ - unsigned mult1pos, mult2pos; /* Where to do pending multiply */ - BNWORD16 const *mult1, *mult2; /* What to multiply by */ - unsigned i; /* Loop counter */ - int isone; /* Flag: accum. is implicitly one */ - BNWORD16 *a, *b; /* Working buffers/accumulators */ - BNWORD16 *t; /* Pointer into the working buffers */ - BNWORD16 inv; /* mod^-1 modulo 2^16 */ - int y; /* bnYield() result */ - - assert(mlen); - assert(n1len <= mlen); - assert(n2len <= mlen); - - /* First, a couple of trivial cases. */ - e1len = lbnNorm_16(e1, e1len); - e2len = lbnNorm_16(e2, e2len); - - /* Ensure that the first exponent is the longer */ - e1bits = lbnBits_16(e1, e1len); - e2bits = lbnBits_16(e2, e2len); - if (e1bits < e2bits) { - i = e1len; e1len = e2len; e2len = i; - i = e1bits; e1bits = e2bits; e2bits = i; - t = (BNWORD16 *)n1; n1 = n2; n2 = t; - t = (BNWORD16 *)e1; e1 = e2; e2 = t; - } - assert(e1bits >= e2bits); - - /* Handle a trivial case */ - if (!e2len) - return lbnExpMod_16(result, n1, n1len, e1, e1len, mod, mlen); - assert(e2bits); - - /* The code below fucks up if the exponents aren't at least 2 bits */ - if (e1bits == 1) { - assert(e2bits == 1); - - LBNALLOC(a, BNWORD16, n1len+n2len); - if (!a) - return -1; - - lbnMul_16(a, n1, n1len, n2, n2len); - /* Do a direct modular reduction */ - if (n1len + n2len >= mlen) - (void)lbnDiv_16(a+mlen, a, n1len+n2len, mod, mlen); - lbnCopy_16(result, a, mlen); - LBNFREE(a, n1len+n2len); - return 0; - } - - /* Okay, now move the exponent pointers to the most-significant word */ - e1 = BIGLITTLE(e1-e1len, e1+e1len-1); - e2 = BIGLITTLE(e2-e2len, e2+e2len-1); - - /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ - w1bits = 0; - while (e1bits > bnExpModThreshTable[w1bits]) - w1bits++; - w2bits = 0; - while (e2bits > bnExpModThreshTable[w2bits]) - w2bits++; - - assert(w1bits >= w2bits); - - /* Allocate working storage: two product buffers and the tables. */ - LBNALLOC(a, BNWORD16, 2*mlen); - if (!a) - return -1; - LBNALLOC(b, BNWORD16, 2*mlen); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ - tblmask = 1u << w1bits; - /* Use buf2 for its size, temporarily */ - buf2 = 1u << w2bits; - - LBNALLOC(t, BNWORD16, mlen); - if (!t) { - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - return -1; - } - table1[0] = t; - table2[0] = result; - - /* - * Okay, we now have some minimal-sized tables - expand them. - * This is allowed to fail! If so, scale back the table sizes - * and proceed. We allocate both tables at the same time - * so if it fails partway through, they'll both be a reasonable - * size rather than one huge and one tiny. - * When i passes buf2 (the number of entries in the e2 window, - * which may be less than the number of entries in the e1 window), - * stop allocating e2 space. - */ - for (i = 1; i < tblmask; i++) { - LBNALLOC(t, BNWORD16, mlen); - if (!t) /* Out of memory! Quit the loop. */ - break; - table1[i] = t; - if (i < buf2) { - LBNALLOC(t, BNWORD16, mlen); - if (!t) { - LBNFREE(table1[i], mlen); - break; - } - table2[i] = t; - } - } - - /* If we stopped, with i < tblmask, shrink the tables appropriately */ - while (tblmask > i) { - w1bits--; - tblmask >>= 1; - } - /* Free up our overallocations */ - while (--i > tblmask) { - if (i < buf2) - LBNFREE(table2[i], mlen); - LBNFREE(table1[i], mlen); - } - /* And shrink the second window too, if needed */ - if (w2bits > w1bits) { - w2bits = w1bits; - buf2 = tblmask; - } - - /* - * From now on, use the w2bits variable for the difference - * between w1bits and w2bits. - */ - w2bits = w1bits-w2bits; - - /* Okay, fill in the tables */ - - /* Compute the necessary modular inverse */ - inv = lbnMontInv1_16(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - /* Convert n1 to Montgomery form */ - - /* Move n1 up "mlen" words into a */ - t = BIGLITTLE(a-mlen, a+mlen); - lbnCopy_16(t, n1, n1len); - lbnZero_16(a, mlen); - /* Do the division - lose the quotient into the high-order words */ - (void)lbnDiv_16(t, a, mlen+n1len, mod, mlen); - /* Copy into first table entry */ - lbnCopy_16(table1[0], a, mlen); - - /* Square a into b */ - lbnMontSquare_16(b, a, mod, mlen, inv); - - /* Use high half of b to initialize the first table */ - t = BIGLITTLE(b-mlen, b+mlen); - for (i = 1; i < tblmask; i++) { - lbnMontMul_16(a, t, table1[i-1], mod, mlen, inv); - lbnCopy_16(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* Convert n2 to Montgomery form */ - - t = BIGLITTLE(a-mlen, a+mlen); - /* Move n2 up "mlen" words into a */ - lbnCopy_16(t, n2, n2len); - lbnZero_16(a, mlen); - /* Do the division - lose the quotient into the high-order words */ - (void)lbnDiv_16(t, a, mlen+n2len, mod, mlen); - /* Copy into first table entry */ - lbnCopy_16(table2[0], a, mlen); - - /* Square it into a */ - lbnMontSquare_16(a, table2[0], mod, mlen, inv); - /* Copy to b, low half */ - lbnCopy_16(b, t, mlen); - - /* Use b to initialize the second table */ - for (i = 1; i < buf2; i++) { - lbnMontMul_16(a, b, table2[i-1], mod, mlen, inv); - lbnCopy_16(table2[i], t, mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* - * Okay, a recap: at this point, the low part of b holds - * n2^2, the high part holds n1^2, and the tables are - * initialized with the odd powers of n1 and n2 from 1 - * through 2*tblmask-1 and 2*buf2-1. - * - * We might use those squares in b later, or we might not. - */ - - /* Initialze the fetch pointer */ - bitpos = (BNWORD16)1 << ((e1bits-1) & (16-1)); /* Initialize mask */ - - /* This should point to the msbit of e1 */ - assert((*e1 & bitpos) != 0); - - /* - * Pre-load the windows. Becuase the window size is - * never larger than the exponent size, there is no need to - * detect running off the end of e1 in here. - * - * The read-ahead is controlled by e1len and the bitpos mask. - * Note that this is *ahead* of e1bits, which tracks the - * most significant end of the window. The purpose of this - * initialization is to get the two w1bits+1 bits apart, - * like they should be. - * - * Note that bitpos and e1len together keep track of the - * lookahead read pointer in the exponent that is used here. - * e2len is not decremented, it is only ever compared with - * e1len as *that* is decremented. - */ - buf1 = buf2 = 0; - for (i = 0; i <= w1bits; i++) { - buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0); - if (e1len <= e2len) - buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e1++,e1--); - if (e1len <= e2len) - BIGLITTLE(e2++,e2--); - bitpos = (BNWORD16)1 << (16-1); - e1len--; - } - } - assert(buf1 & tblmask); - - /* - * Set the pending multiply positions to a location that will - * never be encountered, thus ensuring that nothing will happen - * until the need for a multiply appears and one is scheduled. - */ - mult1pos = mult2pos = e1bits; /* A NULL value */ - mult1 = mult2 = 0; /* Force a crash if we use these */ - - /* - * Okay, now begins the real work. The first step is - * slightly magic, so it's done outside the main loop, - * but it's very similar to what's inside. - */ - isone = 1; /* Buffer is implicitly 1, so replace * by copy */ - e1bits--; /* Start processing the first bit... */ - - /* - * This is just like the multiply in the loop, except that - * - We know the msbit of buf1 is set, and - * - We have the extra value n1^2 floating around. - * So, do the usual computation, and if the result is that - * the buffer should be multiplied by n1^1 immediately - * (which we'd normally then square), we multiply it - * (which reduces to a copy, which reduces to setting a flag) - * by n1^2 and skip the squaring. Thus, we do the - * multiply and the squaring in one step. - */ - assert(buf1 & tblmask); - mult1pos = e1bits - w1bits; - while ((buf1 & 1) == 0) { - buf1 >>= 1; - mult1pos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(mult1pos <= e1bits); - mult1 = table1[buf1>>1]; - buf1 = 0; - - /* Special case: use already-computed value sitting in buffer */ - if (mult1pos == e1bits) - isone = 0; - - /* - * The first multiply by a power of n2. Similar, but - * we might not even want to schedule a multiply if e2 is - * shorter than e1, and the window might be shorter so - * we have to leave the low w2bits bits alone. - */ - if (buf2 & tblmask) { - /* Remember low-order bits for later */ - i = buf2 & ((1u << w2bits) - 1); - buf2 >>= w2bits; - mult2pos = e1bits - w1bits + w2bits; - while ((buf2 & 1) == 0) { - buf2 >>= 1; - mult2pos++; - } - assert(mult2pos <= e1bits); - mult2 = table2[buf2>>1]; - buf2 = i; - - if (mult2pos == e1bits) { - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - lbnCopy_16(t, b, mlen); /* Copy low to high */ - isone = 0; - } else { - lbnMontMul_16(a, t, b, mod, mlen, inv); - t = a; a = b; b = t; - } - } - } - - /* - * At this point, the buffer (which is the high half of b) - * holds either 1 (implicitly, as the "isone" flag is set), - * n1^2, n2^2 or n1^2 * n2^2. - */ - - /* - * The main loop. The procedure is: - * - Advance the windows - * - If the most-significant bit of a window is set, - * schedule a multiply for the appropriate time in the - * future (may be immediately) - * - Perform any pending multiples - * - Check for termination - * - Square the buffers - * - * At any given time, the acumulated product is held in - * the high half of b. - */ - for (;;) { - e1bits--; - - /* Advance the windows */ - assert(buf1 < tblmask); - buf1 <<= 1; - assert(buf2 < tblmask); - buf2 <<= 1; - /* - * This reads ahead of the current exponent position - * (controlled by e1bits), so we have to be able to read - * past the lsb of the exponents without error. - */ - if (e1len) { - buf1 |= ((*e1 & bitpos) != 0); - if (e1len <= e2len) - buf2 |= ((*e2 & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e1++,e1--); - if (e1len <= e2len) - BIGLITTLE(e2++,e2--); - bitpos = (BNWORD16)1 << (16-1); - e1len--; - } - } - - /* Examine the first window for pending multiplies */ - if (buf1 & tblmask) { - mult1pos = e1bits - w1bits; - while ((buf1 & 1) == 0) { - buf1 >>= 1; - mult1pos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(mult1pos <= e1bits); - mult1 = table1[buf1>>1]; - buf1 = 0; - } - - /* - * Examine the second window for pending multiplies. - * Window 2 can be smaller than window 1, but we - * keep the same number of bits in buf2, so we need - * to ignore any low-order bits in the buffer when - * computing what to multiply by, and recompute them - * later. - */ - if (buf2 & tblmask) { - /* Remember low-order bits for later */ - i = buf2 & ((1u << w2bits) - 1); - buf2 >>= w2bits; - mult2pos = e1bits - w1bits + w2bits; - while ((buf2 & 1) == 0) { - buf2 >>= 1; - mult2pos++; - } - assert(mult2pos <= e1bits); - mult2 = table2[buf2>>1]; - buf2 = i; - } - - - /* If we have a pending multiply for e1, do it */ - if (e1bits == mult1pos) { - /* Multiply by the table entry remembered previously */ - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - /* Multiply by 1 is a trivial case */ - lbnCopy_16(t, mult1, mlen); - isone = 0; - } else { - lbnMontMul_16(a, t, mult1, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } - } - - /* If we have a pending multiply for e2, do it */ - if (e1bits == mult2pos) { - /* Multiply by the table entry remembered previously */ - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - /* Multiply by 1 is a trivial case */ - lbnCopy_16(t, mult2, mlen); - isone = 0; - } else { - lbnMontMul_16(a, t, mult2, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } - } - - /* Are we done? */ - if (!e1bits) - break; - - /* Square the buffer */ - if (!isone) { - t = BIGLITTLE(b-mlen, b+mlen); - lbnMontSquare_16(a, t, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } /* for (;;) */ - - assert(!isone); - assert(!buf1); - assert(!buf2); - - /* DONE! */ - - /* Convert result out of Montgomery form */ - t = BIGLITTLE(b-mlen, b+mlen); - lbnCopy_16(b, t, mlen); - lbnZero_16(t, mlen); - lbnMontReduce_16(b, mod, mlen, inv); - lbnCopy_16(result, t, mlen); - - /* Clean up - free intermediate storage */ - y = 0; -#if BNYIELD -yield: -#endif - buf2 = tblmask >> w2bits; - while (--tblmask) { - if (tblmask < buf2) - LBNFREE(table2[tblmask], mlen); - LBNFREE(table1[tblmask], mlen); - } - t = table1[0]; - LBNFREE(t, mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; /* Success */ -} - -/* - * 2^exp (mod mod). This is an optimized version for use in Fermat - * tests. The input value of n is ignored; it is returned with - * "mlen" words valid. - */ -int -lbnTwoExpMod_16(BNWORD16 *n, BNWORD16 const *exp, unsigned elen, - BNWORD16 *mod, unsigned mlen) -{ - unsigned e; /* Copy of high words of the exponent */ - unsigned bits; /* Assorted counter of bits */ - BNWORD16 const *bitptr; - BNWORD16 bitword, bitpos; - BNWORD16 *a, *b, *a1; - BNWORD16 inv; - int y; /* Result of bnYield() */ - - assert(mlen); - - bitptr = BIGLITTLE(exp-elen, exp+elen-1); - bitword = *bitptr; - assert(bitword); - - /* Clear n for future use. */ - lbnZero_16(n, mlen); - - bits = lbnBits_16(exp, elen); - - /* First, a couple of trivial cases. */ - if (bits <= 1) { - /* 2 ^ 0 == 1, 2 ^ 1 == 2 */ - BIGLITTLE(n[-1],n[0]) = (BNWORD16)1<<elen; - return 0; - } - - /* Set bitpos to the most significant bit */ - bitpos = (BNWORD16)1 << ((bits-1) & (16-1)); - - /* Now, count the bits in the modulus. */ - bits = lbnBits_16(mod, mlen); - assert(bits > 1); /* a 1-bit modulus is just stupid... */ - - /* - * We start with 1<<e, where "e" is as many high bits of the - * exponent as we can manage without going over the modulus. - * This first loop finds "e". - */ - e = 1; - while (elen) { - /* Consume the first bit */ - bitpos >>= 1; - if (!bitpos) { - if (!--elen) - break; - bitword = BIGLITTLE(*++bitptr,*--bitptr); - bitpos = (BNWORD16)1<<(16-1); - } - e = (e << 1) | ((bitpos & bitword) != 0); - if (e >= bits) { /* Overflow! Back out. */ - e >>= 1; - break; - } - } - /* - * The bit in "bitpos" being examined by the bit buffer has NOT - * been consumed yet. This may be past the end of the exponent, - * in which case elen == 1. - */ - - /* Okay, now, set bit "e" in n. n is already zero. */ - inv = (BNWORD16)1 << (e & (16-1)); - e /= 16; - BIGLITTLE(n[-e-1],n[e]) = inv; - /* - * The effective length of n in words is now "e+1". - * This is used a little bit later. - */ - - if (!elen) - return 0; /* That was easy! */ - - /* - * We have now processed the first few bits. The next step - * is to convert this to Montgomery form for further squaring. - */ - - /* Allocate working storage: two product buffers */ - LBNALLOC(a, BNWORD16, 2*mlen); - if (!a) - return -1; - LBNALLOC(b, BNWORD16, 2*mlen); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Convert n to Montgomery form */ - inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */ - assert(inv & 1); /* Modulus must be odd */ - inv = lbnMontInv1_16(inv); - /* Move n (length e+1, remember?) up "mlen" words into b */ - /* Note that we lie about a1 for a bit - it's pointing to b */ - a1 = BIGLITTLE(b-mlen,b+mlen); - lbnCopy_16(a1, n, e+1); - lbnZero_16(b, mlen); - /* Do the division - dump the quotient into the high-order words */ - (void)lbnDiv_16(a1, b, mlen+e+1, mod, mlen); - /* - * Now do the first squaring and modular reduction to put - * the number up in a1 where it belongs. - */ - lbnMontSquare_16(a, b, mod, mlen, inv); - /* Fix up a1 to point to where it should go. */ - a1 = BIGLITTLE(a-mlen,a+mlen); - - /* - * Okay, now, a1 holds the number being accumulated, and - * b is a scratch register. Start working: - */ - for (;;) { - /* - * Is the bit set? If so, double a1 as well. - * A modular doubling like this is very cheap. - */ - if (bitpos & bitword) { - /* - * Double the number. If there was a carry out OR - * the result is greater than the modulus, subract - * the modulus. - */ - if (lbnDouble_16(a1, mlen) || - lbnCmp_16(a1, mod, mlen) > 0) - (void)lbnSubN_16(a1, mod, mlen); - } - - /* Advance to the next exponent bit */ - bitpos >>= 1; - if (!bitpos) { - if (!--elen) - break; /* Done! */ - bitword = BIGLITTLE(*++bitptr,*--bitptr); - bitpos = (BNWORD16)1<<(16-1); - } - - /* - * The elen/bitword/bitpos bit buffer is known to be - * non-empty, i.e. there is at least one more unconsumed bit. - * Thus, it's safe to square the number. - */ - lbnMontSquare_16(b, a1, mod, mlen, inv); - /* Rename result (in b) back to a (a1, really). */ - a1 = b; b = a; a = a1; - a1 = BIGLITTLE(a-mlen,a+mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* DONE! Just a little bit of cleanup... */ - - /* - * Convert result out of Montgomery form... this is - * just a Montgomery reduction. - */ - lbnCopy_16(a, a1, mlen); - lbnZero_16(a1, mlen); - lbnMontReduce_16(a, mod, mlen, inv); - lbnCopy_16(n, a1, mlen); - - /* Clean up - free intermediate storage */ - y = 0; -#if BNYIELD -yield: -#endif - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; /* Success */ -} - - -/* - * Returns a substring of the big-endian array of bytes representation - * of the bignum array based on two parameters, the least significant - * byte number (0 to start with the least significant byte) and the - * length. I.e. the number returned is a representation of - * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). - * - * It is an error if the bignum is not at least buflen + lsbyte bytes - * long. - * - * This code assumes that the compiler has the minimal intelligence - * neded to optimize divides and modulo operations on an unsigned data - * type with a power of two. - */ -void -lbnExtractBigBytes_16(BNWORD16 const *n, unsigned char *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD16 t = 0; /* Needed to shut up uninitialized var warnings */ - unsigned shift; - - lsbyte += buflen; - - shift = (8 * lsbyte) % 16; - lsbyte /= (16/8); /* Convert to word offset */ - BIGLITTLE(n -= lsbyte, n += lsbyte); - - if (shift) - t = BIGLITTLE(n[-1],n[0]); - - while (buflen--) { - if (!shift) { - t = BIGLITTLE(*n++,*--n); - shift = 16; - } - shift -= 8; - *buf++ = (unsigned char)(t>>shift); - } -} - -/* - * Merge a big-endian array of bytes into a bignum array. - * The array had better be big enough. This is - * equivalent to extracting the entire bignum into a - * large byte array, copying the input buffer into the - * middle of it, and converting back to a bignum. - * - * The buf is "len" bytes long, and its *last* byte is at - * position "lsbyte" from the end of the bignum. - * - * Note that this is a pain to get right. Fortunately, it's hardly - * critical for efficiency. - */ -void -lbnInsertBigBytes_16(BNWORD16 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD16 t = 0; /* Shut up uninitialized varibale warnings */ - - lsbyte += buflen; - - BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8)); - - /* Load up leading odd bytes */ - if (lsbyte % (16/8)) { - t = BIGLITTLE(*--n,*n++); - t >>= (lsbyte * 8) % 16; - } - - /* The main loop - merge into t, storing at each word boundary. */ - while (buflen--) { - t = (t << 8) | *buf++; - if ((--lsbyte % (16/8)) == 0) - BIGLITTLE(*n++,*--n) = t; - } - - /* Merge odd bytes in t into last word */ - lsbyte = (lsbyte * 8) % 16; - if (lsbyte) { - t <<= lsbyte; - t |= (((BNWORD16)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); - BIGLITTLE(n[0],n[-1]) = t; - } - - return; -} - -/* - * Returns a substring of the little-endian array of bytes representation - * of the bignum array based on two parameters, the least significant - * byte number (0 to start with the least significant byte) and the - * length. I.e. the number returned is a representation of - * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). - * - * It is an error if the bignum is not at least buflen + lsbyte bytes - * long. - * - * This code assumes that the compiler has the minimal intelligence - * neded to optimize divides and modulo operations on an unsigned data - * type with a power of two. - */ -void -lbnExtractLittleBytes_16(BNWORD16 const *n, unsigned char *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD16 t = 0; /* Needed to shut up uninitialized var warnings */ - - BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8)); - - if (lsbyte % (16/8)) { - t = BIGLITTLE(*--n,*n++); - t >>= (lsbyte % (16/8)) * 8 ; - } - - while (buflen--) { - if ((lsbyte++ % (16/8)) == 0) - t = BIGLITTLE(*--n,*n++); - *buf++ = (unsigned char)t; - t >>= 8; - } -} - -/* - * Merge a little-endian array of bytes into a bignum array. - * The array had better be big enough. This is - * equivalent to extracting the entire bignum into a - * large byte array, copying the input buffer into the - * middle of it, and converting back to a bignum. - * - * The buf is "len" bytes long, and its first byte is at - * position "lsbyte" from the end of the bignum. - * - * Note that this is a pain to get right. Fortunately, it's hardly - * critical for efficiency. - */ -void -lbnInsertLittleBytes_16(BNWORD16 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD16 t = 0; /* Shut up uninitialized varibale warnings */ - - /* Move to most-significant end */ - lsbyte += buflen; - buf += buflen; - - BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8)); - - /* Load up leading odd bytes */ - if (lsbyte % (16/8)) { - t = BIGLITTLE(*--n,*n++); - t >>= (lsbyte * 8) % 16; - } - - /* The main loop - merge into t, storing at each word boundary. */ - while (buflen--) { - t = (t << 8) | *--buf; - if ((--lsbyte % (16/8)) == 0) - BIGLITTLE(*n++,*--n) = t; - } - - /* Merge odd bytes in t into last word */ - lsbyte = (lsbyte * 8) % 16; - if (lsbyte) { - t <<= lsbyte; - t |= (((BNWORD16)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); - BIGLITTLE(n[0],n[-1]) = t; - } - - return; -} - -#ifdef DEADCODE /* This was a precursor to the more flexible lbnExtractBytes */ -/* - * Convert a big-endian array of bytes to a bignum. - * Returns the number of words in the bignum. - * Note the expression "16/8" for the number of bytes per word. - * This is so the word-size adjustment will work. - */ -unsigned -lbnFromBytes_16(BNWORD16 *a, unsigned char const *b, unsigned blen) -{ - BNWORD16 t; - unsigned alen = (blen + (16/8-1))/(16/8); - BIGLITTLE(a -= alen, a += alen); - - while (blen) { - t = 0; - do { - t = t << 8 | *b++; - } while (--blen & (16/8-1)); - BIGLITTLE(*a++,*--a) = t; - } - return alen; -} -#endif - -/* - * Computes the GCD of a and b. Modifies both arguments; when it returns, - * one of them is the GCD and the other is trash. The return value - * indicates which: 0 for a, and 1 for b. The length of the retult is - * returned in rlen. Both inputs must have one extra word of precision. - * alen must be >= blen. - * - * TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B). - * This is based on taking out common powers of 2, then repeatedly: - * gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted. - * gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced. - * It gets less reduction per step, but the steps are much faster than - * the division case. - */ -int -lbnGcd_16(BNWORD16 *a, unsigned alen, BNWORD16 *b, unsigned blen, - unsigned *rlen) -{ -#if BNYIELD - int y; -#endif - assert(alen >= blen); - - while (blen != 0) { - (void)lbnDiv_16(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); - alen = lbnNorm_16(a, blen); - if (alen == 0) { - *rlen = blen; - return 1; - } - (void)lbnDiv_16(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); - blen = lbnNorm_16(b, alen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - return y; -#endif - } - *rlen = alen; - return 0; -} - -/* - * Invert "a" modulo "mod" using the extended Euclidean algorithm. - * Note that this only computes one of the cosequences, and uses the - * theorem that the signs flip every step and the absolute value of - * the cosequence values are always bounded by the modulus to avoid - * having to work with negative numbers. - * gcd(a,mod) had better equal 1. Returns 1 if the GCD is NOT 1. - * a must be one word longer than "mod". It is overwritten with the - * result. - * TODO: Use Richard Schroeppel's *much* faster algorithm. - */ -int -lbnInv_16(BNWORD16 *a, unsigned alen, BNWORD16 const *mod, unsigned mlen) -{ - BNWORD16 *b; /* Hold a copy of mod during GCD reduction */ - BNWORD16 *p; /* Temporary for products added to t0 and t1 */ - BNWORD16 *t0, *t1; /* Inverse accumulators */ - BNWORD16 cy; - unsigned blen, t0len, t1len, plen; - int y; - - alen = lbnNorm_16(a, alen); - if (!alen) - return 1; /* No inverse */ - - mlen = lbnNorm_16(mod, mlen); - - assert (alen <= mlen); - - /* Inverse of 1 is 1 */ - if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) { - lbnZero_16(BIGLITTLE(a-alen,a+alen), mlen-alen); - return 0; - } - - /* Allocate a pile of space */ - LBNALLOC(b, BNWORD16, mlen+1); - if (b) { - /* - * Although products are guaranteed to always be less than the - * modulus, it can involve multiplying two 3-word numbers to - * get a 5-word result, requiring a 6th word to store a 0 - * temporarily. Thus, mlen + 1. - */ - LBNALLOC(p, BNWORD16, mlen+1); - if (p) { - LBNALLOC(t0, BNWORD16, mlen); - if (t0) { - LBNALLOC(t1, BNWORD16, mlen); - if (t1) - goto allocated; - LBNFREE(t0, mlen); - } - LBNFREE(p, mlen+1); - } - LBNFREE(b, mlen+1); - } - return -1; - -allocated: - - /* Set t0 to 1 */ - t0len = 1; - BIGLITTLE(t0[-1],t0[0]) = 1; - - /* b = mod */ - lbnCopy_16(b, mod, mlen); - /* blen = mlen (implicitly) */ - - /* t1 = b / a; b = b % a */ - cy = lbnDiv_16(t1, b, mlen, a, alen); - *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy; - t1len = lbnNorm_16(t1, mlen-alen+1); - blen = lbnNorm_16(b, alen); - - /* while (b > 1) */ - while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD16)1) { - /* q = a / b; a = a % b; */ - if (alen < blen || (alen == blen && lbnCmp_16(a, a, alen) < 0)) - assert(0); - cy = lbnDiv_16(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); - *(BIGLITTLE(a-alen-1,a+alen)) = cy; - plen = lbnNorm_16(BIGLITTLE(a-blen,a+blen), alen-blen+1); - assert(plen); - alen = lbnNorm_16(a, blen); - if (!alen) - goto failure; /* GCD not 1 */ - - /* t0 += q * t1; */ - assert(plen+t1len <= mlen+1); - lbnMul_16(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len); - plen = lbnNorm_16(p, plen + t1len); - assert(plen <= mlen); - if (plen > t0len) { - lbnZero_16(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len); - t0len = plen; - } - cy = lbnAddN_16(t0, p, plen); - if (cy) { - if (t0len > plen) { - cy = lbnAdd1_16(BIGLITTLE(t0-plen,t0+plen), - t0len-plen, cy); - } - if (cy) { - BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy; - t0len++; - } - } - - /* if (a <= 1) return a ? t0 : FAIL; */ - if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD16)1) { - if (alen == 0) - goto failure; /* FAIL */ - assert(t0len <= mlen); - lbnCopy_16(a, t0, t0len); - lbnZero_16(BIGLITTLE(a-t0len, a+t0len), mlen-t0len); - goto success; - } - - /* q = b / a; b = b % a; */ - if (blen < alen || (blen == alen && lbnCmp_16(b, a, alen) < 0)) - assert(0); - cy = lbnDiv_16(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); - *(BIGLITTLE(b-blen-1,b+blen)) = cy; - plen = lbnNorm_16(BIGLITTLE(b-alen,b+alen), blen-alen+1); - assert(plen); - blen = lbnNorm_16(b, alen); - if (!blen) - goto failure; /* GCD not 1 */ - - /* t1 += q * t0; */ - assert(plen+t0len <= mlen+1); - lbnMul_16(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len); - plen = lbnNorm_16(p, plen + t0len); - assert(plen <= mlen); - if (plen > t1len) { - lbnZero_16(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len); - t1len = plen; - } - cy = lbnAddN_16(t1, p, plen); - if (cy) { - if (t1len > plen) { - cy = lbnAdd1_16(BIGLITTLE(t1-plen,t0+plen), - t1len-plen, cy); - } - if (cy) { - BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy; - t1len++; - } - } -#if BNYIELD - if (bnYield && (y = bnYield() < 0)) - goto yield; -#endif - } - - if (!blen) - goto failure; /* gcd(a, mod) != 1 -- FAIL */ - - /* return mod-t1 */ - lbnCopy_16(a, mod, mlen); - assert(t1len <= mlen); - cy = lbnSubN_16(a, t1, t1len); - if (cy) { - assert(mlen > t1len); - cy = lbnSub1_16(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy); - assert(!cy); - } - -success: - LBNFREE(t1, mlen); - LBNFREE(t0, mlen); - LBNFREE(p, mlen+1); - LBNFREE(b, mlen+1); - - return 0; - -failure: /* GCD is not 1 - no inverse exists! */ - y = 1; -#if BNYIELD -yield: -#endif - LBNFREE(t1, mlen); - LBNFREE(t0, mlen); - LBNFREE(p, mlen+1); - LBNFREE(b, mlen+1); - - return y; -} - -/* - * Precompute powers of "a" mod "mod". Compute them every "bits" - * for "n" steps. This is sufficient to compute powers of g with - * exponents up to n*bits bits long, i.e. less than 2^(n*bits). - * - * This assumes that the caller has already initialized "array" to point - * to "n" buffers of size "mlen". - */ -int -lbnBasePrecompBegin_16(BNWORD16 **array, unsigned n, unsigned bits, - BNWORD16 const *g, unsigned glen, BNWORD16 *mod, unsigned mlen) -{ - BNWORD16 *a, *b; /* Temporary double-width accumulators */ - BNWORD16 *a1; /* Pointer to high half of a*/ - BNWORD16 inv; /* Montgomery inverse of LSW of mod */ - BNWORD16 *t; - unsigned i; - - glen = lbnNorm_16(g, glen); - assert(glen); - - assert (mlen == lbnNorm_16(mod, mlen)); - assert (glen <= mlen); - - /* Allocate two temporary buffers, and the array slots */ - LBNALLOC(a, BNWORD16, mlen*2); - if (!a) - return -1; - LBNALLOC(b, BNWORD16, mlen*2); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Okay, all ready */ - - /* Convert n to Montgomery form */ - inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */ - assert(inv & 1); /* Modulus must be odd */ - inv = lbnMontInv1_16(inv); - /* Move g up "mlen" words into a (clearing the low mlen words) */ - a1 = BIGLITTLE(a-mlen,a+mlen); - lbnCopy_16(a1, g, glen); - lbnZero_16(a, mlen); - - /* Do the division - dump the quotient into the high-order words */ - (void)lbnDiv_16(a1, a, mlen+glen, mod, mlen); - - /* Copy the first value into the array */ - t = *array; - lbnCopy_16(t, a, mlen); - a1 = a; /* This first value is *not* shifted up */ - - /* Now compute the remaining n-1 array entries */ - assert(bits); - assert(n); - while (--n) { - i = bits; - do { - /* Square a1 into b1 */ - lbnMontSquare_16(b, a1, mod, mlen, inv); - t = b; b = a; a = t; - a1 = BIGLITTLE(a-mlen, a+mlen); - } while (--i); - t = *++array; - lbnCopy_16(t, a1, mlen); - } - - /* Hooray, we're done. */ - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - return 0; -} - -/* - * result = base^exp (mod mod). "array" is a an array of pointers - * to procomputed powers of base, each 2^bits apart. (I.e. array[i] - * is base^(2^(i*bits))). - * - * The algorithm consists of: - * a = b = (powers of g to be raised to the power 2^bits-1) - * a *= b *= (powers of g to be raised to the power 2^bits-2) - * ... - * a *= b *= (powers of g to be raised to the power 1) - * - * All we do is walk the exponent 2^bits-1 times in groups of "bits" bits, - */ -int -lbnBasePrecompExp_16(BNWORD16 *result, BNWORD16 const * const *array, - unsigned bits, BNWORD16 const *exp, unsigned elen, - BNWORD16 const *mod, unsigned mlen) -{ - BNWORD16 *a, *b, *c, *t; - BNWORD16 *a1, *b1; - int anull, bnull; /* Null flags: values are implicitly 1 */ - unsigned i, j; /* Loop counters */ - unsigned mask; /* Exponent bits to examime */ - BNWORD16 const *eptr; /* Pointer into exp */ - BNWORD16 buf, curbits, nextword; /* Bit-buffer varaibles */ - BNWORD16 inv; /* Inverse of LSW of modulus */ - unsigned ewords; /* Words of exponent left */ - int bufbits; /* Number of valid bits */ - int y = 0; - - mlen = lbnNorm_16(mod, mlen); - assert (mlen); - - elen = lbnNorm_16(exp, elen); - if (!elen) { - lbnZero_16(result, mlen); - BIGLITTLE(result[-1],result[0]) = 1; - return 0; - } - /* - * This could be precomputed, but it's so cheap, and it would require - * making the precomputation structure word-size dependent. - */ - inv = lbnMontInv1_16(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - assert(elen); - - /* - * Allocate three temporary buffers. The current numbers generally - * live in the upper halves of these buffers. - */ - LBNALLOC(a, BNWORD16, mlen*2); - if (a) { - LBNALLOC(b, BNWORD16, mlen*2); - if (b) { - LBNALLOC(c, BNWORD16, mlen*2); - if (c) - goto allocated; - LBNFREE(b, 2*mlen); - } - LBNFREE(a, 2*mlen); - } - return -1; - -allocated: - - anull = bnull = 1; - - mask = (1u<<bits) - 1; - for (i = mask; i; --i) { - /* Set up bit buffer for walking the exponent */ - eptr = exp; - buf = BIGLITTLE(*--eptr, *eptr++); - ewords = elen-1; - bufbits = 16; - for (j = 0; ewords || buf; j++) { - /* Shift down current buffer */ - curbits = buf; - buf >>= bits; - /* If necessary, add next word */ - bufbits -= bits; - if (bufbits < 0 && ewords > 0) { - nextword = BIGLITTLE(*--eptr, *eptr++); - ewords--; - curbits |= nextword << (bufbits+bits); - buf = nextword >> -bufbits; - bufbits += 16; - } - /* If appropriate, multiply b *= array[j] */ - if ((curbits & mask) == i) { - BNWORD16 const *d = array[j]; - - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (bnull) { - lbnCopy_16(b1, d, mlen); - bnull = 0; - } else { - lbnMontMul_16(c, b1, d, mod, mlen, inv); - t = c; c = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield() < 0)) - goto yield; -#endif - } - } - - /* Multiply a *= b */ - if (!bnull) { - a1 = BIGLITTLE(a-mlen-1,a+mlen); - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (anull) { - lbnCopy_16(a1, b1, mlen); - anull = 0; - } else { - lbnMontMul_16(c, a1, b1, mod, mlen, inv); - t = c; c = a; a = t; - } - } - } - - assert(!anull); /* If it were, elen would have been 0 */ - - /* Convert out of Montgomery form and return */ - a1 = BIGLITTLE(a-mlen-1,a+mlen); - lbnCopy_16(a, a1, mlen); - lbnZero_16(a1, mlen); - lbnMontReduce_16(a, mod, mlen, inv); - lbnCopy_16(result, a1, mlen); - -#if BNYIELD -yield: -#endif - LBNFREE(c, 2*mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; -} - -/* - * result = base1^exp1 *base2^exp2 (mod mod). "array1" and "array2" are - * arrays of pointers to procomputed powers of the corresponding bases, - * each 2^bits apart. (I.e. array1[i] is base1^(2^(i*bits))). - * - * Bits must be the same in both. (It could be made adjustable, but it's - * a bit of a pain. Just make them both equal to the larger one.) - * - * The algorithm consists of: - * a = b = (powers of base1 and base2 to be raised to the power 2^bits-1) - * a *= b *= (powers of base1 and base2 to be raised to the power 2^bits-2) - * ... - * a *= b *= (powers of base1 and base2 to be raised to the power 1) - * - * All we do is walk the exponent 2^bits-1 times in groups of "bits" bits, - */ -int -lbnDoubleBasePrecompExp_16(BNWORD16 *result, unsigned bits, - BNWORD16 const * const *array1, BNWORD16 const *exp1, unsigned elen1, - BNWORD16 const * const *array2, BNWORD16 const *exp2, - unsigned elen2, BNWORD16 const *mod, unsigned mlen) -{ - BNWORD16 *a, *b, *c, *t; - BNWORD16 *a1, *b1; - int anull, bnull; /* Null flags: values are implicitly 1 */ - unsigned i, j, k; /* Loop counters */ - unsigned mask; /* Exponent bits to examime */ - BNWORD16 const *eptr; /* Pointer into exp */ - BNWORD16 buf, curbits, nextword; /* Bit-buffer varaibles */ - BNWORD16 inv; /* Inverse of LSW of modulus */ - unsigned ewords; /* Words of exponent left */ - int bufbits; /* Number of valid bits */ - int y = 0; - BNWORD16 const * const *array; - - mlen = lbnNorm_16(mod, mlen); - assert (mlen); - - elen1 = lbnNorm_16(exp1, elen1); - if (!elen1) { - return lbnBasePrecompExp_16(result, array2, bits, exp2, elen2, - mod, mlen); - } - elen2 = lbnNorm_16(exp2, elen2); - if (!elen2) { - return lbnBasePrecompExp_16(result, array1, bits, exp1, elen1, - mod, mlen); - } - /* - * This could be precomputed, but it's so cheap, and it would require - * making the precomputation structure word-size dependent. - */ - inv = lbnMontInv1_16(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - assert(elen1); - assert(elen2); - - /* - * Allocate three temporary buffers. The current numbers generally - * live in the upper halves of these buffers. - */ - LBNALLOC(a, BNWORD16, mlen*2); - if (a) { - LBNALLOC(b, BNWORD16, mlen*2); - if (b) { - LBNALLOC(c, BNWORD16, mlen*2); - if (c) - goto allocated; - LBNFREE(b, 2*mlen); - } - LBNFREE(a, 2*mlen); - } - return -1; - -allocated: - - anull = bnull = 1; - - mask = (1u<<bits) - 1; - for (i = mask; i; --i) { - /* Walk each exponent in turn */ - for (k = 0; k < 2; k++) { - /* Set up the exponent for walking */ - array = k ? array2 : array1; - eptr = k ? exp2 : exp1; - ewords = (k ? elen2 : elen1) - 1; - /* Set up bit buffer for walking the exponent */ - buf = BIGLITTLE(*--eptr, *eptr++); - bufbits = 16; - for (j = 0; ewords || buf; j++) { - /* Shift down current buffer */ - curbits = buf; - buf >>= bits; - /* If necessary, add next word */ - bufbits -= bits; - if (bufbits < 0 && ewords > 0) { - nextword = BIGLITTLE(*--eptr, *eptr++); - ewords--; - curbits |= nextword << (bufbits+bits); - buf = nextword >> -bufbits; - bufbits += 16; - } - /* If appropriate, multiply b *= array[j] */ - if ((curbits & mask) == i) { - BNWORD16 const *d = array[j]; - - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (bnull) { - lbnCopy_16(b1, d, mlen); - bnull = 0; - } else { - lbnMontMul_16(c, b1, d, mod, mlen, inv); - t = c; c = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield() < 0)) - goto yield; -#endif - } - } - } - - /* Multiply a *= b */ - if (!bnull) { - a1 = BIGLITTLE(a-mlen-1,a+mlen); - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (anull) { - lbnCopy_16(a1, b1, mlen); - anull = 0; - } else { - lbnMontMul_16(c, a1, b1, mod, mlen, inv); - t = c; c = a; a = t; - } - } - } - - assert(!anull); /* If it were, elen would have been 0 */ - - /* Convert out of Montgomery form and return */ - a1 = BIGLITTLE(a-mlen-1,a+mlen); - lbnCopy_16(a, a1, mlen); - lbnZero_16(a1, mlen); - lbnMontReduce_16(a, mod, mlen, inv); - lbnCopy_16(result, a1, mlen); - -#if BNYIELD -yield: -#endif - LBNFREE(c, 2*mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; -} diff --git a/jni/libzrtp/sources/bnlib/lbn16.h b/jni/libzrtp/sources/bnlib/lbn16.h deleted file mode 100644 index f2237ceb6..000000000 --- a/jni/libzrtp/sources/bnlib/lbn16.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef LBN16_H -#define LBN16_H - -#include "lbn.h" - -#ifndef BNWORD16 -#error 16-bit bignum library requires a 16-bit data type -#endif - -#ifndef lbnCopy_16 -void lbnCopy_16(BNWORD16 *dest, BNWORD16 const *src, unsigned len); -#endif -#ifndef lbnZero_16 -void lbnZero_16(BNWORD16 *num, unsigned len); -#endif -#ifndef lbnNeg_16 -void lbnNeg_16(BNWORD16 *num, unsigned len); -#endif - -#ifndef lbnAdd1_16 -BNWORD16 lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry); -#endif -#ifndef lbnSub1_16 -BNWORD16 lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow); -#endif - -#ifndef lbnAddN_16 -BNWORD16 lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len); -#endif -#ifndef lbnSubN_16 -BNWORD16 lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len); -#endif - -#ifndef lbnCmp_16 -int lbnCmp_16(BNWORD16 const *num1, BNWORD16 const *num2, unsigned len); -#endif - -#ifndef lbnMulN1_16 -void lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k); -#endif -#ifndef lbnMulAdd1_16 -BNWORD16 -lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k); -#endif -#ifndef lbnMulSub1_16 -BNWORD16 lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k); -#endif - -#ifndef lbnLshift_16 -BNWORD16 lbnLshift_16(BNWORD16 *num, unsigned len, unsigned shift); -#endif -#ifndef lbnDouble_16 -BNWORD16 lbnDouble_16(BNWORD16 *num, unsigned len); -#endif -#ifndef lbnRshift_16 -BNWORD16 lbnRshift_16(BNWORD16 *num, unsigned len, unsigned shift); -#endif - -#ifndef lbnMul_16 -void lbnMul_16(BNWORD16 *prod, BNWORD16 const *num1, unsigned len1, - BNWORD16 const *num2, unsigned len2); -#endif -#ifndef lbnSquare_16 -void lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len); -#endif - -#ifndef lbnNorm_16 -unsigned lbnNorm_16(BNWORD16 const *num, unsigned len); -#endif -#ifndef lbnBits_16 -unsigned lbnBits_16(BNWORD16 const *num, unsigned len); -#endif - -#ifndef lbnExtractBigBytes_16 -void lbnExtractBigBytes_16(BNWORD16 const *bn, unsigned char *buf, - unsigned lsbyte, unsigned buflen); -#endif -#ifndef lbnInsertBigytes_16 -void lbnInsertBigBytes_16(BNWORD16 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen); -#endif -#ifndef lbnExtractLittleBytes_16 -void lbnExtractLittleBytes_16(BNWORD16 const *bn, unsigned char *buf, - unsigned lsbyte, unsigned buflen); -#endif -#ifndef lbnInsertLittleBytes_16 -void lbnInsertLittleBytes_16(BNWORD16 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen); -#endif - -#ifndef lbnDiv21_16 -BNWORD16 lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d); -#endif -#ifndef lbnDiv1_16 -BNWORD16 lbnDiv1_16(BNWORD16 *q, BNWORD16 *rem, - BNWORD16 const *n, unsigned len, BNWORD16 d); -#endif -#ifndef lbnModQ_16 -unsigned lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d); -#endif -#ifndef lbnDiv_16 -BNWORD16 -lbnDiv_16(BNWORD16 *q, BNWORD16 *n, unsigned nlen, BNWORD16 *d, unsigned dlen); -#endif - -#ifndef lbnMontInv1_16 -BNWORD16 lbnMontInv1_16(BNWORD16 const x); -#endif -#ifndef lbnMontReduce_16 -void lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned const mlen, - BNWORD16 inv); -#endif -#ifndef lbnToMont_16 -void lbnToMont_16(BNWORD16 *n, unsigned nlen, BNWORD16 *mod, unsigned mlen); -#endif -#ifndef lbnFromMont_16 -void lbnFromMont_16(BNWORD16 *n, BNWORD16 *mod, unsigned len); -#endif - -#ifndef lbnExpMod_16 -int lbnExpMod_16(BNWORD16 *result, BNWORD16 const *n, unsigned nlen, - BNWORD16 const *exp, unsigned elen, BNWORD16 *mod, unsigned mlen); -#endif -#ifndef lbnDoubleExpMod_16 -int lbnDoubleExpMod_16(BNWORD16 *result, - BNWORD16 const *n1, unsigned n1len, BNWORD16 const *e1, unsigned e1len, - BNWORD16 const *n2, unsigned n2len, BNWORD16 const *e2, unsigned e2len, - BNWORD16 *mod, unsigned mlen); -#endif -#ifndef lbnTwoExpMod_16 -int lbnTwoExpMod_16(BNWORD16 *n, BNWORD16 const *exp, unsigned elen, - BNWORD16 *mod, unsigned mlen); -#endif -#ifndef lbnGcd_16 -int lbnGcd_16(BNWORD16 *a, unsigned alen, BNWORD16 *b, unsigned blen, - unsigned *rlen); -#endif -#ifndef lbnInv_16 -int lbnInv_16(BNWORD16 *a, unsigned alen, BNWORD16 const *mod, unsigned mlen); -#endif - -int lbnBasePrecompBegin_16(BNWORD16 **array, unsigned n, unsigned bits, - BNWORD16 const *g, unsigned glen, BNWORD16 *mod, unsigned mlen); -int lbnBasePrecompExp_16(BNWORD16 *result, BNWORD16 const * const *array, - unsigned bits, BNWORD16 const *exp, unsigned elen, - BNWORD16 const *mod, unsigned mlen); -int lbnDoubleBasePrecompExp_16(BNWORD16 *result, unsigned bits, - BNWORD16 const * const *array1, BNWORD16 const *exp1, unsigned elen1, - BNWORD16 const * const *array2, BNWORD16 const *exp2, - unsigned elen2, BNWORD16 const *mod, unsigned mlen); - -#endif /* LBN16_H */ diff --git a/jni/libzrtp/sources/bnlib/lbn32.c b/jni/libzrtp/sources/bnlib/lbn32.c deleted file mode 100644 index 73fedcb07..000000000 --- a/jni/libzrtp/sources/bnlib/lbn32.c +++ /dev/null @@ -1,4073 +0,0 @@ -/* - * lbn32.c - Low-level bignum routines, 32-bit version. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - * - * NOTE: the magic constants "32" and "64" appear in many places in this - * file, including inside identifiers. Because it is not possible to - * ask "#ifdef" of a macro expansion, it is not possible to use the - * preprocessor to conditionalize these properly. Thus, this file is - * intended to be edited with textual search and replace to produce - * alternate word size versions. Any reference to the number of bits - * in a word must be the string "32", and that string must not appear - * otherwise. Any reference to twice this number must appear as "64", - * which likewise must not appear otherwise. Is that clear? - * - * Remember, when doubling the bit size replace the larger number (64) - * first, then the smaller (32). When halving the bit size, do the - * opposite. Otherwise, things will get wierd. Also, be sure to replace - * every instance that appears. (:%s/foo/bar/g in vi) - * - * These routines work with a pointer to the least-significant end of - * an array of WORD32s. The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros - * defined in lbn.h (which expand to x on a big-edian machine and y on a - * little-endian machine) are used to conditionalize the code to work - * either way. If you have no assembly primitives, it doesn't matter. - * Note that on a big-endian machine, the least-significant-end pointer - * is ONE PAST THE END. The bytes are ptr[-1] through ptr[-len]. - * On little-endian, they are ptr[0] through ptr[len-1]. This makes - * perfect sense if you consider pointers to point *between* bytes rather - * than at them. - * - * Because the array index values are unsigned integers, ptr[-i] - * may not work properly, since the index -i is evaluated as an unsigned, - * and if pointers are wider, zero-extension will produce a positive - * number rahter than the needed negative. The expression used in this - * code, *(ptr-i) will, however, work. (The array syntax is equivalent - * to *(ptr+-i), which is a pretty subtle difference.) - * - * Many of these routines will get very unhappy if fed zero-length inputs. - * They use assert() to enforce this. An higher layer of code must make - * sure that these aren't called with zero-length inputs. - * - * Any of these routines can be replaced with more efficient versions - * elsewhere, by just #defining their names. If one of the names - * is #defined, the C code is not compiled in and no declaration is - * made. Use the BNINCLUDE file to do that. Typically, you compile - * asm subroutines with the same name and just, e.g. - * #define lbnMulAdd1_32 lbnMulAdd1_32 - * - * If you want to write asm routines, start with lbnMulAdd1_32(). - * This is the workhorse of modular exponentiation. lbnMulN1_32() is - * also used a fair bit, although not as much and it's defined in terms - * of lbnMulAdd1_32 if that has a custom version. lbnMulSub1_32 and - * lbnDiv21_32 are used in the usual division and remainder finding. - * (Not the Montgomery reduction used in modular exponentiation, though.) - * Once you have lbnMulAdd1_32 defined, writing the other two should - * be pretty easy. (Just make sure you get the sign of the subtraction - * in lbnMulSub1_32 right - it's dest = dest - source * k.) - * - * The only definitions that absolutely need a double-word (BNWORD64) - * type are lbnMulAdd1_32 and lbnMulSub1_32; if those are provided, - * the rest follows. lbnDiv21_32, however, is a lot slower unless you - * have them, and lbnModQ_32 takes after it. That one is used quite a - * bit for prime sieving. - */ - -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include <bnconfig.h> -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_ASSERT_H -#define NO_ASSERT_H 0 -#endif -#ifndef NO_STRING_H -#define NO_STRING_H 0 -#endif -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 0 -#endif -#ifndef NEED_MEMORY_H -#define NEED_MEMORY_H 0 -#endif - -#if !NO_ASSERT_H -#include <assert.h> -#else -#define assert(x) (void)0 -#endif - -#if !NO_STRING_H -#include <string.h> /* For memcpy */ -#elif HAVE_STRINGS_H -#include <strings.h> -#endif -#if NEED_MEMORY_H -#include <memory.h> -#endif - -#include "lbn.h" -#include "lbn32.h" -#include "lbnmem.h" - -#include "kludge.h" - -#ifndef BNWORD32 -#error 32-bit bignum library requires a 32-bit data type -#endif - -/* If this is defined, include bnYield() calls */ -#if BNYIELD -extern int (*bnYield)(void); /* From bn.c */ -#endif - -/* - * Most of the multiply (and Montgomery reduce) routines use an outer - * loop that iterates over one of the operands - a so-called operand - * scanning approach. One big advantage of this is that the assembly - * support routines are simpler. The loops can be rearranged to have - * an outer loop that iterates over the product, a so-called product - * scanning approach. This has the advantage of writing less data - * and doing fewer adds to memory, so is supposedly faster. Some - * code has been written using a product-scanning approach, but - * it appears to be slower, so it is turned off by default. Some - * experimentation would be appreciated. - * - * (The code is also annoying to get right and not very well commented, - * one of my pet peeves about math libraries. I'm sorry.) - */ -#ifndef PRODUCT_SCAN -#define PRODUCT_SCAN 0 -#endif - -/* - * Copy an array of words. <Marvin mode on> Thrilling, isn't it? </Marvin> - * This is a good example of how the byte offsets and BIGLITTLE() macros work. - * Another alternative would have been - * memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD32)), but I find that - * putting operators into conditional macros is confusing. - */ -#ifndef lbnCopy_32 -void -lbnCopy_32(BNWORD32 *dest, BNWORD32 const *src, unsigned len) -{ - memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src), - len * sizeof(*src)); -} -#endif /* !lbnCopy_32 */ - -/* - * Fill n words with zero. This does it manually rather than calling - * memset because it can assume alignment to make things faster while - * memset can't. Note how big-endian numbers are naturally addressed - * using predecrement, while little-endian is postincrement. - */ -#ifndef lbnZero_32 -void -lbnZero_32(BNWORD32 *num, unsigned len) -{ - while (len--) - BIGLITTLE(*--num,*num++) = 0; -} -#endif /* !lbnZero_32 */ - -/* - * Negate an array of words. - * Negation is subtraction from zero. Negating low-order words - * entails doing nothing until a non-zero word is hit. Once that - * is negated, a borrow is generated and never dies until the end - * of the number is hit. Negation with borrow, -x-1, is the same as ~x. - * Repeat that until the end of the number. - * - * Doesn't return borrow out because that's pretty useless - it's - * always set unless the input is 0, which is easy to notice in - * normalized form. - */ -#ifndef lbnNeg_32 -void -lbnNeg_32(BNWORD32 *num, unsigned len) -{ - assert(len); - - /* Skip low-order zero words */ - while (BIGLITTLE(*--num,*num) == 0) { - if (!--len) - return; - LITTLE(num++;) - } - /* Negate the lowest-order non-zero word */ - *num = -*num; - /* Complement all the higher-order words */ - while (--len) { - BIGLITTLE(--num,++num); - *num = ~*num; - } -} -#endif /* !lbnNeg_32 */ - - -/* - * lbnAdd1_32: add the single-word "carry" to the given number. - * Used for minor increments and propagating the carry after - * adding in a shorter bignum. - * - * Technique: If we have a double-width word, presumably the compiler - * can add using its carry in inline code, so we just use a larger - * accumulator to compute the carry from the first addition. - * If not, it's more complex. After adding the first carry, which may - * be > 1, compare the sum and the carry. If the sum wraps (causing a - * carry out from the addition), the result will be less than each of the - * inputs, since the wrap subtracts a number (2^32) which is larger than - * the other input can possibly be. If the sum is >= the carry input, - * return success immediately. - * In either case, if there is a carry, enter a loop incrementing words - * until one does not wrap. Since we are adding 1 each time, the wrap - * will be to 0 and we can test for equality. - */ -#ifndef lbnAdd1_32 /* If defined, it's provided as an asm subroutine */ -#ifdef BNWORD64 -BNWORD32 -lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry) -{ - BNWORD64 t; - assert(len > 0); /* Alternative: if (!len) return carry */ - - t = (BNWORD64)BIGLITTLE(*--num,*num) + carry; - BIGLITTLE(*num,*num++) = (BNWORD32)t; - if ((t >> 32) == 0) - return 0; - while (--len) { - if (++BIGLITTLE(*--num,*num++) != 0) - return 0; - } - return 1; -} -#else /* no BNWORD64 */ -BNWORD32 -lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry) -{ - assert(len > 0); /* Alternative: if (!len) return carry */ - - if ((BIGLITTLE(*--num,*num++) += carry) >= carry) - return 0; - while (--len) { - if (++BIGLITTLE(*--num,*num++) != 0) - return 0; - } - return 1; -} -#endif -#endif/* !lbnAdd1_32 */ - -/* - * lbnSub1_32: subtract the single-word "borrow" from the given number. - * Used for minor decrements and propagating the borrow after - * subtracting a shorter bignum. - * - * Technique: Similar to the add, above. If there is a double-length type, - * use that to generate the first borrow. - * If not, after subtracting the first borrow, which may be > 1, compare - * the difference and the *negative* of the carry. If the subtract wraps - * (causing a borrow out from the subtraction), the result will be at least - * as large as -borrow. If the result < -borrow, then no borrow out has - * appeared and we may return immediately, except when borrow == 0. To - * deal with that case, use the identity that -x = ~x+1, and instead of - * comparing < -borrow, compare for <= ~borrow. - * Either way, if there is a borrow out, enter a loop decrementing words - * until a non-zero word is reached. - * - * Note the cast of ~borrow to (BNWORD32). If the size of an int is larger - * than BNWORD32, C rules say the number is expanded for the arithmetic, so - * the inversion will be done on an int and the value won't be quite what - * is expected. - */ -#ifndef lbnSub1_32 /* If defined, it's provided as an asm subroutine */ -#ifdef BNWORD64 -BNWORD32 -lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow) -{ - BNWORD64 t; - assert(len > 0); /* Alternative: if (!len) return borrow */ - - t = (BNWORD64)BIGLITTLE(*--num,*num) - borrow; - BIGLITTLE(*num,*num++) = (BNWORD32)t; - if ((t >> 32) == 0) - return 0; - while (--len) { - if ((BIGLITTLE(*--num,*num++))-- != 0) - return 0; - } - return 1; -} -#else /* no BNWORD64 */ -BNWORD32 -lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow) -{ - assert(len > 0); /* Alternative: if (!len) return borrow */ - - if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD32)~borrow) - return 0; - while (--len) { - if ((BIGLITTLE(*--num,*num++))-- != 0) - return 0; - } - return 1; -} -#endif -#endif /* !lbnSub1_32 */ - -/* - * lbnAddN_32: add two bignums of the same length, returning the carry (0 or 1). - * One of the building blocks, along with lbnAdd1, of adding two bignums of - * differing lengths. - * - * Technique: Maintain a word of carry. If there is no double-width type, - * use the same technique as in lbnAdd1, above, to maintain the carry by - * comparing the inputs. Adding the carry sources is used as an OR operator; - * at most one of the two comparisons can possibly be true. The first can - * only be true if carry == 1 and x, the result, is 0. In that case the - * second can't possibly be true. - */ -#ifndef lbnAddN_32 -#ifdef BNWORD64 -BNWORD32 -lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) -{ - BNWORD64 t; - - assert(len > 0); - - t = (BNWORD64)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++); - BIGLITTLE(*num1,*num1++) = (BNWORD32)t; - while (--len) { - t = (BNWORD64)BIGLITTLE(*--num1,*num1) + - (BNWORD64)BIGLITTLE(*--num2,*num2++) + (t >> 32); - BIGLITTLE(*num1,*num1++) = (BNWORD32)t; - } - - return (BNWORD32)(t>>32); -} -#else /* no BNWORD64 */ -BNWORD32 -lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) -{ - BNWORD32 x, carry = 0; - - assert(len > 0); /* Alternative: change loop to test at start */ - - do { - x = BIGLITTLE(*--num2,*num2++); - carry = (x += carry) < carry; - carry += (BIGLITTLE(*--num1,*num1++) += x) < x; - } while (--len); - - return carry; -} -#endif -#endif /* !lbnAddN_32 */ - -/* - * lbnSubN_32: add two bignums of the same length, returning the carry (0 or 1). - * One of the building blocks, along with subn1, of subtracting two bignums of - * differing lengths. - * - * Technique: If no double-width type is availble, maintain a word of borrow. - * First, add the borrow to the subtrahend (did you have to learn all those - * awful words in elementary school, too?), and if it overflows, set the - * borrow again. Then subtract the modified subtrahend from the next word - * of input, using the same technique as in subn1, above. - * Adding the borrows is used as an OR operator; at most one of the two - * comparisons can possibly be true. The first can only be true if - * borrow == 1 and x, the result, is 0. In that case the second can't - * possibly be true. - * - * In the double-word case, (BNWORD32)-(t>>32) is subtracted, rather than - * adding t>>32, because the shift would need to sign-extend and that's - * not guaranteed to happen in ANSI C, even with signed types. - */ -#ifndef lbnSubN_32 -#ifdef BNWORD64 -BNWORD32 -lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) -{ - BNWORD64 t; - - assert(len > 0); - - t = (BNWORD64)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++); - BIGLITTLE(*num1,*num1++) = (BNWORD32)t; - - while (--len) { - t = (BNWORD64)BIGLITTLE(*--num1,*num1) - - (BNWORD64)BIGLITTLE(*--num2,*num2++) - (BNWORD32)-(t >> 32); - BIGLITTLE(*num1,*num1++) = (BNWORD32)t; - } - - return -(BNWORD32)(t>>32); -} -#else -BNWORD32 -lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) -{ - BNWORD32 x, borrow = 0; - - assert(len > 0); /* Alternative: change loop to test at start */ - - do { - x = BIGLITTLE(*--num2,*num2++); - borrow = (x += borrow) < borrow; - borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD32)~x; - } while (--len); - - return borrow; -} -#endif -#endif /* !lbnSubN_32 */ - -#ifndef lbnCmp_32 -/* - * lbnCmp_32: compare two bignums of equal length, returning the sign of - * num1 - num2. (-1, 0 or +1). - * - * Technique: Change the little-endian pointers to big-endian pointers - * and compare from the most-significant end until a difference if found. - * When it is, figure out the sign of the difference and return it. - */ -int -lbnCmp_32(BNWORD32 const *num1, BNWORD32 const *num2, unsigned len) -{ - BIGLITTLE(num1 -= len, num1 += len); - BIGLITTLE(num2 -= len, num2 += len); - - while (len--) { - if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) { - if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2)) - return -1; - else - return 1; - } - } - return 0; -} -#endif /* !lbnCmp_32 */ - -/* - * mul32_ppmmaa(ph,pl,x,y,a,b) is an optional routine that - * computes (ph,pl) = x * y + a + b. mul32_ppmma and mul32_ppmm - * are simpler versions. If you want to be lazy, all of these - * can be defined in terms of the others, so here we create any - * that have not been defined in terms of the ones that have been. - */ - -/* Define ones with fewer a's in terms of ones with more a's */ -#if !defined(mul32_ppmma) && defined(mul32_ppmmaa) -#define mul32_ppmma(ph,pl,x,y,a) mul32_ppmmaa(ph,pl,x,y,a,0) -#endif - -#if !defined(mul32_ppmm) && defined(mul32_ppmma) -#define mul32_ppmm(ph,pl,x,y) mul32_ppmma(ph,pl,x,y,0) -#endif - -/* - * Use this definition to test the mul32_ppmm-based operations on machines - * that do not provide mul32_ppmm. Change the final "0" to a "1" to - * enable it. - */ -#if !defined(mul32_ppmm) && defined(BNWORD64) && 0 /* Debugging */ -#define mul32_ppmm(ph,pl,x,y) \ - ({BNWORD64 _ = (BNWORD64)(x)*(y); (pl) = _; (ph) = _>>32;}) -#endif - -#if defined(mul32_ppmm) && !defined(mul32_ppmma) -#define mul32_ppmma(ph,pl,x,y,a) \ - (mul32_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a)) -#endif - -#if defined(mul32_ppmma) && !defined(mul32_ppmmaa) -#define mul32_ppmmaa(ph,pl,x,y,a,b) \ - (mul32_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b)) -#endif - -/* - * lbnMulN1_32: Multiply an n-word input by a 1-word input and store the - * n+1-word product. This uses either the mul32_ppmm and mul32_ppmma - * macros, or C multiplication with the BNWORD64 type. This uses mul32_ppmma - * if available, assuming you won't bother defining it unless you can do - * better than the normal multiplication. - */ -#ifndef lbnMulN1_32 -#ifdef lbnMulAdd1_32 /* If we have this asm primitive, use it. */ -void -lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) -{ - lbnZero_32(out, len); - BIGLITTLE(*(out-len-1),*(out+len)) = lbnMulAdd1_32(out, in, len, k); -} -#elif defined(mul32_ppmm) -void -lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) -{ - BNWORD32 carry, carryin; - - assert(len > 0); - - BIG(--out;--in;); - mul32_ppmm(carry, *out, *in, k); - LITTLE(out++;in++;) - - while (--len) { - BIG(--out;--in;) - carryin = carry; - mul32_ppmma(carry, *out, *in, k, carryin); - LITTLE(out++;in++;) - } - BIGLITTLE(*--out,*out) = carry; -} -#elif defined(BNWORD64) -void -lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) -{ - BNWORD64 p; - - assert(len > 0); - - p = (BNWORD64)BIGLITTLE(*--in,*in++) * k; - BIGLITTLE(*--out,*out++) = (BNWORD32)p; - - while (--len) { - p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + (BNWORD32)(p >> 32); - BIGLITTLE(*--out,*out++) = (BNWORD32)p; - } - BIGLITTLE(*--out,*out) = (BNWORD32)(p >> 32); -} -#else -#error No 32x32 -> 64 multiply available for 32-bit bignum package -#endif -#endif /* lbnMulN1_32 */ - -/* - * lbnMulAdd1_32: Multiply an n-word input by a 1-word input and add the - * low n words of the product to the destination. *Returns the n+1st word - * of the product.* (That turns out to be more convenient than adding - * it into the destination and dealing with a possible unit carry out - * of *that*.) This uses either the mul32_ppmma and mul32_ppmmaa macros, - * or C multiplication with the BNWORD64 type. - * - * If you're going to write assembly primitives, this is the one to - * start with. It is by far the most commonly called function. - */ -#ifndef lbnMulAdd1_32 -#if defined(mul32_ppmm) -BNWORD32 -lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) -{ - BNWORD32 prod, carry, carryin; - - assert(len > 0); - - BIG(--out;--in;); - carryin = *out; - mul32_ppmma(carry, *out, *in, k, carryin); - LITTLE(out++;in++;) - - while (--len) { - BIG(--out;--in;); - carryin = carry; - mul32_ppmmaa(carry, prod, *in, k, carryin, *out); - *out = prod; - LITTLE(out++;in++;) - } - - return carry; -} -#elif defined(BNWORD64) -BNWORD32 -lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) -{ - BNWORD64 p; - - assert(len > 0); - - p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out); - BIGLITTLE(*out,*out++) = (BNWORD32)p; - - while (--len) { - p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + - (BNWORD32)(p >> 32) + BIGLITTLE(*--out,*out); - BIGLITTLE(*out,*out++) = (BNWORD32)p; - } - - return (BNWORD32)(p >> 32); -} -#else -#error No 32x32 -> 64 multiply available for 32-bit bignum package -#endif -#endif /* lbnMulAdd1_32 */ - -/* - * lbnMulSub1_32: Multiply an n-word input by a 1-word input and subtract the - * n-word product from the destination. Returns the n+1st word of the product. - * This uses either the mul32_ppmm and mul32_ppmma macros, or - * C multiplication with the BNWORD64 type. - * - * This is rather uglier than adding, but fortunately it's only used in - * division which is not used too heavily. - */ -#ifndef lbnMulSub1_32 -#if defined(mul32_ppmm) -BNWORD32 -lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) -{ - BNWORD32 prod, carry, carryin; - - assert(len > 0); - - BIG(--in;) - mul32_ppmm(carry, prod, *in, k); - LITTLE(in++;) - carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD32)~prod; - - while (--len) { - BIG(--in;); - carryin = carry; - mul32_ppmma(carry, prod, *in, k, carryin); - LITTLE(in++;) - carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD32)~prod; - } - - return carry; -} -#elif defined(BNWORD64) -BNWORD32 -lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) -{ - BNWORD64 p; - BNWORD32 carry, t; - - assert(len > 0); - - p = (BNWORD64)BIGLITTLE(*--in,*in++) * k; - t = BIGLITTLE(*--out,*out); - carry = (BNWORD32)(p>>32) + ((BIGLITTLE(*out,*out++)=t-(BNWORD32)p) > t); - - while (--len) { - p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + carry; - t = BIGLITTLE(*--out,*out); - carry = (BNWORD32)(p>>32) + - ( (BIGLITTLE(*out,*out++)=t-(BNWORD32)p) > t ); - } - - return carry; -} -#else -#error No 32x32 -> 64 multiply available for 32-bit bignum package -#endif -#endif /* !lbnMulSub1_32 */ - -/* - * Shift n words left "shift" bits. 0 < shift < 32. Returns the - * carry, any bits shifted off the left-hand side (0 <= carry < 2^shift). - */ -#ifndef lbnLshift_32 -BNWORD32 -lbnLshift_32(BNWORD32 *num, unsigned len, unsigned shift) -{ - BNWORD32 x, carry; - - assert(shift > 0); - assert(shift < 32); - - carry = 0; - while (len--) { - BIG(--num;) - x = *num; - *num = (x<<shift) | carry; - LITTLE(num++;) - carry = x >> (32-shift); - } - return carry; -} -#endif /* !lbnLshift_32 */ - -/* - * An optimized version of the above, for shifts of 1. - * Some machines can use add-with-carry tricks for this. - */ -#ifndef lbnDouble_32 -BNWORD32 -lbnDouble_32(BNWORD32 *num, unsigned len) -{ - BNWORD32 x, carry; - - carry = 0; - while (len--) { - BIG(--num;) - x = *num; - *num = (x<<1) | carry; - LITTLE(num++;) - carry = x >> (32-1); - } - return carry; -} -#endif /* !lbnDouble_32 */ - -/* - * Shift n words right "shift" bits. 0 < shift < 32. Returns the - * carry, any bits shifted off the right-hand side (0 <= carry < 2^shift). - */ -#ifndef lbnRshift_32 -BNWORD32 -lbnRshift_32(BNWORD32 *num, unsigned len, unsigned shift) -{ - BNWORD32 x, carry = 0; - - assert(shift > 0); - assert(shift < 32); - - BIGLITTLE(num -= len, num += len); - - while (len--) { - LITTLE(--num;) - x = *num; - *num = (x>>shift) | carry; - BIG(num++;) - carry = x << (32-shift); - } - return carry >> (32-shift); -} -#endif /* !lbnRshift_32 */ - -/* - * Multiply two numbers of the given lengths. prod and num2 may overlap, - * provided that the low len1 bits of prod are free. (This corresponds - * nicely to the place the result is returned from lbnMontReduce_32.) - * - * TODO: Use Karatsuba multiply. The overlap constraints may have - * to get rewhacked. - */ -#ifndef lbnMul_32 -void -lbnMul_32(BNWORD32 *prod, BNWORD32 const *num1, unsigned len1, - BNWORD32 const *num2, unsigned len2) -{ - /* Special case of zero */ - if (!len1 || !len2) { - lbnZero_32(prod, len1+len2); - return; - } - - /* Multiply first word */ - lbnMulN1_32(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); - - /* - * Add in subsequent words, storing the most significant word, - * which is new each time. - */ - while (--len2) { - BIGLITTLE(--prod,prod++); - BIGLITTLE(*(prod-len1-1),*(prod+len1)) = - lbnMulAdd1_32(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); - } -} -#endif /* !lbnMul_32 */ - -/* - * lbnMulX_32 is a square multiply - both inputs are the same length. - * It's normally just a macro wrapper around the general multiply, - * but might be implementable in assembly more efficiently (such as - * when product scanning). - */ -#ifndef lbnMulX_32 -#if defined(BNWORD64) && PRODUCT_SCAN -/* - * Test code to see whether product scanning is any faster. It seems - * to make the C code slower, so PRODUCT_SCAN is not defined. - */ -static void -lbnMulX_32(BNWORD32 *prod, BNWORD32 const *num1, BNWORD32 const *num2, - unsigned len) -{ - BNWORD64 x, y; - BNWORD32 const *p1, *p2; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!len) - return; - - x = (BNWORD64)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); - BIGLITTLE(*--prod, *prod++) = (BNWORD32)x; - x >>= 32; - - for (i = 1; i < len; i++) { - carry = 0; - p1 = num1; - p2 = BIGLITTLE(num2-i-1,num2+i+1); - for (j = 0; j <= i; j++) { - BIG(y = (BNWORD64)*--p1 * *p2++;) - LITTLE(y = (BNWORD64)*p1++ * *--p2;) - x += y; - carry += (x < y); - } - BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; - x = (x >> 32) | (BNWORD64)carry << 32; - } - for (i = 1; i < len; i++) { - carry = 0; - p1 = BIGLITTLE(num1-i,num1+i); - p2 = BIGLITTLE(num2-len,num2+len); - for (j = i; j < len; j++) { - BIG(y = (BNWORD64)*--p1 * *p2++;) - LITTLE(y = (BNWORD64)*p1++ * *--p2;) - x += y; - carry += (x < y); - } - BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; - x = (x >> 32) | (BNWORD64)carry << 32; - } - - BIGLITTLE(*--prod,*prod) = (BNWORD32)x; -} -#else /* !defined(BNWORD64) || !PRODUCT_SCAN */ -/* Default trivial macro definition */ -#define lbnMulX_32(prod, num1, num2, len) lbnMul_32(prod, num1, len, num2, len) -#endif /* !defined(BNWORD64) || !PRODUCT_SCAN */ -#endif /* !lbmMulX_32 */ - -#if !defined(lbnMontMul_32) && defined(BNWORD64) && PRODUCT_SCAN -/* - * Test code for product-scanning multiply. This seems to slow the C - * code down rather than speed it up. - * This does a multiply and Montgomery reduction together, using the - * same loops. The outer loop scans across the product, twice. - * The first pass computes the low half of the product and the - * Montgomery multipliers. These are stored in the product array, - * which contains no data as of yet. x and carry add up the columns - * and propagate carries forward. - * - * The second half multiplies the upper half, adding in the modulus - * times the Montgomery multipliers. The results of this multiply - * are stored. - */ -static void -lbnMontMul_32(BNWORD32 *prod, BNWORD32 const *num1, BNWORD32 const *num2, - BNWORD32 const *mod, unsigned len, BNWORD32 inv) -{ - BNWORD64 x, y; - BNWORD32 const *p1, *p2, *pm; - BNWORD32 *pp; - BNWORD32 t; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!len) - return; - - /* - * This computes directly into the high half of prod, so just - * shift the pointer and consider prod only "len" elements long - * for the rest of the code. - */ - BIGLITTLE(prod -= len, prod += len); - - /* Pass 1 - compute Montgomery multipliers */ - /* First iteration can have certain simplifications. */ - x = (BNWORD64)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); - BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD32)x; - y = (BNWORD64)t * BIGLITTLE(mod[-1],mod[0]); - x += y; - /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */ - carry = (x < y); - assert((BNWORD32)x == 0); - x = x >> 32 | (BNWORD64)carry << 32; - - for (i = 1; i < len; i++) { - carry = 0; - p1 = num1; - p2 = BIGLITTLE(num2-i-1,num2+i+1); - pp = prod; - pm = BIGLITTLE(mod-i-1,mod+i+1); - for (j = 0; j < i; j++) { - y = (BNWORD64)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); - x += y; - carry += (x < y); - y = (BNWORD64)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm); - x += y; - carry += (x < y); - } - y = (BNWORD64)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]); - x += y; - carry += (x < y); - assert(BIGLITTLE(pp == prod-i, pp == prod+i)); - BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD32)x; - assert(BIGLITTLE(pm == mod-1, pm == mod+1)); - y = (BNWORD64)t * BIGLITTLE(pm[0],pm[-1]); - x += y; - carry += (x < y); - assert((BNWORD32)x == 0); - x = x >> 32 | (BNWORD64)carry << 32; - } - - /* Pass 2 - compute reduced product and store */ - for (i = 1; i < len; i++) { - carry = 0; - p1 = BIGLITTLE(num1-i,num1+i); - p2 = BIGLITTLE(num2-len,num2+len); - pm = BIGLITTLE(mod-i,mod+i); - pp = BIGLITTLE(prod-len,prod+len); - for (j = i; j < len; j++) { - y = (BNWORD64)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); - x += y; - carry += (x < y); - y = (BNWORD64)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp); - x += y; - carry += (x < y); - } - assert(BIGLITTLE(pm == mod-len, pm == mod+len)); - assert(BIGLITTLE(pp == prod-i, pp == prod+i)); - BIGLITTLE(pp[0],pp[-1]) = (BNWORD32)x; - x = (x >> 32) | (BNWORD64)carry << 32; - } - - /* Last round of second half, simplified. */ - BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD32)x; - carry = (x >> 32); - - while (carry) - carry -= lbnSubN_32(prod, mod, len); - while (lbnCmp_32(prod, mod, len) >= 0) - (void)lbnSubN_32(prod, mod, len); -} -/* Suppress later definition */ -#define lbnMontMul_32 lbnMontMul_32 -#endif - -#if !defined(lbnSquare_32) && defined(BNWORD64) && PRODUCT_SCAN -/* - * Trial code for product-scanning squaring. This seems to slow the C - * code down rather than speed it up. - */ -void -lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len) -{ - BNWORD64 x, y, z; - BNWORD32 const *p1, *p2; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!len) - return; - - /* Word 0 of product */ - x = (BNWORD64)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]); - BIGLITTLE(*--prod, *prod++) = (BNWORD32)x; - x >>= 32; - - /* Words 1 through len-1 */ - for (i = 1; i < len; i++) { - carry = 0; - y = 0; - p1 = num; - p2 = BIGLITTLE(num-i-1,num+i+1); - for (j = 0; j < (i+1)/2; j++) { - BIG(z = (BNWORD64)*--p1 * *p2++;) - LITTLE(z = (BNWORD64)*p1++ * *--p2;) - y += z; - carry += (y < z); - } - y += z = y; - carry += carry + (y < z); - if ((i & 1) == 0) { - assert(BIGLITTLE(--p1 == p2, p1 == --p2)); - BIG(z = (BNWORD64)*p2 * *p2;) - LITTLE(z = (BNWORD64)*p1 * *p1;) - y += z; - carry += (y < z); - } - x += y; - carry += (x < y); - BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; - x = (x >> 32) | (BNWORD64)carry << 32; - } - /* Words len through 2*len-2 */ - for (i = 1; i < len; i++) { - carry = 0; - y = 0; - p1 = BIGLITTLE(num-i,num+i); - p2 = BIGLITTLE(num-len,num+len); - for (j = 0; j < (len-i)/2; j++) { - BIG(z = (BNWORD64)*--p1 * *p2++;) - LITTLE(z = (BNWORD64)*p1++ * *--p2;) - y += z; - carry += (y < z); - } - y += z = y; - carry += carry + (y < z); - if ((len-i) & 1) { - assert(BIGLITTLE(--p1 == p2, p1 == --p2)); - BIG(z = (BNWORD64)*p2 * *p2;) - LITTLE(z = (BNWORD64)*p1 * *p1;) - y += z; - carry += (y < z); - } - x += y; - carry += (x < y); - BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; - x = (x >> 32) | (BNWORD64)carry << 32; - } - - /* Word 2*len-1 */ - BIGLITTLE(*--prod,*prod) = (BNWORD32)x; -} -/* Suppress later definition */ -#define lbnSquare_32 lbnSquare_32 -#endif - -/* - * Square a number, using optimized squaring to reduce the number of - * primitive multiples that are executed. There may not be any - * overlap of the input and output. - * - * Technique: Consider the partial products in the multiplication - * of "abcde" by itself: - * - * a b c d e - * * a b c d e - * ================== - * ae be ce de ee - * ad bd cd dd de - * ac bc cc cd ce - * ab bb bc bd be - * aa ab ac ad ae - * - * Note that everything above the main diagonal: - * ae be ce de = (abcd) * e - * ad bd cd = (abc) * d - * ac bc = (ab) * c - * ab = (a) * b - * - * is a copy of everything below the main diagonal: - * de - * cd ce - * bc bd be - * ab ac ad ae - * - * Thus, the sum is 2 * (off the diagonal) + diagonal. - * - * This is accumulated beginning with the diagonal (which - * consist of the squares of the digits of the input), which is then - * divided by two, the off-diagonal added, and multiplied by two - * again. The low bit is simply a copy of the low bit of the - * input, so it doesn't need special care. - * - * TODO: Merge the shift by 1 with the squaring loop. - * TODO: Use Karatsuba. (a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W. - */ -#ifndef lbnSquare_32 -void -lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len) -{ - BNWORD32 t; - BNWORD32 *prodx = prod; /* Working copy of the argument */ - BNWORD32 const *numx = num; /* Working copy of the argument */ - unsigned lenx = len; /* Working copy of the argument */ - - if (!len) - return; - - /* First, store all the squares */ - while (lenx--) { -#ifdef mul32_ppmm - BNWORD32 ph, pl; - t = BIGLITTLE(*--numx,*numx++); - mul32_ppmm(ph,pl,t,t); - BIGLITTLE(*--prodx,*prodx++) = pl; - BIGLITTLE(*--prodx,*prodx++) = ph; -#elif defined(BNWORD64) /* use BNWORD64 */ - BNWORD64 p; - t = BIGLITTLE(*--numx,*numx++); - p = (BNWORD64)t * t; - BIGLITTLE(*--prodx,*prodx++) = (BNWORD32)p; - BIGLITTLE(*--prodx,*prodx++) = (BNWORD32)(p>>32); -#else /* Use lbnMulN1_32 */ - t = BIGLITTLE(numx[-1],*numx); - lbnMulN1_32(prodx, numx, 1, t); - BIGLITTLE(--numx,numx++); - BIGLITTLE(prodx -= 2, prodx += 2); -#endif - } - /* Then, shift right 1 bit */ - (void)lbnRshift_32(prod, 2*len, 1); - - /* Then, add in the off-diagonal sums */ - lenx = len; - numx = num; - prodx = prod; - while (--lenx) { - t = BIGLITTLE(*--numx,*numx++); - BIGLITTLE(--prodx,prodx++); - t = lbnMulAdd1_32(prodx, numx, lenx, t); - lbnAdd1_32(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t); - BIGLITTLE(--prodx,prodx++); - } - - /* Shift it back up */ - lbnDouble_32(prod, 2*len); - - /* And set the low bit appropriately */ - BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1; -} -#endif /* !lbnSquare_32 */ - -/* - * lbnNorm_32 - given a number, return a modified length such that the - * most significant digit is non-zero. Zero-length input is okay. - */ -#ifndef lbnNorm_32 -unsigned -lbnNorm_32(BNWORD32 const *num, unsigned len) -{ - BIGLITTLE(num -= len,num += len); - while (len && BIGLITTLE(*num++,*--num) == 0) - --len; - return len; -} -#endif /* lbnNorm_32 */ - -/* - * lbnBits_32 - return the number of significant bits in the array. - * It starts by normalizing the array. Zero-length input is okay. - * Then assuming there's anything to it, it fetches the high word, - * generates a bit length by multiplying the word length by 32, and - * subtracts off 32/2, 32/4, 32/8, ... bits if the high bits are clear. - */ -#ifndef lbnBits_32 -unsigned -lbnBits_32(BNWORD32 const *num, unsigned len) -{ - BNWORD32 t; - unsigned i; - - len = lbnNorm_32(num, len); - if (len) { - t = BIGLITTLE(*(num-len),*(num+(len-1))); - assert(t); - len *= 32; - i = 32/2; - do { - if (t >> i) - t >>= i; - else - len -= i; - } while ((i /= 2) != 0); - } - return len; -} -#endif /* lbnBits_32 */ - -/* - * If defined, use hand-rolled divide rather than compiler's native. - * If the machine doesn't do it in line, the manual code is probably - * faster, since it can assume normalization and the fact that the - * quotient will fit into 32 bits, which a general 64-bit divide - * in a compiler's run-time library can't do. - */ -#ifndef BN_SLOW_DIVIDE_64 -/* Assume that divisors of more than thirty-two bits are slow */ -#define BN_SLOW_DIVIDE_64 (64 > 0x20) -#endif - -/* - * Return (nh<<32|nl) % d, and place the quotient digit into *q. - * It is guaranteed that nh < d, and that d is normalized (with its high - * bit set). If we have a double-width type, it's easy. If not, ooh, - * yuk! - */ -#ifndef lbnDiv21_32 -#if defined(BNWORD64) && !BN_SLOW_DIVIDE_64 -BNWORD32 -lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d) -{ - BNWORD64 n = (BNWORD64)nh << 32 | nl; - - /* Divisor must be normalized */ - assert(d >> (32-1) == 1); - - *q = n / d; - return n % d; -} -#else -/* - * This is where it gets ugly. - * - * Do the division in two halves, using Algorithm D from section 4.3.1 - * of Knuth. Note Theorem B from that section, that the quotient estimate - * is never more than the true quotient, and is never more than two - * too low. - * - * The mapping onto conventional long division is (everything a half word): - * _____________qh___ql_ - * dh dl ) nh.h nh.l nl.h nl.l - * - (qh * d) - * ----------- - * rrrr rrrr nl.l - * - (ql * d) - * ----------- - * rrrr rrrr - * - * The implicit 3/2-digit d*qh and d*ql subtractors are computed this way: - * First, estimate a q digit so that nh/dh works. Subtracting qh*dh from - * the (nh.h nh.l) list leaves a 1/2-word remainder r. Then compute the - * low part of the subtractor, qh * dl. This also needs to be subtracted - * from (nh.h nh.l nl.h) to get the final remainder. So we take the - * remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and - * try to subtract qh * dl from that. Since the remainder is 1/2-word - * long, shifting and adding nl.h results in a single word r. - * It is possible that the remainder we're working with, r, is less than - * the product qh * dl, if we estimated qh too high. The estimation - * technique can produce a qh that is too large (never too small), leading - * to r which is too small. In that case, decrement the digit qh, add - * shifted dh to r (to correct for that error), and subtract dl from the - * product we're comparing r with. That's the "correct" way to do it, but - * just adding dl to r instead of subtracting it from the product is - * equivalent and a lot simpler. You just have to watch out for overflow. - * - * The process is repeated with (rrrr rrrr nl.l) for the low digit of the - * quotient ql. - * - * The various uses of 32/2 for shifts are because of the note about - * automatic editing of this file at the very top of the file. - */ -#define highhalf(x) ( (x) >> 32/2 ) -#define lowhalf(x) ( (x) & (((BNWORD32)1 << 32/2)-1) ) -BNWORD32 -lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d) -{ - BNWORD32 dh = highhalf(d), dl = lowhalf(d); - BNWORD32 qh, ql, prod, r; - - /* Divisor must be normalized */ - assert((d >> (32-1)) == 1); - - /* Do first half-word of division */ - qh = nh / dh; - r = nh % dh; - prod = qh * dl; - - /* - * Add next half-word of numerator to remainder and correct. - * qh may be up to two too large. - */ - r = (r << (32/2)) | highhalf(nl); - if (r < prod) { - --qh; r += d; - if (r >= d && r < prod) { - --qh; r += d; - } - } - r -= prod; - - /* Do second half-word of division */ - ql = r / dh; - r = r % dh; - prod = ql * dl; - - r = (r << (32/2)) | lowhalf(nl); - if (r < prod) { - --ql; r += d; - if (r >= d && r < prod) { - --ql; r += d; - } - } - r -= prod; - - *q = (qh << (32/2)) | ql; - - return r; -} -#endif -#endif /* lbnDiv21_32 */ - - -/* - * In the division functions, the dividend and divisor are referred to - * as "n" and "d", which stand for "numerator" and "denominator". - * - * The quotient is (nlen-dlen+1) digits long. It may be overlapped with - * the high (nlen-dlen) words of the dividend, but one extra word is needed - * on top to hold the top word. - */ - -/* - * Divide an n-word number by a 1-word number, storing the remainder - * and n-1 words of the n-word quotient. The high word is returned. - * It IS legal for rem to point to the same address as n, and for - * q to point one word higher. - * - * TODO: If BN_SLOW_DIVIDE_64, add a divnhalf_32 which uses 32-bit - * dividends if the divisor is half that long. - * TODO: Shift the dividend on the fly to avoid the last division and - * instead have a remainder that needs shifting. - * TODO: Use reciprocals rather than dividing. - */ -#ifndef lbnDiv1_32 -BNWORD32 -lbnDiv1_32(BNWORD32 *q, BNWORD32 *rem, BNWORD32 const *n, unsigned len, - BNWORD32 d) -{ - unsigned shift; - unsigned xlen; - BNWORD32 r; - BNWORD32 qhigh; - - assert(len > 0); - assert(d); - - if (len == 1) { - r = *n; - *rem = r%d; - return r/d; - } - - shift = 0; - r = d; - xlen = 32/2; - do { - if (r >> xlen) - r >>= xlen; - else - shift += xlen; - } while ((xlen /= 2) != 0); - assert((d >> (32-1-shift)) == 1); - d <<= shift; - - BIGLITTLE(q -= len-1,q += len-1); - BIGLITTLE(n -= len,n += len); - - r = BIGLITTLE(*n++,*--n); - if (r < d) { - qhigh = 0; - } else { - qhigh = r/d; - r %= d; - } - - xlen = len; - while (--xlen) - r = lbnDiv21_32(BIGLITTLE(q++,--q), r, BIGLITTLE(*n++,*--n), d); - - /* - * Final correction for shift - shift the quotient up "shift" - * bits, and merge in the extra bits of quotient. Then reduce - * the final remainder mod the real d. - */ - if (shift) { - d >>= shift; - qhigh = (qhigh << shift) | lbnLshift_32(q, len-1, shift); - BIGLITTLE(q[-1],*q) |= r/d; - r %= d; - } - *rem = r; - - return qhigh; -} -#endif - -/* - * This function performs a "quick" modulus of a number with a divisor - * d which is guaranteed to be at most sixteen bits, i.e. less than 65536. - * This applies regardless of the word size the library is compiled with. - * - * This function is important to prime generation, for sieving. - */ -#ifndef lbnModQ_32 -/* If there's a custom lbnMod21_32, no normalization needed */ -#ifdef lbnMod21_32 -unsigned -lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) -{ - unsigned i, shift; - BNWORD32 r; - - assert(len > 0); - - BIGLITTLE(n -= len,n += len); - - /* Try using a compare to avoid the first divide */ - r = BIGLITTLE(*n++,*--n); - if (r >= d) - r %= d; - while (--len) - r = lbnMod21_32(r, BIGLITTLE(*n++,*--n), d); - - return r; -} -#elif defined(BNWORD64) && !BN_SLOW_DIVIDE_64 -unsigned -lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) -{ - BNWORD32 r; - - if (!--len) - return BIGLITTLE(n[-1],n[0]) % d; - - BIGLITTLE(n -= len,n += len); - r = BIGLITTLE(n[-1],n[0]); - - do { - r = (BNWORD32)((((BNWORD64)r<<32) | BIGLITTLE(*n++,*--n)) % d); - } while (--len); - - return r; -} -#elif 32 >= 0x20 -/* - * If the single word size can hold 65535*65536, then this function - * is avilable. - */ -#ifndef highhalf -#define highhalf(x) ( (x) >> 32/2 ) -#define lowhalf(x) ( (x) & ((1 << 32/2)-1) ) -#endif -unsigned -lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) -{ - BNWORD32 r, x; - - BIGLITTLE(n -= len,n += len); - - r = BIGLITTLE(*n++,*--n); - while (--len) { - x = BIGLITTLE(*n++,*--n); - r = (r%d << 32/2) | highhalf(x); - r = (r%d << 32/2) | lowhalf(x); - } - - return r%d; -} -#else -/* Default case - use lbnDiv21_32 */ -unsigned -lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) -{ - unsigned i, shift; - BNWORD32 r; - BNWORD32 q; - - assert(len > 0); - - shift = 0; - r = d; - i = 32; - while (i /= 2) { - if (r >> i) - r >>= i; - else - shift += i; - } - assert(d >> (32-1-shift) == 1); - d <<= shift; - - BIGLITTLE(n -= len,n += len); - - r = BIGLITTLE(*n++,*--n); - if (r >= d) - r %= d; - - while (--len) - r = lbnDiv21_32(&q, r, BIGLITTLE(*n++,*--n), d); - - /* - * Final correction for shift - shift the quotient up "shift" - * bits, and merge in the extra bits of quotient. Then reduce - * the final remainder mod the real d. - */ - if (shift) - r %= d >> shift; - - return r; -} -#endif -#endif /* lbnModQ_32 */ - -/* - * Reduce n mod d and return the quotient. That is, find: - * q = n / d; - * n = n % d; - * d is altered during the execution of this subroutine by normalizing it. - * It must already have its most significant word non-zero; it is shifted - * so its most significant bit is non-zero. - * - * The quotient q is nlen-dlen+1 words long. To make it possible to - * overlap the quptient with the input (you can store it in the high dlen - * words), the high word of the quotient is *not* stored, but is returned. - * (If all you want is the remainder, you don't care about it, anyway.) - * - * This uses algorithm D from Knuth (4.3.1), except that we do binary - * (shift) normalization of the divisor. WARNING: This is hairy! - * - * This function is used for some modular reduction, but it is not used in - * the modular exponentiation loops; they use Montgomery form and the - * corresponding, more efficient, Montgomery reduction. This code - * is needed for the conversion to Montgomery form, however, so it - * has to be here and it might as well be reasonably efficient. - * - * The overall operation is as follows ("top" and "up" refer to the - * most significant end of the number; "bottom" and "down", the least): - * - * - Shift the divisor up until the most significant bit is set. - * - Shift the dividend up the same amount. This will produce the - * correct quotient, and the remainder can be recovered by shifting - * it back down the same number of bits. This may produce an overflow - * word, but the word is always strictly less than the most significant - * divisor word. - * - Estimate the first quotient digit qhat: - * - First take the top two words (one of which is the overflow) of the - * dividend and divide by the top word of the divisor: - * qhat = (nh,nm)/dh. This qhat is >= the correct quotient digit - * and, since dh is normalized, it is at most two over. - * - Second, correct by comparing the top three words. If - * (dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again. - * The second iteration can be simpler because there can't be a third. - * The computation can be simplified by subtracting dh*qhat from - * both sides, suitably shifted. This reduces the left side to - * dl*qhat. On the right, (nh,nm)-dh*qhat is simply the - * remainder r from (nh,nm)%dh, so the right is (r,nl). - * This produces qhat that is almost always correct and at - * most (prob ~ 2/2^32) one too high. - * - Subtract qhat times the divisor (suitably shifted) from the dividend. - * If there is a borrow, qhat was wrong, so decrement it - * and add the divisor back in (once). - * - Store the final quotient digit qhat in the quotient array q. - * - * Repeat the quotient digit computation for successive digits of the - * quotient until the whole quotient has been computed. Then shift the - * divisor and the remainder down to correct for the normalization. - * - * TODO: Special case 2-word divisors. - * TODO: Use reciprocals rather than dividing. - */ -#ifndef divn_32 -BNWORD32 -lbnDiv_32(BNWORD32 *q, BNWORD32 *n, unsigned nlen, BNWORD32 *d, unsigned dlen) -{ - BNWORD32 nh,nm,nl; /* Top three words of the dividend */ - BNWORD32 dh,dl; /* Top two words of the divisor */ - BNWORD32 qhat; /* Extimate of quotient word */ - BNWORD32 r; /* Remainder from quotient estimate division */ - BNWORD32 qhigh; /* High word of quotient */ - unsigned i; /* Temp */ - unsigned shift; /* Bits shifted by normalization */ - unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */ -#ifdef mul32_ppmm - BNWORD32 t32; -#elif defined(BNWORD64) - BNWORD64 t64; -#else /* use lbnMulN1_32 */ - BNWORD32 t2[2]; -#define t2high BIGLITTLE(t2[0],t2[1]) -#define t2low BIGLITTLE(t2[1],t2[0]) -#endif - - assert(dlen); - assert(nlen >= dlen); - - /* - * Special cases for short divisors. The general case uses the - * top top 2 digits of the divisor (d) to estimate a quotient digit, - * so it breaks if there are fewer digits available. Thus, we need - * special cases for a divisor of length 1. A divisor of length - * 2 can have a *lot* of administrivia overhead removed removed, - * so it's probably worth special-casing that case, too. - */ - if (dlen == 1) - return lbnDiv1_32(q, BIGLITTLE(n-1,n), n, nlen, - BIGLITTLE(d[-1],d[0])); - -#if 0 - /* - * @@@ This is not yet written... The general loop will do, - * albeit less efficiently - */ - if (dlen == 2) { - /* - * divisor two digits long: - * use the 3/2 technique from Knuth, but we know - * it's exact. - */ - dh = BIGLITTLE(d[-1],d[0]); - dl = BIGLITTLE(d[-2],d[1]); - shift = 0; - if ((sh & ((BNWORD32)1 << 32-1-shift)) == 0) { - do { - shift++; - } while (dh & (BNWORD32)1<<32-1-shift) == 0); - dh = dh << shift | dl >> (32-shift); - dl <<= shift; - - - } - - - for (shift = 0; (dh & (BNWORD32)1 << 32-1-shift)) == 0; shift++) - ; - if (shift) { - } - dh = dh << shift | dl >> (32-shift); - shift = 0; - while (dh - } -#endif - - dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); - assert(dh); - - /* Normalize the divisor */ - shift = 0; - r = dh; - i = 32/2; - do { - if (r >> i) - r >>= i; - else - shift += i; - } while ((i /= 2) != 0); - - nh = 0; - if (shift) { - lbnLshift_32(d, dlen, shift); - dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); - nh = lbnLshift_32(n, nlen, shift); - } - - /* Assert that dh is now normalized */ - assert(dh >> (32-1)); - - /* Also get the second-most significant word of the divisor */ - dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2))); - - /* - * Adjust pointers: n to point to least significant end of first - * first subtract, and q to one the most-significant end of the - * quotient array. - */ - BIGLITTLE(n -= qlen,n += qlen); - BIGLITTLE(q -= qlen,q += qlen); - - /* Fetch the most significant stored word of the dividend */ - nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); - - /* - * Compute the first digit of the quotient, based on the - * first two words of the dividend (the most significant of which - * is the overflow word h). - */ - if (nh) { - assert(nh < dh); - r = lbnDiv21_32(&qhat, nh, nm, dh); - } else if (nm >= dh) { - qhat = nm/dh; - r = nm % dh; - } else { /* Quotient is zero */ - qhigh = 0; - goto divloop; - } - - /* Now get the third most significant word of the dividend */ - nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); - - /* - * Correct qhat, the estimate of quotient digit. - * qhat can only be high, and at most two words high, - * so the loop can be unrolled and abbreviated. - */ -#ifdef mul32_ppmm - mul32_ppmm(nm, t32, qhat, dl); - if (nm > r || (nm == r && t32 > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - nm -= (t32 < dl); - t32 -= dl; - if (nm > r || (nm == r && t32 > nl)) - qhat--; - } - } -#elif defined(BNWORD64) - t64 = (BNWORD64)qhat * dl; - if (t64 > ((BNWORD64)r << 32) + nl) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) > dh) { - t64 -= dl; - if (t64 > ((BNWORD64)r << 32) + nl) - qhat--; - } - } -#else /* Use lbnMulN1_32 */ - lbnMulN1_32(BIGLITTLE(t2+2,t2), &dl, 1, qhat); - if (t2high > r || (t2high == r && t2low > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - t2high -= (t2low < dl); - t2low -= dl; - if (t2high > r || (t2high == r && t2low > nl)) - qhat--; - } - } -#endif - - /* Do the multiply and subtract */ - r = lbnMulSub1_32(n, d, dlen, qhat); - /* If there was a borrow, add back once. */ - if (r > nh) { /* Borrow? */ - (void)lbnAddN_32(n, d, dlen); - qhat--; - } - - /* Remember the first quotient digit. */ - qhigh = qhat; - - /* Now, the main division loop: */ -divloop: - while (qlen--) { - - /* Advance n */ - nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); - BIGLITTLE(++n,--n); - nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); - - if (nh == dh) { - qhat = ~(BNWORD32)0; - /* Optimized computation of r = (nh,nm) - qhat * dh */ - r = nh + nm; - if (r < nh) - goto subtract; - } else { - assert(nh < dh); - r = lbnDiv21_32(&qhat, nh, nm, dh); - } - - nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); -#ifdef mul32_ppmm - mul32_ppmm(nm, t32, qhat, dl); - if (nm > r || (nm == r && t32 > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - nm -= (t32 < dl); - t32 -= dl; - if (nm > r || (nm == r && t32 > nl)) - qhat--; - } - } -#elif defined(BNWORD64) - t64 = (BNWORD64)qhat * dl; - if (t64 > ((BNWORD64)r<<32) + nl) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - t64 -= dl; - if (t64 > ((BNWORD64)r << 32) + nl) - qhat--; - } - } -#else /* Use lbnMulN1_32 */ - lbnMulN1_32(BIGLITTLE(t2+2,t2), &dl, 1, qhat); - if (t2high > r || (t2high == r && t2low > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - t2high -= (t2low < dl); - t2low -= dl; - if (t2high > r || (t2high == r && t2low > nl)) - qhat--; - } - } -#endif - - /* - * As a point of interest, note that it is not worth checking - * for qhat of 0 or 1 and installing special-case code. These - * occur with probability 2^-32, so spending 1 cycle to check - * for them is only worth it if we save more than 2^15 cycles, - * and a multiply-and-subtract for numbers in the 1024-bit - * range just doesn't take that long. - */ -subtract: - /* - * n points to the least significant end of the substring - * of n to be subtracted from. qhat is either exact or - * one too large. If the subtract gets a borrow, it was - * one too large and the divisor is added back in. It's - * a dlen+1 word add which is guaranteed to produce a - * carry out, so it can be done very simply. - */ - r = lbnMulSub1_32(n, d, dlen, qhat); - if (r > nh) { /* Borrow? */ - (void)lbnAddN_32(n, d, dlen); - qhat--; - } - /* Store the quotient digit */ - BIGLITTLE(*q++,*--q) = qhat; - } - /* Tah dah! */ - - if (shift) { - lbnRshift_32(d, dlen, shift); - lbnRshift_32(n, dlen, shift); - } - - return qhigh; -} -#endif - -/* - * Find the negative multiplicative inverse of x (x must be odd!) modulo 2^32. - * - * This just performs Newton's iteration until it gets the - * inverse. The initial estimate is always correct to 3 bits, and - * sometimes 4. The number of valid bits doubles each iteration. - * (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable - * for the error mod 2^2n. x * y == 1 + k*2^n (mod 2^2n) and follow - * the iteration through.) - */ -#ifndef lbnMontInv1_32 -BNWORD32 -lbnMontInv1_32(BNWORD32 const x) -{ - BNWORD32 y = x, z; - - assert(x & 1); - - while ((z = x*y) != 1) - y *= 2 - z; - return -y; -} -#endif /* !lbnMontInv1_32 */ - -#if defined(BNWORD64) && PRODUCT_SCAN -/* - * Test code for product-scanning Montgomery reduction. - * This seems to slow the C code down rather than speed it up. - * - * The first loop computes the Montgomery multipliers, storing them over - * the low half of the number n. - * - * The second half multiplies the upper half, adding in the modulus - * times the Montgomery multipliers. The results of this multiply - * are stored. - */ -void -lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned mlen, BNWORD32 inv) -{ - BNWORD64 x, y; - BNWORD32 const *pm; - BNWORD32 *pn; - BNWORD32 t; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!mlen) - return; - - /* Pass 1 - compute Montgomery multipliers */ - /* First iteration can have certain simplifications. */ - t = BIGLITTLE(n[-1],n[0]); - x = t; - t *= inv; - BIGLITTLE(n[-1], n[0]) = t; - x += (BNWORD64)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */ - assert((BNWORD32)x == 0); - x = x >> 32; - - for (i = 1; i < mlen; i++) { - carry = 0; - pn = n; - pm = BIGLITTLE(mod-i-1,mod+i+1); - for (j = 0; j < i; j++) { - y = (BNWORD64)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm); - x += y; - carry += (x < y); - } - assert(BIGLITTLE(pn == n-i, pn == n+i)); - y = t = BIGLITTLE(pn[-1], pn[0]); - x += y; - carry += (x < y); - BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD32)x; - assert(BIGLITTLE(pm == mod-1, pm == mod+1)); - y = (BNWORD64)t * BIGLITTLE(pm[0],pm[-1]); - x += y; - carry += (x < y); - assert((BNWORD32)x == 0); - x = x >> 32 | (BNWORD64)carry << 32; - } - - BIGLITTLE(n -= mlen, n += mlen); - - /* Pass 2 - compute upper words and add to n */ - for (i = 1; i < mlen; i++) { - carry = 0; - pm = BIGLITTLE(mod-i,mod+i); - pn = n; - for (j = i; j < mlen; j++) { - y = (BNWORD64)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn); - x += y; - carry += (x < y); - } - assert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen)); - assert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i)); - y = t = BIGLITTLE(*(n-i),*(n+i-1)); - x += y; - carry += (x < y); - BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD32)x; - x = (x >> 32) | (BNWORD64)carry << 32; - } - - /* Last round of second half, simplified. */ - t = BIGLITTLE(*(n-mlen),*(n+mlen-1)); - x += t; - BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD32)x; - carry = (unsigned)(x >> 32); - - while (carry) - carry -= lbnSubN_32(n, mod, mlen); - while (lbnCmp_32(n, mod, mlen) >= 0) - (void)lbnSubN_32(n, mod, mlen); -} -#define lbnMontReduce_32 lbnMontReduce_32 -#endif - -/* - * Montgomery reduce n, modulo mod. This reduces modulo mod and divides by - * 2^(32*mlen). Returns the result in the *top* mlen words of the argument n. - * This is ready for another multiplication using lbnMul_32. - * - * Montgomery representation is a very useful way to encode numbers when - * you're doing lots of modular reduction. What you do is pick a multiplier - * R which is relatively prime to the modulus and very easy to divide by. - * Since the modulus is odd, R is closen as a power of 2, so the division - * is a shift. In fact, it's a shift of an integral number of words, - * so the shift can be implicit - just drop the low-order words. - * - * Now, choose R *larger* than the modulus m, 2^(32*mlen). Then convert - * all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the - * relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. Note that: - * - The Montgomery form of a number depends on the modulus m. - * A fixed modulus m is assumed throughout this discussion. - * - Since R is relaitvely prime to m, multiplication by R is invertible; - * no information about the numbers is lost, they're just scrambled. - * - Adding (and subtracting) numbers in this form works just as usual. - * M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m - * - Multiplying numbers in this form produces a*b*R*R. The problem - * is to divide out the excess factor of R, modulo m as well as to - * reduce to the given length mlen. It turns out that this can be - * done *faster* than a normal divide, which is where the speedup - * in Montgomery division comes from. - * - * Normal reduction chooses a most-significant quotient digit q and then - * subtracts q*m from the number to be reduced. Choosing q is tricky - * and involved (just look at lbnDiv_32 to see!) and is usually - * imperfect, requiring a check for correction after the subtraction. - * - * Montgomery reduction *adds* a multiple of m to the *low-order* part - * of the number to be reduced. This multiple is chosen to make the - * low-order part of the number come out to zero. This can be done - * with no trickery or error using a precomputed inverse of the modulus. - * In this code, the "part" is one word, but any width can be used. - * - * Repeating this step sufficiently often results in a value which - * is a multiple of R (a power of two, remember) but is still (since - * the additions were to the low-order part and thus did not increase - * the value of the number being reduced very much) still not much - * larger than m*R. Then implicitly divide by R and subtract off - * m until the result is in the correct range. - * - * Since the low-order part being cancelled is less than R, the - * multiple of m added must have a multiplier which is at most R-1. - * Assuming that the input is at most m*R-1, the final number is - * at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from - * the high-order part, equivalent to subtracting m*R from the - * while number, produces a result which is at most m*R - m - 1, - * which divided by R is at most m-1. - * - * To convert *to* Montgomery form, you need a regular remainder - * routine, although you can just compute R*R (mod m) and do the - * conversion using Montgomery multiplication. To convert *from* - * Montgomery form, just Montgomery reduce the number to - * remove the extra factor of R. - * - * TODO: Change to a full inverse and use Karatsuba's multiplication - * rather than this word-at-a-time. - */ -#ifndef lbnMontReduce_32 -void -lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned const mlen, - BNWORD32 inv) -{ - BNWORD32 t; - BNWORD32 c = 0; - unsigned len = mlen; - - /* inv must be the negative inverse of mod's least significant word */ - assert((BNWORD32)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD32)-1); - - assert(len); - - do { - t = lbnMulAdd1_32(n, mod, mlen, inv * BIGLITTLE(n[-1],n[0])); - c += lbnAdd1_32(BIGLITTLE(n-mlen,n+mlen), len, t); - BIGLITTLE(--n,++n); - } while (--len); - - /* - * All that adding can cause an overflow past the modulus size, - * but it's unusual, and never by much, so a subtraction loop - * is the right way to deal with it. - * This subtraction happens infrequently - I've only ever seen it - * invoked once per reduction, and then just under 22.5% of the time. - */ - while (c) - c -= lbnSubN_32(n, mod, mlen); - while (lbnCmp_32(n, mod, mlen) >= 0) - (void)lbnSubN_32(n, mod, mlen); -} -#endif /* !lbnMontReduce_32 */ - -/* - * A couple of helpers that you might want to implement atomically - * in asm sometime. - */ -#ifndef lbnMontMul_32 -/* - * Multiply "num1" by "num2", modulo "mod", all of length "len", and - * place the result in the high half of "prod". "inv" is the inverse - * of the least-significant word of the modulus, modulo 2^32. - * This uses numbers in Montgomery form. Reduce using "len" and "inv". - * - * This is implemented as a macro to win on compilers that don't do - * inlining, since it's so trivial. - */ -#define lbnMontMul_32(prod, n1, n2, mod, len, inv) \ - (lbnMulX_32(prod, n1, n2, len), lbnMontReduce_32(prod, mod, len, inv)) -#endif /* !lbnMontMul_32 */ - -#ifndef lbnMontSquare_32 -/* - * Square "n", modulo "mod", both of length "len", and place the result - * in the high half of "prod". "inv" is the inverse of the least-significant - * word of the modulus, modulo 2^32. - * This uses numbers in Montgomery form. Reduce using "len" and "inv". - * - * This is implemented as a macro to win on compilers that don't do - * inlining, since it's so trivial. - */ -#define lbnMontSquare_32(prod, n, mod, len, inv) \ - (lbnSquare_32(prod, n, len), lbnMontReduce_32(prod, mod, len, inv)) - -#endif /* !lbnMontSquare_32 */ - -/* - * Convert a number to Montgomery form - requires mlen + nlen words - * of memory in "n". - */ -void -lbnToMont_32(BNWORD32 *n, unsigned nlen, BNWORD32 *mod, unsigned mlen) -{ - /* Move n up "mlen" words */ - lbnCopy_32(BIGLITTLE(n-mlen,n+mlen), n, nlen); - lbnZero_32(n, mlen); - /* Do the division - dump the quotient in the high-order words */ - (void)lbnDiv_32(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen); -} - -/* - * Convert from Montgomery form. Montgomery reduction is all that is - * needed. - */ -void -lbnFromMont_32(BNWORD32 *n, BNWORD32 *mod, unsigned len) -{ - /* Zero the high words of n */ - lbnZero_32(BIGLITTLE(n-len,n+len), len); - lbnMontReduce_32(n, mod, len, lbnMontInv1_32(mod[BIGLITTLE(-1,0)])); - /* Move n down len words */ - lbnCopy_32(n, BIGLITTLE(n-len,n+len), len); -} - -/* - * The windowed exponentiation algorithm, precomputes a table of odd - * powers of n up to 2^k. See the comment in bnExpMod_32 below for - * an explanation of how it actually works works. - * - * It takes 2^(k-1)-1 multiplies to compute the table, and (e-1)/(k+1) - * multiplies (on average) to perform the exponentiation. To minimize - * the sum, k must vary with e. The optimal window sizes vary with the - * exponent length. Here are some selected values and the boundary cases. - * (An underscore _ has been inserted into some of the numbers to ensure - * that magic strings like 32 do not appear in this table. It should be - * ignored.) - * - * At e = 1 bits, k=1 (0.000000) is best - * At e = 2 bits, k=1 (0.500000) is best - * At e = 4 bits, k=1 (1.500000) is best - * At e = 8 bits, k=2 (3.333333) < k=1 (3.500000) - * At e = 1_6 bits, k=2 (6.000000) is best - * At e = 26 bits, k=3 (9.250000) < k=2 (9.333333) - * At e = 3_2 bits, k=3 (10.750000) is best - * At e = 6_4 bits, k=3 (18.750000) is best - * At e = 82 bits, k=4 (23.200000) < k=3 (23.250000) - * At e = 128 bits, k=4 (3_2.400000) is best - * At e = 242 bits, k=5 (55.1_66667) < k=4 (55.200000) - * At e = 256 bits, k=5 (57.500000) is best - * At e = 512 bits, k=5 (100.1_66667) is best - * At e = 674 bits, k=6 (127.142857) < k=5 (127.1_66667) - * At e = 1024 bits, k=6 (177.142857) is best - * At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857) - * At e = 2048 bits, k=7 (318.875000) is best - * At e = 4096 bits, k=7 (574.875000) is best - * - * The numbers in parentheses are the expected number of multiplications - * needed to do the computation. The normal russian-peasant modular - * exponentiation technique always uses (e-1)/2. For exponents as - * small as 192 bits (below the range of current factoring algorithms), - * half of the multiplies are eliminated, 45.2 as opposed to the naive - * 95.5. Counting the 191 squarings as 3/4 a multiply each (squaring - * proper is just over half of multiplying, but the Montgomery - * reduction in each case is also a multiply), that's 143.25 - * multiplies, for totals of 188.45 vs. 238.75 - a 21% savings. - * For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a - * 24.3% savings. It asymptotically approaches 25%. - * - * Um, actually there's a slightly more accurate way to count, which - * really is the average number of multiplies required, averaged - * uniformly over all 2^(e-1) e-bit numbers, from 2^(e-1) to (2^e)-1. - * It's based on the recurrence that for the last b bits, b <= k, at - * most one multiply is needed (and none at all 1/2^b of the time), - * while when b > k, the odds are 1/2 each way that the bit will be - * 0 (meaning no multiplies to reduce it to the b-1-bit case) and - * 1/2 that the bit will be 1, starting a k-bit window and requiring - * 1 multiply beyond the b-k-bit case. Since the most significant - * bit is always 1, a k-bit window always starts there, and that - * multiply is by 1, so it isn't a multiply at all. Thus, the - * number of multiplies is simply that needed for the last e-k bits. - * This recurrence produces: - * - * At e = 1 bits, k=1 (0.000000) is best - * At e = 2 bits, k=1 (0.500000) is best - * At e = 4 bits, k=1 (1.500000) is best - * At e = 6 bits, k=2 (2.437500) < k=1 (2.500000) - * At e = 8 bits, k=2 (3.109375) is best - * At e = 1_6 bits, k=2 (5.777771) is best - * At e = 24 bits, k=3 (8.437629) < k=2 (8.444444) - * At e = 3_2 bits, k=3 (10.437492) is best - * At e = 6_4 bits, k=3 (18.437500) is best - * At e = 81 bits, k=4 (22.6_40000) < k=3 (22.687500) - * At e = 128 bits, k=4 (3_2.040000) is best - * At e = 241 bits, k=5 (54.611111) < k=4 (54.6_40000) - * At e = 256 bits, k=5 (57.111111) is best - * At e = 512 bits, k=5 (99.777778) is best - * At e = 673 bits, k=6 (126.591837) < k=5 (126.611111) - * At e = 1024 bits, k=6 (176.734694) is best - * At e = 1793 bits, k=7 (286.578125) < k=6 (286.591837) - * At e = 2048 bits, k=7 (318.453125) is best - * At e = 4096 bits, k=7 (574.453125) is best - * - * This has the rollover points at 6, 24, 81, 241, 673 and 1793 instead - * of 8, 26, 82, 242, 674, and 1794. Not a very big difference. - * (The numbers past that are k=8 at 4609 and k=9 at 11521, - * vs. one more in each case for the approximation.) - * - * Given that exponents for which k>7 are useful are uncommon, - * a fixed size table for k <= 7 is used for simplicity. - * - * The basic number of squarings needed is e-1, although a k-bit - * window (for k > 1) can save, on average, k-2 of those, too. - * That savings currently isn't counted here. It would drive the - * crossover points slightly lower. - * (Actually, this win is also reduced in the DoubleExpMod case, - * meaning we'd have to split the tables. Except for that, the - * multiplies by powers of the two bases are independent, so - * the same logic applies to each as the single case.) - * - * Table entry i is the largest number of bits in an exponent to - * process with a window size of i+1. Entry 6 is the largest - * possible unsigned number, so the window will never be more - * than 7 bits, requiring 2^6 = 0x40 slots. - */ -#define BNEXPMOD_MAX_WINDOW 7 -static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = { - 5, 23, 80, 240, 672, 1792, (unsigned)-1 -/* 7, 25, 81, 241, 673, 1793, (unsigned)-1 ### The old approximations */ -}; - -/* - * Perform modular exponentiation, as fast as possible! This uses - * Montgomery reduction, optimized squaring, and windowed exponentiation. - * The modulus "mod" MUST be odd! - * - * This returns 0 on success, -1 on out of memory. - * - * The window algorithm: - * The idea is to keep a running product of b1 = n^(high-order bits of exp), - * and then keep appending exponent bits to it. The following patterns - * apply to a 3-bit window (k = 3): - * To append 0: square - * To append 1: square, multiply by n^1 - * To append 10: square, multiply by n^1, square - * To append 11: square, square, multiply by n^3 - * To append 100: square, multiply by n^1, square, square - * To append 101: square, square, square, multiply by n^5 - * To append 110: square, square, multiply by n^3, square - * To append 111: square, square, square, multiply by n^7 - * - * Since each pattern involves only one multiply, the longer the pattern - * the better, except that a 0 (no multiplies) can be appended directly. - * We precompute a table of odd powers of n, up to 2^k, and can then - * multiply k bits of exponent at a time. Actually, assuming random - * exponents, there is on average one zero bit between needs to - * multiply (1/2 of the time there's none, 1/4 of the time there's 1, - * 1/8 of the time, there's 2, 1/32 of the time, there's 3, etc.), so - * you have to do one multiply per k+1 bits of exponent. - * - * The loop walks down the exponent, squaring the result buffer as - * it goes. There is a wbits+1 bit lookahead buffer, buf, that is - * filled with the upcoming exponent bits. (What is read after the - * end of the exponent is unimportant, but it is filled with zero here.) - * When the most-significant bit of this buffer becomes set, i.e. - * (buf & tblmask) != 0, we have to decide what pattern to multiply - * by, and when to do it. We decide, remember to do it in future - * after a suitable number of squarings have passed (e.g. a pattern - * of "100" in the buffer requires that we multiply by n^1 immediately; - * a pattern of "110" calls for multiplying by n^3 after one more - * squaring), clear the buffer, and continue. - * - * When we start, there is one more optimization: the result buffer - * is implcitly one, so squaring it or multiplying by it can be - * optimized away. Further, if we start with a pattern like "100" - * in the lookahead window, rather than placing n into the buffer - * and then starting to square it, we have already computed n^2 - * to compute the odd-powers table, so we can place that into - * the buffer and save a squaring. - * - * This means that if you have a k-bit window, to compute n^z, - * where z is the high k bits of the exponent, 1/2 of the time - * it requires no squarings. 1/4 of the time, it requires 1 - * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings. - * And the remaining 1/2^(k-1) of the time, the top k bits are a - * 1 followed by k-1 0 bits, so it again only requires k-2 - * squarings, not k-1. The average of these is 1. Add that - * to the one squaring we have to do to compute the table, - * and you'll see that a k-bit window saves k-2 squarings - * as well as reducing the multiplies. (It actually doesn't - * hurt in the case k = 1, either.) - * - * n must have mlen words allocated. Although fewer may be in use - * when n is passed in, all are in use on exit. - */ -int -lbnExpMod_32(BNWORD32 *result, BNWORD32 const *n, unsigned nlen, - BNWORD32 const *e, unsigned elen, BNWORD32 *mod, unsigned mlen) -{ - BNWORD32 *table[1 << (BNEXPMOD_MAX_WINDOW-1)]; - /* Table of odd powers of n */ - unsigned ebits; /* Exponent bits */ - unsigned wbits; /* Window size */ - unsigned tblmask; /* Mask of exponentiation window */ - BNWORD32 bitpos; /* Mask of current look-ahead bit */ - unsigned buf; /* Buffer of exponent bits */ - unsigned multpos; /* Where to do pending multiply */ - BNWORD32 const *mult; /* What to multiply by */ - unsigned i; /* Loop counter */ - int isone; /* Flag: accum. is implicitly one */ - BNWORD32 *a, *b; /* Working buffers/accumulators */ - BNWORD32 *t; /* Pointer into the working buffers */ - BNWORD32 inv; /* mod^-1 modulo 2^32 */ - int y; /* bnYield() result */ - - assert(mlen); - assert(nlen <= mlen); - - /* First, a couple of trivial cases. */ - elen = lbnNorm_32(e, elen); - if (!elen) { - /* x ^ 0 == 1 */ - lbnZero_32(result, mlen); - BIGLITTLE(result[-1],result[0]) = 1; - return 0; - } - ebits = lbnBits_32(e, elen); - if (ebits == 1) { - /* x ^ 1 == x */ - if (n != result) - lbnCopy_32(result, n, nlen); - if (mlen > nlen) - lbnZero_32(BIGLITTLE(result-nlen,result+nlen), - mlen-nlen); - return 0; - } - - /* Okay, now move the exponent pointer to the most-significant word */ - e = BIGLITTLE(e-elen, e+elen-1); - - /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ - wbits = 0; - while (ebits > bnExpModThreshTable[wbits]) - wbits++; - - /* Allocate working storage: two product buffers and the tables. */ - LBNALLOC(a, BNWORD32, 2*mlen); - if (!a) - return -1; - LBNALLOC(b, BNWORD32, 2*mlen); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ - tblmask = 1u << wbits; - - /* We have the result buffer available, so use it. */ - table[0] = result; - - /* - * Okay, we now have a minimal-sized table - expand it. - * This is allowed to fail! If so, scale back the table size - * and proceed. - */ - for (i = 1; i < tblmask; i++) { - LBNALLOC(t, BNWORD32, mlen); - if (!t) /* Out of memory! Quit the loop. */ - break; - table[i] = t; - } - - /* If we stopped, with i < tblmask, shrink the tables appropriately */ - while (tblmask > i) { - wbits--; - tblmask >>= 1; - } - /* Free up our overallocations */ - while (--i > tblmask) - LBNFREE(table[i], mlen); - - /* Okay, fill in the table */ - - /* Compute the necessary modular inverse */ - inv = lbnMontInv1_32(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - /* Convert n to Montgomery form */ - - /* Move n up "mlen" words into a */ - t = BIGLITTLE(a-mlen, a+mlen); - lbnCopy_32(t, n, nlen); - lbnZero_32(a, mlen); - /* Do the division - lose the quotient into the high-order words */ - (void)lbnDiv_32(t, a, mlen+nlen, mod, mlen); - /* Copy into first table entry */ - lbnCopy_32(table[0], a, mlen); - - /* Square a into b */ - lbnMontSquare_32(b, a, mod, mlen, inv); - - /* Use high half of b to initialize the table */ - t = BIGLITTLE(b-mlen, b+mlen); - for (i = 1; i < tblmask; i++) { - lbnMontMul_32(a, t, table[i-1], mod, mlen, inv); - lbnCopy_32(table[i], BIGLITTLE(a-mlen, a+mlen), mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* We might use b = n^2 later... */ - - /* Initialze the fetch pointer */ - bitpos = (BNWORD32)1 << ((ebits-1) & (32-1)); /* Initialize mask */ - - /* This should point to the msbit of e */ - assert((*e & bitpos) != 0); - - /* - * Pre-load the window. Becuase the window size is - * never larger than the exponent size, there is no need to - * detect running off the end of e in here. - * - * The read-ahead is controlled by elen and the bitpos mask. - * Note that this is *ahead* of ebits, which tracks the - * most significant end of the window. The purpose of this - * initialization is to get the two wbits+1 bits apart, - * like they should be. - * - * Note that bitpos and e1len together keep track of the - * lookahead read pointer in the exponent that is used here. - */ - buf = 0; - for (i = 0; i <= wbits; i++) { - buf = (buf << 1) | ((*e & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e++,e--); - bitpos = (BNWORD32)1 << (32-1); - elen--; - } - } - assert(buf & tblmask); - - /* - * Set the pending multiply positions to a location that will - * never be encountered, thus ensuring that nothing will happen - * until the need for a multiply appears and one is scheduled. - */ - multpos = ebits; /* A NULL value */ - mult = 0; /* Force a crash if we use these */ - - /* - * Okay, now begins the real work. The first step is - * slightly magic, so it's done outside the main loop, - * but it's very similar to what's inside. - */ - ebits--; /* Start processing the first bit... */ - isone = 1; - - /* - * This is just like the multiply in the loop, except that - * - We know the msbit of buf is set, and - * - We have the extra value n^2 floating around. - * So, do the usual computation, and if the result is that - * the buffer should be multiplied by n^1 immediately - * (which we'd normally then square), we multiply it - * (which reduces to a copy, which reduces to setting a flag) - * by n^2 and skip the squaring. Thus, we do the - * multiply and the squaring in one step. - */ - assert(buf & tblmask); - multpos = ebits - wbits; - while ((buf & 1) == 0) { - buf >>= 1; - multpos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(multpos <= ebits); - mult = table[buf>>1]; - buf = 0; - - /* Special case: use already-computed value sitting in buffer */ - if (multpos == ebits) - isone = 0; - - /* - * At this point, the buffer (which is the high half of b) holds - * either 1 (implicitly, as the "isone" flag is set), or n^2. - */ - - /* - * The main loop. The procedure is: - * - Advance the window - * - If the most-significant bit of the window is set, - * schedule a multiply for the appropriate time in the - * future (may be immediately) - * - Perform any pending multiples - * - Check for termination - * - Square the buffer - * - * At any given time, the acumulated product is held in - * the high half of b. - */ - for (;;) { - ebits--; - - /* Advance the window */ - assert(buf < tblmask); - buf <<= 1; - /* - * This reads ahead of the current exponent position - * (controlled by ebits), so we have to be able to read - * past the lsb of the exponents without error. - */ - if (elen) { - buf |= ((*e & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e++,e--); - bitpos = (BNWORD32)1 << (32-1); - elen--; - } - } - - /* Examine the window for pending multiplies */ - if (buf & tblmask) { - multpos = ebits - wbits; - while ((buf & 1) == 0) { - buf >>= 1; - multpos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(multpos <= ebits); - mult = table[buf>>1]; - buf = 0; - } - - /* If we have a pending multiply, do it */ - if (ebits == multpos) { - /* Multiply by the table entry remembered previously */ - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - /* Multiply by 1 is a trivial case */ - lbnCopy_32(t, mult, mlen); - isone = 0; - } else { - lbnMontMul_32(a, t, mult, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } - } - - /* Are we done? */ - if (!ebits) - break; - - /* Square the input */ - if (!isone) { - t = BIGLITTLE(b-mlen, b+mlen); - lbnMontSquare_32(a, t, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } /* for (;;) */ - - assert(!isone); - assert(!buf); - - /* DONE! */ - - /* Convert result out of Montgomery form */ - t = BIGLITTLE(b-mlen, b+mlen); - lbnCopy_32(b, t, mlen); - lbnZero_32(t, mlen); - lbnMontReduce_32(b, mod, mlen, inv); - lbnCopy_32(result, t, mlen); - /* - * Clean up - free intermediate storage. - * Do NOT free table[0], which is the result - * buffer. - */ - y = 0; -#if BNYIELD -yield: -#endif - while (--tblmask) - LBNFREE(table[tblmask], mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; /* Success */ -} - -/* - * Compute and return n1^e1 * n2^e2 mod "mod". - * result may be either input buffer, or something separate. - * It must be "mlen" words long. - * - * There is a current position in the exponents, which is kept in e1bits. - * (The exponents are swapped if necessary so e1 is the longer of the two.) - * At any given time, the value in the accumulator is - * n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod". - * As e1bits is counted down, this is updated, by squaring it and doing - * any necessary multiplies. - * To decide on the necessary multiplies, two windows, each w1bits+1 bits - * wide, are maintained in buf1 and buf2, which read *ahead* of the - * e1bits position (with appropriate handling of the case when e1bits - * drops below w1bits+1). When the most-significant bit of either window - * becomes set, indicating that something needs to be multiplied by - * the accumulator or it will get out of sync, the window is examined - * to see which power of n1 or n2 to multiply by, and when (possibly - * later, if the power is greater than 1) the multiply should take - * place. Then the multiply and its location are remembered and the - * window is cleared. - * - * If we had every power of n1 in the table, the multiply would always - * be w1bits steps in the future. But we only keep the odd powers, - * so instead of waiting w1bits squarings and then multiplying - * by n1^k, we wait w1bits-k squarings and multiply by n1. - * - * Actually, w2bits can be less than w1bits, but the window is the same - * size, to make it easier to keep track of where we're reading. The - * appropriate number of low-order bits of the window are just ignored. - */ -int -lbnDoubleExpMod_32(BNWORD32 *result, - BNWORD32 const *n1, unsigned n1len, - BNWORD32 const *e1, unsigned e1len, - BNWORD32 const *n2, unsigned n2len, - BNWORD32 const *e2, unsigned e2len, - BNWORD32 *mod, unsigned mlen) -{ - BNWORD32 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)]; - /* Table of odd powers of n1 */ - BNWORD32 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)]; - /* Table of odd powers of n2 */ - unsigned e1bits, e2bits; /* Exponent bits */ - unsigned w1bits, w2bits; /* Window sizes */ - unsigned tblmask; /* Mask of exponentiation window */ - BNWORD32 bitpos; /* Mask of current look-ahead bit */ - unsigned buf1, buf2; /* Buffer of exponent bits */ - unsigned mult1pos, mult2pos; /* Where to do pending multiply */ - BNWORD32 const *mult1, *mult2; /* What to multiply by */ - unsigned i; /* Loop counter */ - int isone; /* Flag: accum. is implicitly one */ - BNWORD32 *a, *b; /* Working buffers/accumulators */ - BNWORD32 *t; /* Pointer into the working buffers */ - BNWORD32 inv; /* mod^-1 modulo 2^32 */ - int y; /* bnYield() result */ - - assert(mlen); - assert(n1len <= mlen); - assert(n2len <= mlen); - - /* First, a couple of trivial cases. */ - e1len = lbnNorm_32(e1, e1len); - e2len = lbnNorm_32(e2, e2len); - - /* Ensure that the first exponent is the longer */ - e1bits = lbnBits_32(e1, e1len); - e2bits = lbnBits_32(e2, e2len); - if (e1bits < e2bits) { - i = e1len; e1len = e2len; e2len = i; - i = e1bits; e1bits = e2bits; e2bits = i; - t = (BNWORD32 *)n1; n1 = n2; n2 = t; - t = (BNWORD32 *)e1; e1 = e2; e2 = t; - } - assert(e1bits >= e2bits); - - /* Handle a trivial case */ - if (!e2len) - return lbnExpMod_32(result, n1, n1len, e1, e1len, mod, mlen); - assert(e2bits); - - /* The code below fucks up if the exponents aren't at least 2 bits */ - if (e1bits == 1) { - assert(e2bits == 1); - - LBNALLOC(a, BNWORD32, n1len+n2len); - if (!a) - return -1; - - lbnMul_32(a, n1, n1len, n2, n2len); - /* Do a direct modular reduction */ - if (n1len + n2len >= mlen) - (void)lbnDiv_32(a+mlen, a, n1len+n2len, mod, mlen); - lbnCopy_32(result, a, mlen); - LBNFREE(a, n1len+n2len); - return 0; - } - - /* Okay, now move the exponent pointers to the most-significant word */ - e1 = BIGLITTLE(e1-e1len, e1+e1len-1); - e2 = BIGLITTLE(e2-e2len, e2+e2len-1); - - /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ - w1bits = 0; - while (e1bits > bnExpModThreshTable[w1bits]) - w1bits++; - w2bits = 0; - while (e2bits > bnExpModThreshTable[w2bits]) - w2bits++; - - assert(w1bits >= w2bits); - - /* Allocate working storage: two product buffers and the tables. */ - LBNALLOC(a, BNWORD32, 2*mlen); - if (!a) - return -1; - LBNALLOC(b, BNWORD32, 2*mlen); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ - tblmask = 1u << w1bits; - /* Use buf2 for its size, temporarily */ - buf2 = 1u << w2bits; - - LBNALLOC(t, BNWORD32, mlen); - if (!t) { - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - return -1; - } - table1[0] = t; - table2[0] = result; - - /* - * Okay, we now have some minimal-sized tables - expand them. - * This is allowed to fail! If so, scale back the table sizes - * and proceed. We allocate both tables at the same time - * so if it fails partway through, they'll both be a reasonable - * size rather than one huge and one tiny. - * When i passes buf2 (the number of entries in the e2 window, - * which may be less than the number of entries in the e1 window), - * stop allocating e2 space. - */ - for (i = 1; i < tblmask; i++) { - LBNALLOC(t, BNWORD32, mlen); - if (!t) /* Out of memory! Quit the loop. */ - break; - table1[i] = t; - if (i < buf2) { - LBNALLOC(t, BNWORD32, mlen); - if (!t) { - LBNFREE(table1[i], mlen); - break; - } - table2[i] = t; - } - } - - /* If we stopped, with i < tblmask, shrink the tables appropriately */ - while (tblmask > i) { - w1bits--; - tblmask >>= 1; - } - /* Free up our overallocations */ - while (--i > tblmask) { - if (i < buf2) - LBNFREE(table2[i], mlen); - LBNFREE(table1[i], mlen); - } - /* And shrink the second window too, if needed */ - if (w2bits > w1bits) { - w2bits = w1bits; - buf2 = tblmask; - } - - /* - * From now on, use the w2bits variable for the difference - * between w1bits and w2bits. - */ - w2bits = w1bits-w2bits; - - /* Okay, fill in the tables */ - - /* Compute the necessary modular inverse */ - inv = lbnMontInv1_32(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - /* Convert n1 to Montgomery form */ - - /* Move n1 up "mlen" words into a */ - t = BIGLITTLE(a-mlen, a+mlen); - lbnCopy_32(t, n1, n1len); - lbnZero_32(a, mlen); - /* Do the division - lose the quotient into the high-order words */ - (void)lbnDiv_32(t, a, mlen+n1len, mod, mlen); - /* Copy into first table entry */ - lbnCopy_32(table1[0], a, mlen); - - /* Square a into b */ - lbnMontSquare_32(b, a, mod, mlen, inv); - - /* Use high half of b to initialize the first table */ - t = BIGLITTLE(b-mlen, b+mlen); - for (i = 1; i < tblmask; i++) { - lbnMontMul_32(a, t, table1[i-1], mod, mlen, inv); - lbnCopy_32(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* Convert n2 to Montgomery form */ - - t = BIGLITTLE(a-mlen, a+mlen); - /* Move n2 up "mlen" words into a */ - lbnCopy_32(t, n2, n2len); - lbnZero_32(a, mlen); - /* Do the division - lose the quotient into the high-order words */ - (void)lbnDiv_32(t, a, mlen+n2len, mod, mlen); - /* Copy into first table entry */ - lbnCopy_32(table2[0], a, mlen); - - /* Square it into a */ - lbnMontSquare_32(a, table2[0], mod, mlen, inv); - /* Copy to b, low half */ - lbnCopy_32(b, t, mlen); - - /* Use b to initialize the second table */ - for (i = 1; i < buf2; i++) { - lbnMontMul_32(a, b, table2[i-1], mod, mlen, inv); - lbnCopy_32(table2[i], t, mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* - * Okay, a recap: at this point, the low part of b holds - * n2^2, the high part holds n1^2, and the tables are - * initialized with the odd powers of n1 and n2 from 1 - * through 2*tblmask-1 and 2*buf2-1. - * - * We might use those squares in b later, or we might not. - */ - - /* Initialze the fetch pointer */ - bitpos = (BNWORD32)1 << ((e1bits-1) & (32-1)); /* Initialize mask */ - - /* This should point to the msbit of e1 */ - assert((*e1 & bitpos) != 0); - - /* - * Pre-load the windows. Becuase the window size is - * never larger than the exponent size, there is no need to - * detect running off the end of e1 in here. - * - * The read-ahead is controlled by e1len and the bitpos mask. - * Note that this is *ahead* of e1bits, which tracks the - * most significant end of the window. The purpose of this - * initialization is to get the two w1bits+1 bits apart, - * like they should be. - * - * Note that bitpos and e1len together keep track of the - * lookahead read pointer in the exponent that is used here. - * e2len is not decremented, it is only ever compared with - * e1len as *that* is decremented. - */ - buf1 = buf2 = 0; - for (i = 0; i <= w1bits; i++) { - buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0); - if (e1len <= e2len) - buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e1++,e1--); - if (e1len <= e2len) - BIGLITTLE(e2++,e2--); - bitpos = (BNWORD32)1 << (32-1); - e1len--; - } - } - assert(buf1 & tblmask); - - /* - * Set the pending multiply positions to a location that will - * never be encountered, thus ensuring that nothing will happen - * until the need for a multiply appears and one is scheduled. - */ - mult1pos = mult2pos = e1bits; /* A NULL value */ - mult1 = mult2 = 0; /* Force a crash if we use these */ - - /* - * Okay, now begins the real work. The first step is - * slightly magic, so it's done outside the main loop, - * but it's very similar to what's inside. - */ - isone = 1; /* Buffer is implicitly 1, so replace * by copy */ - e1bits--; /* Start processing the first bit... */ - - /* - * This is just like the multiply in the loop, except that - * - We know the msbit of buf1 is set, and - * - We have the extra value n1^2 floating around. - * So, do the usual computation, and if the result is that - * the buffer should be multiplied by n1^1 immediately - * (which we'd normally then square), we multiply it - * (which reduces to a copy, which reduces to setting a flag) - * by n1^2 and skip the squaring. Thus, we do the - * multiply and the squaring in one step. - */ - assert(buf1 & tblmask); - mult1pos = e1bits - w1bits; - while ((buf1 & 1) == 0) { - buf1 >>= 1; - mult1pos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(mult1pos <= e1bits); - mult1 = table1[buf1>>1]; - buf1 = 0; - - /* Special case: use already-computed value sitting in buffer */ - if (mult1pos == e1bits) - isone = 0; - - /* - * The first multiply by a power of n2. Similar, but - * we might not even want to schedule a multiply if e2 is - * shorter than e1, and the window might be shorter so - * we have to leave the low w2bits bits alone. - */ - if (buf2 & tblmask) { - /* Remember low-order bits for later */ - i = buf2 & ((1u << w2bits) - 1); - buf2 >>= w2bits; - mult2pos = e1bits - w1bits + w2bits; - while ((buf2 & 1) == 0) { - buf2 >>= 1; - mult2pos++; - } - assert(mult2pos <= e1bits); - mult2 = table2[buf2>>1]; - buf2 = i; - - if (mult2pos == e1bits) { - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - lbnCopy_32(t, b, mlen); /* Copy low to high */ - isone = 0; - } else { - lbnMontMul_32(a, t, b, mod, mlen, inv); - t = a; a = b; b = t; - } - } - } - - /* - * At this point, the buffer (which is the high half of b) - * holds either 1 (implicitly, as the "isone" flag is set), - * n1^2, n2^2 or n1^2 * n2^2. - */ - - /* - * The main loop. The procedure is: - * - Advance the windows - * - If the most-significant bit of a window is set, - * schedule a multiply for the appropriate time in the - * future (may be immediately) - * - Perform any pending multiples - * - Check for termination - * - Square the buffers - * - * At any given time, the acumulated product is held in - * the high half of b. - */ - for (;;) { - e1bits--; - - /* Advance the windows */ - assert(buf1 < tblmask); - buf1 <<= 1; - assert(buf2 < tblmask); - buf2 <<= 1; - /* - * This reads ahead of the current exponent position - * (controlled by e1bits), so we have to be able to read - * past the lsb of the exponents without error. - */ - if (e1len) { - buf1 |= ((*e1 & bitpos) != 0); - if (e1len <= e2len) - buf2 |= ((*e2 & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e1++,e1--); - if (e1len <= e2len) - BIGLITTLE(e2++,e2--); - bitpos = (BNWORD32)1 << (32-1); - e1len--; - } - } - - /* Examine the first window for pending multiplies */ - if (buf1 & tblmask) { - mult1pos = e1bits - w1bits; - while ((buf1 & 1) == 0) { - buf1 >>= 1; - mult1pos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(mult1pos <= e1bits); - mult1 = table1[buf1>>1]; - buf1 = 0; - } - - /* - * Examine the second window for pending multiplies. - * Window 2 can be smaller than window 1, but we - * keep the same number of bits in buf2, so we need - * to ignore any low-order bits in the buffer when - * computing what to multiply by, and recompute them - * later. - */ - if (buf2 & tblmask) { - /* Remember low-order bits for later */ - i = buf2 & ((1u << w2bits) - 1); - buf2 >>= w2bits; - mult2pos = e1bits - w1bits + w2bits; - while ((buf2 & 1) == 0) { - buf2 >>= 1; - mult2pos++; - } - assert(mult2pos <= e1bits); - mult2 = table2[buf2>>1]; - buf2 = i; - } - - - /* If we have a pending multiply for e1, do it */ - if (e1bits == mult1pos) { - /* Multiply by the table entry remembered previously */ - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - /* Multiply by 1 is a trivial case */ - lbnCopy_32(t, mult1, mlen); - isone = 0; - } else { - lbnMontMul_32(a, t, mult1, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } - } - - /* If we have a pending multiply for e2, do it */ - if (e1bits == mult2pos) { - /* Multiply by the table entry remembered previously */ - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - /* Multiply by 1 is a trivial case */ - lbnCopy_32(t, mult2, mlen); - isone = 0; - } else { - lbnMontMul_32(a, t, mult2, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } - } - - /* Are we done? */ - if (!e1bits) - break; - - /* Square the buffer */ - if (!isone) { - t = BIGLITTLE(b-mlen, b+mlen); - lbnMontSquare_32(a, t, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } /* for (;;) */ - - assert(!isone); - assert(!buf1); - assert(!buf2); - - /* DONE! */ - - /* Convert result out of Montgomery form */ - t = BIGLITTLE(b-mlen, b+mlen); - lbnCopy_32(b, t, mlen); - lbnZero_32(t, mlen); - lbnMontReduce_32(b, mod, mlen, inv); - lbnCopy_32(result, t, mlen); - - /* Clean up - free intermediate storage */ - y = 0; -#if BNYIELD -yield: -#endif - buf2 = tblmask >> w2bits; - while (--tblmask) { - if (tblmask < buf2) - LBNFREE(table2[tblmask], mlen); - LBNFREE(table1[tblmask], mlen); - } - t = table1[0]; - LBNFREE(t, mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; /* Success */ -} - -/* - * 2^exp (mod mod). This is an optimized version for use in Fermat - * tests. The input value of n is ignored; it is returned with - * "mlen" words valid. - */ -int -lbnTwoExpMod_32(BNWORD32 *n, BNWORD32 const *exp, unsigned elen, - BNWORD32 *mod, unsigned mlen) -{ - unsigned e; /* Copy of high words of the exponent */ - unsigned bits; /* Assorted counter of bits */ - BNWORD32 const *bitptr; - BNWORD32 bitword, bitpos; - BNWORD32 *a, *b, *a1; - BNWORD32 inv; - int y; /* Result of bnYield() */ - - assert(mlen); - - bitptr = BIGLITTLE(exp-elen, exp+elen-1); - bitword = *bitptr; - assert(bitword); - - /* Clear n for future use. */ - lbnZero_32(n, mlen); - - bits = lbnBits_32(exp, elen); - - /* First, a couple of trivial cases. */ - if (bits <= 1) { - /* 2 ^ 0 == 1, 2 ^ 1 == 2 */ - BIGLITTLE(n[-1],n[0]) = (BNWORD32)1<<elen; - return 0; - } - - /* Set bitpos to the most significant bit */ - bitpos = (BNWORD32)1 << ((bits-1) & (32-1)); - - /* Now, count the bits in the modulus. */ - bits = lbnBits_32(mod, mlen); - assert(bits > 1); /* a 1-bit modulus is just stupid... */ - - /* - * We start with 1<<e, where "e" is as many high bits of the - * exponent as we can manage without going over the modulus. - * This first loop finds "e". - */ - e = 1; - while (elen) { - /* Consume the first bit */ - bitpos >>= 1; - if (!bitpos) { - if (!--elen) - break; - bitword = BIGLITTLE(*++bitptr,*--bitptr); - bitpos = (BNWORD32)1<<(32-1); - } - e = (e << 1) | ((bitpos & bitword) != 0); - if (e >= bits) { /* Overflow! Back out. */ - e >>= 1; - break; - } - } - /* - * The bit in "bitpos" being examined by the bit buffer has NOT - * been consumed yet. This may be past the end of the exponent, - * in which case elen == 1. - */ - - /* Okay, now, set bit "e" in n. n is already zero. */ - inv = (BNWORD32)1 << (e & (32-1)); - e /= 32; - BIGLITTLE(n[-e-1],n[e]) = inv; - /* - * The effective length of n in words is now "e+1". - * This is used a little bit later. - */ - - if (!elen) - return 0; /* That was easy! */ - - /* - * We have now processed the first few bits. The next step - * is to convert this to Montgomery form for further squaring. - */ - - /* Allocate working storage: two product buffers */ - LBNALLOC(a, BNWORD32, 2*mlen); - if (!a) - return -1; - LBNALLOC(b, BNWORD32, 2*mlen); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Convert n to Montgomery form */ - inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */ - assert(inv & 1); /* Modulus must be odd */ - inv = lbnMontInv1_32(inv); - /* Move n (length e+1, remember?) up "mlen" words into b */ - /* Note that we lie about a1 for a bit - it's pointing to b */ - a1 = BIGLITTLE(b-mlen,b+mlen); - lbnCopy_32(a1, n, e+1); - lbnZero_32(b, mlen); - /* Do the division - dump the quotient into the high-order words */ - (void)lbnDiv_32(a1, b, mlen+e+1, mod, mlen); - /* - * Now do the first squaring and modular reduction to put - * the number up in a1 where it belongs. - */ - lbnMontSquare_32(a, b, mod, mlen, inv); - /* Fix up a1 to point to where it should go. */ - a1 = BIGLITTLE(a-mlen,a+mlen); - - /* - * Okay, now, a1 holds the number being accumulated, and - * b is a scratch register. Start working: - */ - for (;;) { - /* - * Is the bit set? If so, double a1 as well. - * A modular doubling like this is very cheap. - */ - if (bitpos & bitword) { - /* - * Double the number. If there was a carry out OR - * the result is greater than the modulus, subract - * the modulus. - */ - if (lbnDouble_32(a1, mlen) || - lbnCmp_32(a1, mod, mlen) > 0) - (void)lbnSubN_32(a1, mod, mlen); - } - - /* Advance to the next exponent bit */ - bitpos >>= 1; - if (!bitpos) { - if (!--elen) - break; /* Done! */ - bitword = BIGLITTLE(*++bitptr,*--bitptr); - bitpos = (BNWORD32)1<<(32-1); - } - - /* - * The elen/bitword/bitpos bit buffer is known to be - * non-empty, i.e. there is at least one more unconsumed bit. - * Thus, it's safe to square the number. - */ - lbnMontSquare_32(b, a1, mod, mlen, inv); - /* Rename result (in b) back to a (a1, really). */ - a1 = b; b = a; a = a1; - a1 = BIGLITTLE(a-mlen,a+mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* DONE! Just a little bit of cleanup... */ - - /* - * Convert result out of Montgomery form... this is - * just a Montgomery reduction. - */ - lbnCopy_32(a, a1, mlen); - lbnZero_32(a1, mlen); - lbnMontReduce_32(a, mod, mlen, inv); - lbnCopy_32(n, a1, mlen); - - /* Clean up - free intermediate storage */ - y = 0; -#if BNYIELD -yield: -#endif - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; /* Success */ -} - - -/* - * Returns a substring of the big-endian array of bytes representation - * of the bignum array based on two parameters, the least significant - * byte number (0 to start with the least significant byte) and the - * length. I.e. the number returned is a representation of - * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). - * - * It is an error if the bignum is not at least buflen + lsbyte bytes - * long. - * - * This code assumes that the compiler has the minimal intelligence - * neded to optimize divides and modulo operations on an unsigned data - * type with a power of two. - */ -void -lbnExtractBigBytes_32(BNWORD32 const *n, unsigned char *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD32 t = 0; /* Needed to shut up uninitialized var warnings */ - unsigned shift; - - lsbyte += buflen; - - shift = (8 * lsbyte) % 32; - lsbyte /= (32/8); /* Convert to word offset */ - BIGLITTLE(n -= lsbyte, n += lsbyte); - - if (shift) - t = BIGLITTLE(n[-1],n[0]); - - while (buflen--) { - if (!shift) { - t = BIGLITTLE(*n++,*--n); - shift = 32; - } - shift -= 8; - *buf++ = (unsigned char)(t>>shift); - } -} - -/* - * Merge a big-endian array of bytes into a bignum array. - * The array had better be big enough. This is - * equivalent to extracting the entire bignum into a - * large byte array, copying the input buffer into the - * middle of it, and converting back to a bignum. - * - * The buf is "len" bytes long, and its *last* byte is at - * position "lsbyte" from the end of the bignum. - * - * Note that this is a pain to get right. Fortunately, it's hardly - * critical for efficiency. - */ -void -lbnInsertBigBytes_32(BNWORD32 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD32 t = 0; /* Shut up uninitialized varibale warnings */ - - lsbyte += buflen; - - BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8)); - - /* Load up leading odd bytes */ - if (lsbyte % (32/8)) { - t = BIGLITTLE(*--n,*n++); - t >>= (lsbyte * 8) % 32; - } - - /* The main loop - merge into t, storing at each word boundary. */ - while (buflen--) { - t = (t << 8) | *buf++; - if ((--lsbyte % (32/8)) == 0) - BIGLITTLE(*n++,*--n) = t; - } - - /* Merge odd bytes in t into last word */ - lsbyte = (lsbyte * 8) % 32; - if (lsbyte) { - t <<= lsbyte; - t |= (((BNWORD32)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); - BIGLITTLE(n[0],n[-1]) = t; - } - - return; -} - -/* - * Returns a substring of the little-endian array of bytes representation - * of the bignum array based on two parameters, the least significant - * byte number (0 to start with the least significant byte) and the - * length. I.e. the number returned is a representation of - * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). - * - * It is an error if the bignum is not at least buflen + lsbyte bytes - * long. - * - * This code assumes that the compiler has the minimal intelligence - * neded to optimize divides and modulo operations on an unsigned data - * type with a power of two. - */ -void -lbnExtractLittleBytes_32(BNWORD32 const *n, unsigned char *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD32 t = 0; /* Needed to shut up uninitialized var warnings */ - - BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8)); - - if (lsbyte % (32/8)) { - t = BIGLITTLE(*--n,*n++); - t >>= (lsbyte % (32/8)) * 8 ; - } - - while (buflen--) { - if ((lsbyte++ % (32/8)) == 0) - t = BIGLITTLE(*--n,*n++); - *buf++ = (unsigned char)t; - t >>= 8; - } -} - -/* - * Merge a little-endian array of bytes into a bignum array. - * The array had better be big enough. This is - * equivalent to extracting the entire bignum into a - * large byte array, copying the input buffer into the - * middle of it, and converting back to a bignum. - * - * The buf is "len" bytes long, and its first byte is at - * position "lsbyte" from the end of the bignum. - * - * Note that this is a pain to get right. Fortunately, it's hardly - * critical for efficiency. - */ -void -lbnInsertLittleBytes_32(BNWORD32 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD32 t = 0; /* Shut up uninitialized varibale warnings */ - - /* Move to most-significant end */ - lsbyte += buflen; - buf += buflen; - - BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8)); - - /* Load up leading odd bytes */ - if (lsbyte % (32/8)) { - t = BIGLITTLE(*--n,*n++); - t >>= (lsbyte * 8) % 32; - } - - /* The main loop - merge into t, storing at each word boundary. */ - while (buflen--) { - t = (t << 8) | *--buf; - if ((--lsbyte % (32/8)) == 0) - BIGLITTLE(*n++,*--n) = t; - } - - /* Merge odd bytes in t into last word */ - lsbyte = (lsbyte * 8) % 32; - if (lsbyte) { - t <<= lsbyte; - t |= (((BNWORD32)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); - BIGLITTLE(n[0],n[-1]) = t; - } - - return; -} - -#ifdef DEADCODE /* This was a precursor to the more flexible lbnExtractBytes */ -/* - * Convert a big-endian array of bytes to a bignum. - * Returns the number of words in the bignum. - * Note the expression "32/8" for the number of bytes per word. - * This is so the word-size adjustment will work. - */ -unsigned -lbnFromBytes_32(BNWORD32 *a, unsigned char const *b, unsigned blen) -{ - BNWORD32 t; - unsigned alen = (blen + (32/8-1))/(32/8); - BIGLITTLE(a -= alen, a += alen); - - while (blen) { - t = 0; - do { - t = t << 8 | *b++; - } while (--blen & (32/8-1)); - BIGLITTLE(*a++,*--a) = t; - } - return alen; -} -#endif - -/* - * Computes the GCD of a and b. Modifies both arguments; when it returns, - * one of them is the GCD and the other is trash. The return value - * indicates which: 0 for a, and 1 for b. The length of the retult is - * returned in rlen. Both inputs must have one extra word of precision. - * alen must be >= blen. - * - * TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B). - * This is based on taking out common powers of 2, then repeatedly: - * gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted. - * gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced. - * It gets less reduction per step, but the steps are much faster than - * the division case. - */ -int -lbnGcd_32(BNWORD32 *a, unsigned alen, BNWORD32 *b, unsigned blen, - unsigned *rlen) -{ -#if BNYIELD - int y; -#endif - assert(alen >= blen); - - while (blen != 0) { - (void)lbnDiv_32(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); - alen = lbnNorm_32(a, blen); - if (alen == 0) { - *rlen = blen; - return 1; - } - (void)lbnDiv_32(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); - blen = lbnNorm_32(b, alen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - return y; -#endif - } - *rlen = alen; - return 0; -} - -/* - * Invert "a" modulo "mod" using the extended Euclidean algorithm. - * Note that this only computes one of the cosequences, and uses the - * theorem that the signs flip every step and the absolute value of - * the cosequence values are always bounded by the modulus to avoid - * having to work with negative numbers. - * gcd(a,mod) had better equal 1. Returns 1 if the GCD is NOT 1. - * a must be one word longer than "mod". It is overwritten with the - * result. - * TODO: Use Richard Schroeppel's *much* faster algorithm. - */ -int -lbnInv_32(BNWORD32 *a, unsigned alen, BNWORD32 const *mod, unsigned mlen) -{ - BNWORD32 *b; /* Hold a copy of mod during GCD reduction */ - BNWORD32 *p; /* Temporary for products added to t0 and t1 */ - BNWORD32 *t0, *t1; /* Inverse accumulators */ - BNWORD32 cy; - unsigned blen, t0len, t1len, plen; - int y; - - alen = lbnNorm_32(a, alen); - if (!alen) - return 1; /* No inverse */ - - mlen = lbnNorm_32(mod, mlen); - - assert (alen <= mlen); - - /* Inverse of 1 is 1 */ - if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) { - lbnZero_32(BIGLITTLE(a-alen,a+alen), mlen-alen); - return 0; - } - - /* Allocate a pile of space */ - LBNALLOC(b, BNWORD32, mlen+1); - if (b) { - /* - * Although products are guaranteed to always be less than the - * modulus, it can involve multiplying two 3-word numbers to - * get a 5-word result, requiring a 6th word to store a 0 - * temporarily. Thus, mlen + 1. - */ - LBNALLOC(p, BNWORD32, mlen+1); - if (p) { - LBNALLOC(t0, BNWORD32, mlen); - if (t0) { - LBNALLOC(t1, BNWORD32, mlen); - if (t1) - goto allocated; - LBNFREE(t0, mlen); - } - LBNFREE(p, mlen+1); - } - LBNFREE(b, mlen+1); - } - return -1; - -allocated: - - /* Set t0 to 1 */ - t0len = 1; - BIGLITTLE(t0[-1],t0[0]) = 1; - - /* b = mod */ - lbnCopy_32(b, mod, mlen); - /* blen = mlen (implicitly) */ - - /* t1 = b / a; b = b % a */ - cy = lbnDiv_32(t1, b, mlen, a, alen); - *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy; - t1len = lbnNorm_32(t1, mlen-alen+1); - blen = lbnNorm_32(b, alen); - - /* while (b > 1) */ - while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD32)1) { - /* q = a / b; a = a % b; */ - if (alen < blen || (alen == blen && lbnCmp_32(a, a, alen) < 0)) - assert(0); - cy = lbnDiv_32(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); - *(BIGLITTLE(a-alen-1,a+alen)) = cy; - plen = lbnNorm_32(BIGLITTLE(a-blen,a+blen), alen-blen+1); - assert(plen); - alen = lbnNorm_32(a, blen); - if (!alen) - goto failure; /* GCD not 1 */ - - /* t0 += q * t1; */ - assert(plen+t1len <= mlen+1); - lbnMul_32(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len); - plen = lbnNorm_32(p, plen + t1len); - assert(plen <= mlen); - if (plen > t0len) { - lbnZero_32(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len); - t0len = plen; - } - cy = lbnAddN_32(t0, p, plen); - if (cy) { - if (t0len > plen) { - cy = lbnAdd1_32(BIGLITTLE(t0-plen,t0+plen), - t0len-plen, cy); - } - if (cy) { - BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy; - t0len++; - } - } - - /* if (a <= 1) return a ? t0 : FAIL; */ - if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD32)1) { - if (alen == 0) - goto failure; /* FAIL */ - assert(t0len <= mlen); - lbnCopy_32(a, t0, t0len); - lbnZero_32(BIGLITTLE(a-t0len, a+t0len), mlen-t0len); - goto success; - } - - /* q = b / a; b = b % a; */ - if (blen < alen || (blen == alen && lbnCmp_32(b, a, alen) < 0)) - assert(0); - cy = lbnDiv_32(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); - *(BIGLITTLE(b-blen-1,b+blen)) = cy; - plen = lbnNorm_32(BIGLITTLE(b-alen,b+alen), blen-alen+1); - assert(plen); - blen = lbnNorm_32(b, alen); - if (!blen) - goto failure; /* GCD not 1 */ - - /* t1 += q * t0; */ - assert(plen+t0len <= mlen+1); - lbnMul_32(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len); - plen = lbnNorm_32(p, plen + t0len); - assert(plen <= mlen); - if (plen > t1len) { - lbnZero_32(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len); - t1len = plen; - } - cy = lbnAddN_32(t1, p, plen); - if (cy) { - if (t1len > plen) { - cy = lbnAdd1_32(BIGLITTLE(t1-plen,t0+plen), - t1len-plen, cy); - } - if (cy) { - BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy; - t1len++; - } - } -#if BNYIELD - if (bnYield && (y = bnYield() < 0)) - goto yield; -#endif - } - - if (!blen) - goto failure; /* gcd(a, mod) != 1 -- FAIL */ - - /* return mod-t1 */ - lbnCopy_32(a, mod, mlen); - assert(t1len <= mlen); - cy = lbnSubN_32(a, t1, t1len); - if (cy) { - assert(mlen > t1len); - cy = lbnSub1_32(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy); - assert(!cy); - } - -success: - LBNFREE(t1, mlen); - LBNFREE(t0, mlen); - LBNFREE(p, mlen+1); - LBNFREE(b, mlen+1); - - return 0; - -failure: /* GCD is not 1 - no inverse exists! */ - y = 1; -#if BNYIELD -yield: -#endif - LBNFREE(t1, mlen); - LBNFREE(t0, mlen); - LBNFREE(p, mlen+1); - LBNFREE(b, mlen+1); - - return y; -} - -/* - * Precompute powers of "a" mod "mod". Compute them every "bits" - * for "n" steps. This is sufficient to compute powers of g with - * exponents up to n*bits bits long, i.e. less than 2^(n*bits). - * - * This assumes that the caller has already initialized "array" to point - * to "n" buffers of size "mlen". - */ -int -lbnBasePrecompBegin_32(BNWORD32 **array, unsigned n, unsigned bits, - BNWORD32 const *g, unsigned glen, BNWORD32 *mod, unsigned mlen) -{ - BNWORD32 *a, *b; /* Temporary double-width accumulators */ - BNWORD32 *a1; /* Pointer to high half of a*/ - BNWORD32 inv; /* Montgomery inverse of LSW of mod */ - BNWORD32 *t; - unsigned i; - - glen = lbnNorm_32(g, glen); - assert(glen); - - assert (mlen == lbnNorm_32(mod, mlen)); - assert (glen <= mlen); - - /* Allocate two temporary buffers, and the array slots */ - LBNALLOC(a, BNWORD32, mlen*2); - if (!a) - return -1; - LBNALLOC(b, BNWORD32, mlen*2); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Okay, all ready */ - - /* Convert n to Montgomery form */ - inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */ - assert(inv & 1); /* Modulus must be odd */ - inv = lbnMontInv1_32(inv); - /* Move g up "mlen" words into a (clearing the low mlen words) */ - a1 = BIGLITTLE(a-mlen,a+mlen); - lbnCopy_32(a1, g, glen); - lbnZero_32(a, mlen); - - /* Do the division - dump the quotient into the high-order words */ - (void)lbnDiv_32(a1, a, mlen+glen, mod, mlen); - - /* Copy the first value into the array */ - t = *array; - lbnCopy_32(t, a, mlen); - a1 = a; /* This first value is *not* shifted up */ - - /* Now compute the remaining n-1 array entries */ - assert(bits); - assert(n); - while (--n) { - i = bits; - do { - /* Square a1 into b1 */ - lbnMontSquare_32(b, a1, mod, mlen, inv); - t = b; b = a; a = t; - a1 = BIGLITTLE(a-mlen, a+mlen); - } while (--i); - t = *++array; - lbnCopy_32(t, a1, mlen); - } - - /* Hooray, we're done. */ - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - return 0; -} - -/* - * result = base^exp (mod mod). "array" is a an array of pointers - * to procomputed powers of base, each 2^bits apart. (I.e. array[i] - * is base^(2^(i*bits))). - * - * The algorithm consists of: - * a = b = (powers of g to be raised to the power 2^bits-1) - * a *= b *= (powers of g to be raised to the power 2^bits-2) - * ... - * a *= b *= (powers of g to be raised to the power 1) - * - * All we do is walk the exponent 2^bits-1 times in groups of "bits" bits, - */ -int -lbnBasePrecompExp_32(BNWORD32 *result, BNWORD32 const * const *array, - unsigned bits, BNWORD32 const *exp, unsigned elen, - BNWORD32 const *mod, unsigned mlen) -{ - BNWORD32 *a, *b, *c, *t; - BNWORD32 *a1, *b1; - int anull, bnull; /* Null flags: values are implicitly 1 */ - unsigned i, j; /* Loop counters */ - unsigned mask; /* Exponent bits to examime */ - BNWORD32 const *eptr; /* Pointer into exp */ - BNWORD32 buf, curbits, nextword; /* Bit-buffer varaibles */ - BNWORD32 inv; /* Inverse of LSW of modulus */ - unsigned ewords; /* Words of exponent left */ - int bufbits; /* Number of valid bits */ - int y = 0; - - mlen = lbnNorm_32(mod, mlen); - assert (mlen); - - elen = lbnNorm_32(exp, elen); - if (!elen) { - lbnZero_32(result, mlen); - BIGLITTLE(result[-1],result[0]) = 1; - return 0; - } - /* - * This could be precomputed, but it's so cheap, and it would require - * making the precomputation structure word-size dependent. - */ - inv = lbnMontInv1_32(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - assert(elen); - - /* - * Allocate three temporary buffers. The current numbers generally - * live in the upper halves of these buffers. - */ - LBNALLOC(a, BNWORD32, mlen*2); - if (a) { - LBNALLOC(b, BNWORD32, mlen*2); - if (b) { - LBNALLOC(c, BNWORD32, mlen*2); - if (c) - goto allocated; - LBNFREE(b, 2*mlen); - } - LBNFREE(a, 2*mlen); - } - return -1; - -allocated: - - anull = bnull = 1; - - mask = (1u<<bits) - 1; - for (i = mask; i; --i) { - /* Set up bit buffer for walking the exponent */ - eptr = exp; - buf = BIGLITTLE(*--eptr, *eptr++); - ewords = elen-1; - bufbits = 32; - for (j = 0; ewords || buf; j++) { - /* Shift down current buffer */ - curbits = buf; - buf >>= bits; - /* If necessary, add next word */ - bufbits -= bits; - if (bufbits < 0 && ewords > 0) { - nextword = BIGLITTLE(*--eptr, *eptr++); - ewords--; - curbits |= nextword << (bufbits+bits); - buf = nextword >> -bufbits; - bufbits += 32; - } - /* If appropriate, multiply b *= array[j] */ - if ((curbits & mask) == i) { - BNWORD32 const *d = array[j]; - - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (bnull) { - lbnCopy_32(b1, d, mlen); - bnull = 0; - } else { - lbnMontMul_32(c, b1, d, mod, mlen, inv); - t = c; c = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield() < 0)) - goto yield; -#endif - } - } - - /* Multiply a *= b */ - if (!bnull) { - a1 = BIGLITTLE(a-mlen-1,a+mlen); - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (anull) { - lbnCopy_32(a1, b1, mlen); - anull = 0; - } else { - lbnMontMul_32(c, a1, b1, mod, mlen, inv); - t = c; c = a; a = t; - } - } - } - - assert(!anull); /* If it were, elen would have been 0 */ - - /* Convert out of Montgomery form and return */ - a1 = BIGLITTLE(a-mlen-1,a+mlen); - lbnCopy_32(a, a1, mlen); - lbnZero_32(a1, mlen); - lbnMontReduce_32(a, mod, mlen, inv); - lbnCopy_32(result, a1, mlen); - -#if BNYIELD -yield: -#endif - LBNFREE(c, 2*mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; -} - -/* - * result = base1^exp1 *base2^exp2 (mod mod). "array1" and "array2" are - * arrays of pointers to procomputed powers of the corresponding bases, - * each 2^bits apart. (I.e. array1[i] is base1^(2^(i*bits))). - * - * Bits must be the same in both. (It could be made adjustable, but it's - * a bit of a pain. Just make them both equal to the larger one.) - * - * The algorithm consists of: - * a = b = (powers of base1 and base2 to be raised to the power 2^bits-1) - * a *= b *= (powers of base1 and base2 to be raised to the power 2^bits-2) - * ... - * a *= b *= (powers of base1 and base2 to be raised to the power 1) - * - * All we do is walk the exponent 2^bits-1 times in groups of "bits" bits, - */ -int -lbnDoubleBasePrecompExp_32(BNWORD32 *result, unsigned bits, - BNWORD32 const * const *array1, BNWORD32 const *exp1, unsigned elen1, - BNWORD32 const * const *array2, BNWORD32 const *exp2, - unsigned elen2, BNWORD32 const *mod, unsigned mlen) -{ - BNWORD32 *a, *b, *c, *t; - BNWORD32 *a1, *b1; - int anull, bnull; /* Null flags: values are implicitly 1 */ - unsigned i, j, k; /* Loop counters */ - unsigned mask; /* Exponent bits to examime */ - BNWORD32 const *eptr; /* Pointer into exp */ - BNWORD32 buf, curbits, nextword; /* Bit-buffer varaibles */ - BNWORD32 inv; /* Inverse of LSW of modulus */ - unsigned ewords; /* Words of exponent left */ - int bufbits; /* Number of valid bits */ - int y = 0; - BNWORD32 const * const *array; - - mlen = lbnNorm_32(mod, mlen); - assert (mlen); - - elen1 = lbnNorm_32(exp1, elen1); - if (!elen1) { - return lbnBasePrecompExp_32(result, array2, bits, exp2, elen2, - mod, mlen); - } - elen2 = lbnNorm_32(exp2, elen2); - if (!elen2) { - return lbnBasePrecompExp_32(result, array1, bits, exp1, elen1, - mod, mlen); - } - /* - * This could be precomputed, but it's so cheap, and it would require - * making the precomputation structure word-size dependent. - */ - inv = lbnMontInv1_32(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - assert(elen1); - assert(elen2); - - /* - * Allocate three temporary buffers. The current numbers generally - * live in the upper halves of these buffers. - */ - LBNALLOC(a, BNWORD32, mlen*2); - if (a) { - LBNALLOC(b, BNWORD32, mlen*2); - if (b) { - LBNALLOC(c, BNWORD32, mlen*2); - if (c) - goto allocated; - LBNFREE(b, 2*mlen); - } - LBNFREE(a, 2*mlen); - } - return -1; - -allocated: - - anull = bnull = 1; - - mask = (1u<<bits) - 1; - for (i = mask; i; --i) { - /* Walk each exponent in turn */ - for (k = 0; k < 2; k++) { - /* Set up the exponent for walking */ - array = k ? array2 : array1; - eptr = k ? exp2 : exp1; - ewords = (k ? elen2 : elen1) - 1; - /* Set up bit buffer for walking the exponent */ - buf = BIGLITTLE(*--eptr, *eptr++); - bufbits = 32; - for (j = 0; ewords || buf; j++) { - /* Shift down current buffer */ - curbits = buf; - buf >>= bits; - /* If necessary, add next word */ - bufbits -= bits; - if (bufbits < 0 && ewords > 0) { - nextword = BIGLITTLE(*--eptr, *eptr++); - ewords--; - curbits |= nextword << (bufbits+bits); - buf = nextword >> -bufbits; - bufbits += 32; - } - /* If appropriate, multiply b *= array[j] */ - if ((curbits & mask) == i) { - BNWORD32 const *d = array[j]; - - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (bnull) { - lbnCopy_32(b1, d, mlen); - bnull = 0; - } else { - lbnMontMul_32(c, b1, d, mod, mlen, inv); - t = c; c = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield() < 0)) - goto yield; -#endif - } - } - } - - /* Multiply a *= b */ - if (!bnull) { - a1 = BIGLITTLE(a-mlen-1,a+mlen); - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (anull) { - lbnCopy_32(a1, b1, mlen); - anull = 0; - } else { - lbnMontMul_32(c, a1, b1, mod, mlen, inv); - t = c; c = a; a = t; - } - } - } - - assert(!anull); /* If it were, elen would have been 0 */ - - /* Convert out of Montgomery form and return */ - a1 = BIGLITTLE(a-mlen-1,a+mlen); - lbnCopy_32(a, a1, mlen); - lbnZero_32(a1, mlen); - lbnMontReduce_32(a, mod, mlen, inv); - lbnCopy_32(result, a1, mlen); - -#if BNYIELD -yield: -#endif - LBNFREE(c, 2*mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; -} diff --git a/jni/libzrtp/sources/bnlib/lbn32.h b/jni/libzrtp/sources/bnlib/lbn32.h deleted file mode 100644 index e975550bb..000000000 --- a/jni/libzrtp/sources/bnlib/lbn32.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef LBN32_H -#define LBN32_H - -#include "lbn.h" - -#ifndef BNWORD32 -#error 32-bit bignum library requires a 32-bit data type -#endif - -#ifndef lbnCopy_32 -void lbnCopy_32(BNWORD32 *dest, BNWORD32 const *src, unsigned len); -#endif -#ifndef lbnZero_32 -void lbnZero_32(BNWORD32 *num, unsigned len); -#endif -#ifndef lbnNeg_32 -void lbnNeg_32(BNWORD32 *num, unsigned len); -#endif - -#ifndef lbnAdd1_32 -BNWORD32 lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry); -#endif -#ifndef lbnSub1_32 -BNWORD32 lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow); -#endif - -#ifndef lbnAddN_32 -BNWORD32 lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len); -#endif -#ifndef lbnSubN_32 -BNWORD32 lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len); -#endif - -#ifndef lbnCmp_32 -int lbnCmp_32(BNWORD32 const *num1, BNWORD32 const *num2, unsigned len); -#endif - -#ifndef lbnMulN1_32 -void lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k); -#endif -#ifndef lbnMulAdd1_32 -BNWORD32 -lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k); -#endif -#ifndef lbnMulSub1_32 -BNWORD32 lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k); -#endif - -#ifndef lbnLshift_32 -BNWORD32 lbnLshift_32(BNWORD32 *num, unsigned len, unsigned shift); -#endif -#ifndef lbnDouble_32 -BNWORD32 lbnDouble_32(BNWORD32 *num, unsigned len); -#endif -#ifndef lbnRshift_32 -BNWORD32 lbnRshift_32(BNWORD32 *num, unsigned len, unsigned shift); -#endif - -#ifndef lbnMul_32 -void lbnMul_32(BNWORD32 *prod, BNWORD32 const *num1, unsigned len1, - BNWORD32 const *num2, unsigned len2); -#endif -#ifndef lbnSquare_32 -void lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len); -#endif - -#ifndef lbnNorm_32 -unsigned lbnNorm_32(BNWORD32 const *num, unsigned len); -#endif -#ifndef lbnBits_32 -unsigned lbnBits_32(BNWORD32 const *num, unsigned len); -#endif - -#ifndef lbnExtractBigBytes_32 -void lbnExtractBigBytes_32(BNWORD32 const *bn, unsigned char *buf, - unsigned lsbyte, unsigned buflen); -#endif -#ifndef lbnInsertBigytes_32 -void lbnInsertBigBytes_32(BNWORD32 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen); -#endif -#ifndef lbnExtractLittleBytes_32 -void lbnExtractLittleBytes_32(BNWORD32 const *bn, unsigned char *buf, - unsigned lsbyte, unsigned buflen); -#endif -#ifndef lbnInsertLittleBytes_32 -void lbnInsertLittleBytes_32(BNWORD32 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen); -#endif - -#ifndef lbnDiv21_32 -BNWORD32 lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d); -#endif -#ifndef lbnDiv1_32 -BNWORD32 lbnDiv1_32(BNWORD32 *q, BNWORD32 *rem, - BNWORD32 const *n, unsigned len, BNWORD32 d); -#endif -#ifndef lbnModQ_32 -unsigned lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d); -#endif -#ifndef lbnDiv_32 -BNWORD32 -lbnDiv_32(BNWORD32 *q, BNWORD32 *n, unsigned nlen, BNWORD32 *d, unsigned dlen); -#endif - -#ifndef lbnMontInv1_32 -BNWORD32 lbnMontInv1_32(BNWORD32 const x); -#endif -#ifndef lbnMontReduce_32 -void lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned const mlen, - BNWORD32 inv); -#endif -#ifndef lbnToMont_32 -void lbnToMont_32(BNWORD32 *n, unsigned nlen, BNWORD32 *mod, unsigned mlen); -#endif -#ifndef lbnFromMont_32 -void lbnFromMont_32(BNWORD32 *n, BNWORD32 *mod, unsigned len); -#endif - -#ifndef lbnExpMod_32 -int lbnExpMod_32(BNWORD32 *result, BNWORD32 const *n, unsigned nlen, - BNWORD32 const *exp, unsigned elen, BNWORD32 *mod, unsigned mlen); -#endif -#ifndef lbnDoubleExpMod_32 -int lbnDoubleExpMod_32(BNWORD32 *result, - BNWORD32 const *n1, unsigned n1len, BNWORD32 const *e1, unsigned e1len, - BNWORD32 const *n2, unsigned n2len, BNWORD32 const *e2, unsigned e2len, - BNWORD32 *mod, unsigned mlen); -#endif -#ifndef lbnTwoExpMod_32 -int lbnTwoExpMod_32(BNWORD32 *n, BNWORD32 const *exp, unsigned elen, - BNWORD32 *mod, unsigned mlen); -#endif -#ifndef lbnGcd_32 -int lbnGcd_32(BNWORD32 *a, unsigned alen, BNWORD32 *b, unsigned blen, - unsigned *rlen); -#endif -#ifndef lbnInv_32 -int lbnInv_32(BNWORD32 *a, unsigned alen, BNWORD32 const *mod, unsigned mlen); -#endif - -int lbnBasePrecompBegin_32(BNWORD32 **array, unsigned n, unsigned bits, - BNWORD32 const *g, unsigned glen, BNWORD32 *mod, unsigned mlen); -int lbnBasePrecompExp_32(BNWORD32 *result, BNWORD32 const * const *array, - unsigned bits, BNWORD32 const *exp, unsigned elen, - BNWORD32 const *mod, unsigned mlen); -int lbnDoubleBasePrecompExp_32(BNWORD32 *result, unsigned bits, - BNWORD32 const * const *array1, BNWORD32 const *exp1, unsigned elen1, - BNWORD32 const * const *array2, BNWORD32 const *exp2, - unsigned elen2, BNWORD32 const *mod, unsigned mlen); - -#endif /* LBN32_H */ diff --git a/jni/libzrtp/sources/bnlib/lbn64.c b/jni/libzrtp/sources/bnlib/lbn64.c deleted file mode 100644 index e93065224..000000000 --- a/jni/libzrtp/sources/bnlib/lbn64.c +++ /dev/null @@ -1,4073 +0,0 @@ -/* - * lbn64.c - Low-level bignum routines, 64-bit version. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - * - * NOTE: the magic constants "64" and "128" appear in many places in this - * file, including inside identifiers. Because it is not possible to - * ask "#ifdef" of a macro expansion, it is not possible to use the - * preprocessor to conditionalize these properly. Thus, this file is - * intended to be edited with textual search and replace to produce - * alternate word size versions. Any reference to the number of bits - * in a word must be the string "64", and that string must not appear - * otherwise. Any reference to twice this number must appear as "128", - * which likewise must not appear otherwise. Is that clear? - * - * Remember, when doubling the bit size replace the larger number (128) - * first, then the smaller (64). When halving the bit size, do the - * opposite. Otherwise, things will get wierd. Also, be sure to replace - * every instance that appears. (:%s/foo/bar/g in vi) - * - * These routines work with a pointer to the least-significant end of - * an array of WORD64s. The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros - * defined in lbn.h (which expand to x on a big-edian machine and y on a - * little-endian machine) are used to conditionalize the code to work - * either way. If you have no assembly primitives, it doesn't matter. - * Note that on a big-endian machine, the least-significant-end pointer - * is ONE PAST THE END. The bytes are ptr[-1] through ptr[-len]. - * On little-endian, they are ptr[0] through ptr[len-1]. This makes - * perfect sense if you consider pointers to point *between* bytes rather - * than at them. - * - * Because the array index values are unsigned integers, ptr[-i] - * may not work properly, since the index -i is evaluated as an unsigned, - * and if pointers are wider, zero-extension will produce a positive - * number rahter than the needed negative. The expression used in this - * code, *(ptr-i) will, however, work. (The array syntax is equivalent - * to *(ptr+-i), which is a pretty subtle difference.) - * - * Many of these routines will get very unhappy if fed zero-length inputs. - * They use assert() to enforce this. An higher layer of code must make - * sure that these aren't called with zero-length inputs. - * - * Any of these routines can be replaced with more efficient versions - * elsewhere, by just #defining their names. If one of the names - * is #defined, the C code is not compiled in and no declaration is - * made. Use the BNINCLUDE file to do that. Typically, you compile - * asm subroutines with the same name and just, e.g. - * #define lbnMulAdd1_64 lbnMulAdd1_64 - * - * If you want to write asm routines, start with lbnMulAdd1_64(). - * This is the workhorse of modular exponentiation. lbnMulN1_64() is - * also used a fair bit, although not as much and it's defined in terms - * of lbnMulAdd1_64 if that has a custom version. lbnMulSub1_64 and - * lbnDiv21_64 are used in the usual division and remainder finding. - * (Not the Montgomery reduction used in modular exponentiation, though.) - * Once you have lbnMulAdd1_64 defined, writing the other two should - * be pretty easy. (Just make sure you get the sign of the subtraction - * in lbnMulSub1_64 right - it's dest = dest - source * k.) - * - * The only definitions that absolutely need a double-word (BNWORD128) - * type are lbnMulAdd1_64 and lbnMulSub1_64; if those are provided, - * the rest follows. lbnDiv21_64, however, is a lot slower unless you - * have them, and lbnModQ_64 takes after it. That one is used quite a - * bit for prime sieving. - */ - -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include <bnconfig.h> -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_ASSERT_H -#define NO_ASSERT_H 0 -#endif -#ifndef NO_STRING_H -#define NO_STRING_H 0 -#endif -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 0 -#endif -#ifndef NEED_MEMORY_H -#define NEED_MEMORY_H 0 -#endif - -#if !NO_ASSERT_H -#include <assert.h> -#else -#define assert(x) (void)0 -#endif - -#if !NO_STRING_H -#include <string.h> /* For memcpy */ -#elif HAVE_STRINGS_H -#include <strings.h> -#endif -#if NEED_MEMORY_H -#include <memory.h> -#endif - -#include "lbn.h" -#include "lbn64.h" -#include "lbnmem.h" - -#include "kludge.h" - -#ifndef BNWORD64 -#error 64-bit bignum library requires a 64-bit data type -#endif - -/* If this is defined, include bnYield() calls */ -#if BNYIELD -extern int (*bnYield)(void); /* From bn.c */ -#endif - -/* - * Most of the multiply (and Montgomery reduce) routines use an outer - * loop that iterates over one of the operands - a so-called operand - * scanning approach. One big advantage of this is that the assembly - * support routines are simpler. The loops can be rearranged to have - * an outer loop that iterates over the product, a so-called product - * scanning approach. This has the advantage of writing less data - * and doing fewer adds to memory, so is supposedly faster. Some - * code has been written using a product-scanning approach, but - * it appears to be slower, so it is turned off by default. Some - * experimentation would be appreciated. - * - * (The code is also annoying to get right and not very well commented, - * one of my pet peeves about math libraries. I'm sorry.) - */ -#ifndef PRODUCT_SCAN -#define PRODUCT_SCAN 0 -#endif - -/* - * Copy an array of words. <Marvin mode on> Thrilling, isn't it? </Marvin> - * This is a good example of how the byte offsets and BIGLITTLE() macros work. - * Another alternative would have been - * memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD64)), but I find that - * putting operators into conditional macros is confusing. - */ -#ifndef lbnCopy_64 -void -lbnCopy_64(BNWORD64 *dest, BNWORD64 const *src, unsigned len) -{ - memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src), - len * sizeof(*src)); -} -#endif /* !lbnCopy_64 */ - -/* - * Fill n words with zero. This does it manually rather than calling - * memset because it can assume alignment to make things faster while - * memset can't. Note how big-endian numbers are naturally addressed - * using predecrement, while little-endian is postincrement. - */ -#ifndef lbnZero_64 -void -lbnZero_64(BNWORD64 *num, unsigned len) -{ - while (len--) - BIGLITTLE(*--num,*num++) = 0; -} -#endif /* !lbnZero_64 */ - -/* - * Negate an array of words. - * Negation is subtraction from zero. Negating low-order words - * entails doing nothing until a non-zero word is hit. Once that - * is negated, a borrow is generated and never dies until the end - * of the number is hit. Negation with borrow, -x-1, is the same as ~x. - * Repeat that until the end of the number. - * - * Doesn't return borrow out because that's pretty useless - it's - * always set unless the input is 0, which is easy to notice in - * normalized form. - */ -#ifndef lbnNeg_64 -void -lbnNeg_64(BNWORD64 *num, unsigned len) -{ - assert(len); - - /* Skip low-order zero words */ - while (BIGLITTLE(*--num,*num) == 0) { - if (!--len) - return; - LITTLE(num++;) - } - /* Negate the lowest-order non-zero word */ - *num = -*num; - /* Complement all the higher-order words */ - while (--len) { - BIGLITTLE(--num,++num); - *num = ~*num; - } -} -#endif /* !lbnNeg_64 */ - - -/* - * lbnAdd1_64: add the single-word "carry" to the given number. - * Used for minor increments and propagating the carry after - * adding in a shorter bignum. - * - * Technique: If we have a double-width word, presumably the compiler - * can add using its carry in inline code, so we just use a larger - * accumulator to compute the carry from the first addition. - * If not, it's more complex. After adding the first carry, which may - * be > 1, compare the sum and the carry. If the sum wraps (causing a - * carry out from the addition), the result will be less than each of the - * inputs, since the wrap subtracts a number (2^64) which is larger than - * the other input can possibly be. If the sum is >= the carry input, - * return success immediately. - * In either case, if there is a carry, enter a loop incrementing words - * until one does not wrap. Since we are adding 1 each time, the wrap - * will be to 0 and we can test for equality. - */ -#ifndef lbnAdd1_64 /* If defined, it's provided as an asm subroutine */ -#ifdef BNWORD128 -BNWORD64 -lbnAdd1_64(BNWORD64 *num, unsigned len, BNWORD64 carry) -{ - BNWORD128 t; - assert(len > 0); /* Alternative: if (!len) return carry */ - - t = (BNWORD128)BIGLITTLE(*--num,*num) + carry; - BIGLITTLE(*num,*num++) = (BNWORD64)t; - if ((t >> 64) == 0) - return 0; - while (--len) { - if (++BIGLITTLE(*--num,*num++) != 0) - return 0; - } - return 1; -} -#else /* no BNWORD128 */ -BNWORD64 -lbnAdd1_64(BNWORD64 *num, unsigned len, BNWORD64 carry) -{ - assert(len > 0); /* Alternative: if (!len) return carry */ - - if ((BIGLITTLE(*--num,*num++) += carry) >= carry) - return 0; - while (--len) { - if (++BIGLITTLE(*--num,*num++) != 0) - return 0; - } - return 1; -} -#endif -#endif/* !lbnAdd1_64 */ - -/* - * lbnSub1_64: subtract the single-word "borrow" from the given number. - * Used for minor decrements and propagating the borrow after - * subtracting a shorter bignum. - * - * Technique: Similar to the add, above. If there is a double-length type, - * use that to generate the first borrow. - * If not, after subtracting the first borrow, which may be > 1, compare - * the difference and the *negative* of the carry. If the subtract wraps - * (causing a borrow out from the subtraction), the result will be at least - * as large as -borrow. If the result < -borrow, then no borrow out has - * appeared and we may return immediately, except when borrow == 0. To - * deal with that case, use the identity that -x = ~x+1, and instead of - * comparing < -borrow, compare for <= ~borrow. - * Either way, if there is a borrow out, enter a loop decrementing words - * until a non-zero word is reached. - * - * Note the cast of ~borrow to (BNWORD64). If the size of an int is larger - * than BNWORD64, C rules say the number is expanded for the arithmetic, so - * the inversion will be done on an int and the value won't be quite what - * is expected. - */ -#ifndef lbnSub1_64 /* If defined, it's provided as an asm subroutine */ -#ifdef BNWORD128 -BNWORD64 -lbnSub1_64(BNWORD64 *num, unsigned len, BNWORD64 borrow) -{ - BNWORD128 t; - assert(len > 0); /* Alternative: if (!len) return borrow */ - - t = (BNWORD128)BIGLITTLE(*--num,*num) - borrow; - BIGLITTLE(*num,*num++) = (BNWORD64)t; - if ((t >> 64) == 0) - return 0; - while (--len) { - if ((BIGLITTLE(*--num,*num++))-- != 0) - return 0; - } - return 1; -} -#else /* no BNWORD128 */ -BNWORD64 -lbnSub1_64(BNWORD64 *num, unsigned len, BNWORD64 borrow) -{ - assert(len > 0); /* Alternative: if (!len) return borrow */ - - if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD64)~borrow) - return 0; - while (--len) { - if ((BIGLITTLE(*--num,*num++))-- != 0) - return 0; - } - return 1; -} -#endif -#endif /* !lbnSub1_64 */ - -/* - * lbnAddN_64: add two bignums of the same length, returning the carry (0 or 1). - * One of the building blocks, along with lbnAdd1, of adding two bignums of - * differing lengths. - * - * Technique: Maintain a word of carry. If there is no double-width type, - * use the same technique as in lbnAdd1, above, to maintain the carry by - * comparing the inputs. Adding the carry sources is used as an OR operator; - * at most one of the two comparisons can possibly be true. The first can - * only be true if carry == 1 and x, the result, is 0. In that case the - * second can't possibly be true. - */ -#ifndef lbnAddN_64 -#ifdef BNWORD128 -BNWORD64 -lbnAddN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len) -{ - BNWORD128 t; - - assert(len > 0); - - t = (BNWORD128)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++); - BIGLITTLE(*num1,*num1++) = (BNWORD64)t; - while (--len) { - t = (BNWORD128)BIGLITTLE(*--num1,*num1) + - (BNWORD128)BIGLITTLE(*--num2,*num2++) + (t >> 64); - BIGLITTLE(*num1,*num1++) = (BNWORD64)t; - } - - return (BNWORD64)(t>>64); -} -#else /* no BNWORD128 */ -BNWORD64 -lbnAddN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len) -{ - BNWORD64 x, carry = 0; - - assert(len > 0); /* Alternative: change loop to test at start */ - - do { - x = BIGLITTLE(*--num2,*num2++); - carry = (x += carry) < carry; - carry += (BIGLITTLE(*--num1,*num1++) += x) < x; - } while (--len); - - return carry; -} -#endif -#endif /* !lbnAddN_64 */ - -/* - * lbnSubN_64: add two bignums of the same length, returning the carry (0 or 1). - * One of the building blocks, along with subn1, of subtracting two bignums of - * differing lengths. - * - * Technique: If no double-width type is availble, maintain a word of borrow. - * First, add the borrow to the subtrahend (did you have to learn all those - * awful words in elementary school, too?), and if it overflows, set the - * borrow again. Then subtract the modified subtrahend from the next word - * of input, using the same technique as in subn1, above. - * Adding the borrows is used as an OR operator; at most one of the two - * comparisons can possibly be true. The first can only be true if - * borrow == 1 and x, the result, is 0. In that case the second can't - * possibly be true. - * - * In the double-word case, (BNWORD64)-(t>>64) is subtracted, rather than - * adding t>>64, because the shift would need to sign-extend and that's - * not guaranteed to happen in ANSI C, even with signed types. - */ -#ifndef lbnSubN_64 -#ifdef BNWORD128 -BNWORD64 -lbnSubN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len) -{ - BNWORD128 t; - - assert(len > 0); - - t = (BNWORD128)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++); - BIGLITTLE(*num1,*num1++) = (BNWORD64)t; - - while (--len) { - t = (BNWORD128)BIGLITTLE(*--num1,*num1) - - (BNWORD128)BIGLITTLE(*--num2,*num2++) - (BNWORD64)-(t >> 64); - BIGLITTLE(*num1,*num1++) = (BNWORD64)t; - } - - return -(BNWORD64)(t>>64); -} -#else -BNWORD64 -lbnSubN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len) -{ - BNWORD64 x, borrow = 0; - - assert(len > 0); /* Alternative: change loop to test at start */ - - do { - x = BIGLITTLE(*--num2,*num2++); - borrow = (x += borrow) < borrow; - borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD64)~x; - } while (--len); - - return borrow; -} -#endif -#endif /* !lbnSubN_64 */ - -#ifndef lbnCmp_64 -/* - * lbnCmp_64: compare two bignums of equal length, returning the sign of - * num1 - num2. (-1, 0 or +1). - * - * Technique: Change the little-endian pointers to big-endian pointers - * and compare from the most-significant end until a difference if found. - * When it is, figure out the sign of the difference and return it. - */ -int -lbnCmp_64(BNWORD64 const *num1, BNWORD64 const *num2, unsigned len) -{ - BIGLITTLE(num1 -= len, num1 += len); - BIGLITTLE(num2 -= len, num2 += len); - - while (len--) { - if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) { - if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2)) - return -1; - else - return 1; - } - } - return 0; -} -#endif /* !lbnCmp_64 */ - -/* - * mul64_ppmmaa(ph,pl,x,y,a,b) is an optional routine that - * computes (ph,pl) = x * y + a + b. mul64_ppmma and mul64_ppmm - * are simpler versions. If you want to be lazy, all of these - * can be defined in terms of the others, so here we create any - * that have not been defined in terms of the ones that have been. - */ - -/* Define ones with fewer a's in terms of ones with more a's */ -#if !defined(mul64_ppmma) && defined(mul64_ppmmaa) -#define mul64_ppmma(ph,pl,x,y,a) mul64_ppmmaa(ph,pl,x,y,a,0) -#endif - -#if !defined(mul64_ppmm) && defined(mul64_ppmma) -#define mul64_ppmm(ph,pl,x,y) mul64_ppmma(ph,pl,x,y,0) -#endif - -/* - * Use this definition to test the mul64_ppmm-based operations on machines - * that do not provide mul64_ppmm. Change the final "0" to a "1" to - * enable it. - */ -#if !defined(mul64_ppmm) && defined(BNWORD128) && 0 /* Debugging */ -#define mul64_ppmm(ph,pl,x,y) \ - ({BNWORD128 _ = (BNWORD128)(x)*(y); (pl) = _; (ph) = _>>64;}) -#endif - -#if defined(mul64_ppmm) && !defined(mul64_ppmma) -#define mul64_ppmma(ph,pl,x,y,a) \ - (mul64_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a)) -#endif - -#if defined(mul64_ppmma) && !defined(mul64_ppmmaa) -#define mul64_ppmmaa(ph,pl,x,y,a,b) \ - (mul64_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b)) -#endif - -/* - * lbnMulN1_64: Multiply an n-word input by a 1-word input and store the - * n+1-word product. This uses either the mul64_ppmm and mul64_ppmma - * macros, or C multiplication with the BNWORD128 type. This uses mul64_ppmma - * if available, assuming you won't bother defining it unless you can do - * better than the normal multiplication. - */ -#ifndef lbnMulN1_64 -#ifdef lbnMulAdd1_64 /* If we have this asm primitive, use it. */ -void -lbnMulN1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k) -{ - lbnZero_64(out, len); - BIGLITTLE(*(out-len-1),*(out+len)) = lbnMulAdd1_64(out, in, len, k); -} -#elif defined(mul64_ppmm) -void -lbnMulN1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k) -{ - BNWORD64 carry, carryin; - - assert(len > 0); - - BIG(--out;--in;); - mul64_ppmm(carry, *out, *in, k); - LITTLE(out++;in++;) - - while (--len) { - BIG(--out;--in;) - carryin = carry; - mul64_ppmma(carry, *out, *in, k, carryin); - LITTLE(out++;in++;) - } - BIGLITTLE(*--out,*out) = carry; -} -#elif defined(BNWORD128) -void -lbnMulN1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k) -{ - BNWORD128 p; - - assert(len > 0); - - p = (BNWORD128)BIGLITTLE(*--in,*in++) * k; - BIGLITTLE(*--out,*out++) = (BNWORD64)p; - - while (--len) { - p = (BNWORD128)BIGLITTLE(*--in,*in++) * k + (BNWORD64)(p >> 64); - BIGLITTLE(*--out,*out++) = (BNWORD64)p; - } - BIGLITTLE(*--out,*out) = (BNWORD64)(p >> 64); -} -#else -#error No 64x64 -> 128 multiply available for 64-bit bignum package -#endif -#endif /* lbnMulN1_64 */ - -/* - * lbnMulAdd1_64: Multiply an n-word input by a 1-word input and add the - * low n words of the product to the destination. *Returns the n+1st word - * of the product.* (That turns out to be more convenient than adding - * it into the destination and dealing with a possible unit carry out - * of *that*.) This uses either the mul64_ppmma and mul64_ppmmaa macros, - * or C multiplication with the BNWORD128 type. - * - * If you're going to write assembly primitives, this is the one to - * start with. It is by far the most commonly called function. - */ -#ifndef lbnMulAdd1_64 -#if defined(mul64_ppmm) -BNWORD64 -lbnMulAdd1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k) -{ - BNWORD64 prod, carry, carryin; - - assert(len > 0); - - BIG(--out;--in;); - carryin = *out; - mul64_ppmma(carry, *out, *in, k, carryin); - LITTLE(out++;in++;) - - while (--len) { - BIG(--out;--in;); - carryin = carry; - mul64_ppmmaa(carry, prod, *in, k, carryin, *out); - *out = prod; - LITTLE(out++;in++;) - } - - return carry; -} -#elif defined(BNWORD128) -BNWORD64 -lbnMulAdd1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k) -{ - BNWORD128 p; - - assert(len > 0); - - p = (BNWORD128)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out); - BIGLITTLE(*out,*out++) = (BNWORD64)p; - - while (--len) { - p = (BNWORD128)BIGLITTLE(*--in,*in++) * k + - (BNWORD64)(p >> 64) + BIGLITTLE(*--out,*out); - BIGLITTLE(*out,*out++) = (BNWORD64)p; - } - - return (BNWORD64)(p >> 64); -} -#else -#error No 64x64 -> 128 multiply available for 64-bit bignum package -#endif -#endif /* lbnMulAdd1_64 */ - -/* - * lbnMulSub1_64: Multiply an n-word input by a 1-word input and subtract the - * n-word product from the destination. Returns the n+1st word of the product. - * This uses either the mul64_ppmm and mul64_ppmma macros, or - * C multiplication with the BNWORD128 type. - * - * This is rather uglier than adding, but fortunately it's only used in - * division which is not used too heavily. - */ -#ifndef lbnMulSub1_64 -#if defined(mul64_ppmm) -BNWORD64 -lbnMulSub1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k) -{ - BNWORD64 prod, carry, carryin; - - assert(len > 0); - - BIG(--in;) - mul64_ppmm(carry, prod, *in, k); - LITTLE(in++;) - carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD64)~prod; - - while (--len) { - BIG(--in;); - carryin = carry; - mul64_ppmma(carry, prod, *in, k, carryin); - LITTLE(in++;) - carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD64)~prod; - } - - return carry; -} -#elif defined(BNWORD128) -BNWORD64 -lbnMulSub1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k) -{ - BNWORD128 p; - BNWORD64 carry, t; - - assert(len > 0); - - p = (BNWORD128)BIGLITTLE(*--in,*in++) * k; - t = BIGLITTLE(*--out,*out); - carry = (BNWORD64)(p>>64) + ((BIGLITTLE(*out,*out++)=t-(BNWORD64)p) > t); - - while (--len) { - p = (BNWORD128)BIGLITTLE(*--in,*in++) * k + carry; - t = BIGLITTLE(*--out,*out); - carry = (BNWORD64)(p>>64) + - ( (BIGLITTLE(*out,*out++)=t-(BNWORD64)p) > t ); - } - - return carry; -} -#else -#error No 64x64 -> 128 multiply available for 64-bit bignum package -#endif -#endif /* !lbnMulSub1_64 */ - -/* - * Shift n words left "shift" bits. 0 < shift < 64. Returns the - * carry, any bits shifted off the left-hand side (0 <= carry < 2^shift). - */ -#ifndef lbnLshift_64 -BNWORD64 -lbnLshift_64(BNWORD64 *num, unsigned len, unsigned shift) -{ - BNWORD64 x, carry; - - assert(shift > 0); - assert(shift < 64); - - carry = 0; - while (len--) { - BIG(--num;) - x = *num; - *num = (x<<shift) | carry; - LITTLE(num++;) - carry = x >> (64-shift); - } - return carry; -} -#endif /* !lbnLshift_64 */ - -/* - * An optimized version of the above, for shifts of 1. - * Some machines can use add-with-carry tricks for this. - */ -#ifndef lbnDouble_64 -BNWORD64 -lbnDouble_64(BNWORD64 *num, unsigned len) -{ - BNWORD64 x, carry; - - carry = 0; - while (len--) { - BIG(--num;) - x = *num; - *num = (x<<1) | carry; - LITTLE(num++;) - carry = x >> (64-1); - } - return carry; -} -#endif /* !lbnDouble_64 */ - -/* - * Shift n words right "shift" bits. 0 < shift < 64. Returns the - * carry, any bits shifted off the right-hand side (0 <= carry < 2^shift). - */ -#ifndef lbnRshift_64 -BNWORD64 -lbnRshift_64(BNWORD64 *num, unsigned len, unsigned shift) -{ - BNWORD64 x, carry = 0; - - assert(shift > 0); - assert(shift < 64); - - BIGLITTLE(num -= len, num += len); - - while (len--) { - LITTLE(--num;) - x = *num; - *num = (x>>shift) | carry; - BIG(num++;) - carry = x << (64-shift); - } - return carry >> (64-shift); -} -#endif /* !lbnRshift_64 */ - -/* - * Multiply two numbers of the given lengths. prod and num2 may overlap, - * provided that the low len1 bits of prod are free. (This corresponds - * nicely to the place the result is returned from lbnMontReduce_64.) - * - * TODO: Use Karatsuba multiply. The overlap constraints may have - * to get rewhacked. - */ -#ifndef lbnMul_64 -void -lbnMul_64(BNWORD64 *prod, BNWORD64 const *num1, unsigned len1, - BNWORD64 const *num2, unsigned len2) -{ - /* Special case of zero */ - if (!len1 || !len2) { - lbnZero_64(prod, len1+len2); - return; - } - - /* Multiply first word */ - lbnMulN1_64(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); - - /* - * Add in subsequent words, storing the most significant word, - * which is new each time. - */ - while (--len2) { - BIGLITTLE(--prod,prod++); - BIGLITTLE(*(prod-len1-1),*(prod+len1)) = - lbnMulAdd1_64(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); - } -} -#endif /* !lbnMul_64 */ - -/* - * lbnMulX_64 is a square multiply - both inputs are the same length. - * It's normally just a macro wrapper around the general multiply, - * but might be implementable in assembly more efficiently (such as - * when product scanning). - */ -#ifndef lbnMulX_64 -#if defined(BNWORD128) && PRODUCT_SCAN -/* - * Test code to see whether product scanning is any faster. It seems - * to make the C code slower, so PRODUCT_SCAN is not defined. - */ -static void -lbnMulX_64(BNWORD64 *prod, BNWORD64 const *num1, BNWORD64 const *num2, - unsigned len) -{ - BNWORD128 x, y; - BNWORD64 const *p1, *p2; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!len) - return; - - x = (BNWORD128)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); - BIGLITTLE(*--prod, *prod++) = (BNWORD64)x; - x >>= 64; - - for (i = 1; i < len; i++) { - carry = 0; - p1 = num1; - p2 = BIGLITTLE(num2-i-1,num2+i+1); - for (j = 0; j <= i; j++) { - BIG(y = (BNWORD128)*--p1 * *p2++;) - LITTLE(y = (BNWORD128)*p1++ * *--p2;) - x += y; - carry += (x < y); - } - BIGLITTLE(*--prod,*prod++) = (BNWORD64)x; - x = (x >> 64) | (BNWORD128)carry << 64; - } - for (i = 1; i < len; i++) { - carry = 0; - p1 = BIGLITTLE(num1-i,num1+i); - p2 = BIGLITTLE(num2-len,num2+len); - for (j = i; j < len; j++) { - BIG(y = (BNWORD128)*--p1 * *p2++;) - LITTLE(y = (BNWORD128)*p1++ * *--p2;) - x += y; - carry += (x < y); - } - BIGLITTLE(*--prod,*prod++) = (BNWORD64)x; - x = (x >> 64) | (BNWORD128)carry << 64; - } - - BIGLITTLE(*--prod,*prod) = (BNWORD64)x; -} -#else /* !defined(BNWORD128) || !PRODUCT_SCAN */ -/* Default trivial macro definition */ -#define lbnMulX_64(prod, num1, num2, len) lbnMul_64(prod, num1, len, num2, len) -#endif /* !defined(BNWORD128) || !PRODUCT_SCAN */ -#endif /* !lbmMulX_64 */ - -#if !defined(lbnMontMul_64) && defined(BNWORD128) && PRODUCT_SCAN -/* - * Test code for product-scanning multiply. This seems to slow the C - * code down rather than speed it up. - * This does a multiply and Montgomery reduction together, using the - * same loops. The outer loop scans across the product, twice. - * The first pass computes the low half of the product and the - * Montgomery multipliers. These are stored in the product array, - * which contains no data as of yet. x and carry add up the columns - * and propagate carries forward. - * - * The second half multiplies the upper half, adding in the modulus - * times the Montgomery multipliers. The results of this multiply - * are stored. - */ -static void -lbnMontMul_64(BNWORD64 *prod, BNWORD64 const *num1, BNWORD64 const *num2, - BNWORD64 const *mod, unsigned len, BNWORD64 inv) -{ - BNWORD128 x, y; - BNWORD64 const *p1, *p2, *pm; - BNWORD64 *pp; - BNWORD64 t; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!len) - return; - - /* - * This computes directly into the high half of prod, so just - * shift the pointer and consider prod only "len" elements long - * for the rest of the code. - */ - BIGLITTLE(prod -= len, prod += len); - - /* Pass 1 - compute Montgomery multipliers */ - /* First iteration can have certain simplifications. */ - x = (BNWORD128)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); - BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD64)x; - y = (BNWORD128)t * BIGLITTLE(mod[-1],mod[0]); - x += y; - /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */ - carry = (x < y); - assert((BNWORD64)x == 0); - x = x >> 64 | (BNWORD128)carry << 64; - - for (i = 1; i < len; i++) { - carry = 0; - p1 = num1; - p2 = BIGLITTLE(num2-i-1,num2+i+1); - pp = prod; - pm = BIGLITTLE(mod-i-1,mod+i+1); - for (j = 0; j < i; j++) { - y = (BNWORD128)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); - x += y; - carry += (x < y); - y = (BNWORD128)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm); - x += y; - carry += (x < y); - } - y = (BNWORD128)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]); - x += y; - carry += (x < y); - assert(BIGLITTLE(pp == prod-i, pp == prod+i)); - BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD64)x; - assert(BIGLITTLE(pm == mod-1, pm == mod+1)); - y = (BNWORD128)t * BIGLITTLE(pm[0],pm[-1]); - x += y; - carry += (x < y); - assert((BNWORD64)x == 0); - x = x >> 64 | (BNWORD128)carry << 64; - } - - /* Pass 2 - compute reduced product and store */ - for (i = 1; i < len; i++) { - carry = 0; - p1 = BIGLITTLE(num1-i,num1+i); - p2 = BIGLITTLE(num2-len,num2+len); - pm = BIGLITTLE(mod-i,mod+i); - pp = BIGLITTLE(prod-len,prod+len); - for (j = i; j < len; j++) { - y = (BNWORD128)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); - x += y; - carry += (x < y); - y = (BNWORD128)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp); - x += y; - carry += (x < y); - } - assert(BIGLITTLE(pm == mod-len, pm == mod+len)); - assert(BIGLITTLE(pp == prod-i, pp == prod+i)); - BIGLITTLE(pp[0],pp[-1]) = (BNWORD64)x; - x = (x >> 64) | (BNWORD128)carry << 64; - } - - /* Last round of second half, simplified. */ - BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD64)x; - carry = (x >> 64); - - while (carry) - carry -= lbnSubN_64(prod, mod, len); - while (lbnCmp_64(prod, mod, len) >= 0) - (void)lbnSubN_64(prod, mod, len); -} -/* Suppress later definition */ -#define lbnMontMul_64 lbnMontMul_64 -#endif - -#if !defined(lbnSquare_64) && defined(BNWORD128) && PRODUCT_SCAN -/* - * Trial code for product-scanning squaring. This seems to slow the C - * code down rather than speed it up. - */ -void -lbnSquare_64(BNWORD64 *prod, BNWORD64 const *num, unsigned len) -{ - BNWORD128 x, y, z; - BNWORD64 const *p1, *p2; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!len) - return; - - /* Word 0 of product */ - x = (BNWORD128)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]); - BIGLITTLE(*--prod, *prod++) = (BNWORD64)x; - x >>= 64; - - /* Words 1 through len-1 */ - for (i = 1; i < len; i++) { - carry = 0; - y = 0; - p1 = num; - p2 = BIGLITTLE(num-i-1,num+i+1); - for (j = 0; j < (i+1)/2; j++) { - BIG(z = (BNWORD128)*--p1 * *p2++;) - LITTLE(z = (BNWORD128)*p1++ * *--p2;) - y += z; - carry += (y < z); - } - y += z = y; - carry += carry + (y < z); - if ((i & 1) == 0) { - assert(BIGLITTLE(--p1 == p2, p1 == --p2)); - BIG(z = (BNWORD128)*p2 * *p2;) - LITTLE(z = (BNWORD128)*p1 * *p1;) - y += z; - carry += (y < z); - } - x += y; - carry += (x < y); - BIGLITTLE(*--prod,*prod++) = (BNWORD64)x; - x = (x >> 64) | (BNWORD128)carry << 64; - } - /* Words len through 2*len-2 */ - for (i = 1; i < len; i++) { - carry = 0; - y = 0; - p1 = BIGLITTLE(num-i,num+i); - p2 = BIGLITTLE(num-len,num+len); - for (j = 0; j < (len-i)/2; j++) { - BIG(z = (BNWORD128)*--p1 * *p2++;) - LITTLE(z = (BNWORD128)*p1++ * *--p2;) - y += z; - carry += (y < z); - } - y += z = y; - carry += carry + (y < z); - if ((len-i) & 1) { - assert(BIGLITTLE(--p1 == p2, p1 == --p2)); - BIG(z = (BNWORD128)*p2 * *p2;) - LITTLE(z = (BNWORD128)*p1 * *p1;) - y += z; - carry += (y < z); - } - x += y; - carry += (x < y); - BIGLITTLE(*--prod,*prod++) = (BNWORD64)x; - x = (x >> 64) | (BNWORD128)carry << 64; - } - - /* Word 2*len-1 */ - BIGLITTLE(*--prod,*prod) = (BNWORD64)x; -} -/* Suppress later definition */ -#define lbnSquare_64 lbnSquare_64 -#endif - -/* - * Square a number, using optimized squaring to reduce the number of - * primitive multiples that are executed. There may not be any - * overlap of the input and output. - * - * Technique: Consider the partial products in the multiplication - * of "abcde" by itself: - * - * a b c d e - * * a b c d e - * ================== - * ae be ce de ee - * ad bd cd dd de - * ac bc cc cd ce - * ab bb bc bd be - * aa ab ac ad ae - * - * Note that everything above the main diagonal: - * ae be ce de = (abcd) * e - * ad bd cd = (abc) * d - * ac bc = (ab) * c - * ab = (a) * b - * - * is a copy of everything below the main diagonal: - * de - * cd ce - * bc bd be - * ab ac ad ae - * - * Thus, the sum is 2 * (off the diagonal) + diagonal. - * - * This is accumulated beginning with the diagonal (which - * consist of the squares of the digits of the input), which is then - * divided by two, the off-diagonal added, and multiplied by two - * again. The low bit is simply a copy of the low bit of the - * input, so it doesn't need special care. - * - * TODO: Merge the shift by 1 with the squaring loop. - * TODO: Use Karatsuba. (a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W. - */ -#ifndef lbnSquare_64 -void -lbnSquare_64(BNWORD64 *prod, BNWORD64 const *num, unsigned len) -{ - BNWORD64 t; - BNWORD64 *prodx = prod; /* Working copy of the argument */ - BNWORD64 const *numx = num; /* Working copy of the argument */ - unsigned lenx = len; /* Working copy of the argument */ - - if (!len) - return; - - /* First, store all the squares */ - while (lenx--) { -#ifdef mul64_ppmm - BNWORD64 ph, pl; - t = BIGLITTLE(*--numx,*numx++); - mul64_ppmm(ph,pl,t,t); - BIGLITTLE(*--prodx,*prodx++) = pl; - BIGLITTLE(*--prodx,*prodx++) = ph; -#elif defined(BNWORD128) /* use BNWORD128 */ - BNWORD128 p; - t = BIGLITTLE(*--numx,*numx++); - p = (BNWORD128)t * t; - BIGLITTLE(*--prodx,*prodx++) = (BNWORD64)p; - BIGLITTLE(*--prodx,*prodx++) = (BNWORD64)(p>>64); -#else /* Use lbnMulN1_64 */ - t = BIGLITTLE(numx[-1],*numx); - lbnMulN1_64(prodx, numx, 1, t); - BIGLITTLE(--numx,numx++); - BIGLITTLE(prodx -= 2, prodx += 2); -#endif - } - /* Then, shift right 1 bit */ - (void)lbnRshift_64(prod, 2*len, 1); - - /* Then, add in the off-diagonal sums */ - lenx = len; - numx = num; - prodx = prod; - while (--lenx) { - t = BIGLITTLE(*--numx,*numx++); - BIGLITTLE(--prodx,prodx++); - t = lbnMulAdd1_64(prodx, numx, lenx, t); - lbnAdd1_64(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t); - BIGLITTLE(--prodx,prodx++); - } - - /* Shift it back up */ - lbnDouble_64(prod, 2*len); - - /* And set the low bit appropriately */ - BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1; -} -#endif /* !lbnSquare_64 */ - -/* - * lbnNorm_64 - given a number, return a modified length such that the - * most significant digit is non-zero. Zero-length input is okay. - */ -#ifndef lbnNorm_64 -unsigned -lbnNorm_64(BNWORD64 const *num, unsigned len) -{ - BIGLITTLE(num -= len,num += len); - while (len && BIGLITTLE(*num++,*--num) == 0) - --len; - return len; -} -#endif /* lbnNorm_64 */ - -/* - * lbnBits_64 - return the number of significant bits in the array. - * It starts by normalizing the array. Zero-length input is okay. - * Then assuming there's anything to it, it fetches the high word, - * generates a bit length by multiplying the word length by 64, and - * subtracts off 64/2, 64/4, 64/8, ... bits if the high bits are clear. - */ -#ifndef lbnBits_64 -unsigned -lbnBits_64(BNWORD64 const *num, unsigned len) -{ - BNWORD64 t; - unsigned i; - - len = lbnNorm_64(num, len); - if (len) { - t = BIGLITTLE(*(num-len),*(num+(len-1))); - assert(t); - len *= 64; - i = 64/2; - do { - if (t >> i) - t >>= i; - else - len -= i; - } while ((i /= 2) != 0); - } - return len; -} -#endif /* lbnBits_64 */ - -/* - * If defined, use hand-rolled divide rather than compiler's native. - * If the machine doesn't do it in line, the manual code is probably - * faster, since it can assume normalization and the fact that the - * quotient will fit into 64 bits, which a general 128-bit divide - * in a compiler's run-time library can't do. - */ -#ifndef BN_SLOW_DIVIDE_128 -/* Assume that divisors of more than thirty-two bits are slow */ -#define BN_SLOW_DIVIDE_128 (128 > 0x20) -#endif - -/* - * Return (nh<<64|nl) % d, and place the quotient digit into *q. - * It is guaranteed that nh < d, and that d is normalized (with its high - * bit set). If we have a double-width type, it's easy. If not, ooh, - * yuk! - */ -#ifndef lbnDiv21_64 -#if defined(BNWORD128) && !BN_SLOW_DIVIDE_128 -BNWORD64 -lbnDiv21_64(BNWORD64 *q, BNWORD64 nh, BNWORD64 nl, BNWORD64 d) -{ - BNWORD128 n = (BNWORD128)nh << 64 | nl; - - /* Divisor must be normalized */ - assert(d >> (64-1) == 1); - - *q = n / d; - return n % d; -} -#else -/* - * This is where it gets ugly. - * - * Do the division in two halves, using Algorithm D from section 4.3.1 - * of Knuth. Note Theorem B from that section, that the quotient estimate - * is never more than the true quotient, and is never more than two - * too low. - * - * The mapping onto conventional long division is (everything a half word): - * _____________qh___ql_ - * dh dl ) nh.h nh.l nl.h nl.l - * - (qh * d) - * ----------- - * rrrr rrrr nl.l - * - (ql * d) - * ----------- - * rrrr rrrr - * - * The implicit 3/2-digit d*qh and d*ql subtractors are computed this way: - * First, estimate a q digit so that nh/dh works. Subtracting qh*dh from - * the (nh.h nh.l) list leaves a 1/2-word remainder r. Then compute the - * low part of the subtractor, qh * dl. This also needs to be subtracted - * from (nh.h nh.l nl.h) to get the final remainder. So we take the - * remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and - * try to subtract qh * dl from that. Since the remainder is 1/2-word - * long, shifting and adding nl.h results in a single word r. - * It is possible that the remainder we're working with, r, is less than - * the product qh * dl, if we estimated qh too high. The estimation - * technique can produce a qh that is too large (never too small), leading - * to r which is too small. In that case, decrement the digit qh, add - * shifted dh to r (to correct for that error), and subtract dl from the - * product we're comparing r with. That's the "correct" way to do it, but - * just adding dl to r instead of subtracting it from the product is - * equivalent and a lot simpler. You just have to watch out for overflow. - * - * The process is repeated with (rrrr rrrr nl.l) for the low digit of the - * quotient ql. - * - * The various uses of 64/2 for shifts are because of the note about - * automatic editing of this file at the very top of the file. - */ -#define highhalf(x) ( (x) >> 64/2 ) -#define lowhalf(x) ( (x) & (((BNWORD64)1 << 64/2)-1) ) -BNWORD64 -lbnDiv21_64(BNWORD64 *q, BNWORD64 nh, BNWORD64 nl, BNWORD64 d) -{ - BNWORD64 dh = highhalf(d), dl = lowhalf(d); - BNWORD64 qh, ql, prod, r; - - /* Divisor must be normalized */ - assert((d >> (64-1)) == 1); - - /* Do first half-word of division */ - qh = nh / dh; - r = nh % dh; - prod = qh * dl; - - /* - * Add next half-word of numerator to remainder and correct. - * qh may be up to two too large. - */ - r = (r << (64/2)) | highhalf(nl); - if (r < prod) { - --qh; r += d; - if (r >= d && r < prod) { - --qh; r += d; - } - } - r -= prod; - - /* Do second half-word of division */ - ql = r / dh; - r = r % dh; - prod = ql * dl; - - r = (r << (64/2)) | lowhalf(nl); - if (r < prod) { - --ql; r += d; - if (r >= d && r < prod) { - --ql; r += d; - } - } - r -= prod; - - *q = (qh << (64/2)) | ql; - - return r; -} -#endif -#endif /* lbnDiv21_64 */ - - -/* - * In the division functions, the dividend and divisor are referred to - * as "n" and "d", which stand for "numerator" and "denominator". - * - * The quotient is (nlen-dlen+1) digits long. It may be overlapped with - * the high (nlen-dlen) words of the dividend, but one extra word is needed - * on top to hold the top word. - */ - -/* - * Divide an n-word number by a 1-word number, storing the remainder - * and n-1 words of the n-word quotient. The high word is returned. - * It IS legal for rem to point to the same address as n, and for - * q to point one word higher. - * - * TODO: If BN_SLOW_DIVIDE_128, add a divnhalf_64 which uses 64-bit - * dividends if the divisor is half that long. - * TODO: Shift the dividend on the fly to avoid the last division and - * instead have a remainder that needs shifting. - * TODO: Use reciprocals rather than dividing. - */ -#ifndef lbnDiv1_64 -BNWORD64 -lbnDiv1_64(BNWORD64 *q, BNWORD64 *rem, BNWORD64 const *n, unsigned len, - BNWORD64 d) -{ - unsigned shift; - unsigned xlen; - BNWORD64 r; - BNWORD64 qhigh; - - assert(len > 0); - assert(d); - - if (len == 1) { - r = *n; - *rem = r%d; - return r/d; - } - - shift = 0; - r = d; - xlen = 64/2; - do { - if (r >> xlen) - r >>= xlen; - else - shift += xlen; - } while ((xlen /= 2) != 0); - assert((d >> (64-1-shift)) == 1); - d <<= shift; - - BIGLITTLE(q -= len-1,q += len-1); - BIGLITTLE(n -= len,n += len); - - r = BIGLITTLE(*n++,*--n); - if (r < d) { - qhigh = 0; - } else { - qhigh = r/d; - r %= d; - } - - xlen = len; - while (--xlen) - r = lbnDiv21_64(BIGLITTLE(q++,--q), r, BIGLITTLE(*n++,*--n), d); - - /* - * Final correction for shift - shift the quotient up "shift" - * bits, and merge in the extra bits of quotient. Then reduce - * the final remainder mod the real d. - */ - if (shift) { - d >>= shift; - qhigh = (qhigh << shift) | lbnLshift_64(q, len-1, shift); - BIGLITTLE(q[-1],*q) |= r/d; - r %= d; - } - *rem = r; - - return qhigh; -} -#endif - -/* - * This function performs a "quick" modulus of a number with a divisor - * d which is guaranteed to be at most sixteen bits, i.e. less than 65536. - * This applies regardless of the word size the library is compiled with. - * - * This function is important to prime generation, for sieving. - */ -#ifndef lbnModQ_64 -/* If there's a custom lbnMod21_64, no normalization needed */ -#ifdef lbnMod21_64 -unsigned -lbnModQ_64(BNWORD64 const *n, unsigned len, unsigned d) -{ - unsigned i, shift; - BNWORD64 r; - - assert(len > 0); - - BIGLITTLE(n -= len,n += len); - - /* Try using a compare to avoid the first divide */ - r = BIGLITTLE(*n++,*--n); - if (r >= d) - r %= d; - while (--len) - r = lbnMod21_64(r, BIGLITTLE(*n++,*--n), d); - - return r; -} -#elif defined(BNWORD128) && !BN_SLOW_DIVIDE_128 -unsigned -lbnModQ_64(BNWORD64 const *n, unsigned len, unsigned d) -{ - BNWORD64 r; - - if (!--len) - return BIGLITTLE(n[-1],n[0]) % d; - - BIGLITTLE(n -= len,n += len); - r = BIGLITTLE(n[-1],n[0]); - - do { - r = (BNWORD64)((((BNWORD128)r<<64) | BIGLITTLE(*n++,*--n)) % d); - } while (--len); - - return r; -} -#elif 64 >= 0x20 -/* - * If the single word size can hold 65535*65536, then this function - * is avilable. - */ -#ifndef highhalf -#define highhalf(x) ( (x) >> 64/2 ) -#define lowhalf(x) ( (x) & ((1 << 64/2)-1) ) -#endif -unsigned -lbnModQ_64(BNWORD64 const *n, unsigned len, unsigned d) -{ - BNWORD64 r, x; - - BIGLITTLE(n -= len,n += len); - - r = BIGLITTLE(*n++,*--n); - while (--len) { - x = BIGLITTLE(*n++,*--n); - r = (r%d << 64/2) | highhalf(x); - r = (r%d << 64/2) | lowhalf(x); - } - - return r%d; -} -#else -/* Default case - use lbnDiv21_64 */ -unsigned -lbnModQ_64(BNWORD64 const *n, unsigned len, unsigned d) -{ - unsigned i, shift; - BNWORD64 r; - BNWORD64 q; - - assert(len > 0); - - shift = 0; - r = d; - i = 64; - while (i /= 2) { - if (r >> i) - r >>= i; - else - shift += i; - } - assert(d >> (64-1-shift) == 1); - d <<= shift; - - BIGLITTLE(n -= len,n += len); - - r = BIGLITTLE(*n++,*--n); - if (r >= d) - r %= d; - - while (--len) - r = lbnDiv21_64(&q, r, BIGLITTLE(*n++,*--n), d); - - /* - * Final correction for shift - shift the quotient up "shift" - * bits, and merge in the extra bits of quotient. Then reduce - * the final remainder mod the real d. - */ - if (shift) - r %= d >> shift; - - return r; -} -#endif -#endif /* lbnModQ_64 */ - -/* - * Reduce n mod d and return the quotient. That is, find: - * q = n / d; - * n = n % d; - * d is altered during the execution of this subroutine by normalizing it. - * It must already have its most significant word non-zero; it is shifted - * so its most significant bit is non-zero. - * - * The quotient q is nlen-dlen+1 words long. To make it possible to - * overlap the quptient with the input (you can store it in the high dlen - * words), the high word of the quotient is *not* stored, but is returned. - * (If all you want is the remainder, you don't care about it, anyway.) - * - * This uses algorithm D from Knuth (4.3.1), except that we do binary - * (shift) normalization of the divisor. WARNING: This is hairy! - * - * This function is used for some modular reduction, but it is not used in - * the modular exponentiation loops; they use Montgomery form and the - * corresponding, more efficient, Montgomery reduction. This code - * is needed for the conversion to Montgomery form, however, so it - * has to be here and it might as well be reasonably efficient. - * - * The overall operation is as follows ("top" and "up" refer to the - * most significant end of the number; "bottom" and "down", the least): - * - * - Shift the divisor up until the most significant bit is set. - * - Shift the dividend up the same amount. This will produce the - * correct quotient, and the remainder can be recovered by shifting - * it back down the same number of bits. This may produce an overflow - * word, but the word is always strictly less than the most significant - * divisor word. - * - Estimate the first quotient digit qhat: - * - First take the top two words (one of which is the overflow) of the - * dividend and divide by the top word of the divisor: - * qhat = (nh,nm)/dh. This qhat is >= the correct quotient digit - * and, since dh is normalized, it is at most two over. - * - Second, correct by comparing the top three words. If - * (dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again. - * The second iteration can be simpler because there can't be a third. - * The computation can be simplified by subtracting dh*qhat from - * both sides, suitably shifted. This reduces the left side to - * dl*qhat. On the right, (nh,nm)-dh*qhat is simply the - * remainder r from (nh,nm)%dh, so the right is (r,nl). - * This produces qhat that is almost always correct and at - * most (prob ~ 2/2^64) one too high. - * - Subtract qhat times the divisor (suitably shifted) from the dividend. - * If there is a borrow, qhat was wrong, so decrement it - * and add the divisor back in (once). - * - Store the final quotient digit qhat in the quotient array q. - * - * Repeat the quotient digit computation for successive digits of the - * quotient until the whole quotient has been computed. Then shift the - * divisor and the remainder down to correct for the normalization. - * - * TODO: Special case 2-word divisors. - * TODO: Use reciprocals rather than dividing. - */ -#ifndef divn_64 -BNWORD64 -lbnDiv_64(BNWORD64 *q, BNWORD64 *n, unsigned nlen, BNWORD64 *d, unsigned dlen) -{ - BNWORD64 nh,nm,nl; /* Top three words of the dividend */ - BNWORD64 dh,dl; /* Top two words of the divisor */ - BNWORD64 qhat; /* Extimate of quotient word */ - BNWORD64 r; /* Remainder from quotient estimate division */ - BNWORD64 qhigh; /* High word of quotient */ - unsigned i; /* Temp */ - unsigned shift; /* Bits shifted by normalization */ - unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */ -#ifdef mul64_ppmm - BNWORD64 t64; -#elif defined(BNWORD128) - BNWORD128 t128; -#else /* use lbnMulN1_64 */ - BNWORD64 t2[2]; -#define t2high BIGLITTLE(t2[0],t2[1]) -#define t2low BIGLITTLE(t2[1],t2[0]) -#endif - - assert(dlen); - assert(nlen >= dlen); - - /* - * Special cases for short divisors. The general case uses the - * top top 2 digits of the divisor (d) to estimate a quotient digit, - * so it breaks if there are fewer digits available. Thus, we need - * special cases for a divisor of length 1. A divisor of length - * 2 can have a *lot* of administrivia overhead removed removed, - * so it's probably worth special-casing that case, too. - */ - if (dlen == 1) - return lbnDiv1_64(q, BIGLITTLE(n-1,n), n, nlen, - BIGLITTLE(d[-1],d[0])); - -#if 0 - /* - * @@@ This is not yet written... The general loop will do, - * albeit less efficiently - */ - if (dlen == 2) { - /* - * divisor two digits long: - * use the 3/2 technique from Knuth, but we know - * it's exact. - */ - dh = BIGLITTLE(d[-1],d[0]); - dl = BIGLITTLE(d[-2],d[1]); - shift = 0; - if ((sh & ((BNWORD64)1 << 64-1-shift)) == 0) { - do { - shift++; - } while (dh & (BNWORD64)1<<64-1-shift) == 0); - dh = dh << shift | dl >> (64-shift); - dl <<= shift; - - - } - - - for (shift = 0; (dh & (BNWORD64)1 << 64-1-shift)) == 0; shift++) - ; - if (shift) { - } - dh = dh << shift | dl >> (64-shift); - shift = 0; - while (dh - } -#endif - - dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); - assert(dh); - - /* Normalize the divisor */ - shift = 0; - r = dh; - i = 64/2; - do { - if (r >> i) - r >>= i; - else - shift += i; - } while ((i /= 2) != 0); - - nh = 0; - if (shift) { - lbnLshift_64(d, dlen, shift); - dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); - nh = lbnLshift_64(n, nlen, shift); - } - - /* Assert that dh is now normalized */ - assert(dh >> (64-1)); - - /* Also get the second-most significant word of the divisor */ - dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2))); - - /* - * Adjust pointers: n to point to least significant end of first - * first subtract, and q to one the most-significant end of the - * quotient array. - */ - BIGLITTLE(n -= qlen,n += qlen); - BIGLITTLE(q -= qlen,q += qlen); - - /* Fetch the most significant stored word of the dividend */ - nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); - - /* - * Compute the first digit of the quotient, based on the - * first two words of the dividend (the most significant of which - * is the overflow word h). - */ - if (nh) { - assert(nh < dh); - r = lbnDiv21_64(&qhat, nh, nm, dh); - } else if (nm >= dh) { - qhat = nm/dh; - r = nm % dh; - } else { /* Quotient is zero */ - qhigh = 0; - goto divloop; - } - - /* Now get the third most significant word of the dividend */ - nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); - - /* - * Correct qhat, the estimate of quotient digit. - * qhat can only be high, and at most two words high, - * so the loop can be unrolled and abbreviated. - */ -#ifdef mul64_ppmm - mul64_ppmm(nm, t64, qhat, dl); - if (nm > r || (nm == r && t64 > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - nm -= (t64 < dl); - t64 -= dl; - if (nm > r || (nm == r && t64 > nl)) - qhat--; - } - } -#elif defined(BNWORD128) - t128 = (BNWORD128)qhat * dl; - if (t128 > ((BNWORD128)r << 64) + nl) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) > dh) { - t128 -= dl; - if (t128 > ((BNWORD128)r << 64) + nl) - qhat--; - } - } -#else /* Use lbnMulN1_64 */ - lbnMulN1_64(BIGLITTLE(t2+2,t2), &dl, 1, qhat); - if (t2high > r || (t2high == r && t2low > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - t2high -= (t2low < dl); - t2low -= dl; - if (t2high > r || (t2high == r && t2low > nl)) - qhat--; - } - } -#endif - - /* Do the multiply and subtract */ - r = lbnMulSub1_64(n, d, dlen, qhat); - /* If there was a borrow, add back once. */ - if (r > nh) { /* Borrow? */ - (void)lbnAddN_64(n, d, dlen); - qhat--; - } - - /* Remember the first quotient digit. */ - qhigh = qhat; - - /* Now, the main division loop: */ -divloop: - while (qlen--) { - - /* Advance n */ - nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); - BIGLITTLE(++n,--n); - nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); - - if (nh == dh) { - qhat = ~(BNWORD64)0; - /* Optimized computation of r = (nh,nm) - qhat * dh */ - r = nh + nm; - if (r < nh) - goto subtract; - } else { - assert(nh < dh); - r = lbnDiv21_64(&qhat, nh, nm, dh); - } - - nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); -#ifdef mul64_ppmm - mul64_ppmm(nm, t64, qhat, dl); - if (nm > r || (nm == r && t64 > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - nm -= (t64 < dl); - t64 -= dl; - if (nm > r || (nm == r && t64 > nl)) - qhat--; - } - } -#elif defined(BNWORD128) - t128 = (BNWORD128)qhat * dl; - if (t128 > ((BNWORD128)r<<64) + nl) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - t128 -= dl; - if (t128 > ((BNWORD128)r << 64) + nl) - qhat--; - } - } -#else /* Use lbnMulN1_64 */ - lbnMulN1_64(BIGLITTLE(t2+2,t2), &dl, 1, qhat); - if (t2high > r || (t2high == r && t2low > nl)) { - /* Decrement qhat and adjust comparison parameters */ - qhat--; - if ((r += dh) >= dh) { - t2high -= (t2low < dl); - t2low -= dl; - if (t2high > r || (t2high == r && t2low > nl)) - qhat--; - } - } -#endif - - /* - * As a point of interest, note that it is not worth checking - * for qhat of 0 or 1 and installing special-case code. These - * occur with probability 2^-64, so spending 1 cycle to check - * for them is only worth it if we save more than 2^15 cycles, - * and a multiply-and-subtract for numbers in the 1024-bit - * range just doesn't take that long. - */ -subtract: - /* - * n points to the least significant end of the substring - * of n to be subtracted from. qhat is either exact or - * one too large. If the subtract gets a borrow, it was - * one too large and the divisor is added back in. It's - * a dlen+1 word add which is guaranteed to produce a - * carry out, so it can be done very simply. - */ - r = lbnMulSub1_64(n, d, dlen, qhat); - if (r > nh) { /* Borrow? */ - (void)lbnAddN_64(n, d, dlen); - qhat--; - } - /* Store the quotient digit */ - BIGLITTLE(*q++,*--q) = qhat; - } - /* Tah dah! */ - - if (shift) { - lbnRshift_64(d, dlen, shift); - lbnRshift_64(n, dlen, shift); - } - - return qhigh; -} -#endif - -/* - * Find the negative multiplicative inverse of x (x must be odd!) modulo 2^64. - * - * This just performs Newton's iteration until it gets the - * inverse. The initial estimate is always correct to 3 bits, and - * sometimes 4. The number of valid bits doubles each iteration. - * (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable - * for the error mod 2^2n. x * y == 1 + k*2^n (mod 2^2n) and follow - * the iteration through.) - */ -#ifndef lbnMontInv1_64 -BNWORD64 -lbnMontInv1_64(BNWORD64 const x) -{ - BNWORD64 y = x, z; - - assert(x & 1); - - while ((z = x*y) != 1) - y *= 2 - z; - return -y; -} -#endif /* !lbnMontInv1_64 */ - -#if defined(BNWORD128) && PRODUCT_SCAN -/* - * Test code for product-scanning Montgomery reduction. - * This seems to slow the C code down rather than speed it up. - * - * The first loop computes the Montgomery multipliers, storing them over - * the low half of the number n. - * - * The second half multiplies the upper half, adding in the modulus - * times the Montgomery multipliers. The results of this multiply - * are stored. - */ -void -lbnMontReduce_64(BNWORD64 *n, BNWORD64 const *mod, unsigned mlen, BNWORD64 inv) -{ - BNWORD128 x, y; - BNWORD64 const *pm; - BNWORD64 *pn; - BNWORD64 t; - unsigned carry; - unsigned i, j; - - /* Special case of zero */ - if (!mlen) - return; - - /* Pass 1 - compute Montgomery multipliers */ - /* First iteration can have certain simplifications. */ - t = BIGLITTLE(n[-1],n[0]); - x = t; - t *= inv; - BIGLITTLE(n[-1], n[0]) = t; - x += (BNWORD128)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */ - assert((BNWORD64)x == 0); - x = x >> 64; - - for (i = 1; i < mlen; i++) { - carry = 0; - pn = n; - pm = BIGLITTLE(mod-i-1,mod+i+1); - for (j = 0; j < i; j++) { - y = (BNWORD128)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm); - x += y; - carry += (x < y); - } - assert(BIGLITTLE(pn == n-i, pn == n+i)); - y = t = BIGLITTLE(pn[-1], pn[0]); - x += y; - carry += (x < y); - BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD64)x; - assert(BIGLITTLE(pm == mod-1, pm == mod+1)); - y = (BNWORD128)t * BIGLITTLE(pm[0],pm[-1]); - x += y; - carry += (x < y); - assert((BNWORD64)x == 0); - x = x >> 64 | (BNWORD128)carry << 64; - } - - BIGLITTLE(n -= mlen, n += mlen); - - /* Pass 2 - compute upper words and add to n */ - for (i = 1; i < mlen; i++) { - carry = 0; - pm = BIGLITTLE(mod-i,mod+i); - pn = n; - for (j = i; j < mlen; j++) { - y = (BNWORD128)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn); - x += y; - carry += (x < y); - } - assert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen)); - assert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i)); - y = t = BIGLITTLE(*(n-i),*(n+i-1)); - x += y; - carry += (x < y); - BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD64)x; - x = (x >> 64) | (BNWORD128)carry << 64; - } - - /* Last round of second half, simplified. */ - t = BIGLITTLE(*(n-mlen),*(n+mlen-1)); - x += t; - BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD64)x; - carry = (unsigned)(x >> 64); - - while (carry) - carry -= lbnSubN_64(n, mod, mlen); - while (lbnCmp_64(n, mod, mlen) >= 0) - (void)lbnSubN_64(n, mod, mlen); -} -#define lbnMontReduce_64 lbnMontReduce_64 -#endif - -/* - * Montgomery reduce n, modulo mod. This reduces modulo mod and divides by - * 2^(64*mlen). Returns the result in the *top* mlen words of the argument n. - * This is ready for another multiplication using lbnMul_64. - * - * Montgomery representation is a very useful way to encode numbers when - * you're doing lots of modular reduction. What you do is pick a multiplier - * R which is relatively prime to the modulus and very easy to divide by. - * Since the modulus is odd, R is closen as a power of 2, so the division - * is a shift. In fact, it's a shift of an integral number of words, - * so the shift can be implicit - just drop the low-order words. - * - * Now, choose R *larger* than the modulus m, 2^(64*mlen). Then convert - * all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the - * relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. Note that: - * - The Montgomery form of a number depends on the modulus m. - * A fixed modulus m is assumed throughout this discussion. - * - Since R is relaitvely prime to m, multiplication by R is invertible; - * no information about the numbers is lost, they're just scrambled. - * - Adding (and subtracting) numbers in this form works just as usual. - * M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m - * - Multiplying numbers in this form produces a*b*R*R. The problem - * is to divide out the excess factor of R, modulo m as well as to - * reduce to the given length mlen. It turns out that this can be - * done *faster* than a normal divide, which is where the speedup - * in Montgomery division comes from. - * - * Normal reduction chooses a most-significant quotient digit q and then - * subtracts q*m from the number to be reduced. Choosing q is tricky - * and involved (just look at lbnDiv_64 to see!) and is usually - * imperfect, requiring a check for correction after the subtraction. - * - * Montgomery reduction *adds* a multiple of m to the *low-order* part - * of the number to be reduced. This multiple is chosen to make the - * low-order part of the number come out to zero. This can be done - * with no trickery or error using a precomputed inverse of the modulus. - * In this code, the "part" is one word, but any width can be used. - * - * Repeating this step sufficiently often results in a value which - * is a multiple of R (a power of two, remember) but is still (since - * the additions were to the low-order part and thus did not increase - * the value of the number being reduced very much) still not much - * larger than m*R. Then implicitly divide by R and subtract off - * m until the result is in the correct range. - * - * Since the low-order part being cancelled is less than R, the - * multiple of m added must have a multiplier which is at most R-1. - * Assuming that the input is at most m*R-1, the final number is - * at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from - * the high-order part, equivalent to subtracting m*R from the - * while number, produces a result which is at most m*R - m - 1, - * which divided by R is at most m-1. - * - * To convert *to* Montgomery form, you need a regular remainder - * routine, although you can just compute R*R (mod m) and do the - * conversion using Montgomery multiplication. To convert *from* - * Montgomery form, just Montgomery reduce the number to - * remove the extra factor of R. - * - * TODO: Change to a full inverse and use Karatsuba's multiplication - * rather than this word-at-a-time. - */ -#ifndef lbnMontReduce_64 -void -lbnMontReduce_64(BNWORD64 *n, BNWORD64 const *mod, unsigned const mlen, - BNWORD64 inv) -{ - BNWORD64 t; - BNWORD64 c = 0; - unsigned len = mlen; - - /* inv must be the negative inverse of mod's least significant word */ - assert((BNWORD64)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD64)-1); - - assert(len); - - do { - t = lbnMulAdd1_64(n, mod, mlen, inv * BIGLITTLE(n[-1],n[0])); - c += lbnAdd1_64(BIGLITTLE(n-mlen,n+mlen), len, t); - BIGLITTLE(--n,++n); - } while (--len); - - /* - * All that adding can cause an overflow past the modulus size, - * but it's unusual, and never by much, so a subtraction loop - * is the right way to deal with it. - * This subtraction happens infrequently - I've only ever seen it - * invoked once per reduction, and then just under 22.5% of the time. - */ - while (c) - c -= lbnSubN_64(n, mod, mlen); - while (lbnCmp_64(n, mod, mlen) >= 0) - (void)lbnSubN_64(n, mod, mlen); -} -#endif /* !lbnMontReduce_64 */ - -/* - * A couple of helpers that you might want to implement atomically - * in asm sometime. - */ -#ifndef lbnMontMul_64 -/* - * Multiply "num1" by "num2", modulo "mod", all of length "len", and - * place the result in the high half of "prod". "inv" is the inverse - * of the least-significant word of the modulus, modulo 2^64. - * This uses numbers in Montgomery form. Reduce using "len" and "inv". - * - * This is implemented as a macro to win on compilers that don't do - * inlining, since it's so trivial. - */ -#define lbnMontMul_64(prod, n1, n2, mod, len, inv) \ - (lbnMulX_64(prod, n1, n2, len), lbnMontReduce_64(prod, mod, len, inv)) -#endif /* !lbnMontMul_64 */ - -#ifndef lbnMontSquare_64 -/* - * Square "n", modulo "mod", both of length "len", and place the result - * in the high half of "prod". "inv" is the inverse of the least-significant - * word of the modulus, modulo 2^64. - * This uses numbers in Montgomery form. Reduce using "len" and "inv". - * - * This is implemented as a macro to win on compilers that don't do - * inlining, since it's so trivial. - */ -#define lbnMontSquare_64(prod, n, mod, len, inv) \ - (lbnSquare_64(prod, n, len), lbnMontReduce_64(prod, mod, len, inv)) - -#endif /* !lbnMontSquare_64 */ - -/* - * Convert a number to Montgomery form - requires mlen + nlen words - * of memory in "n". - */ -void -lbnToMont_64(BNWORD64 *n, unsigned nlen, BNWORD64 *mod, unsigned mlen) -{ - /* Move n up "mlen" words */ - lbnCopy_64(BIGLITTLE(n-mlen,n+mlen), n, nlen); - lbnZero_64(n, mlen); - /* Do the division - dump the quotient in the high-order words */ - (void)lbnDiv_64(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen); -} - -/* - * Convert from Montgomery form. Montgomery reduction is all that is - * needed. - */ -void -lbnFromMont_64(BNWORD64 *n, BNWORD64 *mod, unsigned len) -{ - /* Zero the high words of n */ - lbnZero_64(BIGLITTLE(n-len,n+len), len); - lbnMontReduce_64(n, mod, len, lbnMontInv1_64(mod[BIGLITTLE(-1,0)])); - /* Move n down len words */ - lbnCopy_64(n, BIGLITTLE(n-len,n+len), len); -} - -/* - * The windowed exponentiation algorithm, precomputes a table of odd - * powers of n up to 2^k. See the comment in bnExpMod_64 below for - * an explanation of how it actually works works. - * - * It takes 2^(k-1)-1 multiplies to compute the table, and (e-1)/(k+1) - * multiplies (on average) to perform the exponentiation. To minimize - * the sum, k must vary with e. The optimal window sizes vary with the - * exponent length. Here are some selected values and the boundary cases. - * (An underscore _ has been inserted into some of the numbers to ensure - * that magic strings like 64 do not appear in this table. It should be - * ignored.) - * - * At e = 1 bits, k=1 (0.000000) is best - * At e = 2 bits, k=1 (0.500000) is best - * At e = 4 bits, k=1 (1.500000) is best - * At e = 8 bits, k=2 (3.333333) < k=1 (3.500000) - * At e = 1_6 bits, k=2 (6.000000) is best - * At e = 26 bits, k=3 (9.250000) < k=2 (9.333333) - * At e = 3_2 bits, k=3 (10.750000) is best - * At e = 6_4 bits, k=3 (18.750000) is best - * At e = 82 bits, k=4 (23.200000) < k=3 (23.250000) - * At e = 128 bits, k=4 (3_2.400000) is best - * At e = 242 bits, k=5 (55.1_66667) < k=4 (55.200000) - * At e = 256 bits, k=5 (57.500000) is best - * At e = 512 bits, k=5 (100.1_66667) is best - * At e = 674 bits, k=6 (127.142857) < k=5 (127.1_66667) - * At e = 1024 bits, k=6 (177.142857) is best - * At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857) - * At e = 2048 bits, k=7 (318.875000) is best - * At e = 4096 bits, k=7 (574.875000) is best - * - * The numbers in parentheses are the expected number of multiplications - * needed to do the computation. The normal russian-peasant modular - * exponentiation technique always uses (e-1)/2. For exponents as - * small as 192 bits (below the range of current factoring algorithms), - * half of the multiplies are eliminated, 45.2 as opposed to the naive - * 95.5. Counting the 191 squarings as 3/4 a multiply each (squaring - * proper is just over half of multiplying, but the Montgomery - * reduction in each case is also a multiply), that's 143.25 - * multiplies, for totals of 188.45 vs. 238.75 - a 21% savings. - * For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a - * 24.3% savings. It asymptotically approaches 25%. - * - * Um, actually there's a slightly more accurate way to count, which - * really is the average number of multiplies required, averaged - * uniformly over all 2^(e-1) e-bit numbers, from 2^(e-1) to (2^e)-1. - * It's based on the recurrence that for the last b bits, b <= k, at - * most one multiply is needed (and none at all 1/2^b of the time), - * while when b > k, the odds are 1/2 each way that the bit will be - * 0 (meaning no multiplies to reduce it to the b-1-bit case) and - * 1/2 that the bit will be 1, starting a k-bit window and requiring - * 1 multiply beyond the b-k-bit case. Since the most significant - * bit is always 1, a k-bit window always starts there, and that - * multiply is by 1, so it isn't a multiply at all. Thus, the - * number of multiplies is simply that needed for the last e-k bits. - * This recurrence produces: - * - * At e = 1 bits, k=1 (0.000000) is best - * At e = 2 bits, k=1 (0.500000) is best - * At e = 4 bits, k=1 (1.500000) is best - * At e = 6 bits, k=2 (2.437500) < k=1 (2.500000) - * At e = 8 bits, k=2 (3.109375) is best - * At e = 1_6 bits, k=2 (5.777771) is best - * At e = 24 bits, k=3 (8.437629) < k=2 (8.444444) - * At e = 3_2 bits, k=3 (10.437492) is best - * At e = 6_4 bits, k=3 (18.437500) is best - * At e = 81 bits, k=4 (22.6_40000) < k=3 (22.687500) - * At e = 128 bits, k=4 (3_2.040000) is best - * At e = 241 bits, k=5 (54.611111) < k=4 (54.6_40000) - * At e = 256 bits, k=5 (57.111111) is best - * At e = 512 bits, k=5 (99.777778) is best - * At e = 673 bits, k=6 (126.591837) < k=5 (126.611111) - * At e = 1024 bits, k=6 (176.734694) is best - * At e = 1793 bits, k=7 (286.578125) < k=6 (286.591837) - * At e = 2048 bits, k=7 (318.453125) is best - * At e = 4096 bits, k=7 (574.453125) is best - * - * This has the rollover points at 6, 24, 81, 241, 673 and 1793 instead - * of 8, 26, 82, 242, 674, and 1794. Not a very big difference. - * (The numbers past that are k=8 at 4609 and k=9 at 11521, - * vs. one more in each case for the approximation.) - * - * Given that exponents for which k>7 are useful are uncommon, - * a fixed size table for k <= 7 is used for simplicity. - * - * The basic number of squarings needed is e-1, although a k-bit - * window (for k > 1) can save, on average, k-2 of those, too. - * That savings currently isn't counted here. It would drive the - * crossover points slightly lower. - * (Actually, this win is also reduced in the DoubleExpMod case, - * meaning we'd have to split the tables. Except for that, the - * multiplies by powers of the two bases are independent, so - * the same logic applies to each as the single case.) - * - * Table entry i is the largest number of bits in an exponent to - * process with a window size of i+1. Entry 6 is the largest - * possible unsigned number, so the window will never be more - * than 7 bits, requiring 2^6 = 0x40 slots. - */ -#define BNEXPMOD_MAX_WINDOW 7 -static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = { - 5, 23, 80, 240, 672, 1792, (unsigned)-1 -/* 7, 25, 81, 241, 673, 1793, (unsigned)-1 ### The old approximations */ -}; - -/* - * Perform modular exponentiation, as fast as possible! This uses - * Montgomery reduction, optimized squaring, and windowed exponentiation. - * The modulus "mod" MUST be odd! - * - * This returns 0 on success, -1 on out of memory. - * - * The window algorithm: - * The idea is to keep a running product of b1 = n^(high-order bits of exp), - * and then keep appending exponent bits to it. The following patterns - * apply to a 3-bit window (k = 3): - * To append 0: square - * To append 1: square, multiply by n^1 - * To append 10: square, multiply by n^1, square - * To append 11: square, square, multiply by n^3 - * To append 100: square, multiply by n^1, square, square - * To append 101: square, square, square, multiply by n^5 - * To append 110: square, square, multiply by n^3, square - * To append 111: square, square, square, multiply by n^7 - * - * Since each pattern involves only one multiply, the longer the pattern - * the better, except that a 0 (no multiplies) can be appended directly. - * We precompute a table of odd powers of n, up to 2^k, and can then - * multiply k bits of exponent at a time. Actually, assuming random - * exponents, there is on average one zero bit between needs to - * multiply (1/2 of the time there's none, 1/4 of the time there's 1, - * 1/8 of the time, there's 2, 1/64 of the time, there's 3, etc.), so - * you have to do one multiply per k+1 bits of exponent. - * - * The loop walks down the exponent, squaring the result buffer as - * it goes. There is a wbits+1 bit lookahead buffer, buf, that is - * filled with the upcoming exponent bits. (What is read after the - * end of the exponent is unimportant, but it is filled with zero here.) - * When the most-significant bit of this buffer becomes set, i.e. - * (buf & tblmask) != 0, we have to decide what pattern to multiply - * by, and when to do it. We decide, remember to do it in future - * after a suitable number of squarings have passed (e.g. a pattern - * of "100" in the buffer requires that we multiply by n^1 immediately; - * a pattern of "110" calls for multiplying by n^3 after one more - * squaring), clear the buffer, and continue. - * - * When we start, there is one more optimization: the result buffer - * is implcitly one, so squaring it or multiplying by it can be - * optimized away. Further, if we start with a pattern like "100" - * in the lookahead window, rather than placing n into the buffer - * and then starting to square it, we have already computed n^2 - * to compute the odd-powers table, so we can place that into - * the buffer and save a squaring. - * - * This means that if you have a k-bit window, to compute n^z, - * where z is the high k bits of the exponent, 1/2 of the time - * it requires no squarings. 1/4 of the time, it requires 1 - * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings. - * And the remaining 1/2^(k-1) of the time, the top k bits are a - * 1 followed by k-1 0 bits, so it again only requires k-2 - * squarings, not k-1. The average of these is 1. Add that - * to the one squaring we have to do to compute the table, - * and you'll see that a k-bit window saves k-2 squarings - * as well as reducing the multiplies. (It actually doesn't - * hurt in the case k = 1, either.) - * - * n must have mlen words allocated. Although fewer may be in use - * when n is passed in, all are in use on exit. - */ -int -lbnExpMod_64(BNWORD64 *result, BNWORD64 const *n, unsigned nlen, - BNWORD64 const *e, unsigned elen, BNWORD64 *mod, unsigned mlen) -{ - BNWORD64 *table[1 << (BNEXPMOD_MAX_WINDOW-1)]; - /* Table of odd powers of n */ - unsigned ebits; /* Exponent bits */ - unsigned wbits; /* Window size */ - unsigned tblmask; /* Mask of exponentiation window */ - BNWORD64 bitpos; /* Mask of current look-ahead bit */ - unsigned buf; /* Buffer of exponent bits */ - unsigned multpos; /* Where to do pending multiply */ - BNWORD64 const *mult; /* What to multiply by */ - unsigned i; /* Loop counter */ - int isone; /* Flag: accum. is implicitly one */ - BNWORD64 *a, *b; /* Working buffers/accumulators */ - BNWORD64 *t; /* Pointer into the working buffers */ - BNWORD64 inv; /* mod^-1 modulo 2^64 */ - int y; /* bnYield() result */ - - assert(mlen); - assert(nlen <= mlen); - - /* First, a couple of trivial cases. */ - elen = lbnNorm_64(e, elen); - if (!elen) { - /* x ^ 0 == 1 */ - lbnZero_64(result, mlen); - BIGLITTLE(result[-1],result[0]) = 1; - return 0; - } - ebits = lbnBits_64(e, elen); - if (ebits == 1) { - /* x ^ 1 == x */ - if (n != result) - lbnCopy_64(result, n, nlen); - if (mlen > nlen) - lbnZero_64(BIGLITTLE(result-nlen,result+nlen), - mlen-nlen); - return 0; - } - - /* Okay, now move the exponent pointer to the most-significant word */ - e = BIGLITTLE(e-elen, e+elen-1); - - /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ - wbits = 0; - while (ebits > bnExpModThreshTable[wbits]) - wbits++; - - /* Allocate working storage: two product buffers and the tables. */ - LBNALLOC(a, BNWORD64, 2*mlen); - if (!a) - return -1; - LBNALLOC(b, BNWORD64, 2*mlen); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ - tblmask = 1u << wbits; - - /* We have the result buffer available, so use it. */ - table[0] = result; - - /* - * Okay, we now have a minimal-sized table - expand it. - * This is allowed to fail! If so, scale back the table size - * and proceed. - */ - for (i = 1; i < tblmask; i++) { - LBNALLOC(t, BNWORD64, mlen); - if (!t) /* Out of memory! Quit the loop. */ - break; - table[i] = t; - } - - /* If we stopped, with i < tblmask, shrink the tables appropriately */ - while (tblmask > i) { - wbits--; - tblmask >>= 1; - } - /* Free up our overallocations */ - while (--i > tblmask) - LBNFREE(table[i], mlen); - - /* Okay, fill in the table */ - - /* Compute the necessary modular inverse */ - inv = lbnMontInv1_64(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - /* Convert n to Montgomery form */ - - /* Move n up "mlen" words into a */ - t = BIGLITTLE(a-mlen, a+mlen); - lbnCopy_64(t, n, nlen); - lbnZero_64(a, mlen); - /* Do the division - lose the quotient into the high-order words */ - (void)lbnDiv_64(t, a, mlen+nlen, mod, mlen); - /* Copy into first table entry */ - lbnCopy_64(table[0], a, mlen); - - /* Square a into b */ - lbnMontSquare_64(b, a, mod, mlen, inv); - - /* Use high half of b to initialize the table */ - t = BIGLITTLE(b-mlen, b+mlen); - for (i = 1; i < tblmask; i++) { - lbnMontMul_64(a, t, table[i-1], mod, mlen, inv); - lbnCopy_64(table[i], BIGLITTLE(a-mlen, a+mlen), mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* We might use b = n^2 later... */ - - /* Initialze the fetch pointer */ - bitpos = (BNWORD64)1 << ((ebits-1) & (64-1)); /* Initialize mask */ - - /* This should point to the msbit of e */ - assert((*e & bitpos) != 0); - - /* - * Pre-load the window. Becuase the window size is - * never larger than the exponent size, there is no need to - * detect running off the end of e in here. - * - * The read-ahead is controlled by elen and the bitpos mask. - * Note that this is *ahead* of ebits, which tracks the - * most significant end of the window. The purpose of this - * initialization is to get the two wbits+1 bits apart, - * like they should be. - * - * Note that bitpos and e1len together keep track of the - * lookahead read pointer in the exponent that is used here. - */ - buf = 0; - for (i = 0; i <= wbits; i++) { - buf = (buf << 1) | ((*e & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e++,e--); - bitpos = (BNWORD64)1 << (64-1); - elen--; - } - } - assert(buf & tblmask); - - /* - * Set the pending multiply positions to a location that will - * never be encountered, thus ensuring that nothing will happen - * until the need for a multiply appears and one is scheduled. - */ - multpos = ebits; /* A NULL value */ - mult = 0; /* Force a crash if we use these */ - - /* - * Okay, now begins the real work. The first step is - * slightly magic, so it's done outside the main loop, - * but it's very similar to what's inside. - */ - ebits--; /* Start processing the first bit... */ - isone = 1; - - /* - * This is just like the multiply in the loop, except that - * - We know the msbit of buf is set, and - * - We have the extra value n^2 floating around. - * So, do the usual computation, and if the result is that - * the buffer should be multiplied by n^1 immediately - * (which we'd normally then square), we multiply it - * (which reduces to a copy, which reduces to setting a flag) - * by n^2 and skip the squaring. Thus, we do the - * multiply and the squaring in one step. - */ - assert(buf & tblmask); - multpos = ebits - wbits; - while ((buf & 1) == 0) { - buf >>= 1; - multpos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(multpos <= ebits); - mult = table[buf>>1]; - buf = 0; - - /* Special case: use already-computed value sitting in buffer */ - if (multpos == ebits) - isone = 0; - - /* - * At this point, the buffer (which is the high half of b) holds - * either 1 (implicitly, as the "isone" flag is set), or n^2. - */ - - /* - * The main loop. The procedure is: - * - Advance the window - * - If the most-significant bit of the window is set, - * schedule a multiply for the appropriate time in the - * future (may be immediately) - * - Perform any pending multiples - * - Check for termination - * - Square the buffer - * - * At any given time, the acumulated product is held in - * the high half of b. - */ - for (;;) { - ebits--; - - /* Advance the window */ - assert(buf < tblmask); - buf <<= 1; - /* - * This reads ahead of the current exponent position - * (controlled by ebits), so we have to be able to read - * past the lsb of the exponents without error. - */ - if (elen) { - buf |= ((*e & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e++,e--); - bitpos = (BNWORD64)1 << (64-1); - elen--; - } - } - - /* Examine the window for pending multiplies */ - if (buf & tblmask) { - multpos = ebits - wbits; - while ((buf & 1) == 0) { - buf >>= 1; - multpos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(multpos <= ebits); - mult = table[buf>>1]; - buf = 0; - } - - /* If we have a pending multiply, do it */ - if (ebits == multpos) { - /* Multiply by the table entry remembered previously */ - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - /* Multiply by 1 is a trivial case */ - lbnCopy_64(t, mult, mlen); - isone = 0; - } else { - lbnMontMul_64(a, t, mult, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } - } - - /* Are we done? */ - if (!ebits) - break; - - /* Square the input */ - if (!isone) { - t = BIGLITTLE(b-mlen, b+mlen); - lbnMontSquare_64(a, t, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } /* for (;;) */ - - assert(!isone); - assert(!buf); - - /* DONE! */ - - /* Convert result out of Montgomery form */ - t = BIGLITTLE(b-mlen, b+mlen); - lbnCopy_64(b, t, mlen); - lbnZero_64(t, mlen); - lbnMontReduce_64(b, mod, mlen, inv); - lbnCopy_64(result, t, mlen); - /* - * Clean up - free intermediate storage. - * Do NOT free table[0], which is the result - * buffer. - */ - y = 0; -#if BNYIELD -yield: -#endif - while (--tblmask) - LBNFREE(table[tblmask], mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; /* Success */ -} - -/* - * Compute and return n1^e1 * n2^e2 mod "mod". - * result may be either input buffer, or something separate. - * It must be "mlen" words long. - * - * There is a current position in the exponents, which is kept in e1bits. - * (The exponents are swapped if necessary so e1 is the longer of the two.) - * At any given time, the value in the accumulator is - * n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod". - * As e1bits is counted down, this is updated, by squaring it and doing - * any necessary multiplies. - * To decide on the necessary multiplies, two windows, each w1bits+1 bits - * wide, are maintained in buf1 and buf2, which read *ahead* of the - * e1bits position (with appropriate handling of the case when e1bits - * drops below w1bits+1). When the most-significant bit of either window - * becomes set, indicating that something needs to be multiplied by - * the accumulator or it will get out of sync, the window is examined - * to see which power of n1 or n2 to multiply by, and when (possibly - * later, if the power is greater than 1) the multiply should take - * place. Then the multiply and its location are remembered and the - * window is cleared. - * - * If we had every power of n1 in the table, the multiply would always - * be w1bits steps in the future. But we only keep the odd powers, - * so instead of waiting w1bits squarings and then multiplying - * by n1^k, we wait w1bits-k squarings and multiply by n1. - * - * Actually, w2bits can be less than w1bits, but the window is the same - * size, to make it easier to keep track of where we're reading. The - * appropriate number of low-order bits of the window are just ignored. - */ -int -lbnDoubleExpMod_64(BNWORD64 *result, - BNWORD64 const *n1, unsigned n1len, - BNWORD64 const *e1, unsigned e1len, - BNWORD64 const *n2, unsigned n2len, - BNWORD64 const *e2, unsigned e2len, - BNWORD64 *mod, unsigned mlen) -{ - BNWORD64 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)]; - /* Table of odd powers of n1 */ - BNWORD64 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)]; - /* Table of odd powers of n2 */ - unsigned e1bits, e2bits; /* Exponent bits */ - unsigned w1bits, w2bits; /* Window sizes */ - unsigned tblmask; /* Mask of exponentiation window */ - BNWORD64 bitpos; /* Mask of current look-ahead bit */ - unsigned buf1, buf2; /* Buffer of exponent bits */ - unsigned mult1pos, mult2pos; /* Where to do pending multiply */ - BNWORD64 const *mult1, *mult2; /* What to multiply by */ - unsigned i; /* Loop counter */ - int isone; /* Flag: accum. is implicitly one */ - BNWORD64 *a, *b; /* Working buffers/accumulators */ - BNWORD64 *t; /* Pointer into the working buffers */ - BNWORD64 inv; /* mod^-1 modulo 2^64 */ - int y; /* bnYield() result */ - - assert(mlen); - assert(n1len <= mlen); - assert(n2len <= mlen); - - /* First, a couple of trivial cases. */ - e1len = lbnNorm_64(e1, e1len); - e2len = lbnNorm_64(e2, e2len); - - /* Ensure that the first exponent is the longer */ - e1bits = lbnBits_64(e1, e1len); - e2bits = lbnBits_64(e2, e2len); - if (e1bits < e2bits) { - i = e1len; e1len = e2len; e2len = i; - i = e1bits; e1bits = e2bits; e2bits = i; - t = (BNWORD64 *)n1; n1 = n2; n2 = t; - t = (BNWORD64 *)e1; e1 = e2; e2 = t; - } - assert(e1bits >= e2bits); - - /* Handle a trivial case */ - if (!e2len) - return lbnExpMod_64(result, n1, n1len, e1, e1len, mod, mlen); - assert(e2bits); - - /* The code below fucks up if the exponents aren't at least 2 bits */ - if (e1bits == 1) { - assert(e2bits == 1); - - LBNALLOC(a, BNWORD64, n1len+n2len); - if (!a) - return -1; - - lbnMul_64(a, n1, n1len, n2, n2len); - /* Do a direct modular reduction */ - if (n1len + n2len >= mlen) - (void)lbnDiv_64(a+mlen, a, n1len+n2len, mod, mlen); - lbnCopy_64(result, a, mlen); - LBNFREE(a, n1len+n2len); - return 0; - } - - /* Okay, now move the exponent pointers to the most-significant word */ - e1 = BIGLITTLE(e1-e1len, e1+e1len-1); - e2 = BIGLITTLE(e2-e2len, e2+e2len-1); - - /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ - w1bits = 0; - while (e1bits > bnExpModThreshTable[w1bits]) - w1bits++; - w2bits = 0; - while (e2bits > bnExpModThreshTable[w2bits]) - w2bits++; - - assert(w1bits >= w2bits); - - /* Allocate working storage: two product buffers and the tables. */ - LBNALLOC(a, BNWORD64, 2*mlen); - if (!a) - return -1; - LBNALLOC(b, BNWORD64, 2*mlen); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ - tblmask = 1u << w1bits; - /* Use buf2 for its size, temporarily */ - buf2 = 1u << w2bits; - - LBNALLOC(t, BNWORD64, mlen); - if (!t) { - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - return -1; - } - table1[0] = t; - table2[0] = result; - - /* - * Okay, we now have some minimal-sized tables - expand them. - * This is allowed to fail! If so, scale back the table sizes - * and proceed. We allocate both tables at the same time - * so if it fails partway through, they'll both be a reasonable - * size rather than one huge and one tiny. - * When i passes buf2 (the number of entries in the e2 window, - * which may be less than the number of entries in the e1 window), - * stop allocating e2 space. - */ - for (i = 1; i < tblmask; i++) { - LBNALLOC(t, BNWORD64, mlen); - if (!t) /* Out of memory! Quit the loop. */ - break; - table1[i] = t; - if (i < buf2) { - LBNALLOC(t, BNWORD64, mlen); - if (!t) { - LBNFREE(table1[i], mlen); - break; - } - table2[i] = t; - } - } - - /* If we stopped, with i < tblmask, shrink the tables appropriately */ - while (tblmask > i) { - w1bits--; - tblmask >>= 1; - } - /* Free up our overallocations */ - while (--i > tblmask) { - if (i < buf2) - LBNFREE(table2[i], mlen); - LBNFREE(table1[i], mlen); - } - /* And shrink the second window too, if needed */ - if (w2bits > w1bits) { - w2bits = w1bits; - buf2 = tblmask; - } - - /* - * From now on, use the w2bits variable for the difference - * between w1bits and w2bits. - */ - w2bits = w1bits-w2bits; - - /* Okay, fill in the tables */ - - /* Compute the necessary modular inverse */ - inv = lbnMontInv1_64(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - /* Convert n1 to Montgomery form */ - - /* Move n1 up "mlen" words into a */ - t = BIGLITTLE(a-mlen, a+mlen); - lbnCopy_64(t, n1, n1len); - lbnZero_64(a, mlen); - /* Do the division - lose the quotient into the high-order words */ - (void)lbnDiv_64(t, a, mlen+n1len, mod, mlen); - /* Copy into first table entry */ - lbnCopy_64(table1[0], a, mlen); - - /* Square a into b */ - lbnMontSquare_64(b, a, mod, mlen, inv); - - /* Use high half of b to initialize the first table */ - t = BIGLITTLE(b-mlen, b+mlen); - for (i = 1; i < tblmask; i++) { - lbnMontMul_64(a, t, table1[i-1], mod, mlen, inv); - lbnCopy_64(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* Convert n2 to Montgomery form */ - - t = BIGLITTLE(a-mlen, a+mlen); - /* Move n2 up "mlen" words into a */ - lbnCopy_64(t, n2, n2len); - lbnZero_64(a, mlen); - /* Do the division - lose the quotient into the high-order words */ - (void)lbnDiv_64(t, a, mlen+n2len, mod, mlen); - /* Copy into first table entry */ - lbnCopy_64(table2[0], a, mlen); - - /* Square it into a */ - lbnMontSquare_64(a, table2[0], mod, mlen, inv); - /* Copy to b, low half */ - lbnCopy_64(b, t, mlen); - - /* Use b to initialize the second table */ - for (i = 1; i < buf2; i++) { - lbnMontMul_64(a, b, table2[i-1], mod, mlen, inv); - lbnCopy_64(table2[i], t, mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* - * Okay, a recap: at this point, the low part of b holds - * n2^2, the high part holds n1^2, and the tables are - * initialized with the odd powers of n1 and n2 from 1 - * through 2*tblmask-1 and 2*buf2-1. - * - * We might use those squares in b later, or we might not. - */ - - /* Initialze the fetch pointer */ - bitpos = (BNWORD64)1 << ((e1bits-1) & (64-1)); /* Initialize mask */ - - /* This should point to the msbit of e1 */ - assert((*e1 & bitpos) != 0); - - /* - * Pre-load the windows. Becuase the window size is - * never larger than the exponent size, there is no need to - * detect running off the end of e1 in here. - * - * The read-ahead is controlled by e1len and the bitpos mask. - * Note that this is *ahead* of e1bits, which tracks the - * most significant end of the window. The purpose of this - * initialization is to get the two w1bits+1 bits apart, - * like they should be. - * - * Note that bitpos and e1len together keep track of the - * lookahead read pointer in the exponent that is used here. - * e2len is not decremented, it is only ever compared with - * e1len as *that* is decremented. - */ - buf1 = buf2 = 0; - for (i = 0; i <= w1bits; i++) { - buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0); - if (e1len <= e2len) - buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e1++,e1--); - if (e1len <= e2len) - BIGLITTLE(e2++,e2--); - bitpos = (BNWORD64)1 << (64-1); - e1len--; - } - } - assert(buf1 & tblmask); - - /* - * Set the pending multiply positions to a location that will - * never be encountered, thus ensuring that nothing will happen - * until the need for a multiply appears and one is scheduled. - */ - mult1pos = mult2pos = e1bits; /* A NULL value */ - mult1 = mult2 = 0; /* Force a crash if we use these */ - - /* - * Okay, now begins the real work. The first step is - * slightly magic, so it's done outside the main loop, - * but it's very similar to what's inside. - */ - isone = 1; /* Buffer is implicitly 1, so replace * by copy */ - e1bits--; /* Start processing the first bit... */ - - /* - * This is just like the multiply in the loop, except that - * - We know the msbit of buf1 is set, and - * - We have the extra value n1^2 floating around. - * So, do the usual computation, and if the result is that - * the buffer should be multiplied by n1^1 immediately - * (which we'd normally then square), we multiply it - * (which reduces to a copy, which reduces to setting a flag) - * by n1^2 and skip the squaring. Thus, we do the - * multiply and the squaring in one step. - */ - assert(buf1 & tblmask); - mult1pos = e1bits - w1bits; - while ((buf1 & 1) == 0) { - buf1 >>= 1; - mult1pos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(mult1pos <= e1bits); - mult1 = table1[buf1>>1]; - buf1 = 0; - - /* Special case: use already-computed value sitting in buffer */ - if (mult1pos == e1bits) - isone = 0; - - /* - * The first multiply by a power of n2. Similar, but - * we might not even want to schedule a multiply if e2 is - * shorter than e1, and the window might be shorter so - * we have to leave the low w2bits bits alone. - */ - if (buf2 & tblmask) { - /* Remember low-order bits for later */ - i = buf2 & ((1u << w2bits) - 1); - buf2 >>= w2bits; - mult2pos = e1bits - w1bits + w2bits; - while ((buf2 & 1) == 0) { - buf2 >>= 1; - mult2pos++; - } - assert(mult2pos <= e1bits); - mult2 = table2[buf2>>1]; - buf2 = i; - - if (mult2pos == e1bits) { - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - lbnCopy_64(t, b, mlen); /* Copy low to high */ - isone = 0; - } else { - lbnMontMul_64(a, t, b, mod, mlen, inv); - t = a; a = b; b = t; - } - } - } - - /* - * At this point, the buffer (which is the high half of b) - * holds either 1 (implicitly, as the "isone" flag is set), - * n1^2, n2^2 or n1^2 * n2^2. - */ - - /* - * The main loop. The procedure is: - * - Advance the windows - * - If the most-significant bit of a window is set, - * schedule a multiply for the appropriate time in the - * future (may be immediately) - * - Perform any pending multiples - * - Check for termination - * - Square the buffers - * - * At any given time, the acumulated product is held in - * the high half of b. - */ - for (;;) { - e1bits--; - - /* Advance the windows */ - assert(buf1 < tblmask); - buf1 <<= 1; - assert(buf2 < tblmask); - buf2 <<= 1; - /* - * This reads ahead of the current exponent position - * (controlled by e1bits), so we have to be able to read - * past the lsb of the exponents without error. - */ - if (e1len) { - buf1 |= ((*e1 & bitpos) != 0); - if (e1len <= e2len) - buf2 |= ((*e2 & bitpos) != 0); - bitpos >>= 1; - if (!bitpos) { - BIGLITTLE(e1++,e1--); - if (e1len <= e2len) - BIGLITTLE(e2++,e2--); - bitpos = (BNWORD64)1 << (64-1); - e1len--; - } - } - - /* Examine the first window for pending multiplies */ - if (buf1 & tblmask) { - mult1pos = e1bits - w1bits; - while ((buf1 & 1) == 0) { - buf1 >>= 1; - mult1pos++; - } - /* Intermediates can wrap, but final must NOT */ - assert(mult1pos <= e1bits); - mult1 = table1[buf1>>1]; - buf1 = 0; - } - - /* - * Examine the second window for pending multiplies. - * Window 2 can be smaller than window 1, but we - * keep the same number of bits in buf2, so we need - * to ignore any low-order bits in the buffer when - * computing what to multiply by, and recompute them - * later. - */ - if (buf2 & tblmask) { - /* Remember low-order bits for later */ - i = buf2 & ((1u << w2bits) - 1); - buf2 >>= w2bits; - mult2pos = e1bits - w1bits + w2bits; - while ((buf2 & 1) == 0) { - buf2 >>= 1; - mult2pos++; - } - assert(mult2pos <= e1bits); - mult2 = table2[buf2>>1]; - buf2 = i; - } - - - /* If we have a pending multiply for e1, do it */ - if (e1bits == mult1pos) { - /* Multiply by the table entry remembered previously */ - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - /* Multiply by 1 is a trivial case */ - lbnCopy_64(t, mult1, mlen); - isone = 0; - } else { - lbnMontMul_64(a, t, mult1, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } - } - - /* If we have a pending multiply for e2, do it */ - if (e1bits == mult2pos) { - /* Multiply by the table entry remembered previously */ - t = BIGLITTLE(b-mlen, b+mlen); - if (isone) { - /* Multiply by 1 is a trivial case */ - lbnCopy_64(t, mult2, mlen); - isone = 0; - } else { - lbnMontMul_64(a, t, mult2, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } - } - - /* Are we done? */ - if (!e1bits) - break; - - /* Square the buffer */ - if (!isone) { - t = BIGLITTLE(b-mlen, b+mlen); - lbnMontSquare_64(a, t, mod, mlen, inv); - /* Swap a and b */ - t = a; a = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } /* for (;;) */ - - assert(!isone); - assert(!buf1); - assert(!buf2); - - /* DONE! */ - - /* Convert result out of Montgomery form */ - t = BIGLITTLE(b-mlen, b+mlen); - lbnCopy_64(b, t, mlen); - lbnZero_64(t, mlen); - lbnMontReduce_64(b, mod, mlen, inv); - lbnCopy_64(result, t, mlen); - - /* Clean up - free intermediate storage */ - y = 0; -#if BNYIELD -yield: -#endif - buf2 = tblmask >> w2bits; - while (--tblmask) { - if (tblmask < buf2) - LBNFREE(table2[tblmask], mlen); - LBNFREE(table1[tblmask], mlen); - } - t = table1[0]; - LBNFREE(t, mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; /* Success */ -} - -/* - * 2^exp (mod mod). This is an optimized version for use in Fermat - * tests. The input value of n is ignored; it is returned with - * "mlen" words valid. - */ -int -lbnTwoExpMod_64(BNWORD64 *n, BNWORD64 const *exp, unsigned elen, - BNWORD64 *mod, unsigned mlen) -{ - unsigned e; /* Copy of high words of the exponent */ - unsigned bits; /* Assorted counter of bits */ - BNWORD64 const *bitptr; - BNWORD64 bitword, bitpos; - BNWORD64 *a, *b, *a1; - BNWORD64 inv; - int y; /* Result of bnYield() */ - - assert(mlen); - - bitptr = BIGLITTLE(exp-elen, exp+elen-1); - bitword = *bitptr; - assert(bitword); - - /* Clear n for future use. */ - lbnZero_64(n, mlen); - - bits = lbnBits_64(exp, elen); - - /* First, a couple of trivial cases. */ - if (bits <= 1) { - /* 2 ^ 0 == 1, 2 ^ 1 == 2 */ - BIGLITTLE(n[-1],n[0]) = (BNWORD64)1<<elen; - return 0; - } - - /* Set bitpos to the most significant bit */ - bitpos = (BNWORD64)1 << ((bits-1) & (64-1)); - - /* Now, count the bits in the modulus. */ - bits = lbnBits_64(mod, mlen); - assert(bits > 1); /* a 1-bit modulus is just stupid... */ - - /* - * We start with 1<<e, where "e" is as many high bits of the - * exponent as we can manage without going over the modulus. - * This first loop finds "e". - */ - e = 1; - while (elen) { - /* Consume the first bit */ - bitpos >>= 1; - if (!bitpos) { - if (!--elen) - break; - bitword = BIGLITTLE(*++bitptr,*--bitptr); - bitpos = (BNWORD64)1<<(64-1); - } - e = (e << 1) | ((bitpos & bitword) != 0); - if (e >= bits) { /* Overflow! Back out. */ - e >>= 1; - break; - } - } - /* - * The bit in "bitpos" being examined by the bit buffer has NOT - * been consumed yet. This may be past the end of the exponent, - * in which case elen == 1. - */ - - /* Okay, now, set bit "e" in n. n is already zero. */ - inv = (BNWORD64)1 << (e & (64-1)); - e /= 64; - BIGLITTLE(n[-e-1],n[e]) = inv; - /* - * The effective length of n in words is now "e+1". - * This is used a little bit later. - */ - - if (!elen) - return 0; /* That was easy! */ - - /* - * We have now processed the first few bits. The next step - * is to convert this to Montgomery form for further squaring. - */ - - /* Allocate working storage: two product buffers */ - LBNALLOC(a, BNWORD64, 2*mlen); - if (!a) - return -1; - LBNALLOC(b, BNWORD64, 2*mlen); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Convert n to Montgomery form */ - inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */ - assert(inv & 1); /* Modulus must be odd */ - inv = lbnMontInv1_64(inv); - /* Move n (length e+1, remember?) up "mlen" words into b */ - /* Note that we lie about a1 for a bit - it's pointing to b */ - a1 = BIGLITTLE(b-mlen,b+mlen); - lbnCopy_64(a1, n, e+1); - lbnZero_64(b, mlen); - /* Do the division - dump the quotient into the high-order words */ - (void)lbnDiv_64(a1, b, mlen+e+1, mod, mlen); - /* - * Now do the first squaring and modular reduction to put - * the number up in a1 where it belongs. - */ - lbnMontSquare_64(a, b, mod, mlen, inv); - /* Fix up a1 to point to where it should go. */ - a1 = BIGLITTLE(a-mlen,a+mlen); - - /* - * Okay, now, a1 holds the number being accumulated, and - * b is a scratch register. Start working: - */ - for (;;) { - /* - * Is the bit set? If so, double a1 as well. - * A modular doubling like this is very cheap. - */ - if (bitpos & bitword) { - /* - * Double the number. If there was a carry out OR - * the result is greater than the modulus, subract - * the modulus. - */ - if (lbnDouble_64(a1, mlen) || - lbnCmp_64(a1, mod, mlen) > 0) - (void)lbnSubN_64(a1, mod, mlen); - } - - /* Advance to the next exponent bit */ - bitpos >>= 1; - if (!bitpos) { - if (!--elen) - break; /* Done! */ - bitword = BIGLITTLE(*++bitptr,*--bitptr); - bitpos = (BNWORD64)1<<(64-1); - } - - /* - * The elen/bitword/bitpos bit buffer is known to be - * non-empty, i.e. there is at least one more unconsumed bit. - * Thus, it's safe to square the number. - */ - lbnMontSquare_64(b, a1, mod, mlen, inv); - /* Rename result (in b) back to a (a1, really). */ - a1 = b; b = a; a = a1; - a1 = BIGLITTLE(a-mlen,a+mlen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - goto yield; -#endif - } - - /* DONE! Just a little bit of cleanup... */ - - /* - * Convert result out of Montgomery form... this is - * just a Montgomery reduction. - */ - lbnCopy_64(a, a1, mlen); - lbnZero_64(a1, mlen); - lbnMontReduce_64(a, mod, mlen, inv); - lbnCopy_64(n, a1, mlen); - - /* Clean up - free intermediate storage */ - y = 0; -#if BNYIELD -yield: -#endif - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; /* Success */ -} - - -/* - * Returns a substring of the big-endian array of bytes representation - * of the bignum array based on two parameters, the least significant - * byte number (0 to start with the least significant byte) and the - * length. I.e. the number returned is a representation of - * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). - * - * It is an error if the bignum is not at least buflen + lsbyte bytes - * long. - * - * This code assumes that the compiler has the minimal intelligence - * neded to optimize divides and modulo operations on an unsigned data - * type with a power of two. - */ -void -lbnExtractBigBytes_64(BNWORD64 const *n, unsigned char *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD64 t = 0; /* Needed to shut up uninitialized var warnings */ - unsigned shift; - - lsbyte += buflen; - - shift = (8 * lsbyte) % 64; - lsbyte /= (64/8); /* Convert to word offset */ - BIGLITTLE(n -= lsbyte, n += lsbyte); - - if (shift) - t = BIGLITTLE(n[-1],n[0]); - - while (buflen--) { - if (!shift) { - t = BIGLITTLE(*n++,*--n); - shift = 64; - } - shift -= 8; - *buf++ = (unsigned char)(t>>shift); - } -} - -/* - * Merge a big-endian array of bytes into a bignum array. - * The array had better be big enough. This is - * equivalent to extracting the entire bignum into a - * large byte array, copying the input buffer into the - * middle of it, and converting back to a bignum. - * - * The buf is "len" bytes long, and its *last* byte is at - * position "lsbyte" from the end of the bignum. - * - * Note that this is a pain to get right. Fortunately, it's hardly - * critical for efficiency. - */ -void -lbnInsertBigBytes_64(BNWORD64 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD64 t = 0; /* Shut up uninitialized varibale warnings */ - - lsbyte += buflen; - - BIGLITTLE(n -= lsbyte/(64/8), n += lsbyte/(64/8)); - - /* Load up leading odd bytes */ - if (lsbyte % (64/8)) { - t = BIGLITTLE(*--n,*n++); - t >>= (lsbyte * 8) % 64; - } - - /* The main loop - merge into t, storing at each word boundary. */ - while (buflen--) { - t = (t << 8) | *buf++; - if ((--lsbyte % (64/8)) == 0) - BIGLITTLE(*n++,*--n) = t; - } - - /* Merge odd bytes in t into last word */ - lsbyte = (lsbyte * 8) % 64; - if (lsbyte) { - t <<= lsbyte; - t |= (((BNWORD64)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); - BIGLITTLE(n[0],n[-1]) = t; - } - - return; -} - -/* - * Returns a substring of the little-endian array of bytes representation - * of the bignum array based on two parameters, the least significant - * byte number (0 to start with the least significant byte) and the - * length. I.e. the number returned is a representation of - * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). - * - * It is an error if the bignum is not at least buflen + lsbyte bytes - * long. - * - * This code assumes that the compiler has the minimal intelligence - * neded to optimize divides and modulo operations on an unsigned data - * type with a power of two. - */ -void -lbnExtractLittleBytes_64(BNWORD64 const *n, unsigned char *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD64 t = 0; /* Needed to shut up uninitialized var warnings */ - - BIGLITTLE(n -= lsbyte/(64/8), n += lsbyte/(64/8)); - - if (lsbyte % (64/8)) { - t = BIGLITTLE(*--n,*n++); - t >>= (lsbyte % (64/8)) * 8 ; - } - - while (buflen--) { - if ((lsbyte++ % (64/8)) == 0) - t = BIGLITTLE(*--n,*n++); - *buf++ = (unsigned char)t; - t >>= 8; - } -} - -/* - * Merge a little-endian array of bytes into a bignum array. - * The array had better be big enough. This is - * equivalent to extracting the entire bignum into a - * large byte array, copying the input buffer into the - * middle of it, and converting back to a bignum. - * - * The buf is "len" bytes long, and its first byte is at - * position "lsbyte" from the end of the bignum. - * - * Note that this is a pain to get right. Fortunately, it's hardly - * critical for efficiency. - */ -void -lbnInsertLittleBytes_64(BNWORD64 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen) -{ - BNWORD64 t = 0; /* Shut up uninitialized varibale warnings */ - - /* Move to most-significant end */ - lsbyte += buflen; - buf += buflen; - - BIGLITTLE(n -= lsbyte/(64/8), n += lsbyte/(64/8)); - - /* Load up leading odd bytes */ - if (lsbyte % (64/8)) { - t = BIGLITTLE(*--n,*n++); - t >>= (lsbyte * 8) % 64; - } - - /* The main loop - merge into t, storing at each word boundary. */ - while (buflen--) { - t = (t << 8) | *--buf; - if ((--lsbyte % (64/8)) == 0) - BIGLITTLE(*n++,*--n) = t; - } - - /* Merge odd bytes in t into last word */ - lsbyte = (lsbyte * 8) % 64; - if (lsbyte) { - t <<= lsbyte; - t |= (((BNWORD64)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); - BIGLITTLE(n[0],n[-1]) = t; - } - - return; -} - -#ifdef DEADCODE /* This was a precursor to the more flexible lbnExtractBytes */ -/* - * Convert a big-endian array of bytes to a bignum. - * Returns the number of words in the bignum. - * Note the expression "64/8" for the number of bytes per word. - * This is so the word-size adjustment will work. - */ -unsigned -lbnFromBytes_64(BNWORD64 *a, unsigned char const *b, unsigned blen) -{ - BNWORD64 t; - unsigned alen = (blen + (64/8-1))/(64/8); - BIGLITTLE(a -= alen, a += alen); - - while (blen) { - t = 0; - do { - t = t << 8 | *b++; - } while (--blen & (64/8-1)); - BIGLITTLE(*a++,*--a) = t; - } - return alen; -} -#endif - -/* - * Computes the GCD of a and b. Modifies both arguments; when it returns, - * one of them is the GCD and the other is trash. The return value - * indicates which: 0 for a, and 1 for b. The length of the retult is - * returned in rlen. Both inputs must have one extra word of precision. - * alen must be >= blen. - * - * TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B). - * This is based on taking out common powers of 2, then repeatedly: - * gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted. - * gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced. - * It gets less reduction per step, but the steps are much faster than - * the division case. - */ -int -lbnGcd_64(BNWORD64 *a, unsigned alen, BNWORD64 *b, unsigned blen, - unsigned *rlen) -{ -#if BNYIELD - int y; -#endif - assert(alen >= blen); - - while (blen != 0) { - (void)lbnDiv_64(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); - alen = lbnNorm_64(a, blen); - if (alen == 0) { - *rlen = blen; - return 1; - } - (void)lbnDiv_64(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); - blen = lbnNorm_64(b, alen); -#if BNYIELD - if (bnYield && (y = bnYield()) < 0) - return y; -#endif - } - *rlen = alen; - return 0; -} - -/* - * Invert "a" modulo "mod" using the extended Euclidean algorithm. - * Note that this only computes one of the cosequences, and uses the - * theorem that the signs flip every step and the absolute value of - * the cosequence values are always bounded by the modulus to avoid - * having to work with negative numbers. - * gcd(a,mod) had better equal 1. Returns 1 if the GCD is NOT 1. - * a must be one word longer than "mod". It is overwritten with the - * result. - * TODO: Use Richard Schroeppel's *much* faster algorithm. - */ -int -lbnInv_64(BNWORD64 *a, unsigned alen, BNWORD64 const *mod, unsigned mlen) -{ - BNWORD64 *b; /* Hold a copy of mod during GCD reduction */ - BNWORD64 *p; /* Temporary for products added to t0 and t1 */ - BNWORD64 *t0, *t1; /* Inverse accumulators */ - BNWORD64 cy; - unsigned blen, t0len, t1len, plen; - int y; - - alen = lbnNorm_64(a, alen); - if (!alen) - return 1; /* No inverse */ - - mlen = lbnNorm_64(mod, mlen); - - assert (alen <= mlen); - - /* Inverse of 1 is 1 */ - if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) { - lbnZero_64(BIGLITTLE(a-alen,a+alen), mlen-alen); - return 0; - } - - /* Allocate a pile of space */ - LBNALLOC(b, BNWORD64, mlen+1); - if (b) { - /* - * Although products are guaranteed to always be less than the - * modulus, it can involve multiplying two 3-word numbers to - * get a 5-word result, requiring a 6th word to store a 0 - * temporarily. Thus, mlen + 1. - */ - LBNALLOC(p, BNWORD64, mlen+1); - if (p) { - LBNALLOC(t0, BNWORD64, mlen); - if (t0) { - LBNALLOC(t1, BNWORD64, mlen); - if (t1) - goto allocated; - LBNFREE(t0, mlen); - } - LBNFREE(p, mlen+1); - } - LBNFREE(b, mlen+1); - } - return -1; - -allocated: - - /* Set t0 to 1 */ - t0len = 1; - BIGLITTLE(t0[-1],t0[0]) = 1; - - /* b = mod */ - lbnCopy_64(b, mod, mlen); - /* blen = mlen (implicitly) */ - - /* t1 = b / a; b = b % a */ - cy = lbnDiv_64(t1, b, mlen, a, alen); - *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy; - t1len = lbnNorm_64(t1, mlen-alen+1); - blen = lbnNorm_64(b, alen); - - /* while (b > 1) */ - while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD64)1) { - /* q = a / b; a = a % b; */ - if (alen < blen || (alen == blen && lbnCmp_64(a, a, alen) < 0)) - assert(0); - cy = lbnDiv_64(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); - *(BIGLITTLE(a-alen-1,a+alen)) = cy; - plen = lbnNorm_64(BIGLITTLE(a-blen,a+blen), alen-blen+1); - assert(plen); - alen = lbnNorm_64(a, blen); - if (!alen) - goto failure; /* GCD not 1 */ - - /* t0 += q * t1; */ - assert(plen+t1len <= mlen+1); - lbnMul_64(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len); - plen = lbnNorm_64(p, plen + t1len); - assert(plen <= mlen); - if (plen > t0len) { - lbnZero_64(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len); - t0len = plen; - } - cy = lbnAddN_64(t0, p, plen); - if (cy) { - if (t0len > plen) { - cy = lbnAdd1_64(BIGLITTLE(t0-plen,t0+plen), - t0len-plen, cy); - } - if (cy) { - BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy; - t0len++; - } - } - - /* if (a <= 1) return a ? t0 : FAIL; */ - if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD64)1) { - if (alen == 0) - goto failure; /* FAIL */ - assert(t0len <= mlen); - lbnCopy_64(a, t0, t0len); - lbnZero_64(BIGLITTLE(a-t0len, a+t0len), mlen-t0len); - goto success; - } - - /* q = b / a; b = b % a; */ - if (blen < alen || (blen == alen && lbnCmp_64(b, a, alen) < 0)) - assert(0); - cy = lbnDiv_64(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); - *(BIGLITTLE(b-blen-1,b+blen)) = cy; - plen = lbnNorm_64(BIGLITTLE(b-alen,b+alen), blen-alen+1); - assert(plen); - blen = lbnNorm_64(b, alen); - if (!blen) - goto failure; /* GCD not 1 */ - - /* t1 += q * t0; */ - assert(plen+t0len <= mlen+1); - lbnMul_64(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len); - plen = lbnNorm_64(p, plen + t0len); - assert(plen <= mlen); - if (plen > t1len) { - lbnZero_64(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len); - t1len = plen; - } - cy = lbnAddN_64(t1, p, plen); - if (cy) { - if (t1len > plen) { - cy = lbnAdd1_64(BIGLITTLE(t1-plen,t0+plen), - t1len-plen, cy); - } - if (cy) { - BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy; - t1len++; - } - } -#if BNYIELD - if (bnYield && (y = bnYield() < 0)) - goto yield; -#endif - } - - if (!blen) - goto failure; /* gcd(a, mod) != 1 -- FAIL */ - - /* return mod-t1 */ - lbnCopy_64(a, mod, mlen); - assert(t1len <= mlen); - cy = lbnSubN_64(a, t1, t1len); - if (cy) { - assert(mlen > t1len); - cy = lbnSub1_64(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy); - assert(!cy); - } - -success: - LBNFREE(t1, mlen); - LBNFREE(t0, mlen); - LBNFREE(p, mlen+1); - LBNFREE(b, mlen+1); - - return 0; - -failure: /* GCD is not 1 - no inverse exists! */ - y = 1; -#if BNYIELD -yield: -#endif - LBNFREE(t1, mlen); - LBNFREE(t0, mlen); - LBNFREE(p, mlen+1); - LBNFREE(b, mlen+1); - - return y; -} - -/* - * Precompute powers of "a" mod "mod". Compute them every "bits" - * for "n" steps. This is sufficient to compute powers of g with - * exponents up to n*bits bits long, i.e. less than 2^(n*bits). - * - * This assumes that the caller has already initialized "array" to point - * to "n" buffers of size "mlen". - */ -int -lbnBasePrecompBegin_64(BNWORD64 **array, unsigned n, unsigned bits, - BNWORD64 const *g, unsigned glen, BNWORD64 *mod, unsigned mlen) -{ - BNWORD64 *a, *b; /* Temporary double-width accumulators */ - BNWORD64 *a1; /* Pointer to high half of a*/ - BNWORD64 inv; /* Montgomery inverse of LSW of mod */ - BNWORD64 *t; - unsigned i; - - glen = lbnNorm_64(g, glen); - assert(glen); - - assert (mlen == lbnNorm_64(mod, mlen)); - assert (glen <= mlen); - - /* Allocate two temporary buffers, and the array slots */ - LBNALLOC(a, BNWORD64, mlen*2); - if (!a) - return -1; - LBNALLOC(b, BNWORD64, mlen*2); - if (!b) { - LBNFREE(a, 2*mlen); - return -1; - } - - /* Okay, all ready */ - - /* Convert n to Montgomery form */ - inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */ - assert(inv & 1); /* Modulus must be odd */ - inv = lbnMontInv1_64(inv); - /* Move g up "mlen" words into a (clearing the low mlen words) */ - a1 = BIGLITTLE(a-mlen,a+mlen); - lbnCopy_64(a1, g, glen); - lbnZero_64(a, mlen); - - /* Do the division - dump the quotient into the high-order words */ - (void)lbnDiv_64(a1, a, mlen+glen, mod, mlen); - - /* Copy the first value into the array */ - t = *array; - lbnCopy_64(t, a, mlen); - a1 = a; /* This first value is *not* shifted up */ - - /* Now compute the remaining n-1 array entries */ - assert(bits); - assert(n); - while (--n) { - i = bits; - do { - /* Square a1 into b1 */ - lbnMontSquare_64(b, a1, mod, mlen, inv); - t = b; b = a; a = t; - a1 = BIGLITTLE(a-mlen, a+mlen); - } while (--i); - t = *++array; - lbnCopy_64(t, a1, mlen); - } - - /* Hooray, we're done. */ - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - return 0; -} - -/* - * result = base^exp (mod mod). "array" is a an array of pointers - * to procomputed powers of base, each 2^bits apart. (I.e. array[i] - * is base^(2^(i*bits))). - * - * The algorithm consists of: - * a = b = (powers of g to be raised to the power 2^bits-1) - * a *= b *= (powers of g to be raised to the power 2^bits-2) - * ... - * a *= b *= (powers of g to be raised to the power 1) - * - * All we do is walk the exponent 2^bits-1 times in groups of "bits" bits, - */ -int -lbnBasePrecompExp_64(BNWORD64 *result, BNWORD64 const * const *array, - unsigned bits, BNWORD64 const *exp, unsigned elen, - BNWORD64 const *mod, unsigned mlen) -{ - BNWORD64 *a, *b, *c, *t; - BNWORD64 *a1, *b1; - int anull, bnull; /* Null flags: values are implicitly 1 */ - unsigned i, j; /* Loop counters */ - unsigned mask; /* Exponent bits to examime */ - BNWORD64 const *eptr; /* Pointer into exp */ - BNWORD64 buf, curbits, nextword; /* Bit-buffer varaibles */ - BNWORD64 inv; /* Inverse of LSW of modulus */ - unsigned ewords; /* Words of exponent left */ - int bufbits; /* Number of valid bits */ - int y = 0; - - mlen = lbnNorm_64(mod, mlen); - assert (mlen); - - elen = lbnNorm_64(exp, elen); - if (!elen) { - lbnZero_64(result, mlen); - BIGLITTLE(result[-1],result[0]) = 1; - return 0; - } - /* - * This could be precomputed, but it's so cheap, and it would require - * making the precomputation structure word-size dependent. - */ - inv = lbnMontInv1_64(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - assert(elen); - - /* - * Allocate three temporary buffers. The current numbers generally - * live in the upper halves of these buffers. - */ - LBNALLOC(a, BNWORD64, mlen*2); - if (a) { - LBNALLOC(b, BNWORD64, mlen*2); - if (b) { - LBNALLOC(c, BNWORD64, mlen*2); - if (c) - goto allocated; - LBNFREE(b, 2*mlen); - } - LBNFREE(a, 2*mlen); - } - return -1; - -allocated: - - anull = bnull = 1; - - mask = (1u<<bits) - 1; - for (i = mask; i; --i) { - /* Set up bit buffer for walking the exponent */ - eptr = exp; - buf = BIGLITTLE(*--eptr, *eptr++); - ewords = elen-1; - bufbits = 64; - for (j = 0; ewords || buf; j++) { - /* Shift down current buffer */ - curbits = buf; - buf >>= bits; - /* If necessary, add next word */ - bufbits -= bits; - if (bufbits < 0 && ewords > 0) { - nextword = BIGLITTLE(*--eptr, *eptr++); - ewords--; - curbits |= nextword << (bufbits+bits); - buf = nextword >> -bufbits; - bufbits += 64; - } - /* If appropriate, multiply b *= array[j] */ - if ((curbits & mask) == i) { - BNWORD64 const *d = array[j]; - - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (bnull) { - lbnCopy_64(b1, d, mlen); - bnull = 0; - } else { - lbnMontMul_64(c, b1, d, mod, mlen, inv); - t = c; c = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield() < 0)) - goto yield; -#endif - } - } - - /* Multiply a *= b */ - if (!bnull) { - a1 = BIGLITTLE(a-mlen-1,a+mlen); - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (anull) { - lbnCopy_64(a1, b1, mlen); - anull = 0; - } else { - lbnMontMul_64(c, a1, b1, mod, mlen, inv); - t = c; c = a; a = t; - } - } - } - - assert(!anull); /* If it were, elen would have been 0 */ - - /* Convert out of Montgomery form and return */ - a1 = BIGLITTLE(a-mlen-1,a+mlen); - lbnCopy_64(a, a1, mlen); - lbnZero_64(a1, mlen); - lbnMontReduce_64(a, mod, mlen, inv); - lbnCopy_64(result, a1, mlen); - -#if BNYIELD -yield: -#endif - LBNFREE(c, 2*mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; -} - -/* - * result = base1^exp1 *base2^exp2 (mod mod). "array1" and "array2" are - * arrays of pointers to procomputed powers of the corresponding bases, - * each 2^bits apart. (I.e. array1[i] is base1^(2^(i*bits))). - * - * Bits must be the same in both. (It could be made adjustable, but it's - * a bit of a pain. Just make them both equal to the larger one.) - * - * The algorithm consists of: - * a = b = (powers of base1 and base2 to be raised to the power 2^bits-1) - * a *= b *= (powers of base1 and base2 to be raised to the power 2^bits-2) - * ... - * a *= b *= (powers of base1 and base2 to be raised to the power 1) - * - * All we do is walk the exponent 2^bits-1 times in groups of "bits" bits, - */ -int -lbnDoubleBasePrecompExp_64(BNWORD64 *result, unsigned bits, - BNWORD64 const * const *array1, BNWORD64 const *exp1, unsigned elen1, - BNWORD64 const * const *array2, BNWORD64 const *exp2, - unsigned elen2, BNWORD64 const *mod, unsigned mlen) -{ - BNWORD64 *a, *b, *c, *t; - BNWORD64 *a1, *b1; - int anull, bnull; /* Null flags: values are implicitly 1 */ - unsigned i, j, k; /* Loop counters */ - unsigned mask; /* Exponent bits to examime */ - BNWORD64 const *eptr; /* Pointer into exp */ - BNWORD64 buf, curbits, nextword; /* Bit-buffer varaibles */ - BNWORD64 inv; /* Inverse of LSW of modulus */ - unsigned ewords; /* Words of exponent left */ - int bufbits; /* Number of valid bits */ - int y = 0; - BNWORD64 const * const *array; - - mlen = lbnNorm_64(mod, mlen); - assert (mlen); - - elen1 = lbnNorm_64(exp1, elen1); - if (!elen1) { - return lbnBasePrecompExp_64(result, array2, bits, exp2, elen2, - mod, mlen); - } - elen2 = lbnNorm_64(exp2, elen2); - if (!elen2) { - return lbnBasePrecompExp_64(result, array1, bits, exp1, elen1, - mod, mlen); - } - /* - * This could be precomputed, but it's so cheap, and it would require - * making the precomputation structure word-size dependent. - */ - inv = lbnMontInv1_64(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ - - assert(elen1); - assert(elen2); - - /* - * Allocate three temporary buffers. The current numbers generally - * live in the upper halves of these buffers. - */ - LBNALLOC(a, BNWORD64, mlen*2); - if (a) { - LBNALLOC(b, BNWORD64, mlen*2); - if (b) { - LBNALLOC(c, BNWORD64, mlen*2); - if (c) - goto allocated; - LBNFREE(b, 2*mlen); - } - LBNFREE(a, 2*mlen); - } - return -1; - -allocated: - - anull = bnull = 1; - - mask = (1u<<bits) - 1; - for (i = mask; i; --i) { - /* Walk each exponent in turn */ - for (k = 0; k < 2; k++) { - /* Set up the exponent for walking */ - array = k ? array2 : array1; - eptr = k ? exp2 : exp1; - ewords = (k ? elen2 : elen1) - 1; - /* Set up bit buffer for walking the exponent */ - buf = BIGLITTLE(*--eptr, *eptr++); - bufbits = 64; - for (j = 0; ewords || buf; j++) { - /* Shift down current buffer */ - curbits = buf; - buf >>= bits; - /* If necessary, add next word */ - bufbits -= bits; - if (bufbits < 0 && ewords > 0) { - nextword = BIGLITTLE(*--eptr, *eptr++); - ewords--; - curbits |= nextword << (bufbits+bits); - buf = nextword >> -bufbits; - bufbits += 64; - } - /* If appropriate, multiply b *= array[j] */ - if ((curbits & mask) == i) { - BNWORD64 const *d = array[j]; - - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (bnull) { - lbnCopy_64(b1, d, mlen); - bnull = 0; - } else { - lbnMontMul_64(c, b1, d, mod, mlen, inv); - t = c; c = b; b = t; - } -#if BNYIELD - if (bnYield && (y = bnYield() < 0)) - goto yield; -#endif - } - } - } - - /* Multiply a *= b */ - if (!bnull) { - a1 = BIGLITTLE(a-mlen-1,a+mlen); - b1 = BIGLITTLE(b-mlen-1,b+mlen); - if (anull) { - lbnCopy_64(a1, b1, mlen); - anull = 0; - } else { - lbnMontMul_64(c, a1, b1, mod, mlen, inv); - t = c; c = a; a = t; - } - } - } - - assert(!anull); /* If it were, elen would have been 0 */ - - /* Convert out of Montgomery form and return */ - a1 = BIGLITTLE(a-mlen-1,a+mlen); - lbnCopy_64(a, a1, mlen); - lbnZero_64(a1, mlen); - lbnMontReduce_64(a, mod, mlen, inv); - lbnCopy_64(result, a1, mlen); - -#if BNYIELD -yield: -#endif - LBNFREE(c, 2*mlen); - LBNFREE(b, 2*mlen); - LBNFREE(a, 2*mlen); - - return y; -} diff --git a/jni/libzrtp/sources/bnlib/lbn64.h b/jni/libzrtp/sources/bnlib/lbn64.h deleted file mode 100644 index 283e248c5..000000000 --- a/jni/libzrtp/sources/bnlib/lbn64.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef LBN64_H -#define LBN64_H - -#include "lbn.h" - -#ifndef BNWORD64 -#error 64-bit bignum library requires a 64-bit data type -#endif - -#ifndef lbnCopy_64 -void lbnCopy_64(BNWORD64 *dest, BNWORD64 const *src, unsigned len); -#endif -#ifndef lbnZero_64 -void lbnZero_64(BNWORD64 *num, unsigned len); -#endif -#ifndef lbnNeg_64 -void lbnNeg_64(BNWORD64 *num, unsigned len); -#endif - -#ifndef lbnAdd1_64 -BNWORD64 lbnAdd1_64(BNWORD64 *num, unsigned len, BNWORD64 carry); -#endif -#ifndef lbnSub1_64 -BNWORD64 lbnSub1_64(BNWORD64 *num, unsigned len, BNWORD64 borrow); -#endif - -#ifndef lbnAddN_64 -BNWORD64 lbnAddN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len); -#endif -#ifndef lbnSubN_64 -BNWORD64 lbnSubN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len); -#endif - -#ifndef lbnCmp_64 -int lbnCmp_64(BNWORD64 const *num1, BNWORD64 const *num2, unsigned len); -#endif - -#ifndef lbnMulN1_64 -void lbnMulN1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k); -#endif -#ifndef lbnMulAdd1_64 -BNWORD64 -lbnMulAdd1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k); -#endif -#ifndef lbnMulSub1_64 -BNWORD64 lbnMulSub1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k); -#endif - -#ifndef lbnLshift_64 -BNWORD64 lbnLshift_64(BNWORD64 *num, unsigned len, unsigned shift); -#endif -#ifndef lbnDouble_64 -BNWORD64 lbnDouble_64(BNWORD64 *num, unsigned len); -#endif -#ifndef lbnRshift_64 -BNWORD64 lbnRshift_64(BNWORD64 *num, unsigned len, unsigned shift); -#endif - -#ifndef lbnMul_64 -void lbnMul_64(BNWORD64 *prod, BNWORD64 const *num1, unsigned len1, - BNWORD64 const *num2, unsigned len2); -#endif -#ifndef lbnSquare_64 -void lbnSquare_64(BNWORD64 *prod, BNWORD64 const *num, unsigned len); -#endif - -#ifndef lbnNorm_64 -unsigned lbnNorm_64(BNWORD64 const *num, unsigned len); -#endif -#ifndef lbnBits_64 -unsigned lbnBits_64(BNWORD64 const *num, unsigned len); -#endif - -#ifndef lbnExtractBigBytes_64 -void lbnExtractBigBytes_64(BNWORD64 const *bn, unsigned char *buf, - unsigned lsbyte, unsigned buflen); -#endif -#ifndef lbnInsertBigytes_64 -void lbnInsertBigBytes_64(BNWORD64 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen); -#endif -#ifndef lbnExtractLittleBytes_64 -void lbnExtractLittleBytes_64(BNWORD64 const *bn, unsigned char *buf, - unsigned lsbyte, unsigned buflen); -#endif -#ifndef lbnInsertLittleBytes_64 -void lbnInsertLittleBytes_64(BNWORD64 *n, unsigned char const *buf, - unsigned lsbyte, unsigned buflen); -#endif - -#ifndef lbnDiv21_64 -BNWORD64 lbnDiv21_64(BNWORD64 *q, BNWORD64 nh, BNWORD64 nl, BNWORD64 d); -#endif -#ifndef lbnDiv1_64 -BNWORD64 lbnDiv1_64(BNWORD64 *q, BNWORD64 *rem, - BNWORD64 const *n, unsigned len, BNWORD64 d); -#endif -#ifndef lbnModQ_64 -unsigned lbnModQ_64(BNWORD64 const *n, unsigned len, unsigned d); -#endif -#ifndef lbnDiv_64 -BNWORD64 -lbnDiv_64(BNWORD64 *q, BNWORD64 *n, unsigned nlen, BNWORD64 *d, unsigned dlen); -#endif - -#ifndef lbnMontInv1_64 -BNWORD64 lbnMontInv1_64(BNWORD64 const x); -#endif -#ifndef lbnMontReduce_64 -void lbnMontReduce_64(BNWORD64 *n, BNWORD64 const *mod, unsigned const mlen, - BNWORD64 inv); -#endif -#ifndef lbnToMont_64 -void lbnToMont_64(BNWORD64 *n, unsigned nlen, BNWORD64 *mod, unsigned mlen); -#endif -#ifndef lbnFromMont_64 -void lbnFromMont_64(BNWORD64 *n, BNWORD64 *mod, unsigned len); -#endif - -#ifndef lbnExpMod_64 -int lbnExpMod_64(BNWORD64 *result, BNWORD64 const *n, unsigned nlen, - BNWORD64 const *exp, unsigned elen, BNWORD64 *mod, unsigned mlen); -#endif -#ifndef lbnDoubleExpMod_64 -int lbnDoubleExpMod_64(BNWORD64 *result, - BNWORD64 const *n1, unsigned n1len, BNWORD64 const *e1, unsigned e1len, - BNWORD64 const *n2, unsigned n2len, BNWORD64 const *e2, unsigned e2len, - BNWORD64 *mod, unsigned mlen); -#endif -#ifndef lbnTwoExpMod_64 -int lbnTwoExpMod_64(BNWORD64 *n, BNWORD64 const *exp, unsigned elen, - BNWORD64 *mod, unsigned mlen); -#endif -#ifndef lbnGcd_64 -int lbnGcd_64(BNWORD64 *a, unsigned alen, BNWORD64 *b, unsigned blen, - unsigned *rlen); -#endif -#ifndef lbnInv_64 -int lbnInv_64(BNWORD64 *a, unsigned alen, BNWORD64 const *mod, unsigned mlen); -#endif - -int lbnBasePrecompBegin_64(BNWORD64 **array, unsigned n, unsigned bits, - BNWORD64 const *g, unsigned glen, BNWORD64 *mod, unsigned mlen); -int lbnBasePrecompExp_64(BNWORD64 *result, BNWORD64 const * const *array, - unsigned bits, BNWORD64 const *exp, unsigned elen, - BNWORD64 const *mod, unsigned mlen); -int lbnDoubleBasePrecompExp_64(BNWORD64 *result, unsigned bits, - BNWORD64 const * const *array1, BNWORD64 const *exp1, unsigned elen1, - BNWORD64 const * const *array2, BNWORD64 const *exp2, - unsigned elen2, BNWORD64 const *mod, unsigned mlen); - -#endif /* LBN64_H */ diff --git a/jni/libzrtp/sources/bnlib/lbnmem.c b/jni/libzrtp/sources/bnlib/lbnmem.c deleted file mode 100644 index 56d2002f3..000000000 --- a/jni/libzrtp/sources/bnlib/lbnmem.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * lbnmem.c - low-level bignum memory handling. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - * - * Note that in all cases, the pointers passed around - * are pointers to the *least* significant end of the word. - * On big-endian machines, these are pointers to the *end* - * of the allocated range. - * - * BNSECURE is a simple level of security; for more security - * change these function to use locked unswappable memory. - */ -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include <bnconfig.h> -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_STDLIB_H -#define NO_STDLIB_H 0 -#endif -#ifndef NO_STRING_H -#define NO_STRING_H 0 -#endif -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 0 -#endif -#ifndef NEED_MEMORY_H -#define NEED_MEMORY_H 0 -#endif - -#if !NO_STDLIB_H -#include <stdlib.h> /* For malloc() & co. */ -#else -void *malloc(); -void *realloc(); -void free(); -#endif - -#if !NO_STRING_H -#include <string.h> /* For memset */ -#elif HAVE_STRINGS_H -#include <strings.h> -#endif -#if NEED_MEMORY_H -#include <memory.h> -#endif - -#ifndef DBMALLOC -#define DBMALLOC 0 -#endif -#if DBMALLOC -/* Development debugging */ -#include "../dbmalloc/malloc.h" -#endif - -#include "lbn.h" -#include "lbnmem.h" - -#include "kludge.h" - -#ifndef lbnMemWipe -void -lbnMemWipe(void *ptr, unsigned bytes) -{ - memset(ptr, 0, bytes); -} -#define lbnMemWipe(ptr, bytes) memset(ptr, 0, bytes) -#endif - -#ifndef lbnMemAlloc -void * -lbnMemAlloc(unsigned bytes) -{ - return malloc(bytes); -} -#define lbnMemAlloc(bytes) malloc(bytes) -#endif - -#ifndef lbnMemFree -void -lbnMemFree(void *ptr, unsigned bytes) -{ - lbnMemWipe(ptr, bytes); - free(ptr); -} -#endif - -#ifndef lbnRealloc -#if defined(lbnMemRealloc) || !BNSECURE -void * -lbnRealloc(void *ptr, unsigned oldbytes, unsigned newbytes) -{ - if (ptr) { - BIG(ptr = (char *)ptr - oldbytes;) - if (newbytes < oldbytes) - memmove(ptr, (char *)ptr + oldbytes-newbytes, oldbytes); - } -#ifdef lbnMemRealloc - ptr = lbnMemRealloc(ptr, oldbytes, newbytes); -#else - ptr = realloc(ptr, newbytes); -#endif - if (ptr) { - if (newbytes > oldbytes) - memmove((char *)ptr + newbytes-oldbytes, ptr, oldbytes); - BIG(ptr = (char *)ptr + newbytes;) - } - - return ptr; -} - -#else /* BNSECURE */ - -void * -lbnRealloc(void *oldptr, unsigned oldbytes, unsigned newbytes) -{ - void *newptr = lbnMemAlloc(newbytes); - - if (!newptr) - return newptr; - if (!oldptr) - return BIGLITTLE((char *)newptr+newbytes, newptr); - - /* - * The following copies are a bit non-obvious in the big-endian case - * because one of the pointers points to the *end* of allocated memory. - */ - if (newbytes > oldbytes) { /* Copy all of old into part of new */ - BIG(newptr = (char *)newptr + newbytes;) - BIG(oldptr = (char *)oldptr - oldbytes;) - memcpy(BIGLITTLE((char *)newptr-oldbytes, newptr), oldptr, - oldbytes); - } else { /* Copy part of old into all of new */ - memcpy(newptr, BIGLITTLE((char *)oldptr-newbytes, oldptr), - newbytes); - BIG(newptr = (char *)newptr + newbytes;) - BIG(oldptr = (char *)oldptr - oldbytes;) - } - - lbnMemFree(oldptr, oldbytes); - - return newptr; -} -#endif /* BNSECURE */ -#endif /* !lbnRealloc */ diff --git a/jni/libzrtp/sources/bnlib/lbnmem.h b/jni/libzrtp/sources/bnlib/lbnmem.h deleted file mode 100644 index f77298b32..000000000 --- a/jni/libzrtp/sources/bnlib/lbnmem.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Operations on the usual buffers of bytes - */ -#ifndef BNSECURE -#define BNSECURE 1 -#endif - -/* - * These operations act on buffers of memory, just like malloc & free. - * One exception: it is not legal to pass a NULL pointer to lbnMemFree. - */ - -#ifndef lbnMemAlloc -void *lbnMemAlloc(unsigned bytes); -#endif - -#ifndef lbnMemFree -void lbnMemFree(void *ptr, unsigned bytes); -#endif - -/* This wipes out a buffer of bytes if necessary needed. */ - -#ifndef lbnMemWipe -#if BNSECURE -void lbnMemWipe(void *ptr, unsigned bytes); -#else -#define lbnMemWipe(ptr, bytes) (void)(ptr,bytes) -#endif -#endif /* !lbnMemWipe */ - -/* - * lbnRealloc is NOT like realloc(); it's endian-sensitive! - * If lbnMemRealloc is #defined, lbnRealloc will be defined in terms of it. - * It is legal to pass a NULL pointer to lbnRealloc, although oldbytes - * will always be sero. - */ -#ifndef lbnRealloc -void *lbnRealloc(void *ptr, unsigned oldbytes, unsigned newbytes); -#endif - - -/* - * These macros are the ones actually used most often in the math library. - * They take and return pointers to the *end* of the given buffer, and - * take sizes in terms of words, not bytes. - * - * Note that LBNALLOC takes the pointer as an argument instead of returning - * the value. - * - * Note also that these macros are only useable if you have included - * lbn.h (for the BIG and BIGLITTLE macros), which this file does NOT include. - */ - -#define LBNALLOC(p,type,words) BIGLITTLE( \ - if ( ((p) = (type *)lbnMemAlloc((words)*sizeof*(p))) != 0) \ - (p) += (words), \ - (p) = (type *)lbnMemAlloc((words) * sizeof*(p)) \ - ) -#define LBNFREE(p,words) lbnMemFree((p) BIG(-(words)), (words) * sizeof*(p)) -#define LBNREALLOC(p,old,new) \ - lbnRealloc(p, (old) * sizeof*(p), (new) * sizeof*(p)) -#define LBNWIPE(p,words) lbnMemWipe((p) BIG(-(words)), (words) * sizeof*(p)) - diff --git a/jni/libzrtp/sources/bnlib/legal.c b/jni/libzrtp/sources/bnlib/legal.c deleted file mode 100644 index 343db140d..000000000 --- a/jni/libzrtp/sources/bnlib/legal.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * bnlib - BigNum multiprecision integer math library. - * Copyright (c) 1995, 2005 Colin Plumb. All rights reserved. - * For licensing information, please contact - * Philip R. Zimmermann <prz@mit.edu>, http://philzimmermann.com - * - * This subroutine library is licensed to the general public under - * the GNU GPL, version 2. Any software that uses code under a GPL - * license is itself subject to the same GPL licensing terms. - * - * For licensing bnlib under alternate terms, so that you can use it without - * your own product becoming infected with the obligations of the GPL, - * you should contact Philip Zimmermann, who has unlimited sublicensing - * rights under non-GPL terms. - * - * This module must be packaged together with the rest of the bnlib - * source code. That's why it's in a .c file. - * - * Lawyers have requested that the following information be included: - * - * Warranties: - * This software is provided "as is," with no warranty expressed - * or implied. - * - * Export controls: - * This software may be subject to export controls by the US Commerce - * Department's Bureau of Industry and Security. - * - */ - -/* Force inclusion of this copyright string. It may be commented out only - * if necessary in order to squeeze bnlib into memory-starved environments. */ -#include "legal.h" -volatile const char bnCopyright[] = - "\0bnlib Copyright (c) 1995, 2005 Colin Plumb."; - - -/**************************************************************************** - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. - -****************************************************************************/ diff --git a/jni/libzrtp/sources/bnlib/legal.h b/jni/libzrtp/sources/bnlib/legal.h deleted file mode 100644 index e28cd917c..000000000 --- a/jni/libzrtp/sources/bnlib/legal.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * We want the copyright string to be accessable to the unix strings command - * in the final linked binary, and we don't want the linker to remove it if - * it's not referenced, so we do that by using the volatile qualifier. - * - * ANSI C standard, section 3.5.3: "An object that has volatile-qualified - * type may be modified in ways unknown to the implementation or have - * other unknown side effects." Yes, we can't expect a compiler to - * understand law... - */ -extern volatile const char bnCopyright[]; diff --git a/jni/libzrtp/sources/bnlib/prime.c b/jni/libzrtp/sources/bnlib/prime.c deleted file mode 100644 index adf17d61b..000000000 --- a/jni/libzrtp/sources/bnlib/prime.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * Prime generation using the bignum library and sieving. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - */ -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include <bnconfig.h> -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_ASSERT_H -#define NO_ASSERT_H 0 -#endif -#if !NO_ASSERT_H -#include <assert.h> -#else -#define assert(x) (void)0 -#endif - -#include <stdarg.h> /* We just can't live without this... */ - -#ifndef BNDEBUG -#define BNDEBUG 1 -#endif -#if BNDEBUG -#include <stdio.h> -#endif - -#include "bn.h" -#include "lbnmem.h" -#include "prime.h" -#include "sieve.h" - -#include "kludge.h" - -/* Size of the shuffle table */ -#define SHUFFLE 256 -/* Size of the sieve area */ -#define SIEVE 32768u/16 - -/* Confirmation tests. The first one *must* be 2 */ -static unsigned const confirm[] = {2, 3, 5, 7, 11, 13, 17}; -#define CONFIRMTESTS (sizeof(confirm)/sizeof(*confirm)) - -/* - * Helper function that does the slow primality test. - * bn is the input bignum; a and e are temporary buffers that are - * allocated by the caller to save overhead. - * - * Returns 0 if prime, >0 if not prime, and -1 on error (out of memory). - * If not prime, returns the number of modular exponentiations performed. - * Calls the given progress function with a '*' for each primality test - * that is passed. - * - * The testing consists of strong pseudoprimality tests, to the bases given - * in the confirm[] array above. (Also called Miller-Rabin, although that's - * not technically correct if we're using fixed bases.) Some people worry - * that this might not be enough. Number theorists may wish to generate - * primality proofs, but for random inputs, this returns non-primes with - * a probability which is quite negligible, which is good enough. - * - * It has been proved (see Carl Pomerance, "On the Distribution of - * Pseudoprimes", Math. Comp. v.37 (1981) pp. 587-593) that the number of - * pseudoprimes (composite numbers that pass a Fermat test to the base 2) - * less than x is bounded by: - * exp(ln(x)^(5/14)) <= P_2(x) ### CHECK THIS FORMULA - it looks wrong! ### - * P_2(x) <= x * exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))). - * Thus, the local density of Pseudoprimes near x is at most - * exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))), and at least - * exp(ln(x)^(5/14) - ln(x)). Here are some values of this function - * for various k-bit numbers x = 2^k: - * Bits Density <= Bit equivalent Density >= Bit equivalent - * 128 3.577869e-07 21.414396 4.202213e-37 120.840190 - * 192 4.175629e-10 31.157288 4.936250e-56 183.724558 - * 256 5.804314e-13 40.647940 4.977813e-75 246.829095 - * 384 1.578039e-18 59.136573 3.938861e-113 373.400096 - * 512 5.858255e-24 77.175803 2.563353e-151 500.253110 - * 768 1.489276e-34 112.370944 7.872825e-228 754.422724 - * 1024 6.633188e-45 146.757062 1.882404e-304 1008.953565 - * - * As you can see, there's quite a bit of slop between these estimates. - * In fact, the density of pseudoprimes is conjectured to be closer to the - * square of that upper bound. E.g. the density of pseudoprimes of size - * 256 is around 3 * 10^-27. The density of primes is very high, from - * 0.005636 at 256 bits to 0.001409 at 1024 bits, i.e. more than 10^-3. - * - * For those people used to cryptographic levels of security where the - * 56 bits of DES key space is too small because it's exhaustible with - * custom hardware searching engines, note that you are not generating - * 50,000,000 primes per second on each of 56,000 custom hardware chips - * for several hours. The chances that another Dinosaur Killer asteroid - * will land today is about 10^-11 or 2^-36, so it would be better to - * spend your time worrying about *that*. Well, okay, there should be - * some derating for the chance that astronomers haven't seen it yet, - * but I think you get the idea. For a good feel about the probability - * of various events, I have heard that a good book is by E'mile Borel, - * "Les Probabilite's et la vie". (The 's are accents, not apostrophes.) - * - * For more on the subject, try "Finding Four Million Large Random Primes", - * by Ronald Rivest, in Advancess in Cryptology: Proceedings of Crypto - * '90. He used a small-divisor test, then a Fermat test to the base 2, - * and then 8 iterations of a Miller-Rabin test. About 718 million random - * 256-bit integers were generated, 43,741,404 passed the small divisor - * test, 4,058,000 passed the Fermat test, and all 4,058,000 passed all - * 8 iterations of the Miller-Rabin test, proving their primality beyond - * most reasonable doubts. - * - * If the probability of getting a pseudoprime is some small p, then the - * probability of not getting it in t trials is (1-p)^t. Remember that, - * for small p, (1-p)^(1/p) ~ 1/e, the base of natural logarithms. - * (This is more commonly expressed as e = lim_{x\to\infty} (1+1/x)^x.) - * Thus, (1-p)^t ~ e^(-p*t) = exp(-p*t). So the odds of being able to - * do this many tests without seeing a pseudoprime if you assume that - * p = 10^-6 (one in a million) is one in 57.86. If you assume that - * p = 2*10^-6, it's one in 3347.6. So it's implausible that the density - * of pseudoprimes is much more than one millionth the density of primes. - * - * He also gives a theoretical argument that the chance of finding a - * 256-bit non-prime which satisfies one Fermat test to the base 2 is - * less than 10^-22. The small divisor test improves this number, and - * if the numbers are 512 bits (as needed for a 1024-bit key) the odds - * of failure shrink to about 10^-44. Thus, he concludes, for practical - * purposes *one* Fermat test to the base 2 is sufficient. - */ -static int -primeTest(struct BigNum const *bn, struct BigNum *e, struct BigNum *a, - int (*f)(void *arg, int c), void *arg) -{ - unsigned i, j; - unsigned k, l; - int err; - -#if BNDEBUG /* Debugging */ - /* - * This is debugging code to test the sieving stage. - * If the sieving is wrong, it will let past numbers with - * small divisors. The prime test here will still work, and - * weed them out, but you'll be doing a lot more slow tests, - * and presumably excluding from consideration some other numbers - * which might be prime. This check just verifies that none - * of the candidates have any small divisors. If this - * code is enabled and never triggers, you can feel quite - * confident that the sieving is doing its job. - */ - i = bnLSWord(bn); - if (!(i % 2)) printf("bn div by 2!"); - i = bnModQ(bn, 51051); /* 51051 = 3 * 7 * 11 * 13 * 17 */ - if (!(i % 3)) printf("bn div by 3!"); - if (!(i % 7)) printf("bn div by 7!"); - if (!(i % 11)) printf("bn div by 11!"); - if (!(i % 13)) printf("bn div by 13!"); - if (!(i % 17)) printf("bn div by 17!"); - i = bnModQ(bn, 63365); /* 63365 = 5 * 19 * 23 * 29 */ - if (!(i % 5)) printf("bn div by 5!"); - if (!(i % 19)) printf("bn div by 19!"); - if (!(i % 23)) printf("bn div by 23!"); - if (!(i % 29)) printf("bn div by 29!"); - i = bnModQ(bn, 47027); /* 47027 = 31 * 37 * 41 */ - if (!(i % 31)) printf("bn div by 31!"); - if (!(i % 37)) printf("bn div by 37!"); - if (!(i % 41)) printf("bn div by 41!"); -#endif - - /* - * Now, check that bn is prime. If it passes to the base 2, - * it's prime beyond all reasonable doubt, and everything else - * is just gravy, but it gives people warm fuzzies to do it. - * - * This starts with verifying Euler's criterion for a base of 2. - * This is the fastest pseudoprimality test that I know of, - * saving a modular squaring over a Fermat test, as well as - * being stronger. 7/8 of the time, it's as strong as a strong - * pseudoprimality test, too. (The exception being when bn == - * 1 mod 8 and 2 is a quartic residue, i.e. bn is of the form - * a^2 + (8*b)^2.) The precise series of tricks used here is - * not documented anywhere, so here's an explanation. - * Euler's criterion states that if p is prime then a^((p-1)/2) - * is congruent to Jacobi(a,p), modulo p. Jacobi(a,p) is - * a function which is +1 if a is a square modulo p, and -1 if - * it is not. For a = 2, this is particularly simple. It's - * +1 if p == +/-1 (mod 8), and -1 if m == +/-3 (mod 8). - * If p == 3 mod 4, then all a strong test does is compute - * 2^((p-1)/2). and see if it's +1 or -1. (Euler's criterion - * says *which* it should be.) If p == 5 (mod 8), then - * 2^((p-1)/2) is -1, so the initial step in a strong test, - * looking at 2^((p-1)/4), is wasted - you're not going to - * find a +/-1 before then if it *is* prime, and it shouldn't - * have either of those values if it isn't. So don't bother. - * - * The remaining case is p == 1 (mod 8). In this case, we - * expect 2^((p-1)/2) == 1 (mod p), so we expect that the - * square root of this, 2^((p-1)/4), will be +/-1 (mod p). - * Evaluating this saves us a modular squaring 1/4 of the time. - * If it's -1, a strong pseudoprimality test would call p - * prime as well. Only if the result is +1, indicating that - * 2 is not only a quadratic residue, but a quartic one as well, - * does a strong pseudoprimality test verify more things than - * this test does. Good enough. - * - * We could back that down another step, looking at 2^((p-1)/8) - * if there was a cheap way to determine if 2 were expected to - * be a quartic residue or not. Dirichlet proved that 2 is - * a quartic residue iff p is of the form a^2 + (8*b^2). - * All primes == 1 (mod 4) can be expressed as a^2 + (2*b)^2, - * but I see no cheap way to evaluate this condition. - */ - if (bnCopy(e, bn) < 0) - return -1; - (void)bnSubQ(e, 1); - l = bnLSWord(e); - - j = 1; /* Where to start in prime array for strong prime tests */ - - if (l & 7) { - bnRShift(e, 1); - if (bnTwoExpMod(a, e, bn) < 0) - return -1; - if ((l & 7) == 6) { - /* bn == 7 mod 8, expect +1 */ - if (bnBits(a) != 1) - return 1; /* Not prime */ - k = 1; - } else { - /* bn == 3 or 5 mod 8, expect -1 == bn-1 */ - if (bnAddQ(a, 1) < 0) - return -1; - if (bnCmp(a, bn) != 0) - return 1; /* Not prime */ - k = 1; - if (l & 4) { - /* bn == 5 mod 8, make odd for strong tests */ - bnRShift(e, 1); - k = 2; - } - } - } else { - /* bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn */ - bnRShift(e, 2); - if (bnTwoExpMod(a, e, bn) < 0) - return -1; - if (bnBits(a) == 1) { - j = 0; /* Re-do strong prime test to base 2 */ - } else { - if (bnAddQ(a, 1) < 0) - return -1; - if (bnCmp(a, bn) != 0) - return 1; /* Not prime */ - } - k = 2 + bnMakeOdd(e); - } - /* It's prime! Now go on to confirmation tests */ - - /* - * Now, e = (bn-1)/2^k is odd. k >= 1, and has a given value - * with probability 2^-k, so its expected value is 2. - * j = 1 in the usual case when the previous test was as good as - * a strong prime test, but 1/8 of the time, j = 0 because - * the strong prime test to the base 2 needs to be re-done. - */ - for (i = j; i < CONFIRMTESTS; i++) { - if (f && (err = f(arg, '*')) < 0) - return err; - (void)bnSetQ(a, confirm[i]); - if (bnExpMod(a, a, e, bn) < 0) - return -1; - if (bnBits(a) == 1) - continue; /* Passed this test */ - - l = k; - for (;;) { - if (bnAddQ(a, 1) < 0) - return -1; - if (bnCmp(a, bn) == 0) /* Was result bn-1? */ - break; /* Prime */ - if (!--l) /* Reached end, not -1? luck? */ - return i+2-j; /* Failed, not prime */ - /* This portion is executed, on average, once. */ - (void)bnSubQ(a, 1); /* Put a back where it was. */ - if (bnSquare(a, a) < 0 || bnMod(a, a, bn) < 0) - return -1; - if (bnBits(a) == 1) - return i+2-j; /* Failed, not prime */ - } - /* It worked (to the base confirm[i]) */ - } - - /* Yes, we've decided that it's prime. */ - if (f && (err = f(arg, '*')) < 0) - return err; - return 0; /* Prime! */ -} - -/* - * Add x*y to bn, which is usually (but not always) < 65536. - * Do it in a simple linear manner. - */ -static int -bnAddMult(struct BigNum *bn, unsigned x, unsigned y) -{ - unsigned long z = (unsigned long)x * y; - - while (z > 65535) { - if (bnAddQ(bn, 65535) < 0) - return -1; - z -= 65535; - } - return bnAddQ(bn, (unsigned)z); -} - -static int -bnSubMult(struct BigNum *bn, unsigned x, unsigned y) -{ - unsigned long z = (unsigned long)x * y; - - while (z > 65535) { - if (bnSubQ(bn, 65535) < 0) - return -1; - z -= 65535; - } - return bnSubQ(bn, (unsigned)z); -} - -/* - * Modifies the bignum to return a nearby (slightly larger) number which - * is a probable prime. Returns >=0 on success or -1 on failure (out of - * memory). The return value is the number of unsuccessful modular - * exponentiations performed. This never gives up searching. - * - * All other arguments are optional. They may be NULL. They are: - * - * unsigned (*rand)(unsigned limit) - * For better distributed numbers, supply a non-null pointer to a - * function which returns a random x, 0 <= x < limit. (It may make it - * simpler to know that 0 < limit <= SHUFFLE, so you need at most a byte.) - * The program generates a large window of sieve data and then does - * pseudoprimality tests on the data. If a rand function is supplied, - * the candidates which survive sieving are shuffled with a window of - * size SHUFFLE before testing to increase the uniformity of the prime - * selection. This isn't perfect, but it reduces the correlation between - * the size of the prime-free gap before a prime and the probability - * that that prime will be found by a sequential search. - * - * If rand is NULL, sequential search is used. If you want sequential - * search, note that the search begins with the given number; if you're - * trying to generate consecutive primes, you must increment the previous - * one by two before calling this again. - * - * int (*f)(void *arg, int c), void *arg - * The function f argument, if non-NULL, is called with progress indicator - * characters for printing. A dot (.) is written every time a primality test - * is failed, a star (*) every time one is passed, and a slash (/) in the - * (very rare) case that the sieve was emptied without finding a prime - * and is being refilled. f is also passed the void *arg argument for - * private context storage. If f returns < 0, the test aborts and returns - * that value immediately. (bn is set to the last value tested, so you - * can increment bn and continue.) - * - * The "exponent" argument, and following unsigned numbers, are exponents - * for which an inverse is desired, modulo p. For a d to exist such that - * (x^e)^d == x (mod p), then d*e == 1 (mod p-1), so gcd(e,p-1) must be 1. - * The prime returned is constrained to not be congruent to 1 modulo - * any of the zero-terminated list of 16-bit numbers. Note that this list - * should contain all the small prime factors of e. (You'll have to test - * for large prime factors of e elsewhere, but the chances of needing to - * generate another prime are low.) - * - * The list is terminated by a 0, and may be empty. - */ -int -primeGen(struct BigNum *bn, unsigned (*rand)(unsigned), - int (*f)(void *arg, int c), void *arg, unsigned exponent, ...) -{ - int retval; - int modexps = 0; - unsigned short offsets[SHUFFLE]; - unsigned i, j; - unsigned p, q, prev; - struct BigNum a, e; -#ifdef MSDOS - unsigned char *sieve; -#else - unsigned char sieve[SIEVE]; -#endif - -#ifdef MSDOS - sieve = lbnMemAlloc(SIEVE); - if (!sieve) - return -1; -#endif - - bnBegin(&a); - bnBegin(&e); - -#if 0 /* Self-test (not used for production) */ -{ - struct BigNum t; - static unsigned char const prime1[] = {5}; - static unsigned char const prime2[] = {7}; - static unsigned char const prime3[] = {11}; - static unsigned char const prime4[] = {1, 1}; /* 257 */ - static unsigned char const prime5[] = {0xFF, 0xF1}; /* 65521 */ - static unsigned char const prime6[] = {1, 0, 1}; /* 65537 */ - static unsigned char const prime7[] = {1, 0, 3}; /* 65539 */ - /* A small prime: 1234567891 */ - static unsigned char const prime8[] = {0x49, 0x96, 0x02, 0xD3}; - /* A slightly larger prime: 12345678901234567891 */ - static unsigned char const prime9[] = { - 0xAB, 0x54, 0xA9, 0x8C, 0xEB, 0x1F, 0x0A, 0xD3 }; - /* - * No, 123456789012345678901234567891 isn't prime; it's just a - * lucky, easy-to-remember conicidence. (You have to go to - * ...4567907 for a prime.) - */ - static struct { - unsigned char const *prime; - unsigned size; - } const primelist[] = { - { prime1, sizeof(prime1) }, - { prime2, sizeof(prime2) }, - { prime3, sizeof(prime3) }, - { prime4, sizeof(prime4) }, - { prime5, sizeof(prime5) }, - { prime6, sizeof(prime6) }, - { prime7, sizeof(prime7) }, - { prime8, sizeof(prime8) }, - { prime9, sizeof(prime9) } }; - - bnBegin(&t); - - for (i = 0; i < sizeof(primelist)/sizeof(primelist[0]); i++) { - bnInsertBytes(&t, primelist[i].prime, 0, - primelist[i].size); - bnCopy(&e, &t); - (void)bnSubQ(&e, 1); - bnTwoExpMod(&a, &e, &t); - p = bnBits(&a); - if (p != 1) { - printf( - "Bug: Fermat(2) %u-bit output (1 expected)\n", p); - fputs("Prime = 0x", stdout); - for (j = 0; j < primelist[i].size; j++) - printf("%02X", primelist[i].prime[j]); - putchar('\n'); - } - bnSetQ(&a, 3); - bnExpMod(&a, &a, &e, &t); - p = bnBits(&a); - if (p != 1) { - printf( - "Bug: Fermat(3) %u-bit output (1 expected)\n", p); - fputs("Prime = 0x", stdout); - for (j = 0; j < primelist[i].size; j++) - printf("%02X", primelist[i].prime[j]); - putchar('\n'); - } - } - - bnEnd(&t); -} -#endif - - /* First, make sure that bn is odd. */ - if ((bnLSWord(bn) & 1) == 0) - (void)bnAddQ(bn, 1); - -retry: - /* Then build a sieve starting at bn. */ - sieveBuild(sieve, SIEVE, bn, 2, 0); - - /* Do the extra exponent sieving */ - if (exponent) { - va_list ap; - unsigned t = exponent; - - va_start(ap, exponent); - - do { - /* The exponent had better be odd! */ - assert(t & 1); - - i = bnModQ(bn, t); - /* Find 1-i */ - if (i == 0) - i = 1; - else if (--i) - i = t - i; - - /* Divide by 2, modulo the exponent */ - i = (i & 1) ? i/2 + t/2 + 1 : i/2; - - /* Remove all following multiples from the sieve. */ - sieveSingle(sieve, SIEVE, i, t); - - /* Get the next exponent value */ - t = va_arg(ap, unsigned); - } while (t); - - va_end(ap); - } - - /* Fill up the offsets array with the first SHUFFLE candidates */ - i = p = 0; - /* Get first prime */ - if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) { - offsets[i++] = p; - p = sieveSearch(sieve, SIEVE, p); - } - /* - * Okay, from this point onwards, p is always the next entry - * from the sieve, that has not been added to the shuffle table, - * and is 0 iff the sieve has been exhausted. - * - * If we want to shuffle, then fill the shuffle table until the - * sieve is exhausted or the table is full. - */ - if (rand && p) { - do { - offsets[i++] = p; - p = sieveSearch(sieve, SIEVE, p); - } while (p && i < SHUFFLE); - } - - /* Choose a random candidate for experimentation */ - prev = 0; - while (i) { - /* Pick a random entry from the shuffle table */ - j = rand ? rand(i) : 0; - q = offsets[j]; /* The entry to use */ - - /* Replace the entry with some more data, if possible */ - if (p) { - offsets[j] = p; - p = sieveSearch(sieve, SIEVE, p); - } else { - offsets[j] = offsets[--i]; - offsets[i] = 0; - } - - /* Adjust bn to have the right value */ - if ((q > prev ? bnAddMult(bn, q-prev, 2) - : bnSubMult(bn, prev-q, 2)) < 0) - goto failed; - prev = q; - - /* Now do the Fermat tests */ - retval = primeTest(bn, &e, &a, f, arg); - if (retval <= 0) - goto done; /* Success or error */ - modexps += retval; - if (f && (retval = f(arg, '.')) < 0) - goto done; - } - - /* Ran out of sieve space - increase bn and keep trying. */ - if (bnAddMult(bn, SIEVE*8-prev, 2) < 0) - goto failed; - if (f && (retval = f(arg, '/')) < 0) - goto done; - goto retry; - -failed: - retval = -1; -done: - bnEnd(&e); - bnEnd(&a); - lbnMemWipe(offsets, sizeof(offsets)); -#ifdef MSDOS - lbnMemFree(sieve, SIEVE); -#else - lbnMemWipe(sieve, sizeof(sieve)); -#endif - - return retval < 0 ? retval : modexps + CONFIRMTESTS; -} - -/* - * Similar, but searches forward from the given starting value in steps of - * "step" rather than 1. The step size must be even, and bn must be odd. - * Among other possibilities, this can be used to generate "strong" - * primes, where p-1 has a large prime factor. - */ -int -primeGenStrong(struct BigNum *bn, struct BigNum const *step, - int (*f)(void *arg, int c), void *arg) -{ - int retval; - unsigned p, prev; - struct BigNum a, e; - int modexps = 0; -#ifdef MSDOS - unsigned char *sieve; -#else - unsigned char sieve[SIEVE]; -#endif - -#ifdef MSDOS - sieve = lbnMemAlloc(SIEVE); - if (!sieve) - return -1; -#endif - - /* Step must be even and bn must be odd */ - assert((bnLSWord(step) & 1) == 0); - assert((bnLSWord(bn) & 1) == 1); - - bnBegin(&a); - bnBegin(&e); - - for (;;) { - if (sieveBuildBig(sieve, SIEVE, bn, step, 0) < 0) - goto failed; - - p = prev = 0; - if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) { - do { - /* - * Adjust bn to have the right value, - * adding (p-prev) * 2*step. - */ - assert(p >= prev); - /* Compute delta into a */ - if (bnMulQ(&a, step, p-prev) < 0) - goto failed; - if (bnAdd(bn, &a) < 0) - goto failed; - prev = p; - - retval = primeTest(bn, &e, &a, f, arg); - if (retval <= 0) - goto done; /* Success! */ - modexps += retval; - if (f && (retval = f(arg, '.')) < 0) - goto done; - - /* And try again */ - p = sieveSearch(sieve, SIEVE, p); - } while (p); - } - - /* Ran out of sieve space - increase bn and keep trying. */ -#if SIEVE*8 == 65536 - /* Corner case that will never actually happen */ - if (!prev) { - if (bnAdd(bn, step) < 0) - goto failed; - p = 65535; - } else { - p = (unsigned)(SIEVE*8 - prev); - } -#else - p = SIEVE*8 - prev; -#endif - if (bnMulQ(&a, step, p) < 0 || bnAdd(bn, &a) < 0) - goto failed; - if (f && (retval = f(arg, '/')) < 0) - goto done; - } /* for (;;) */ - -failed: - retval = -1; - -done: - - bnEnd(&e); - bnEnd(&a); -#ifdef MSDOS - lbnMemFree(sieve, SIEVE); -#else - lbnMemWipe(sieve, sizeof(sieve)); -#endif - return retval < 0 ? retval : modexps + CONFIRMTESTS; -} diff --git a/jni/libzrtp/sources/bnlib/prime.h b/jni/libzrtp/sources/bnlib/prime.h deleted file mode 100644 index faff72299..000000000 --- a/jni/libzrtp/sources/bnlib/prime.h +++ /dev/null @@ -1,12 +0,0 @@ -struct BigNum; - -/* Generate a prime >= bn. leaving the result in bn. */ -int primeGen(struct BigNum *bn, unsigned (*randfunc)(unsigned), - int (*f)(void *arg, int c), void *arg, unsigned exponent, ...); - -/* - * Generate a prime of the form bn + k*step. Step must be even and - * bn must be odd. - */ -int primeGenStrong(struct BigNum *bn, struct BigNum const *step, - int (*f)(void *arg, int c), void *arg); diff --git a/jni/libzrtp/sources/bnlib/sieve.c b/jni/libzrtp/sources/bnlib/sieve.c deleted file mode 100644 index 7362ff521..000000000 --- a/jni/libzrtp/sources/bnlib/sieve.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * sieve.c - Trial division for prime finding. - * - * Copyright (c) 1995 Colin Plumb. All rights reserved. - * For licensing and other legal details, see the file legal.c. - * - * Finding primes: - * - Sieve 1 to find the small primes for - * - Sieve 2 to find the candidate large primes, then - * - Pseudo-primality test. - * - * An important question is how much trial division by small primes - * should we do? The answer is a LOT. Even a heavily optimized - * Fermat test to the base 2 (the simplest pseudoprimality test) - * is much more expensive than a division. - * - * For an prime of n k-bit words, a Fermat test to the base 2 requires n*k - * modular squarings, each of which involves n*(n+1)/2 signle-word multiplies - * in the squaring and n*(n+1) multiplies in the modular reduction, plus - * some overhead to get into and out of Montgomery form. This is a total - * of 3/2 * k * n^2 * (n+1). Equivalently, if n*k = b bits, it's - * 3/2 * (b/k+1) * b^2 / k. - * - * A modulo operation requires n single-word divides. Let's assume that - * a divide is 4 times the cost of a multiply. That's 4*n multiplies. - * However, you only have to do the division once for your entire - * search. It can be amortized over 10-15 primes. So it's - * really more like n/3 multiplies. This is b/3k. - * - * Now, let's suppose you have a candidate prime t. Your options - * are to a) do trial division by a prime p, then do a Fermat test, - * or to do the Fermat test directly. Doing the trial division - * costs b/3k multiplies, but a certain fraction of the time (1/p), it - * saves you 3/2 b^3 / k^2 multiplies. Thus, it's worth it doing the - * division as long as b/3k < 3/2 * (b/k+1) * b^2 / k / p. - * I.e. p < 9/2 * (b/k + 1) * b = 9/2 * (b^2/k + b). - * E.g. for k=16 and b=256, p < 9/2 * 17 * 256 = 19584. - * Solving for k=16 and k=32 at a few interesting value of b: - * - * k=16, b=256: p < 19584 k=32, b=256: p < 10368 - * k=16, b=384: p < 43200 k=32, b=384; p < 22464 - * k=16, b=512: p < 76032 k=32, b=512: p < 39168 - * k=16, b=640: p < 118080 k=32, b=640: p < 60480 - * - * H'm... before using the highly-optimized Fermat test, I got much larger - * numbers (64K to 256K), and designed the sieve for that. Maybe it needs - * to be reduced. It *is* true that the desirable sieve size increases - * rapidly with increasing prime size, and it's the larger primes that are - * worrisome in any case. I'll leave it as is (64K) for now while I - * think about it. - * - * A bit of tweaking the division (we can compute a reciprocal and do - * multiplies instead, turning 4*n into 4 + 2*n) would increase all the - * numbers by a factor of 2 or so. - * - * - * Bit k in a sieve corresponds to the number a + k*b. - * For a given a and b, the sieve's job is to find the values of - * k for which a + k*b == 0 (mod p). Multiplying by b^-1 and - * isolating k, you get k == -a*b^-1 (mod p). So the values of - * k which should be worked on are k = (-a*b^-1 mod p) + i * p, - * for i = 0, 1, 2,... - * - * Note how this is still easy to use with very large b, if you need it. - * It just requires computing (b mod p) and then finding the multiplicative - * inverse of that. - * - * - * How large a space to search to ensure that one will hit a prime? - * The average density is known, but the primes behave oddly, and sometimes - * there are large gaps. It is conjectured by shanks that the first gap - * of size "delta" will occur at approximately exp(sqrt(delta)), so a delta - * of 65536 is conjectured to be to contain a prime up to e^256. - * Remembering the handy 2<->e conversion ratios: - * ln(2) = 0.693147 log2(e) = 1.442695 - * This covers up to 369 bits. Damn, not enough! Still, it'll have to do. - * - * Cramer's conjecture (he proved it for "most" cases) is that in the limit, - * as p goes to infinity, the largest gap after a prime p tends to (ln(p))^2. - * So, for a 1024-bit p, the interval to the next prime is expected to be - * about 709.78^2, or 503791. We'd need to enlarge our space by a factor of - * 8 to be sure. It isn't worth the hassle. - * - * Note that a span of this size is expected to contain 92 primes even - * in the vicinity of 2^1024 (it's 369 at 256 bits and 492 at 192 bits). - * So the probability of failure is pretty low. - */ -#ifndef HAVE_CONFIG_H -#define HAVE_CONFIG_H 0 -#endif -#if HAVE_CONFIG_H -#include <bnconfig.h> -#endif - -/* - * Some compilers complain about #if FOO if FOO isn't defined, - * so do the ANSI-mandated thing explicitly... - */ -#ifndef NO_ASSERT_H -#define NO_ASSERT_H 0 -#endif -#ifndef NO_LIMITS_H -#define NO_LIMITS_H 0 -#endif -#ifndef NO_STRING_H -#define NO_STRING_H 0 -#endif -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 0 -#endif -#ifndef NEED_MEMORY_H -#define NEED_MEMORY_H 0 -#endif - -#if !NO_ASSERT_H -#include <assert.h> -#else -#define assert(x) (void)0 -#endif - -#if !NO_LIMITS_H -#include <limits.h> /* For UINT_MAX */ -#endif /* If not avail, default value of 0 is safe */ - -#if !NO_STRING_H -#include <string.h> /* for memset() */ -#elif HAVE_STRINGS_H -#include <strings.h> -#endif -#if NEED_MEMORY_H -#include <memory.h> -#endif - -#include "bn.h" -#include "sieve.h" -#ifdef MSDOS -#include "lbnmem.h" -#endif - -#include "kludge.h" - -/* - * Each array stores potential primes as 1 bits in little-endian bytes. - * Bit k in an array represents a + k*b, for some parameters a and b - * of the sieve. Currently, b is hardcoded to 2. - * - * Various factors of 16 arise because these are all *byte* sizes, and - * skipping even numbers, 16 numbers fit into a byte's worth of bitmap. - */ - -/* - * The first number in the small prime sieve. This could be raised to - * 3 if you want to squeeze bytes out aggressively for a smaller SMALL - * table, and doing so would let one more prime into the end of the array, - * but there is no sense making it larger if you're generating small - * primes up to the limit if 2^16, since it doesn't save any memory and - * would require extra code to ignore 65537 in the last byte, which is - * over the 16-bit limit. - */ -#define SMALLSTART 1 - -/* - * Size of sieve used to find large primes, in bytes. For compatibility - * with 16-bit-int systems, the largest prime that can appear in it, - * SMALL * 16 + SMALLSTART - 2, must be < 65536. Since 65537 is a prime, - * this is the absolute maximum table size. - */ -#define SMALL (65536/16) - -/* - * Compute the multiplicative inverse of x, modulo mod, using the extended - * Euclidean algorithm. The classical EEA returns two results, traditionally - * named s and t, but only one (t) is needed or computed here. - * It is unrolled twice to avoid some variable-swapping, and because negating - * t every other round makes all the number positive and less than the - * modulus, which makes fixed-length arithmetic easier. - * - * If gcd(x, mod) != 1, then this will return 0. - */ -static unsigned -sieveModInvert(unsigned x, unsigned mod) -{ - unsigned y; - unsigned t0, t1; - unsigned q; - - if (x <= 1) - return x; /* 0 and 1 are self-inverse */ - /* - * The first round is simplified based on the - * initial conditions t0 = 1 and t1 = 0. - */ - t1 = mod / x; - y = mod % x; - if (y <= 1) - return y ? mod - t1 : 0; - t0 = 1; - - do { - q = x / y; - x = x % y; - t0 += q * t1; - if (x <= 1) - return x ? t0 : 0; - q = y / x; - y = y % x; - t1 += q * t0; - } while (y > 1); - return y ? mod - t1 : 0; -} - - -/* - * Perform a single sieving operation on an array. Clear bits "start", - * "start+step", "start+2*step", etc. from the array, up to the size - * limit (in BYTES) "size". All of the arguments must fit into 16 bits - * for portability. - * - * This is the core of the sieving operation. In addition to being - * called from the sieving functions, it is useful to call directly if, - * say, you want to exclude primes congruent to 1 mod 3, or whatever. - * (Although in that case, it would be better to change the sieving to - * use a step size of 6 and start == 5 (mod 6).) - * - * Originally, this was inlined in the code below (with various checks - * turned off where they could be inferred from the environment), but it - * turns out that all the sieving is so fast that it makes a negligible - * speed difference and smaller, cleaner code was preferred. - * - * Rather than increment a bit index through the array and clear - * the corresponding bit, this code takes advantage of the fact that - * every eighth increment must use the same bit position in a byte. - * I.e. start + k*step == start + (k+8)*step (mod 8). Thus, a bitmask - * can be computed only eight times and used for all multiples. Thus, the - * outer loop is over (k mod 8) while the inner loop is over (k div 8). - * - * The only further trickiness is that this code is designed to accept - * start, step, and size up to 65535 on 16-bit machines. On such a - * machine, the computation "start+step" can overflow, so we need to - * insert an extra check for that situation. - */ -void -sieveSingle(unsigned char *array, unsigned size, unsigned start, unsigned step) -{ - unsigned bit; - unsigned char mask; - unsigned i; - -#if UINT_MAX < 0x1ffff - /* Unsigned is small; add checks for wrap */ - for (bit = 0; bit < 8; bit++) { - i = start/8; - if (i >= size) - break; - mask = ~(1 << (start & 7)); - do { - array[i] &= mask; - i += step; - } while (i >= step && i < size); - start += step; - if (start < step) /* Overflow test */ - break; - } -#else - /* Unsigned has the range - no overflow possible */ - for (bit = 0; bit < 8; bit++) { - i = start/8; - if (i >= size) - break; - mask = ~(1 << (start & 7)); - do { - array[i] &= mask; - i += step; - } while (i < size); - start += step; - } -#endif -} - -/* - * Returns the index of the next bit set in the given array. The search - * begins after the specified bit, so if you care about bit 0, you need - * to check it explicitly yourself. This returns 0 if no bits are found. - * - * Note that the size is in bytes, and that it takes and returns BIT - * positions. If the array represents odd numbers only, as usual, the - * returned values must be doubled to turn them into offsets from the - * initial number. - */ -unsigned -sieveSearch(unsigned char const *array, unsigned size, unsigned start) -{ - unsigned i; /* Loop index */ - unsigned char t; /* Temp */ - - if (!++start) - return 0; - i = start/8; - if (i >= size) - return 0; /* Done! */ - - /* Deal with odd-bit beginnings => search the first byte */ - if (start & 7) { - t = array[i++] >> (start & 7); - if (t) { - if (!(t & 15)) { - t >>= 4; - start += 4; - } - if (!(t & 3)) { - t >>= 2; - start += 2; - } - if (!(t & 1)) - start += 1; - return start; - } else if (i == size) { - return 0; /* Done */ - } - } - - /* Now the main search loop */ - - do { - if ((t = array[i]) != 0) { - start = 8*i; - if (!(t & 15)) { - t >>= 4; - start += 4; - } - if (!(t & 3)) { - t >>= 2; - start += 2; - } - if (!(t & 1)) - start += 1; - return start; - } - } while (++i < size); - - /* Failed */ - return 0; -} - -/* - * Build a table of small primes for sieving larger primes with. This - * could be cached between calls to sieveBuild, but it's so fast that - * it's really not worth it. This code takes a few milliseconds to run. - */ -static void -sieveSmall(unsigned char *array, unsigned size) -{ - unsigned i; /* Loop index */ - unsigned p; /* The current prime */ - - /* Initialize to all 1s */ - memset(array, 0xFF, size); - -#if SMALLSTART == 1 - /* Mark 1 as NOT prime */ - array[0] = 0xfe; - i = 1; /* Index of first prime */ -#else - i = 0; /* Index of first prime */ -#endif - - /* - * Okay, now sieve via the primes up to 256, obtained from the - * table itself. We know the maximum possible table size is - * 65536, and sieveSingle() can cope with out-of-range inputs - * safely, and the time required is trivial, so it isn't adaptive - * based on the array size. - * - * Convert each bit position into a prime, compute a starting - * sieve position (the square of the prime), and remove multiples - * from the table, using sieveSingle(). I used to have that - * code in line here, but the speed difference was so small it - * wasn't worth it. If a compiler really wants to waste memory, - * it can inline it. - */ - do { - p = 2 * i + SMALLSTART; - if (p > 256) - break; - /* Start at square of p */ - sieveSingle(array, size, (p*p-SMALLSTART)/2, p); - - /* And find the next prime */ - i = sieveSearch(array, 16, i); - } while (i); -} - - -/* - * This is the primary sieving function. It fills in the array with - * a sieve (multiples of small primes removed) beginning at bn and - * proceeding in steps of "step". - * - * It generates a small array to get the primes to sieve by. It's - * generated on the fly - sieveSmall is fast enough to make that - * perfectly acceptable. - * - * The caller should take the array, walk it with sieveSearch, and - * apply a stronger primality test to the numbers that are returned. - * - * If the "dbl" flag non-zero (at least 1), this also sieves 2*bn+1, in - * steps of 2*step. If dbl is 2 or more, this also sieve 4*bn+3, - * in steps of 4*step, and so on for arbitrarily high values of "dbl". - * This is convenient for finding primes such that (p-1)/2 is also prime. - * This is particularly efficient because sieveSingle is controlled by the - * parameter s = -n/step (mod p). (In fact, we find t = -1/step (mod p) - * and multiply that by n (mod p).) If you have -n/step (mod p), then - * finding -(2*n+1)/(2*step) (mod p), which is -n/step - 1/(2*step) (mod p), - * reduces to finding -1/(2*step) (mod p), or t/2 (mod p), and adding that - * to s = -n/step (mod p). Dividing by 2 modulo an odd p is easy - - * if even, divide directly. Otherwise, add p (which produces an even - * sum), and divide by 2. Very simple. And this produces s' and t' - * for step' = 2*step. It can be repeated for step'' = 4*step and so on. - * - * Note that some of the math is complicated by the fact that 2*p might - * not fit into an unsigned, so rather than if (odd(x)) x = (x+p)/2, - * we do if (odd(x)) x = x/2 + p/2 + 1; - * - * TODO: Do the double-sieving by sieving the larger number, and then - * just subtract one from the remainder to get the other parameter. - * (bn-1)/2 is divisible by an odd p iff bn-1 is divisible, which is - * true iff bn == 1 mod p. This requires using a step size of 4. - */ -int -sieveBuild(unsigned char *array, unsigned size, struct BigNum const *bn, - unsigned step, unsigned dbl) -{ - unsigned i, j; /* Loop index */ - unsigned p; /* Current small prime */ - unsigned s; /* Where to start operations in the big sieve */ - unsigned t; /* Step modulo p, the current prime */ -#ifdef MSDOS /* Use dynamic allocation rather than on the stack */ - unsigned char *small; -#else - unsigned char small[SMALL]; -#endif - - assert(array); - -#ifdef MSDOS - small = lbnMemAlloc(SMALL); /* Which allocator? Not secure. */ - if (!small) - return -1; /* Failed */ -#endif - - /* - * An odd step is a special case, since we must sieve by 2, - * which isn't in the small prime array and has a few other - * special properties. These are: - * - Since the numbers are stored in binary, we don't need to - * use bnModQ to find the remainder. - * - If step is odd, then t = step % 2 is 1, which allows - * the elimination of a lot of math. Inverting and negating - * t don't change it, and multiplying s by 1 is a no-op, - * so t isn't actually mentioned. - * - Since this is the first sieving, instead of calling - * sieveSingle, we can just use memset to fill the array - * with 0x55 or 0xAA. Since a 1 bit means possible prime - * (i.e. NOT divisible by 2), and the least significant bit - * is first, if bn % 2 == 0, we use 0xAA (bit 0 = bn is NOT - * prime), while if bn % 2 == 1, use 0x55. - * (If step is even, bn must be odd, so fill the array with 0xFF.) - * - Any doublings need not be considered, since 2*bn+1 is odd, and - * 2*step is even, so none of these numbers are divisible by 2. - */ - if (step & 1) { - s = bnLSWord(bn) & 1; - memset(array, 0xAA >> s, size); - } else { - /* Initialize the array to all 1's */ - memset(array, 255, size); - assert(bnLSWord(bn) & 1); - } - - /* - * This could be cached between calls to sieveBuild, but - * it's really not worth it; sieveSmall is *very* fast. - * sieveSmall returns a sieve of odd primes. - */ - sieveSmall(small, SMALL); - - /* - * Okay, now sieve via the primes up to ssize*16+SMALLSTART-1, - * obtained from the small table. - */ - i = (small[0] & 1) ? 0 : sieveSearch(small, SMALL, 0); - do { - p = 2 * i + SMALLSTART; - - /* - * Modulo is usually very expensive, but step is usually - * small, so this conditional is worth it. - */ - t = (step < p) ? step : step % p; - if (!t) { - /* - * Instead of assert failing, returning all zero - * bits is the "correct" thing to do, but I think - * that the caller should take care of that - * themselves before starting. - */ - assert(bnModQ(bn, p) != 0); - continue; - } - /* - * Get inverse of step mod p. 0 < t < p, and p is prime, - * so it has an inverse and sieveModInvert can't return 0. - */ - t = sieveModInvert(t, p); - assert(t); - /* Negate t, so now t == -1/step (mod p) */ - t = p - t; - - /* Now get the bignum modulo the prime. */ - s = bnModQ(bn, p); - - /* Multiply by t, the negative inverse of step size */ -#if UINT_MAX/0xffff < 0xffff - s = (unsigned)(((unsigned long)s * t) % p); -#else - s = (s * t) % p; -#endif - - /* s is now the starting bit position, so sieve */ - sieveSingle(array, size, s, p); - - /* Now do the double sieves as desired. */ - for (j = 0; j < dbl; j++) { - /* Halve t modulo p */ -#if UINT_MAX < 0x1ffff - t = (t & 1) ? p/2 + t/2 + 1 : t/2; - /* Add t to s, modulo p with overflow checks. */ - s += t; - if (s >= p || s < t) - s -= p; -#else - if (t & 1) - t += p; - t /= 2; - /* Add t to s, modulo p */ - s += t; - if (s >= p) - s -= p; -#endif - sieveSingle(array, size, s, p); - } - - /* And find the next prime */ - } while ((i = sieveSearch(small, SMALL, i)) != 0); - -#ifdef MSDOS - lbnMemFree(small, SMALL); -#endif - return 0; /* Success */ -} - -/* - * Similar to the above, but use "step" (which must be even) as a step - * size rather than a fixed value of 2. If "step" has any small divisors - * other than 2, this will blow up. - * - * Returns -1 on out of memory (MSDOS only, actually), and -2 - * if step is found to be non-prime. - */ -int -sieveBuildBig(unsigned char *array, unsigned size, struct BigNum const *bn, - struct BigNum const *step, unsigned dbl) -{ - unsigned i, j; /* Loop index */ - unsigned p; /* Current small prime */ - unsigned s; /* Where to start operations in the big sieve */ - unsigned t; /* step modulo p, the current prime */ -#ifdef MSDOS /* Use dynamic allocation rather than on the stack */ - unsigned char *small; -#else - unsigned char small[SMALL]; -#endif - - assert(array); - -#ifdef MSDOS - small = lbnMemAlloc(SMALL); /* Which allocator? Not secure. */ - if (!small) - return -1; /* Failed */ -#endif - /* - * An odd step is a special case, since we must sieve by 2, - * which isn't in the small prime array and has a few other - * special properties. These are: - * - Since the numbers are stored in binary, we don't need to - * use bnModQ to find the remainder. - * - If step is odd, then t = step % 2 is 1, which allows - * the elimination of a lot of math. Inverting and negating - * t don't change it, and multiplying s by 1 is a no-op, - * so t isn't actually mentioned. - * - Since this is the first sieving, instead of calling - * sieveSingle, we can just use memset to fill the array - * with 0x55 or 0xAA. Since a 1 bit means possible prime - * (i.e. NOT divisible by 2), and the least significant bit - * is first, if bn % 2 == 0, we use 0xAA (bit 0 = bn is NOT - * prime), while if bn % 2 == 1, use 0x55. - * (If step is even, bn must be odd, so fill the array with 0xFF.) - * - Any doublings need not be considered, since 2*bn+1 is odd, and - * 2*step is even, so none of these numbers are divisible by 2. - */ - if (bnLSWord(step) & 1) { - s = bnLSWord(bn) & 1; - memset(array, 0xAA >> s, size); - } else { - /* Initialize the array to all 1's */ - memset(array, 255, size); - assert(bnLSWord(bn) & 1); - } - - /* - * This could be cached between calls to sieveBuild, but - * it's really not worth it; sieveSmall is *very* fast. - * sieveSmall returns a sieve of the odd primes. - */ - sieveSmall(small, SMALL); - - /* - * Okay, now sieve via the primes up to ssize*16+SMALLSTART-1, - * obtained from the small table. - */ - i = (small[0] & 1) ? 0 : sieveSearch(small, SMALL, 0); - do { - p = 2 * i + SMALLSTART; - - t = bnModQ(step, p); - if (!t) { - assert(bnModQ(bn, p) != 0); - continue; - } - /* Get negative inverse of step */ - t = sieveModInvert(bnModQ(step, p), p); - assert(t); - t = p-t; - - /* Okay, we have a prime - get the remainder */ - s = bnModQ(bn, p); - - /* Now multiply s by the negative inverse of step (mod p) */ -#if UINT_MAX/0xffff < 0xffff - s = (unsigned)(((unsigned long)s * t) % p); -#else - s = (s * t) % p; -#endif - /* We now have the starting bit pos */ - sieveSingle(array, size, s, p); - - /* Now do the double sieves as desired. */ - for (j = 0; j < dbl; j++) { - /* Halve t modulo p */ -#if UINT_MAX < 0x1ffff - t = (t & 1) ? p/2 + t/2 + 1 : t/2; - /* Add t to s, modulo p with overflow checks. */ - s += t; - if (s >= p || s < t) - s -= p; -#else - if (t & 1) - t += p; - t /= 2; - /* Add t to s, modulo p */ - s += t; - if (s >= p) - s -= p; -#endif - sieveSingle(array, size, s, p); - } - - /* And find the next prime */ - } while ((i = sieveSearch(small, SMALL, i)) != 0); - -#ifdef MSDOS - lbnMemFree(small, SMALL); -#endif - return 0; /* Success */ -} diff --git a/jni/libzrtp/sources/bnlib/sieve.h b/jni/libzrtp/sources/bnlib/sieve.h deleted file mode 100644 index 22ed6cebc..000000000 --- a/jni/libzrtp/sources/bnlib/sieve.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * sieve.h - Trial division for prime finding. - * - * This is generally not intended for direct use by a user of the library; - * the prime.c and dhprime.c functions. are more likely to be used. - * However, a special application may need these. - */ -struct BigNum; - -/* Remove multiples of a single number from the sieve */ -void -sieveSingle(unsigned char *array, unsigned size, unsigned start, unsigned step); - -/* Build a sieve starting at the number and incrementing by "step". */ -int sieveBuild(unsigned char *array, unsigned size, struct BigNum const *bn, - unsigned step, unsigned dbl); - -/* Similar, but uses a >16-bit step size */ -int sieveBuildBig(unsigned char *array, unsigned size, struct BigNum const *bn, - struct BigNum const *step, unsigned dbl); - -/* Return the next bit set in the sieve (or 0 on failure) */ -unsigned sieveSearch(unsigned char const *array, unsigned size, unsigned start); diff --git a/jni/libzrtp/sources/cmake/Modules/GeneratePackage.cmake b/jni/libzrtp/sources/cmake/Modules/GeneratePackage.cmake index 506b22430..43a3d11ef 100644 --- a/jni/libzrtp/sources/cmake/Modules/GeneratePackage.cmake +++ b/jni/libzrtp/sources/cmake/Modules/GeneratePackage.cmake @@ -23,7 +23,7 @@ MACRO(GENERATE_PACKAGING PACKAGE VERSION) # others "\\\\.#" "/#" - "/build*" + "/build/" "/autom4te\\\\.cache/" "/_build/" "/doc/html/" @@ -37,9 +37,6 @@ MACRO(GENERATE_PACKAGING PACKAGE VERSION) "\\\\.la$" "\\\\.sh$" "Makefile\\\\.in$" - "\\\\.directory$" - "\\\\._.DS_Store$" - "\\\\._buildmac$" ) SET(CPACK_PACKAGE_VENDOR "Werner Dittmann") @@ -55,20 +52,24 @@ MACRO(GENERATE_PACKAGING PACKAGE VERSION) # SPECFILE() - ADD_CUSTOM_TARGET(svncheck - COMMAND cd $(CMAKE_SOURCE_DIR) && LC_ALL=C git status | grep -q "nothing to commit .working directory clean.") + ADD_CUSTOM_TARGET( svncheck + COMMAND cd $(CMAKE_SOURCE_DIR) && LC_ALL=C git status | grep -q "nothing to commit .working directory clean." + ) - SET(AUTOBUILD_COMMAND - COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/*.tar.bz2 + SET( AUTOBUILD_COMMAND + COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/package/*.tar.bz2 COMMAND ${CMAKE_MAKE_PROGRAM} package_source + COMMAND ${CMAKE_COMMAND} -E copy ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.bz2 ${CMAKE_BINARY_DIR}/package + COMMAND ${CMAKE_COMMAND} -E remove ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.bz2 # COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/package/${PACKAGE}.changes" "${CMAKE_BINARY_DIR}/package/${PACKAGE}.changes" ) - ADD_CUSTOM_TARGET(srcpackage_local - ${AUTOBUILD_COMMAND}) - - ADD_CUSTOM_TARGET(srcpackage - COMMAND ${CMAKE_MAKE_PROGRAM} svncheck - ${AUTOBUILD_COMMAND}) + ADD_CUSTOM_TARGET( srcpackage_local + ${AUTOBUILD_COMMAND} + ) - ENDMACRO(GENERATE_PACKAGING) + ADD_CUSTOM_TARGET( srcpackage + COMMAND ${CMAKE_MAKE_PROGRAM} svncheck + ${AUTOBUILD_COMMAND} + ) +ENDMACRO(GENERATE_PACKAGING) diff --git a/jni/libzrtp/sources/common/EventClass.cpp b/jni/libzrtp/sources/common/EventClass.cpp deleted file mode 100644 index bfe117f96..000000000 --- a/jni/libzrtp/sources/common/EventClass.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// -// EventClass.cpp: implementation file -// -// Copyright (C) Walter E. Capers. All rights reserved -// -// This source is free to use as you like. If you make -// any changes please keep me in the loop. Email them to -// walt.capers@comcast.net. -// -// PURPOSE: -// -// To implement event signals as a C++ object -// -// REVISIONS -// ======================================================= -// Date: 10.25.07 -// Name: Walter E. Capers -// Description: File creation -// -// Date: 11/02/07 -// Name: Walter E. Capers -// Description: removed unnessary code identified by On Freund from Code Project -// -// -#include "Thread.h" - -#ifndef WINDOWS -#include <sys/time.h> -#endif - -#include <iostream> -using namespace std; - -CEventClass::CEventClass(void) -:m_bCreated(TRUE) -{ - memset(&m_owner,0,sizeof(ThreadId_t)); -#ifdef WINDOWS - m_event = CreateEvent(NULL,FALSE,FALSE,NULL); - if( !m_event ) - { - m_bCreated = FALSE; - } -#else - pthread_mutexattr_t mattr; - - pthread_mutexattr_init(&mattr); - pthread_mutex_init(&m_lock,&mattr); - pthread_cond_init(&m_ready,NULL); - -#endif -} - -CEventClass::~CEventClass(void) -{ -#ifdef WINDOWS - CloseHandle(m_event); -#else - pthread_cond_destroy(&m_ready); - pthread_mutex_destroy(&m_lock); -#endif -} - - -/** - * - * Set - * set an event to signaled - * - **/ -void -CEventClass::Set() -{ -#ifdef WINDOWS - SetEvent(m_event); -#else - pthread_cond_signal(&m_ready); -#endif -} - -/** - * - * Wait - * wait for an event -- wait for an event object - * to be set to signaled. must be paired with a - * call to reset within the same thread. - * - **/ -BOOL -CEventClass::Wait(DWORD tmout) -{ - - try - { - ThreadId_t id = CThread::ThreadId(); - if( CThread::ThreadIdsEqual(&id,&m_owner) ) - { - throw "\n\tinvalid Wait call, Wait can not be called more than once" - "\n\twithout a corresponding call to Reset!\n"; - } - ThreadId_t zero; - memset(&zero,0,sizeof(ThreadId_t)); - - if( memcmp(&zero,&m_owner,sizeof(ThreadId_t)) != 0 ) - { - throw "\n\tanother thread is already waiting on this event!\n"; - } - - m_owner = CThread::ThreadId(); -#ifdef WINDOWS - tmout = tmout == 0 ? INFINITE : tmout; - DWORD rc = WaitForSingleObject(m_event, tmout); - e_timeout = FALSE; - if (rc == WAIT_OBJECT_0) { - return TRUE; - } - else if (rc == WAIT_TIMEOUT) { - e_timeout = TRUE; - return TRUE; - } - else - return FALSE; -#else - pthread_mutex_lock(&m_lock); - e_timeout = FALSE; - if (tmout == 0) { - pthread_cond_wait(&m_ready,&m_lock); - return TRUE; - } - struct timespec ts; - timeval tv; - gettimeofday(&tv, NULL); - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = tv.tv_usec * 1000l; - ts.tv_sec += tmout / 1000; - ts.tv_nsec += (tmout % 1000) * 1000000l; - while(ts.tv_nsec > 1000000000l) { - ++ts.tv_sec; - ts.tv_nsec -= 1000000000l; - } - int rc = pthread_cond_timedwait(&m_ready, &m_lock, &ts); - if (rc == ETIMEDOUT) - e_timeout = TRUE; - return TRUE; -#endif - } - catch( char *psz ) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CEventClass::Wait",MB_ICONHAND); - exit(-1); -#else - cerr << "Fatal exception CEventClass::Wait: " << psz; -#endif - - } - return TRUE; -} - - -/** - * - * Reset - * reset an event flag to unsignaled - * wait must be paired with reset within the same thread. - * - **/ -void -CEventClass::Reset() -{ - try - { - ThreadId_t id = CThread::ThreadId(); - if( !CThread::ThreadIdsEqual(&id,&m_owner) ) - { - throw "\n\tunbalanced call to Reset, Reset must be called from\n" - "\n\tthe same Wait-Reset pair!\n"; - } - - memset(&m_owner,0,sizeof(ThreadId_t)); - -#ifndef WINDOWS - pthread_mutex_unlock(&m_lock); -#endif - } - catch( char *psz ) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CEventClass::Reset",MB_ICONHAND); - exit(-1); -#else - cerr << "Fatal exception CEventClass::Reset: " << psz; -#endif - - } -} - diff --git a/jni/libzrtp/sources/common/EventClass.h b/jni/libzrtp/sources/common/EventClass.h deleted file mode 100644 index d9a15e721..000000000 --- a/jni/libzrtp/sources/common/EventClass.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// EventClass.h: header file -// -// Copyright (C) Walter E. Capers. All rights reserved -// -// This source is free to use as you like. If you make -// any changes please keep me in the loop. Email them to -// walt.capers@comcast.net. -// -// PURPOSE: -// -// To implement event signals as a C++ object -// -// REVISIONS -// ======================================================= -// Date: 10.25.07 -// Name: Walter E. Capers -// Description: File creation -// -// Date: -// Name: -// Description: -// -// -#ifndef EVENT_CLASS -#define EVENT_CLASS - -class CEventClass -{ -private: - ThreadId_t m_owner; -#ifdef WINDOWS - HANDLE m_event; -#else - pthread_cond_t m_ready; - pthread_mutex_t m_lock; -#endif -public: - BOOL e_timeout; - BOOL m_bCreated; - void Set(); - BOOL Wait(DWORD tmout =0); - void Reset(); - CEventClass(void); - ~CEventClass(void); -}; - -#endif - diff --git a/jni/libzrtp/sources/common/MutexClass.cpp b/jni/libzrtp/sources/common/MutexClass.cpp deleted file mode 100644 index ebf8e4e04..000000000 --- a/jni/libzrtp/sources/common/MutexClass.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// MutexClass.cpp: implementation file -// -// Copyright (C) Walter E. Capers. All rights reserved -// -// This source is free to use as you like. If you make -// any changes please keep me in the loop. Email them to -// walt.capers@comcast.net. -// -// PURPOSE: -// -// To implement mutexes as a C++ object -// -// REVISIONS -// ======================================================= -// Date: 10.25.07 -// Name: Walter E. Capers -// Description: File creation -// -// Date: -// Name: -// Description: -// -// -#include "Thread.h" - -#include <iostream> -using namespace std; - -CMutexClass::CMutexClass(void) -:m_bCreated(TRUE) -{ -#ifdef WINDOWS - m_mutex = CreateMutex(NULL,FALSE,NULL); - if( !m_mutex ) m_bCreated = FALSE; -#else - pthread_mutexattr_t mattr; - - pthread_mutexattr_init( &mattr ); - pthread_mutex_init(&m_mutex,&mattr); - -#endif - memset(&m_owner,0,sizeof(ThreadId_t)); - -} - -CMutexClass::~CMutexClass(void) -{ -#ifdef WINDOWS - WaitForSingleObject(m_mutex,INFINITE); - CloseHandle(m_mutex); -#else - pthread_mutex_lock(&m_mutex); - pthread_mutex_unlock(&m_mutex); - pthread_mutex_destroy(&m_mutex); -#endif -} - -/** - * - * Lock - * the same thread can not lock the same mutex - * more than once - * - **/ -void -CMutexClass::Lock() -{ - ThreadId_t id = CThread::ThreadId(); - try { - if(CThread::ThreadIdsEqual(&m_owner,&id) ) - throw "\n\tthe same thread can not acquire a mutex twice!\n"; // the mutex is already locked by this thread -#ifdef WINDOWS - WaitForSingleObject(m_mutex,INFINITE); -#else - pthread_mutex_lock(&m_mutex); -#endif - m_owner = CThread::ThreadId(); - } - catch( char *psz ) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CMutexClass::Lock",MB_ICONHAND); - exit(-1); -#else - cerr << "Fatal exception CMutexClass::Lock : " << psz; -#endif - - - } - -} - -/** - * - * Unlock - * releases a mutex. only the thread that acquires - * the mutex can release it. - * - **/ -void -CMutexClass::Unlock() -{ - ThreadId_t id = CThread::ThreadId(); - try - { - if( ! CThread::ThreadIdsEqual(&id,&m_owner) ) - throw "\n\tonly the thread that acquires a mutex can release it!"; - - memset(&m_owner,0,sizeof(ThreadId_t)); -#ifdef WINDOWS - ReleaseMutex(m_mutex); -#else - pthread_mutex_unlock(&m_mutex); -#endif - } - catch ( char *psz) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CMutexClass::Unlock",MB_ICONHAND); - exit(-1); -#else - cerr << "Fatal exception CMutexClass::Unlock : " << psz; -#endif - - } -} - diff --git a/jni/libzrtp/sources/common/MutexClass.h b/jni/libzrtp/sources/common/MutexClass.h deleted file mode 100644 index a3600f47f..000000000 --- a/jni/libzrtp/sources/common/MutexClass.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// MutexClass.h: header file -// -// Copyright (C) Walter E. Capers. All rights reserved -// -// This source is free to use as you like. If you make -// any changes please keep me in the loop. Email them to -// walt.capers@comcast.net. -// -// PURPOSE: -// -// To implement mutexes as a C++ object -// -// REVISIONS -// ======================================================= -// Date: 10.25.07 -// Name: Walter E. Capers -// Description: File creation -// -// Date: -// Name: -// Description: -// -// - -#ifndef MUTEX_CLASS -#define MUTEX_CLASS - -#ifndef WINDOWS -#if defined(WIN32) || defined(WIN64) -#define WINDOWS -#endif -#endif - -#ifndef WINDOWS -#include <pthread.h> -#endif -#include <common/Thread.h> - -class CMutexClass -{ -private: -#ifdef WINDOWS - HANDLE m_mutex; -#else - pthread_mutex_t m_mutex; -#endif - ThreadId_t m_owner; -public: - BOOL m_bCreated; - void Lock(); - void Unlock(); - CMutexClass(void); - ~CMutexClass(void); -}; -#endif - diff --git a/jni/libzrtp/sources/common/Thread.cpp b/jni/libzrtp/sources/common/Thread.cpp deleted file mode 100644 index 1bec1f01a..000000000 --- a/jni/libzrtp/sources/common/Thread.cpp +++ /dev/null @@ -1,1129 +0,0 @@ -// -// Thread.cpp: implementation file -// -// Copyright (C) Walter E. Capers. All rights reserved -// -// This source is free to use as you like. If you make -// any changes please keep me in the loop. Email your changes -// to walt.capers@comcast.net. -// -// PURPOSE: -// -// To implement threading as a C++ object -// -// NOTES: -// This object supports two types of thread models, event driven and -// interval driven. Under the event driven model, a thread waits -// in a paused state until the member function Event is called. When -// the Event function is called the thread wakes up and calls OnTask. -// Under the interval driven model, the thread wakes up every -// m_dwIdle milli-seconds and calls OnTask. -// -// You can switch between the two models from within the same object. -// -// COMPILER NOTES: -// On Unix you must use -lpthread a -lrt -// On Windows you must specify threaded under C++ code generation -// -// REVISIONS -// ======================================================= -// Date: 10.24.07 -// Name: Walter E. Capers -// Description: File creation -// -// Date: 10.24.07 11:49 am -// Name: Walter E. Capers -// Description: Added SetIdle function to allow the idle time to be altered -// independent of the SetThreadType member function. -// Added sleep interval to Stop function. -// -// Date: 10.25.07 -// Name: Walter E. Capers -// Description: Added support for other non-windows platforms. -// -// Added static functions: ThreadIdsEqual and ThreadId. -// -// Added que for handling multiple events. -// -// Created the CEventClass and CMutexClass classes to facilitate -// platform independence. -// -// Date: 10.26.07 -// Name: Walter E. Capers -// Description: Made object production ready... -// Added more comments -// -// Addressed various issues with threads on UNIX systems. -// -- there was a defect in the Sleep function -// -- there was a defect in the main thread function THKERNEL -// , when transitioning between thread models the CEvent::Reset -// function was not being called when it was necessary resulting -// in a lock up. -// -// Transition between thread types also failed on WINDOWS since the Event -// member function was being called from within SetThreadType. This -// resulted in an Event usage error. To correct the problem m_event.Set -// is called instead. Also, eliminated unecessary logic. -// -// Got rid of OnStart, OnStop, OnDestroy... Could not override with a derived -// class, not sure why I will come back to in a later release. -// -// Changed default behavior of thread. If OnTask is not redefined in the derived -// class the default version now expects a CTask object. The Class for CTask -// is defined in thread.h. A class must be derived from CTask to use it in -// the default version of OnTask(LPVOID). -// -// Date: 11.01.07 -// Name: Walter E. Capers -// Description: I introduced more logic and ASSERTIONS to insure the integrity of CThread objects. -// Both the Homogeneous and Specialized thread types can be physically set using the -// SetThreadType member function. If the thread type is not set, the thread will -// determine its type based on calls to member functions; however, this does not -// apply to interval-based threads. Interval-based threads must be implicitly -// identified using the SetThreadType member function. The new integrity tests -// are implemented to insure usage consistency with a CThread object. -// -// New member functions AtCapacity and PercentCapacity were added to determine -// if a thread is truly busy. AtCapacity will return TRUE under one of two -// conditions: the thread is processing an event and its stack is full, the thread -// is not running. These new functions allow thread objects to be placed in arrays -// and tasked based on their workloads. -// -// The Event member function has been modified to verify that a thread is running -// before posting an event. This resolved a problem on SunOS were threads did not -// start right away; there was a small delay of a few milliseconds. -// -// Error flags are automatically reset when certain member functions are called this -// isolates error occurrences to specific call sequences. -// -// -// Date: 11.01.07 -// Name: Walter E. Capers -// Description: In THKernel, changed how events are released. Events are now released right after -// They are recieved. - -#include "Thread.h" -#ifdef USE_BEGIN_THREAD -#include <process.h> -#endif - - - -#ifndef WINDOWS - -#include <unistd.h> -#include <pthread.h> - -extern "C" -{ - //int usleep(useconds_t useconds); -#ifdef NANO_SECOND_SLEEP - int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); -#endif -} - -void Sleep( unsigned int milli ) -{ -#ifdef NANO_SECOND_SLEEP - struct timespec interval, remainder; - milli = milli * 1000000; - interval.tv_sec= 0; - interval.tv_nsec=milli; - nanosleep(&interval,&remainder); -#else - usleep(milli*1000); -#endif -} -#endif - -#include <iostream> -using namespace std; - -/** - * - * _THKERNEL - * thread callback function used by CreateThread - * - * - **/ -#ifdef WINDOWS -#ifdef USE_BEGIN_THREAD -unsigned __stdcall -#else -DWORD WINAPI -#endif -#else -LPVOID -#endif -_THKERNEL( LPVOID lpvData /* CThread Object */ - ) -{ - CThread *pThread = (CThread *)lpvData; - ThreadType_t lastType; - /* - * - * initialization - * - */ - - - pThread->m_mutex.Lock(); - pThread->m_state = ThreadStateWaiting; - pThread->m_bRunning = TRUE; -#ifndef WINDOWS - pThread->m_dwId = CThread::ThreadId(); -#endif - pThread->m_mutex.Unlock(); - - while( TRUE ) - { - lastType = pThread->m_type; - - if( lastType == ThreadTypeHomogeneous || - lastType == ThreadTypeSpecialized || - lastType == ThreadTypeNotDefined ) - { - if( ! pThread->m_event.Wait() ) // wait for a message - break; - pThread->m_event.Reset(); // message recieved - } - - if( ! pThread->KernelProcess() ) - break; - - - /*if( lastType == ThreadTypeHomogeneous || - lastType == ThreadTypeSpecialized || - lastType == ThreadTypeNotDefined ) - { - pThread->m_event.Reset(); - } */ - - if( pThread->m_type == ThreadTypeIntervalDriven ) - Sleep(pThread->m_dwIdle); - - } - - - pThread->m_mutex.Lock(); - pThread->m_state = ThreadStateDown; - pThread->m_bRunning = FALSE; - pThread->m_mutex.Unlock(); - - -#ifdef WINDOWS - return 0; -#else - return (LPVOID)0; -#endif -} - -/** - * - * FromSameThread - * determines if the calling thread is the same - * as the thread assoicated with the object - * - **/ -BOOL -CThread::FromSameThread() -{ - ThreadId_t id = ThreadId(); - if( ThreadIdsEqual(&id,&m_dwId) ) return TRUE; - return FALSE; -} - -/** - * - * OnTask - * called when a thread is tasked using the Event - * member function - * - **/ -BOOL -CThread::OnTask( LPVOID lpvData /*data passed from thread*/ - ) -{ - ASSERT(lpvData && m_type == ThreadTypeHomogeneous); - - if( m_type != ThreadTypeHomogeneous ) - { - cerr << "Warning CThread::OnTask:\n\tOnTask(LPVOID) called for a non-homogeneous thread!\n"; - return FALSE; - } - - ((CTask *)lpvData)->SetTaskStatus(TaskStatusBeingProcessed); - BOOL bReturn = ((CTask *)lpvData)->Task(); - ((CTask *)lpvData)->SetTaskStatus(TaskStatusCompleted); - - return bReturn; -} - - - -/** - * - * OnTask - * overloaded implementation of OnTask that - * takes no arguments - * - **/ -BOOL -CThread::OnTask() -{ - ASSERT(m_type == ThreadTypeIntervalDriven); - if( m_type != ThreadTypeIntervalDriven ) - { - cerr << "Warning CThread::OnTask:\n\tOnTask() called for a non-event driven thread!\n"; - return FALSE; - } - - printf("\nthread is alive\n"); - - return TRUE; -} - -/** - * - * CEvent - * used to place tasks on the threads event queue - * wakes up thread. - * - **/ -BOOL -CThread::Event(CTask *pvTask /* data to be processed by thread */ - ) -{ - m_mutex.Lock(); - - ASSERT(m_type == ThreadTypeHomogeneous || - m_type == ThreadTypeNotDefined ); - - try - { - if( FromSameThread() ) - { - throw "\n\tit is illegal for a thread to place an event on its own event stack!\n"; - } - - - // make sure that the thread is running - if( !m_bRunning && m_dwObjectCondition == NO_ERRORS ) - { - m_mutex.Unlock(); - PingThread(m_dwIdle*2); // wait two idle cycles for it to start - m_mutex.Lock(); - } - if( !m_bRunning ) // if it is not running return FALSE; - { - m_mutex.Unlock(); - return FALSE; - } - - - if( m_dwObjectCondition & ILLEGAL_USE_OF_EVENT ) - m_dwObjectCondition = m_dwObjectCondition ^ ILLEGAL_USE_OF_EVENT; - if( m_dwObjectCondition & EVENT_AND_TYPE_DONT_MATCH) - m_dwObjectCondition = m_dwObjectCondition ^ EVENT_AND_TYPE_DONT_MATCH; - - if( m_type != ThreadTypeHomogeneous && - m_type != ThreadTypeNotDefined ) - { - m_mutex.Unlock(); - m_dwObjectCondition |= ILLEGAL_USE_OF_EVENT; - m_dwObjectCondition |= EVENT_AND_TYPE_DONT_MATCH; - m_state = ThreadStateFault; - cerr << "Warning: invalid call to CEvent::Event(CTask *), thread type is not specialized\n"; - - return FALSE; - } - - m_type = ThreadTypeHomogeneous; - m_mutex.Unlock(); - - pvTask->SetId(&m_dwId); - if( ! Push((LPVOID)pvTask) ) - return FALSE; - - pvTask->SetTaskStatus(TaskStatusWaitingOnQueue); - m_event.Set(); - - } - catch (char *psz) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CThread::CEvent",MB_ICONHAND); - exit(-1); -#else - cerr << "Fatal exception CThread::CEvent(CTask *pvTask):" << psz; -#endif - - } - return TRUE; -} - -/** - * - * Event - * used to place tasks on the threads event queue - * wakes up thread. - * - **/ -BOOL -CThread::Event(LPVOID lpvData /* data to be processed by thread */ - ) -{ - - m_mutex.Lock(); - ASSERT( m_type == ThreadTypeSpecialized || - m_type == ThreadTypeNotDefined ); - try - { - if( FromSameThread() ) - { - throw "\n\tit is illegal for a thread to place an event on its own event stack!\n"; - } - } - catch (char *psz) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CThread::CEvent",MB_ICONHAND); - exit(-1); -#else - cerr << "Fatal exception CThread::CEvent(LPVOID lpvData):" << psz; -#endif - - } - - // make sure that the thread is running - if( !m_bRunning && m_dwObjectCondition == NO_ERRORS ) - { - m_mutex.Unlock(); - PingThread(m_dwIdle*2); // wait two idle cycles for it to start - m_mutex.Lock(); - } - if( !m_bRunning ) // if it is not running return FALSE; - { - m_mutex.Unlock(); - return FALSE; - } - - if( m_dwObjectCondition & ILLEGAL_USE_OF_EVENT ) - m_dwObjectCondition = m_dwObjectCondition ^ ILLEGAL_USE_OF_EVENT; - if( m_dwObjectCondition & EVENT_AND_TYPE_DONT_MATCH) - m_dwObjectCondition = m_dwObjectCondition ^ EVENT_AND_TYPE_DONT_MATCH; - - if( m_type != ThreadTypeSpecialized && - m_type != ThreadTypeNotDefined ) - { - m_dwObjectCondition |= ILLEGAL_USE_OF_EVENT; - m_dwObjectCondition |= EVENT_AND_TYPE_DONT_MATCH; - cerr << "Warning: invalid call to CEvent::Event(LPVOID), thread type is not specialized\n"; - m_mutex.Unlock(); - return FALSE; - } - m_type = ThreadTypeSpecialized; - - m_mutex.Unlock(); - if( ! Push(lpvData) ) - { - return FALSE; - } - - m_event.Set(); - - return TRUE; -} - - -/** - * - * SetPriority - * sets a threads run priority, see SetThreadPriority - * Note: only works for Windows family of operating systems - * - * - **/ -void -CThread::SetPriority(DWORD dwPriority) -{ - -#ifdef WINDOWS - SetThreadPriority(m_thread,dwPriority); -#endif -} - - -/** - * - * KernelProcess - * routes thread activity - * - **/ -BOOL -CThread::KernelProcess() -{ - - m_mutex.Lock(); - m_state = ThreadStateBusy; - if( !m_bRunning ) - { - m_state = ThreadStateShuttingDown; - m_mutex.Unlock(); - return FALSE; - } - m_mutex.Unlock(); - - if( !Empty() ) - { - while( !Empty() ) - { - Pop(); - if( !OnTask(m_lpvProcessor) ) - { - m_mutex.Lock(); - m_lpvProcessor = NULL; - m_state = ThreadStateShuttingDown; - m_mutex.Unlock(); - return FALSE; - } - } - m_mutex.Lock(); - m_lpvProcessor = NULL; - m_state = ThreadStateWaiting; - } - else { - if( !OnTask() ) - { - m_mutex.Lock(); - m_state = ThreadStateShuttingDown; - m_mutex.Unlock(); - return FALSE; - } - m_mutex.Lock(); - m_state = ThreadStateWaiting; - } - - m_mutex.Unlock(); - - return TRUE; -} - - -/** - * - * GetEventsPending - * returns the total number of vents waiting - * in the event que - * - **/ -unsigned int -CThread::GetEventsPending() -{ - unsigned int chEventsWaiting; - - m_mutex.Lock(); - chEventsWaiting = m_queuePos; - m_mutex.Unlock(); - - return chEventsWaiting; -} - - -/** - * - * CThread - * instanciates thread object and - * starts thread. - * - **/ -CThread::CThread(void) -:m_bRunning(FALSE) -#ifdef WINDOWS -,m_thread(NULL) -#endif -,m_dwId(0L) -,m_state(ThreadStateDown) -,m_dwIdle(100) -,m_lppvQueue(NULL) -,m_lpvProcessor(NULL) -,m_chQueue(QUEUE_SIZE) -,m_type(ThreadTypeNotDefined) -,m_stackSize(DEFAULT_STACK_SIZE) -,m_queuePos(0) -,m_StopTimeout(30) -{ - - m_dwObjectCondition = NO_ERRORS; - - m_lppvQueue = new LPVOID [QUEUE_SIZE]; - - if( !m_lppvQueue ) - { - m_dwObjectCondition |= MEMORY_FAULT; - m_state = ThreadStateFault; - return; - } - - if( !m_mutex.m_bCreated ) - { - perror("mutex creation failed"); - m_dwObjectCondition |= MUTEX_CREATION; - m_state = ThreadStateFault; - return; - } - - - if( !m_event.m_bCreated ) - { - perror("event creation failed"); - m_dwObjectCondition |= EVENT_CREATION; - m_state = ThreadStateFault; - return; - } - - - Start(); - -} - - -/** - * - * PercentCapacity - * returns a floating point value identifying - * the current workload of the thread - * - **/ -float -CThread::PercentCapacity() -{ - float fValue = 0; - m_mutex.Lock(); - fValue = (float)m_queuePos/m_chQueue; - m_mutex.Unlock(); - return fValue; -} - -/** - * - * SetQueueSize - * changes the threads queue size - * - **/ -BOOL -CThread::SetQueueSize( unsigned int ch ) -{ - LPVOID * newQueue = NULL; - - m_mutex.Lock(); - ASSERT(ch > m_queuePos); - - if( ch <= m_queuePos ) - { - cerr << "Warning CThread::SetQueueSize:\n\tthe new queue size is less than the number of tasks on a non-empty queue! Request ignored.\n"; - m_mutex.Unlock(); - return FALSE; - } - - newQueue = new LPVOID [ch]; - if( !newQueue ) - { - cerr << "Warning CThread::SetQueueSize:\n\ta low memory, could not reallocate queue!\n"; - m_mutex.Unlock(); - return FALSE; - } - - for( unsigned int i=0;i<m_queuePos; i++ ) - { - newQueue[i] = m_lppvQueue[i]; - } - - delete [] m_lppvQueue; - - m_chQueue = ch; - m_lppvQueue = newQueue; - - m_mutex.Unlock(); - - return TRUE; -} - - - -/** - * - * Empty - * returns a value of TRUE if there are no items on the threads que - * otherwise a value of FALSE is returned. - * - **/ -BOOL -CThread::Empty() -{ - m_mutex.Lock(); - if( m_queuePos <= 0 ) - { - m_mutex.Unlock(); - return TRUE; - } - m_mutex.Unlock(); - return FALSE; -} - - - -/** - * - * Push - * place a data object in the threads que - * - **/ -BOOL -CThread::Push( LPVOID lpv ) -{ - if( !lpv ) return TRUE; - - m_mutex.Lock(); - - if( m_queuePos+1 >= m_chQueue ) { - m_dwObjectCondition |= STACK_OVERFLOW; - m_mutex.Unlock(); - return FALSE; - } - if( m_dwObjectCondition & STACK_EMPTY ) - m_dwObjectCondition = m_dwObjectCondition ^ STACK_EMPTY; - - if( m_dwObjectCondition & STACK_OVERFLOW ) - m_dwObjectCondition = m_dwObjectCondition ^ STACK_OVERFLOW; - - m_lppvQueue[m_queuePos++] = lpv; - if( m_queuePos+1 >= m_chQueue ) - m_dwObjectCondition |= STACK_FULL; - - m_mutex.Unlock(); - return TRUE; -} - - -/** - * - * Pop - * move an object from the input que to the processor - * - **/ -BOOL -CThread::Pop() -{ - - m_mutex.Lock(); - if( m_queuePos-1 < 0 ) - { - m_queuePos = 0; - m_dwObjectCondition |= STACK_EMPTY; - m_mutex.Unlock(); - return FALSE; - } - if( m_dwObjectCondition & STACK_EMPTY ) - m_dwObjectCondition = m_dwObjectCondition ^ STACK_EMPTY; - if( m_dwObjectCondition & STACK_OVERFLOW ) - m_dwObjectCondition = m_dwObjectCondition ^ STACK_OVERFLOW; - if( m_dwObjectCondition & STACK_FULL ) - m_dwObjectCondition = m_dwObjectCondition ^ STACK_FULL; - - m_queuePos--; - m_lpvProcessor = m_lppvQueue[m_queuePos]; - m_mutex.Unlock(); - return TRUE; -} - - -/** - * - * SetThreadType - * specifies the type of threading that is to be performed. - * - * ThreadTypeEventDriven (default): an event must be physically sent - * to the thread using the Event member - * function. - * - * ThreadTypeIntervalDriven : an event occurs automatically every - * dwIdle milli seconds. - * - **/ -void -CThread::SetThreadType(ThreadType_t typ, - DWORD dwIdle) -{ - - try - { - if( FromSameThread() ) - { - throw "\n\tit is illegal for a thread to change its own type!\n"; - } - - - m_mutex.Lock(); - m_dwIdle = dwIdle; - - - if( m_type == typ ) { - m_mutex.Unlock(); - return; - } - if( m_dwObjectCondition & ILLEGAL_USE_OF_EVENT ) - m_dwObjectCondition = m_dwObjectCondition ^ ILLEGAL_USE_OF_EVENT; - if( m_dwObjectCondition & EVENT_AND_TYPE_DONT_MATCH ) - m_dwObjectCondition = m_dwObjectCondition ^ EVENT_AND_TYPE_DONT_MATCH; - - m_type = typ; - - - m_mutex.Unlock(); - m_event.Set(); - } - catch (char *psz) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CThread::SetThreadType",MB_ICONHAND); - exit(-1); -#else - cerr << "Fatal exception CThread::SetThreadType(ThreadType_t typ):" << psz; -#endif - - } -} - - -/** - * - * Stop - * stop thread - * - **/ -BOOL -CThread::Stop() -{ - try - { - if( FromSameThread() ) - { - throw "\n\tit is illegal for a thread to attempt to signal itself to stop!\n"; - } - - m_mutex.Lock(); - m_bRunning = FALSE; - m_mutex.Unlock(); - m_event.Set(); - - int ticks = (m_StopTimeout*1000)/100; - - for( int i=0; i<ticks; i++ ) - { - Sleep(100); - - m_mutex.Lock(); - if( m_state == ThreadStateDown ) - { - m_mutex.Unlock(); - return TRUE; - } - m_mutex.Unlock(); - - } - } - catch (char *psz) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CThread::Stop",MB_ICONHAND); - exit(-1); -#else - cerr << "Fatal exception CThread::Stop():" << psz; -#endif - - } - return FALSE; -} - - -/** - * - * SetIdle - * changes the threads idle interval - * - **/ -void -CThread::SetIdle(DWORD dwIdle) -{ - m_mutex.Lock(); - m_dwIdle = dwIdle; - m_mutex.Unlock(); -} - -/** - * - * Start - * start thread - * - **/ -BOOL -CThread::Start() -{ - try - { - if( FromSameThread() ) - { - throw "\n\tit is illegal for a thread to attempt to start itself!\n"; - } - - - m_mutex.Lock(); - if( m_bRunning ) - { - m_mutex.Unlock(); - return TRUE; - } - - m_mutex.Unlock(); - - - if( m_dwObjectCondition & THREAD_CREATION ) - m_dwObjectCondition = m_dwObjectCondition ^ THREAD_CREATION; - -#ifdef WINDOWS - if( m_thread ) CloseHandle(m_thread); -#ifdef USE_BEGIN_THREAD - m_thread = (HANDLE )_beginthreadex(NULL,(unsigned int)m_stackSize,_THKERNEL,(LPVOID)this,0,&m_dwId); -#else - m_thread = CreateThread(NULL,m_stackSize ,_THKERNEL,(LPVOID)this,0,&m_dwId); -#endif - if( !m_thread ) - { - perror("thread creation failed"); - m_dwObjectCondition |= THREAD_CREATION; - m_state = ThreadStateFault; - return FALSE; - } -#else - pthread_attr_t attr; - - pthread_attr_init(&attr); - -#ifdef VMS - if( m_stackSize == 0 ) - pthread_attr_setstacksize(&attr,PTHREAD_STACK_MIN*10); -#endif - if( m_stackSize != 0 ) - pthread_attr_setstacksize(&attr,m_stackSize); - - int error = pthread_create(&m_thread,&attr,_THKERNEL,(LPVOID)this); - - if( error != 0 ) - { - m_dwObjectCondition |= THREAD_CREATION; - m_state = ThreadStateFault; - -#if defined(HPUX) || defined(SUNOS) || defined(LINUX) - switch(error)/* show the thread error */ - { - - case EINVAL: - cerr << "error: attr in an invalid thread attributes object\n"; - break; - case EAGAIN: - cerr << "error: the necessary resources to create a thread are not\n"; - cerr << "available.\n"; - break; - case EPERM: - cerr << "error: the caller does not have the privileges to create\n"; - cerr << "the thread with the specified attr object.\n"; - break; -#if defined(HPUX) - case ENOSYS: - - cerr << "error: pthread_create not implemented!\n"; - if( __is_threadlib_linked()==0 ) - { - cerr << "error: threaded library not being used, improper linkage \"-lpthread -lc\"!\n"; - } - break; -#endif - default: - cerr << "error: an unknown error was encountered attempting to create\n"; - cerr << "the requested thread.\n"; - break; - } -#else - cerr << "error: could not create thread, pthread_create failed (" << error << ")!\n"; -#endif - return FALSE; - } -#endif - } - catch (char *psz) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CThread::Start",MB_ICONHAND); -#else - cerr << "Fatal exception CThread::Start():" << psz; -#endif - exit(-1); - } - return TRUE; -} - -/** - * - * AtCapacity - * returns TRUE if the threads queue is full, and the thread - * is busy processing an event or the thread is not running - * - **/ -BOOL -CThread::AtCapacity() -{ - m_mutex.Lock(); - if( ((m_dwObjectCondition & STACK_OVERFLOW || - m_dwObjectCondition & STACK_FULL ) && - m_state == ThreadStateBusy) || !m_bRunning) - { - m_mutex.Unlock(); - return TRUE; - } - m_mutex.Unlock(); - return FALSE; -} - -/** - * - * ThreadState - * return the current state of the thread - * - **/ -ThreadState_t -CThread::ThreadState() -{ - ThreadState_t currentState; - m_mutex.Lock(); - currentState = m_state; - m_mutex.Unlock(); - return currentState; -} - -/** - * - * ~CThread - * destructor. Stop should be called prior to destruction to - * allow for gracefull thread termination. - * - **/ -CThread::~CThread(void) -{ - if( m_bRunning ) // gracefull termination - { - try - { - if( !Stop() ) - { - throw "\n\tthread failed to stop in a timely manner!\n"; - } - } - catch( char *psz ) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CThread::Stop",MB_ICONHAND); - exit(-1); -#else - cerr << "Fatal exception CThread::Stop: " << psz; -#endif - } - } -#ifdef WINDOWS - CloseHandle(m_thread); -#endif - - delete [] m_lppvQueue; -} - - -/** - * - * PingThread - * used to determine if a thread is running - * - **/ -BOOL -CThread::PingThread(DWORD dwTimeout /* timeout in milli-seconds */ - ) -{ - DWORD dwTotal = 0; - - while(TRUE) - { - if( dwTotal > dwTimeout && dwTimeout > 0 ) - return FALSE; - m_mutex.Lock(); - if( m_bRunning ) - { - m_mutex.Unlock(); - return TRUE; - } - dwTotal += m_dwIdle; - m_mutex.Unlock(); - Sleep(m_dwIdle); - } - - return FALSE; -} - -/** - * - * WaitTillExit - * blocks caller until thread exits - * - **/ -void -CThread::WaitTillExit() -{ - - /* - * - * prevent users from calling this function from within the same thread - * of execution - * - */ - try - { - if( FromSameThread() ) - throw "\n\tthis function can not be called from within the same thread!\n"; - - - - - if( !m_bRunning ) return; - - -#ifdef WINDOWS - WaitForSingleObject(m_thread,INFINITE); -#else - LPVOID lpv; - - pthread_join(m_thread,&lpv); -#endif - } - catch( char *psz ) - { -#ifdef WINDOWS - MessageBoxA(NULL,&psz[2],"Fatal exception CThread::WaitTillExit",MB_ICONHAND); - exit(-1); -#else - cerr << "Fatal exception CThread::WaitTillExit: " << psz; -#endif - - } -} - - - - diff --git a/jni/libzrtp/sources/common/Thread.h b/jni/libzrtp/sources/common/Thread.h deleted file mode 100644 index ca7725547..000000000 --- a/jni/libzrtp/sources/common/Thread.h +++ /dev/null @@ -1,315 +0,0 @@ -// -// Thread.h: header file -// -// Copyright (C) Walter E. Capers. All rights reserved -// -// This source is free to use as you like. If you make -// any changes please keep me in the loop. Email them to -// walt.capers@comcast.net. -// -// PURPOSE: -// -// To implement Win32 threading as a C++ object -// -// REVISIONS -// ======================================================= -// Date: 10.24.07 -// Name: Walter E. Capers -// Description: File creation -// -// Date: 10.24.07 11:49 am -// Name: Walter E. Capers -// Description: Added SetIdle function to allow the idle time to be altered -// independent of the SetThreadType member function. -// Date: 10.31.07 -// Name: Walter E. Capers -// Description: Added support for beginthreadex -// To use compile with -DUSE_BEGIN_THREAD -// -// - -#ifndef THREAD_CLASS -#define THREAD_CLASS - -#ifndef WINDOWS -#if defined(_WIN32) || defined(_WIN64) -#define WINDOWS -#endif -#endif -#ifdef __APPLE__ -#define VMS -#endif - -#ifndef WINDOWS -#include <stdio.h> -#include <string.h> -//#include <malloc.h> -#include <memory.h> -#include <pthread.h> -#include <stdlib.h> -#include <time.h> -#include <errno.h> -typedef unsigned char BOOL; -#define TRUE 1 -#define FALSE 0 -typedef long DWORD; -typedef void *LPVOID; -#else -#include "afx.h" -/* #include <windows.h> */ -#include <stdio.h> -#endif - -#if defined(AS400) || defined(OS400) -typedef pthread_id_np_t ThreadId_t; -#elif defined(VMS) || defined(__NetBSD__) -typedef pthread_t ThreadId_t; -#else -#ifdef USE_BEGIN_THREAD -typedef unsigned ThreadId_t; -#else -typedef DWORD ThreadId_t; -#endif -#endif - -#include <common/MutexClass.h> -#include <common/EventClass.h> - -#define QUEUE_SIZE 100 -#define DEFAULT_STACK_SIZE 0 -#ifndef WINDOWS -void Sleep( unsigned int mseconds); -#endif - -#ifndef ASSERT -#if defined(DEBUG) || defined(_DEBUG) -#define ASSERT(test) if( !(test) ) { \ - fprintf(stderr,"\nASSERT(%s) FAILS, %s line %d\n",#test,__FILE__, __LINE__); exit(0);} -#else -#define ASSERT(test) -#endif -#endif - - -typedef enum { - ThreadStateBusy, // thread is currently handling a task - ThreadStateWaiting, // thread is waiting for something to do - ThreadStateDown, // thread is not running - ThreadStateShuttingDown, // thread is in the process of shutting down - ThreadStateFault // an error has occured and the thread could not - // be launched -} ThreadState_t; - -typedef enum { - ThreadTypeHomogeneous, - ThreadTypeSpecialized, - ThreadTypeIntervalDriven, - ThreadTypeNotDefined } ThreadType_t; - - -typedef enum { - TaskStatusNotSubmitted, - TaskStatusWaitingOnQueue, - TaskStatusBeingProcessed, - TaskStatusCompleted } TaskStatus_t; - -class CTask -{ -private: - TaskStatus_t m_state; - ThreadId_t m_dwThread; -public: - CMutexClass m_mutex; - - void SetTaskStatus(TaskStatus_t state) - { - m_mutex.Lock(); - m_state=state; - m_mutex.Unlock(); - } - - void SetId(ThreadId_t *pid) - { - memcpy(&m_dwThread,pid,sizeof(ThreadId_t)); - } - - /** - * - * Wait - * waits for upto timeoutSeconds for a task - * to complete - * - **/ - BOOL Wait(int timeoutSeconds) - { - timeoutSeconds = timeoutSeconds * 1000; - if( Status() != TaskStatusCompleted && - timeoutSeconds > 0 ) - { - Sleep(100); - timeoutSeconds = timeoutSeconds - 100; - } - if( Status() == TaskStatusCompleted ) return TRUE; - return FALSE; - } - - /** - * - * Status - * returns current state of a task - * - **/ - TaskStatus_t Status() - { - TaskStatus_t state ; - - m_mutex.Lock(); - state = m_state; - m_mutex.Unlock(); - return state; - } - - void Thread(ThreadId_t *pId) - { - memcpy(pId,&m_dwThread,sizeof(ThreadId_t)); - } - - CTask(){m_state=TaskStatusNotSubmitted; memset(&m_dwThread,0,sizeof(ThreadId_t)); } - ~CTask(){} - virtual BOOL Task()=0; -}; - - -class CThread -#ifdef WINDOWS - : public CObject // use CObject as a base class so object can be used in lists and - // object arrays -#endif -{ -private: - CEventClass m_event; // event controller - int m_StopTimeout; // specifies a timeout value for stop - // if a thread fails to stop within m_StopTimeout - // seconds an exception is thrown - - BOOL m_bRunning; // set to TRUE if thread is running -#ifdef WINDOWS - HANDLE m_thread; // thread handle -#else - pthread_t m_thread; // thread handle -#endif - ThreadId_t m_dwId; // id of this thread - LPVOID *m_lppvQueue; // task que - unsigned int m_chQueue; // que depth - unsigned int m_queuePos; // current que possition - LPVOID m_lpvProcessor; // data which is currently being processed - ThreadState_t m_state; // current state of thread see thread state data - // structure. - DWORD m_dwIdle; // used for Sleep periods - ThreadType_t m_type; - DWORD m_stackSize; // thread stack size -#define NO_ERRORS 0 -#define MUTEX_CREATION 0x01 -#define EVENT_CREATION 0x02 -#define THREAD_CREATION 0x04 -#define UNKNOWN 0x08 -#define ILLEGAL_USE_OF_EVENT 0x10 -#define MEMORY_FAULT 0x20 -#define EVENT_AND_TYPE_DONT_MATCH 0x40 -#define STACK_OVERFLOW 0x80 -#define STACK_EMPTY 0x100 -#define STACK_FULL 0x200 - - DWORD m_dwObjectCondition; - BOOL Push(LPVOID lpv); - BOOL Pop(); - BOOL Empty(); -public: - /** - * - * user definable member functions - * - **/ - CMutexClass m_mutex; // mutex that protects threads internal data - - virtual BOOL OnTask(LPVOID lpvData); // called when an event occurs - virtual BOOL OnTask(); // called when a time interval has elapsed - - CThread(void); - ~CThread(void); -#ifdef WINDOWS -#ifdef USE_BEGIN_THREAD - friend unsigned __stdcall _THKERNEL(LPVOID lpvData); -#else - friend DWORD WINAPI _THKERNEL( LPVOID lpvData ); -#endif -#else - friend LPVOID _THKERNEL(LPVOID lpvData); -#endif - BOOL FromSameThread(); - float PercentCapacity(); - void WaitTillExit(); - BOOL KernelProcess(); - BOOL Event(LPVOID lpvData=NULL); - BOOL Event(CTask *pvTask); - void SetOnStopTimeout(int seconds ) { m_StopTimeout = seconds; } - BOOL SetQueueSize( unsigned int ch ); - BOOL Stop(); - BOOL Start(); - void GetId(ThreadId_t *pId) { memcpy(pId,&m_dwId,sizeof(ThreadId_t)); } // returns thread id - ThreadState_t ThreadState(); - BOOL PingThread(DWORD dwTimeout=0); - BOOL AtCapacity(); -#ifdef WINDOWS - void SetPriority(DWORD dwPriority=THREAD_PRIORITY_NORMAL); -#else - void SetPriority(DWORD dwPriority=0); -#endif - DWORD GetErrorFlags() { return m_dwObjectCondition; } // returns state of object - void SetThreadType(ThreadType_t typ=ThreadTypeNotDefined,DWORD dwIdle=100); - void SetIdle(DWORD dwIdle=100); - unsigned int GetEventsPending(); - static BOOL ThreadIdsEqual(ThreadId_t *p1, - ThreadId_t *p2) - { -#if defined(AS400)||defined(OS400) - return(( memcmp(p1,p2,sizeof(ThreadId_t))==0)?TRUE:FALSE); -#elif defined(VMS) || defined(__NetBSD__) - return (( pthread_equal(*p1,*p2) )?TRUE:FALSE ); -#else - return ((*p1 == *p2)?TRUE:FALSE); -#endif - - } - - static ThreadId_t ThreadId() - { - ThreadId_t thisThreadsId ; -#if defined(AS400) || defined(OS400) - pthread_t thread; -#endif - -#ifdef WINDOWS - thisThreadsId = (ThreadId_t)GetCurrentThreadId(); -#else - -#if defined(AS400) || defined(OS400) - thread = pthread_self(); - pthread_getunique_np(&thread,&thisThreadsId); -#elif defined(ALPHA) || defined(DEC) || defined(VMS) -#ifdef VMS - thisThreadsId = pthread_self(); -#else - thisThreadsId = pthread_getsequence_np(pthread_self()); -#endif -#else - thisThreadsId = pthread_self(); -#endif -#endif - return thisThreadsId; - } - - -}; -#endif - diff --git a/jni/libzrtp/sources/common/osSpecifics.c b/jni/libzrtp/sources/common/osSpecifics.c deleted file mode 100644 index 3345363de..000000000 --- a/jni/libzrtp/sources/common/osSpecifics.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright (C) 2012-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - - -#include <stdint.h> -#include <common/osSpecifics.h> - - -#if defined(_WIN32) || defined(_WIN64) - -#else - -#endif - -#if defined(_WIN32) || defined(_WIN64) -# include <WinSock2.h> -# include <time.h> - -uint64_t zrtpGetTickCount() -{ - // return GetTickCount64(); //works only on 64bit OS - unsigned long long ret; - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - ret = ft.dwHighDateTime; - ret <<= 32; - ret |= ft.dwLowDateTime; - - return ret / 10; //return msec -} -#else -# include <netinet/in.h> -# include <sys/time.h> - -uint64_t zrtpGetTickCount() -{ - struct timeval tv; - gettimeofday(&tv, 0); - - return ((uint64_t)tv.tv_sec) * (uint64_t)1000 + ((uint64_t)tv.tv_usec) / (uint64_t)1000; -} - -#endif - -uint32_t zrtpNtohl (uint32_t net) -{ - return ntohl(net); -} - -uint16_t zrtpNtohs (uint16_t net) -{ - return ntohs(net); -} - -uint32_t zrtpHtonl (uint32_t host) -{ - return htonl(host); -} -uint16_t zrtpHtons (uint16_t host) -{ - return htons(host); -} - diff --git a/jni/libzrtp/sources/common/osSpecifics.h b/jni/libzrtp/sources/common/osSpecifics.h deleted file mode 100644 index 50306883d..000000000 --- a/jni/libzrtp/sources/common/osSpecifics.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright (C) 2012-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _OSSPECIFICS_H_ -#define _OSSPECIFICS_H_ - -/** - * @file osSpecifics.h - * @brief Some functions to adapt to OS and/or compiler specific handling - * @defgroup GNU_ZRTP The GNU ZRTP C++ implementation - * @{ - * - * This modules contains some functions that are either specific for a particular - * OS or use include files that are not common. - * - * This header file shall not #include system specific header files and shall also - * not use specific #ifdef stuff. Refer to @c osSpecifics.c for the OS specific - * #include, #ifdef and implementations. - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#ifndef __EXPORT - #if (defined _WIN32 || defined __CYGWIN__) && defined(_DLL) - #define __EXPORT __declspec(dllimport) - #define __LOCAL - #elif __GNUC__ >= 4 - #define __EXPORT __attribute__ ((visibility("default"))) - #define __LOCAL __attribute__ ((visibility("hidden"))) - #else - #define __EXPORT - #define __LOCAL - #endif -#endif - -#if defined(_WIN32) || defined(_WIN64) -# define snprintf _snprintf -#endif - -#if defined(__cplusplus) -extern "C" -{ -#endif -/** - * Get surrent system time in milli-second. - * - * @return current time in ms. - */ -extern uint64_t zrtpGetTickCount(); - -/** - * Convert a 32bit variable from network to host order. - * - * Replaces the macros found in @c inet.h or @c WinSock2.h. Use this function - * to avoid different includes freamed with @c #idef in the sources. Including - * @c WinSock2 will increase compile time and may lead to other subtle problems - * because @c WinSock2 also includes @c windows.h. - * - * @param net 32bit variable in network byte order. - * - * @return 32bit variable in host byte order. - */ -extern uint32_t zrtpNtohl (uint32_t net); - -/** - * Convert a 16bit variable from network to host order. - * - * @param net 16bit variable in network byte order. - * - * @return 16bit variable in host byte order. - * - * @sa zrtpNtohl() - */ -extern uint16_t zrtpNtohs (uint16_t net); - -/** - * Convert a 32bit variable from host to network order. - * - * @param host 32bit variable in host byte order. - * - * @return 32bit variable in network byte order. - * - * @sa zrtpNtohl() - */ -extern uint32_t zrtpHtonl (uint32_t host); - -/** - * Convert a 16bit variable from host to network order. - * - * @param host 16bit variable in host byte order. - * - * @return 16bit variable in network byte order. - * - * @sa zrtpNtohl() - */ -extern uint16_t zrtpHtons (uint16_t host); - -#if defined(__cplusplus) -} -#endif - - -/** - * @} - */ -#endif diff --git a/jni/libzrtp/sources/cryptcommon/ZrtpRandom.cpp b/jni/libzrtp/sources/cryptcommon/ZrtpRandom.cpp deleted file mode 100644 index c19fa82b0..000000000 --- a/jni/libzrtp/sources/cryptcommon/ZrtpRandom.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2006-2013 Werner Dittmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <fcntl.h> - -#include <cryptcommon/ZrtpRandom.h> -#include <cryptcommon/aescpp.h> -#include <common/Thread.h> -#include <zrtp/crypto/sha2.h> - -static sha512_ctx mainCtx; - -static CMutexClass lockRandom; - -static bool initialized = false; - -/* - * Random bits are produced as follows. - * First stir new entropy into the random state (zrtp->rand_ctx). - * Then make a copy of the random context and finalize it. - * Use the digest to seed an AES-256 context and, if space remains, to - * initialize a counter. - * Then encrypt the counter with the AES-256 context, incrementing it - * per block, until we have produced the desired quantity of data. - */ -/*----------------------------------------------------------------------------*/ -int ZrtpRandom::getRandomData(uint8_t* buffer, uint32_t length) { - - AESencrypt aesCtx; - sha512_ctx randCtx2; - uint8_t md[SHA512_DIGEST_SIZE]; - uint8_t ctr[AES_BLOCK_SIZE]; - uint8_t rdata[AES_BLOCK_SIZE]; - uint32_t generated = length; - - /* - * Add entropy from system state - * We will include whatever happens to be in the buffer, it can't hurt - */ - ZrtpRandom::addEntropy(buffer, length); - - lockRandom.Lock(); - - /* Copy the mainCtx and finalize it into the md buffer */ - memcpy(&randCtx2, &mainCtx, sizeof(sha512_ctx)); - sha512_end(md, &randCtx2); - - lockRandom.Unlock(); - - /* Key an AES context from this buffer */ - aesCtx.key256(md); - - /* Initialize counter, using excess from md if available */ - memset (ctr, 0, sizeof(ctr)); - if (SHA512_DIGEST_SIZE > (256/8)) { - uint32_t ctrbytes = SHA512_DIGEST_SIZE - (256/8); - if (ctrbytes > AES_BLOCK_SIZE) - ctrbytes = AES_BLOCK_SIZE; - memcpy(ctr + sizeof(ctr) - ctrbytes, md + (256/8), ctrbytes); - } - - /* Encrypt counter, copy to destination buffer, increment counter */ - while (length) { - uint8_t *ctrptr; - uint32_t copied; - aesCtx.encrypt(ctr, rdata); - copied = (sizeof(rdata) < length) ? sizeof(rdata) : length; - memcpy (buffer, rdata, copied); - buffer += copied; - length -= copied; - - /* Increment counter */ - ctrptr = ctr + sizeof(ctr) - 1; - while (ctrptr >= ctr) { - if ((*ctrptr-- += 1) != 0) { - break; - } - } - } - memset(&randCtx2, 0, sizeof(randCtx2)); - memset(md, 0, sizeof(md)); - memset(&aesCtx, 0, sizeof(aesCtx)); - memset(ctr, 0, sizeof(ctr)); - memset(rdata, 0, sizeof(rdata)); - - return generated; -} - - -int ZrtpRandom::addEntropy(const uint8_t *buffer, uint32_t length) -{ - - uint8_t newSeed[64]; - size_t len = getSystemSeed(newSeed, sizeof(newSeed)); - - lockRandom.Lock(); - initialize(); - - if (buffer && length) { - sha512_hash(buffer, length, &mainCtx); - } - if (len > 0) { - sha512_hash(newSeed, len, &mainCtx); - length += len; - } - lockRandom.Unlock(); - return length; -} - - -void ZrtpRandom::initialize() { - if (initialized) - return; - - sha512_begin(&mainCtx); - initialized = true; -} - -/* - * This works for Linux and similar systems. For other systems add - * other functions (using #ifdef conditional compile) to get some - * random data that we can use as seed for the internal PRNG below. - */ - -size_t ZrtpRandom::getSystemSeed(uint8_t *seed, size_t length) -{ - size_t num = 0; - -#if !(defined(_WIN32) || defined(_WIN64)) - int rnd = open("/dev/urandom", O_RDONLY); - if (rnd >= 0) { - num = read(rnd, seed, length); - close(rnd); - } - else - return num; -#endif - return num; -} - -int zrtp_AddEntropy(const uint8_t *buffer, uint32_t length) { - return ZrtpRandom::addEntropy(buffer, length); -} - -int zrtp_getRandomData(uint8_t *buffer, uint32_t length) { - return ZrtpRandom::getRandomData(buffer, length); -} diff --git a/jni/libzrtp/sources/cryptcommon/ZrtpRandom.h b/jni/libzrtp/sources/cryptcommon/ZrtpRandom.h deleted file mode 100644 index d3eedf764..000000000 --- a/jni/libzrtp/sources/cryptcommon/ZrtpRandom.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _ZRTPRANDOM_H_ -#define _ZRTPRANDOM_H_ - -/** - * @file ZrtpCommon.h - * @brief ZRTP standalone random number generator - * @defgroup GNU_ZRTP The GNU ZRTP C++ implementation - * @{ - */ - -#include <string.h> -#if !(defined(_WIN32) || defined(_WIN64)) -#include <unistd.h> -#endif -#include <stdint.h> -#include <sys/types.h> - -#ifdef __cplusplus -class ZrtpRandom { -public: - /** - * @brief This method adds entropy to the PRNG. - * - * An application may seed some entropy data to the PRNG. If the @c buffer is - * @c NULL or the @c length is zero then the method adds at least some system - * entropy. - * - * @param buffer some entropy data to add - * - * @param length length of entropy data in bytes - * - * @return on success: number of entropy bytes added, on failure: -1. Number of - * bytes added may be bigger then @c length because of added system - * entropy. - */ - static int addEntropy(const uint8_t *buffer, uint32_t length); - - /** - * @brief Get some random data. - * - * @param buffer that will contain the random data - * - * @param length how many bytes of random data to generate - * - * @return the number of generated random data bytes - */ - static int getRandomData(uint8_t *buffer, uint32_t length); - -private: - static void initialize(); - static size_t getSystemSeed(uint8_t *seed, size_t length); - -}; -#endif - -#ifdef __cplusplus -extern "C" -{ -#endif - -int zrtp_AddEntropy(const uint8_t *buffer, uint32_t length); - -int zrtp_getRandomData(uint8_t *buffer, uint32_t length); - -#ifdef __cplusplus -} -#endif - -#endif /* ZRTPRANDOM */ \ No newline at end of file diff --git a/jni/libzrtp/sources/cryptcommon/aes.h b/jni/libzrtp/sources/cryptcommon/aes.h deleted file mode 100644 index 40927fb7e..000000000 --- a/jni/libzrtp/sources/cryptcommon/aes.h +++ /dev/null @@ -1,198 +0,0 @@ -/* ---------------------------------------------------------------------------- -Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. - -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: - - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. - -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 - - This file contains the definitions required to use AES in C. See aesopt.h - for optimisation details. -*/ - -#ifndef _AES_H -#define _AES_H - -#include <stdlib.h> - -/* This include is used to find 8 & 32 bit unsigned integer types */ -#include "brg_types.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#define AES_128 /* if a fast 128 bit key scheduler is needed */ -#define AES_192 /* if a fast 192 bit key scheduler is needed */ -#define AES_256 /* if a fast 256 bit key scheduler is needed */ -#define AES_VAR /* if variable key size scheduler is needed */ -#define AES_MODES /* if support is needed for modes */ - -/* The following must also be set in assembler files if being used */ - -#define AES_ENCRYPT /* if support for encryption is needed */ -#define AES_DECRYPT /* if support for decryption is needed */ -#define AES_REV_DKS /* define to reverse decryption key schedule */ - -#define AES_BLOCK_SIZE 16 /* the AES block size in bytes */ -#define N_COLS 4 /* the number of columns in the state */ - -/* The key schedule length is 11, 13 or 15 16-byte blocks for 128, */ -/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes */ -/* or 44, 52 or 60 32-bit words. */ - -#if defined( AES_VAR ) || defined( AES_256 ) -#define KS_LENGTH 60 -#elif defined( AES_192 ) -#define KS_LENGTH 52 -#else -#define KS_LENGTH 44 -#endif - -#define AES_RETURN INT_RETURN - -/* the character array 'inf' in the following structures is used */ -/* to hold AES context information. This AES code uses cx->inf.b[0] */ -/* to hold the number of rounds multiplied by 16. The other three */ -/* elements can be used by code that implements additional modes */ - -typedef union -{ uint_32t l; - uint_8t b[4]; -} aes_inf; - -typedef struct -{ uint_32t ks[KS_LENGTH]; - aes_inf inf; -} aes_encrypt_ctx; - -typedef struct -{ uint_32t ks[KS_LENGTH]; - aes_inf inf; -} aes_decrypt_ctx; - -/* This routine must be called before first use if non-static */ -/* tables are being used */ - -AES_RETURN aes_init(void); - -/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */ -/* those in the range 128 <= key_len <= 256 are given in bits */ - -#if defined( AES_ENCRYPT ) - -#if defined( AES_128 ) || defined( AES_VAR) -AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); -#endif - -#if defined( AES_192 ) || defined( AES_VAR) -AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); -#endif - -#if defined( AES_256 ) || defined( AES_VAR) -AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); -#endif - -#if defined( AES_VAR ) -AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]); -#endif - -AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]); - -#endif - -#if defined( AES_DECRYPT ) - -#if defined( AES_128 ) || defined( AES_VAR) -AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); -#endif - -#if defined( AES_192 ) || defined( AES_VAR) -AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); -#endif - -#if defined( AES_256 ) || defined( AES_VAR) -AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); -#endif - -#if defined( AES_VAR ) -AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]); -#endif - -AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]); - -#endif - -#if defined( AES_MODES ) - -/* Multiple calls to the following subroutines for multiple block */ -/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */ -/* long messages incremantally provided that the context AND the iv */ -/* are preserved between all such calls. For the ECB and CBC modes */ -/* each individual call within a series of incremental calls must */ -/* process only full blocks (i.e. len must be a multiple of 16) but */ -/* the CFB, OFB and CTR mode calls can handle multiple incremental */ -/* calls of any length. Each mode is reset when a new AES key is */ -/* set but ECB and CBC operations can be reset without setting a */ -/* new key by setting a new IV value. To reset CFB, OFB and CTR */ -/* without setting the key, aes_mode_reset() must be called and the */ -/* IV must be set. NOTE: All these calls update the IV on exit so */ -/* this has to be reset if a new operation with the same IV as the */ -/* previous one is required (or decryption follows encryption with */ -/* the same IV array). */ - -AES_RETURN aes_test_alignment_detection(unsigned int n); - -AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, const aes_encrypt_ctx cx[1]); - -AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, const aes_decrypt_ctx cx[1]); - -AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, const aes_encrypt_ctx cx[1]); - -AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, const aes_decrypt_ctx cx[1]); - -AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]); - -AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, aes_encrypt_ctx cx[1]); - -AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, aes_encrypt_ctx cx[1]); - -#define aes_ofb_encrypt aes_ofb_crypt -#define aes_ofb_decrypt aes_ofb_crypt - -AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, aes_encrypt_ctx cx[1]); - -typedef void cbuf_inc(unsigned char *cbuf); - -#define aes_ctr_encrypt aes_ctr_crypt -#define aes_ctr_decrypt aes_ctr_crypt - -AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]); - -#endif - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/jni/libzrtp/sources/cryptcommon/aes_modes.c b/jni/libzrtp/sources/cryptcommon/aes_modes.c deleted file mode 100644 index 2ffa783bf..000000000 --- a/jni/libzrtp/sources/cryptcommon/aes_modes.c +++ /dev/null @@ -1,946 +0,0 @@ -/* ---------------------------------------------------------------------------- -Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. - -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: - - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. - -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 - - These subroutines implement multiple block AES modes for ECB, CBC, CFB, - OFB and CTR encryption, The code provides support for the VIA Advanced - Cryptography Engine (ACE). - - NOTE: In the following subroutines, the AES contexts (ctx) must be - 16 byte aligned if VIA ACE is being used -*/ - -#include <string.h> -#include <assert.h> - -#include "aesopt.h" - -#if defined( AES_MODES ) -#if defined(__cplusplus) -extern "C" -{ -#endif - -#if defined( _MSC_VER ) && ( _MSC_VER > 800 ) -#pragma intrinsic(memcpy) -#endif - -#define BFR_BLOCKS 8 - -/* These values are used to detect long word alignment in order to */ -/* speed up some buffer operations. This facility may not work on */ -/* some machines so this define can be commented out if necessary */ - -#define FAST_BUFFER_OPERATIONS - -#define lp32(x) ((uint_32t*)(x)) - -#if defined( USE_VIA_ACE_IF_PRESENT ) - -#include "aes_via_ace.h" - -#pragma pack(16) - -aligned_array(unsigned long, enc_gen_table, 12, 16) = NEH_ENC_GEN_DATA; -aligned_array(unsigned long, enc_load_table, 12, 16) = NEH_ENC_LOAD_DATA; -aligned_array(unsigned long, enc_hybrid_table, 12, 16) = NEH_ENC_HYBRID_DATA; -aligned_array(unsigned long, dec_gen_table, 12, 16) = NEH_DEC_GEN_DATA; -aligned_array(unsigned long, dec_load_table, 12, 16) = NEH_DEC_LOAD_DATA; -aligned_array(unsigned long, dec_hybrid_table, 12, 16) = NEH_DEC_HYBRID_DATA; - -/* NOTE: These control word macros must only be used after */ -/* a key has been set up because they depend on key size */ -/* See the VIA ACE documentation for key type information */ -/* and aes_via_ace.h for non-default NEH_KEY_TYPE values */ - -#ifndef NEH_KEY_TYPE -# define NEH_KEY_TYPE NEH_HYBRID -#endif - -#if NEH_KEY_TYPE == NEH_LOAD -#define kd_adr(c) ((uint_8t*)(c)->ks) -#elif NEH_KEY_TYPE == NEH_GENERATE -#define kd_adr(c) ((uint_8t*)(c)->ks + (c)->inf.b[0]) -#elif NEH_KEY_TYPE == NEH_HYBRID -#define kd_adr(c) ((uint_8t*)(c)->ks + ((c)->inf.b[0] == 160 ? 160 : 0)) -#else -#error no key type defined for VIA ACE -#endif - -#else - -#define aligned_array(type, name, no, stride) type name[no] -#define aligned_auto(type, name, no, stride) type name[no] - -#endif - -#if defined( _MSC_VER ) && _MSC_VER > 1200 - -#define via_cwd(cwd, ty, dir, len) \ - unsigned long* cwd = (dir##_##ty##_table + ((len - 128) >> 4)) - -#else - -#define via_cwd(cwd, ty, dir, len) \ - aligned_auto(unsigned long, cwd, 4, 16); \ - cwd[1] = cwd[2] = cwd[3] = 0; \ - cwd[0] = neh_##dir##_##ty##_key(len) - -#endif - -/* test the code for detecting and setting pointer alignment */ - -AES_RETURN aes_test_alignment_detection(unsigned int n) /* 4 <= n <= 16 */ -{ uint_8t p[16]; - uint_32t i, count_eq = 0, count_neq = 0; - - if(n < 4 || n > 16) - return EXIT_FAILURE; - - for(i = 0; i < n; ++i) - { - uint_8t *qf = ALIGN_FLOOR(p + i, n), - *qh = ALIGN_CEIL(p + i, n); - - if(qh == qf) - ++count_eq; - else if(qh == qf + n) - ++count_neq; - else - return EXIT_FAILURE; - } - return (count_eq != 1 || count_neq != n - 1 ? EXIT_FAILURE : EXIT_SUCCESS); -} - -AES_RETURN aes_mode_reset(aes_encrypt_ctx ctx[1]) -{ - ctx->inf.b[2] = 0; - return EXIT_SUCCESS; -} - -AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, const aes_encrypt_ctx ctx[1]) -{ int nb = len >> 4; - - if(len & (AES_BLOCK_SIZE - 1)) - return EXIT_FAILURE; - -#if defined( USE_VIA_ACE_IF_PRESENT ) - - if(ctx->inf.b[1] == 0xff) - { uint_8t *ksp = (uint_8t*)(ctx->ks); - via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192); - - if(ALIGN_OFFSET( ctx, 16 )) - return EXIT_FAILURE; - - if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 )) - { - via_ecb_op5(ksp, cwd, ibuf, obuf, nb); - } - else - { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); - uint_8t *ip, *op; - - while(nb) - { - int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb); - - ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); - op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); - - if(ip != ibuf) - memcpy(buf, ibuf, m * AES_BLOCK_SIZE); - - via_ecb_op5(ksp, cwd, ip, op, m); - - if(op != obuf) - memcpy(obuf, buf, m * AES_BLOCK_SIZE); - - ibuf += m * AES_BLOCK_SIZE; - obuf += m * AES_BLOCK_SIZE; - nb -= m; - } - } - - return EXIT_SUCCESS; - } - -#endif - -#if !defined( ASSUME_VIA_ACE_PRESENT ) - while(nb--) - { - if(aes_encrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - } -#endif - return EXIT_SUCCESS; -} - -AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, const aes_decrypt_ctx ctx[1]) -{ int nb = len >> 4; - - if(len & (AES_BLOCK_SIZE - 1)) - return EXIT_FAILURE; - -#if defined( USE_VIA_ACE_IF_PRESENT ) - - if(ctx->inf.b[1] == 0xff) - { uint_8t *ksp = kd_adr(ctx); - via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192); - - if(ALIGN_OFFSET( ctx, 16 )) - return EXIT_FAILURE; - - if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 )) - { - via_ecb_op5(ksp, cwd, ibuf, obuf, nb); - } - else - { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); - uint_8t *ip, *op; - - while(nb) - { - int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb); - - ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); - op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); - - if(ip != ibuf) - memcpy(buf, ibuf, m * AES_BLOCK_SIZE); - - via_ecb_op5(ksp, cwd, ip, op, m); - - if(op != obuf) - memcpy(obuf, buf, m * AES_BLOCK_SIZE); - - ibuf += m * AES_BLOCK_SIZE; - obuf += m * AES_BLOCK_SIZE; - nb -= m; - } - } - - return EXIT_SUCCESS; - } - -#endif - -#if !defined( ASSUME_VIA_ACE_PRESENT ) - while(nb--) - { - if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - } -#endif - return EXIT_SUCCESS; -} - -AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, const aes_encrypt_ctx ctx[1]) -{ int nb = len >> 4; - - if(len & (AES_BLOCK_SIZE - 1)) - return EXIT_FAILURE; - -#if defined( USE_VIA_ACE_IF_PRESENT ) - - if(ctx->inf.b[1] == 0xff) - { uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv; - aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16); - via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192); - - if(ALIGN_OFFSET( ctx, 16 )) - return EXIT_FAILURE; - - if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */ - { - ivp = liv; - memcpy(liv, iv, AES_BLOCK_SIZE); - } - - if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 )) - { - via_cbc_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp); - } - else - { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); - uint_8t *ip, *op; - - while(nb) - { - int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb); - - ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); - op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); - - if(ip != ibuf) - memcpy(buf, ibuf, m * AES_BLOCK_SIZE); - - via_cbc_op7(ksp, cwd, ip, op, m, ivp, ivp); - - if(op != obuf) - memcpy(obuf, buf, m * AES_BLOCK_SIZE); - - ibuf += m * AES_BLOCK_SIZE; - obuf += m * AES_BLOCK_SIZE; - nb -= m; - } - } - - if(iv != ivp) - memcpy(iv, ivp, AES_BLOCK_SIZE); - - return EXIT_SUCCESS; - } - -#endif - -#if !defined( ASSUME_VIA_ACE_PRESENT ) -# ifdef FAST_BUFFER_OPERATIONS - if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( iv, 4 )) - while(nb--) - { - lp32(iv)[0] ^= lp32(ibuf)[0]; - lp32(iv)[1] ^= lp32(ibuf)[1]; - lp32(iv)[2] ^= lp32(ibuf)[2]; - lp32(iv)[3] ^= lp32(ibuf)[3]; - if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - memcpy(obuf, iv, AES_BLOCK_SIZE); - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - } - else -# endif - while(nb--) - { - iv[ 0] ^= ibuf[ 0]; iv[ 1] ^= ibuf[ 1]; - iv[ 2] ^= ibuf[ 2]; iv[ 3] ^= ibuf[ 3]; - iv[ 4] ^= ibuf[ 4]; iv[ 5] ^= ibuf[ 5]; - iv[ 6] ^= ibuf[ 6]; iv[ 7] ^= ibuf[ 7]; - iv[ 8] ^= ibuf[ 8]; iv[ 9] ^= ibuf[ 9]; - iv[10] ^= ibuf[10]; iv[11] ^= ibuf[11]; - iv[12] ^= ibuf[12]; iv[13] ^= ibuf[13]; - iv[14] ^= ibuf[14]; iv[15] ^= ibuf[15]; - if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - memcpy(obuf, iv, AES_BLOCK_SIZE); - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - } -#endif - return EXIT_SUCCESS; -} - -AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, const aes_decrypt_ctx ctx[1]) -{ unsigned char tmp[AES_BLOCK_SIZE]; - int nb = len >> 4; - - if(len & (AES_BLOCK_SIZE - 1)) - return EXIT_FAILURE; - -#if defined( USE_VIA_ACE_IF_PRESENT ) - - if(ctx->inf.b[1] == 0xff) - { uint_8t *ksp = kd_adr(ctx), *ivp = iv; - aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16); - via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192); - - if(ALIGN_OFFSET( ctx, 16 )) - return EXIT_FAILURE; - - if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */ - { - ivp = liv; - memcpy(liv, iv, AES_BLOCK_SIZE); - } - - if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 )) - { - via_cbc_op6(ksp, cwd, ibuf, obuf, nb, ivp); - } - else - { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); - uint_8t *ip, *op; - - while(nb) - { - int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb); - - ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); - op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); - - if(ip != ibuf) - memcpy(buf, ibuf, m * AES_BLOCK_SIZE); - - via_cbc_op6(ksp, cwd, ip, op, m, ivp); - - if(op != obuf) - memcpy(obuf, buf, m * AES_BLOCK_SIZE); - - ibuf += m * AES_BLOCK_SIZE; - obuf += m * AES_BLOCK_SIZE; - nb -= m; - } - } - - if(iv != ivp) - memcpy(iv, ivp, AES_BLOCK_SIZE); - - return EXIT_SUCCESS; - } -#endif - -#if !defined( ASSUME_VIA_ACE_PRESENT ) -# ifdef FAST_BUFFER_OPERATIONS - if(!ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 )) - while(nb--) - { - memcpy(tmp, ibuf, AES_BLOCK_SIZE); - if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - lp32(obuf)[0] ^= lp32(iv)[0]; - lp32(obuf)[1] ^= lp32(iv)[1]; - lp32(obuf)[2] ^= lp32(iv)[2]; - lp32(obuf)[3] ^= lp32(iv)[3]; - memcpy(iv, tmp, AES_BLOCK_SIZE); - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - } - else -# endif - while(nb--) - { - memcpy(tmp, ibuf, AES_BLOCK_SIZE); - if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - obuf[ 0] ^= iv[ 0]; obuf[ 1] ^= iv[ 1]; - obuf[ 2] ^= iv[ 2]; obuf[ 3] ^= iv[ 3]; - obuf[ 4] ^= iv[ 4]; obuf[ 5] ^= iv[ 5]; - obuf[ 6] ^= iv[ 6]; obuf[ 7] ^= iv[ 7]; - obuf[ 8] ^= iv[ 8]; obuf[ 9] ^= iv[ 9]; - obuf[10] ^= iv[10]; obuf[11] ^= iv[11]; - obuf[12] ^= iv[12]; obuf[13] ^= iv[13]; - obuf[14] ^= iv[14]; obuf[15] ^= iv[15]; - memcpy(iv, tmp, AES_BLOCK_SIZE); - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - } -#endif - return EXIT_SUCCESS; -} - -AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, aes_encrypt_ctx ctx[1]) -{ int cnt = 0, b_pos = (int)ctx->inf.b[2], nb; - - if(b_pos) /* complete any partial block */ - { - while(b_pos < AES_BLOCK_SIZE && cnt < len) - { - *obuf++ = (iv[b_pos++] ^= *ibuf++); - cnt++; - } - - b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); - } - - if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */ - { -#if defined( USE_VIA_ACE_IF_PRESENT ) - - if(ctx->inf.b[1] == 0xff) - { int m; - uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv; - aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16); - via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192); - - if(ALIGN_OFFSET( ctx, 16 )) - return EXIT_FAILURE; - - if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */ - { - ivp = liv; - memcpy(liv, iv, AES_BLOCK_SIZE); - } - - if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 )) - { - via_cfb_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp); - ibuf += nb * AES_BLOCK_SIZE; - obuf += nb * AES_BLOCK_SIZE; - cnt += nb * AES_BLOCK_SIZE; - } - else /* input, output or both are unaligned */ - { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); - uint_8t *ip, *op; - - while(nb) - { - m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m; - - ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); - op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); - - if(ip != ibuf) - memcpy(buf, ibuf, m * AES_BLOCK_SIZE); - - via_cfb_op7(ksp, cwd, ip, op, m, ivp, ivp); - - if(op != obuf) - memcpy(obuf, buf, m * AES_BLOCK_SIZE); - - ibuf += m * AES_BLOCK_SIZE; - obuf += m * AES_BLOCK_SIZE; - cnt += m * AES_BLOCK_SIZE; - } - } - - if(ivp != iv) - memcpy(iv, ivp, AES_BLOCK_SIZE); - } -#else -# ifdef FAST_BUFFER_OPERATIONS - if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 )) - while(cnt + AES_BLOCK_SIZE <= len) - { - assert(b_pos == 0); - if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - lp32(obuf)[0] = lp32(iv)[0] ^= lp32(ibuf)[0]; - lp32(obuf)[1] = lp32(iv)[1] ^= lp32(ibuf)[1]; - lp32(obuf)[2] = lp32(iv)[2] ^= lp32(ibuf)[2]; - lp32(obuf)[3] = lp32(iv)[3] ^= lp32(ibuf)[3]; - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - cnt += AES_BLOCK_SIZE; - } - else -# endif - while(cnt + AES_BLOCK_SIZE <= len) - { - assert(b_pos == 0); - if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - obuf[ 0] = iv[ 0] ^= ibuf[ 0]; obuf[ 1] = iv[ 1] ^= ibuf[ 1]; - obuf[ 2] = iv[ 2] ^= ibuf[ 2]; obuf[ 3] = iv[ 3] ^= ibuf[ 3]; - obuf[ 4] = iv[ 4] ^= ibuf[ 4]; obuf[ 5] = iv[ 5] ^= ibuf[ 5]; - obuf[ 6] = iv[ 6] ^= ibuf[ 6]; obuf[ 7] = iv[ 7] ^= ibuf[ 7]; - obuf[ 8] = iv[ 8] ^= ibuf[ 8]; obuf[ 9] = iv[ 9] ^= ibuf[ 9]; - obuf[10] = iv[10] ^= ibuf[10]; obuf[11] = iv[11] ^= ibuf[11]; - obuf[12] = iv[12] ^= ibuf[12]; obuf[13] = iv[13] ^= ibuf[13]; - obuf[14] = iv[14] ^= ibuf[14]; obuf[15] = iv[15] ^= ibuf[15]; - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - cnt += AES_BLOCK_SIZE; - } -#endif - } - - while(cnt < len) - { - if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - - while(cnt < len && b_pos < AES_BLOCK_SIZE) - { - *obuf++ = (iv[b_pos++] ^= *ibuf++); - cnt++; - } - - b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); - } - - ctx->inf.b[2] = (uint_8t)b_pos; - return EXIT_SUCCESS; -} - -AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, aes_encrypt_ctx ctx[1]) -{ int cnt = 0, b_pos = (int)ctx->inf.b[2], nb; - - if(b_pos) /* complete any partial block */ - { uint_8t t; - - while(b_pos < AES_BLOCK_SIZE && cnt < len) - { - t = *ibuf++; - *obuf++ = t ^ iv[b_pos]; - iv[b_pos++] = t; - cnt++; - } - - b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); - } - - if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */ - { -#if defined( USE_VIA_ACE_IF_PRESENT ) - - if(ctx->inf.b[1] == 0xff) - { int m; - uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv; - aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16); - via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192); - - if(ALIGN_OFFSET( ctx, 16 )) - return EXIT_FAILURE; - - if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */ - { - ivp = liv; - memcpy(liv, iv, AES_BLOCK_SIZE); - } - - if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 )) - { - via_cfb_op6(ksp, cwd, ibuf, obuf, nb, ivp); - ibuf += nb * AES_BLOCK_SIZE; - obuf += nb * AES_BLOCK_SIZE; - cnt += nb * AES_BLOCK_SIZE; - } - else /* input, output or both are unaligned */ - { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); - uint_8t *ip, *op; - - while(nb) - { - m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m; - - ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); - op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); - - if(ip != ibuf) /* input buffer is not aligned */ - memcpy(buf, ibuf, m * AES_BLOCK_SIZE); - - via_cfb_op6(ksp, cwd, ip, op, m, ivp); - - if(op != obuf) /* output buffer is not aligned */ - memcpy(obuf, buf, m * AES_BLOCK_SIZE); - - ibuf += m * AES_BLOCK_SIZE; - obuf += m * AES_BLOCK_SIZE; - cnt += m * AES_BLOCK_SIZE; - } - } - - if(ivp != iv) - memcpy(iv, ivp, AES_BLOCK_SIZE); - } -#else -# ifdef FAST_BUFFER_OPERATIONS - if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) &&!ALIGN_OFFSET( iv, 4 )) - while(cnt + AES_BLOCK_SIZE <= len) - { uint_32t t; - - assert(b_pos == 0); - if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - t = lp32(ibuf)[0], lp32(obuf)[0] = t ^ lp32(iv)[0], lp32(iv)[0] = t; - t = lp32(ibuf)[1], lp32(obuf)[1] = t ^ lp32(iv)[1], lp32(iv)[1] = t; - t = lp32(ibuf)[2], lp32(obuf)[2] = t ^ lp32(iv)[2], lp32(iv)[2] = t; - t = lp32(ibuf)[3], lp32(obuf)[3] = t ^ lp32(iv)[3], lp32(iv)[3] = t; - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - cnt += AES_BLOCK_SIZE; - } - else -# endif - while(cnt + AES_BLOCK_SIZE <= len) - { uint_8t t; - - assert(b_pos == 0); - if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - t = ibuf[ 0], obuf[ 0] = t ^ iv[ 0], iv[ 0] = t; - t = ibuf[ 1], obuf[ 1] = t ^ iv[ 1], iv[ 1] = t; - t = ibuf[ 2], obuf[ 2] = t ^ iv[ 2], iv[ 2] = t; - t = ibuf[ 3], obuf[ 3] = t ^ iv[ 3], iv[ 3] = t; - t = ibuf[ 4], obuf[ 4] = t ^ iv[ 4], iv[ 4] = t; - t = ibuf[ 5], obuf[ 5] = t ^ iv[ 5], iv[ 5] = t; - t = ibuf[ 6], obuf[ 6] = t ^ iv[ 6], iv[ 6] = t; - t = ibuf[ 7], obuf[ 7] = t ^ iv[ 7], iv[ 7] = t; - t = ibuf[ 8], obuf[ 8] = t ^ iv[ 8], iv[ 8] = t; - t = ibuf[ 9], obuf[ 9] = t ^ iv[ 9], iv[ 9] = t; - t = ibuf[10], obuf[10] = t ^ iv[10], iv[10] = t; - t = ibuf[11], obuf[11] = t ^ iv[11], iv[11] = t; - t = ibuf[12], obuf[12] = t ^ iv[12], iv[12] = t; - t = ibuf[13], obuf[13] = t ^ iv[13], iv[13] = t; - t = ibuf[14], obuf[14] = t ^ iv[14], iv[14] = t; - t = ibuf[15], obuf[15] = t ^ iv[15], iv[15] = t; - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - cnt += AES_BLOCK_SIZE; - } -#endif - } - - while(cnt < len) - { uint_8t t; - - if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - - while(cnt < len && b_pos < AES_BLOCK_SIZE) - { - t = *ibuf++; - *obuf++ = t ^ iv[b_pos]; - iv[b_pos++] = t; - cnt++; - } - - b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); - } - - ctx->inf.b[2] = (uint_8t)b_pos; - return EXIT_SUCCESS; -} - -AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *iv, aes_encrypt_ctx ctx[1]) -{ int cnt = 0, b_pos = (int)ctx->inf.b[2], nb; - - if(b_pos) /* complete any partial block */ - { - while(b_pos < AES_BLOCK_SIZE && cnt < len) - { - *obuf++ = iv[b_pos++] ^ *ibuf++; - cnt++; - } - - b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); - } - - if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */ - { -#if defined( USE_VIA_ACE_IF_PRESENT ) - - if(ctx->inf.b[1] == 0xff) - { int m; - uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv; - aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16); - via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192); - - if(ALIGN_OFFSET( ctx, 16 )) - return EXIT_FAILURE; - - if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */ - { - ivp = liv; - memcpy(liv, iv, AES_BLOCK_SIZE); - } - - if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 )) - { - via_ofb_op6(ksp, cwd, ibuf, obuf, nb, ivp); - ibuf += nb * AES_BLOCK_SIZE; - obuf += nb * AES_BLOCK_SIZE; - cnt += nb * AES_BLOCK_SIZE; - } - else /* input, output or both are unaligned */ - { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); - uint_8t *ip, *op; - - while(nb) - { - m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m; - - ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); - op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); - - if(ip != ibuf) - memcpy(buf, ibuf, m * AES_BLOCK_SIZE); - - via_ofb_op6(ksp, cwd, ip, op, m, ivp); - - if(op != obuf) - memcpy(obuf, buf, m * AES_BLOCK_SIZE); - - ibuf += m * AES_BLOCK_SIZE; - obuf += m * AES_BLOCK_SIZE; - cnt += m * AES_BLOCK_SIZE; - } - } - - if(ivp != iv) - memcpy(iv, ivp, AES_BLOCK_SIZE); - } -#else -# ifdef FAST_BUFFER_OPERATIONS - if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 )) - while(cnt + AES_BLOCK_SIZE <= len) - { - assert(b_pos == 0); - if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - lp32(obuf)[0] = lp32(iv)[0] ^ lp32(ibuf)[0]; - lp32(obuf)[1] = lp32(iv)[1] ^ lp32(ibuf)[1]; - lp32(obuf)[2] = lp32(iv)[2] ^ lp32(ibuf)[2]; - lp32(obuf)[3] = lp32(iv)[3] ^ lp32(ibuf)[3]; - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - cnt += AES_BLOCK_SIZE; - } - else -# endif - while(cnt + AES_BLOCK_SIZE <= len) - { - assert(b_pos == 0); - if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - obuf[ 0] = iv[ 0] ^ ibuf[ 0]; obuf[ 1] = iv[ 1] ^ ibuf[ 1]; - obuf[ 2] = iv[ 2] ^ ibuf[ 2]; obuf[ 3] = iv[ 3] ^ ibuf[ 3]; - obuf[ 4] = iv[ 4] ^ ibuf[ 4]; obuf[ 5] = iv[ 5] ^ ibuf[ 5]; - obuf[ 6] = iv[ 6] ^ ibuf[ 6]; obuf[ 7] = iv[ 7] ^ ibuf[ 7]; - obuf[ 8] = iv[ 8] ^ ibuf[ 8]; obuf[ 9] = iv[ 9] ^ ibuf[ 9]; - obuf[10] = iv[10] ^ ibuf[10]; obuf[11] = iv[11] ^ ibuf[11]; - obuf[12] = iv[12] ^ ibuf[12]; obuf[13] = iv[13] ^ ibuf[13]; - obuf[14] = iv[14] ^ ibuf[14]; obuf[15] = iv[15] ^ ibuf[15]; - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - cnt += AES_BLOCK_SIZE; - } -#endif - } - - while(cnt < len) - { - if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - - while(cnt < len && b_pos < AES_BLOCK_SIZE) - { - *obuf++ = iv[b_pos++] ^ *ibuf++; - cnt++; - } - - b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); - } - - ctx->inf.b[2] = (uint_8t)b_pos; - return EXIT_SUCCESS; -} - -#define BFR_LENGTH (BFR_BLOCKS * AES_BLOCK_SIZE) - -AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf, - int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx ctx[1]) -{ unsigned char *ip; - int i, blen, b_pos = (int)(ctx->inf.b[2]); - -#if defined( USE_VIA_ACE_IF_PRESENT ) - aligned_auto(uint_8t, buf, BFR_LENGTH, 16); - if(ctx->inf.b[1] == 0xff && ALIGN_OFFSET( ctx, 16 )) - return EXIT_FAILURE; -#else - uint_8t buf[BFR_LENGTH]; -#endif - - if(b_pos) - { - memcpy(buf, cbuf, AES_BLOCK_SIZE); - if(aes_ecb_encrypt(buf, buf, AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - - while(b_pos < AES_BLOCK_SIZE && len) - { - *obuf++ = *ibuf++ ^ buf[b_pos++]; - --len; - } - - if(len) - ctr_inc(cbuf), b_pos = 0; - } - - while(len) - { - blen = (len > BFR_LENGTH ? BFR_LENGTH : len), len -= blen; - - for(i = 0, ip = buf; i < (blen >> 4); ++i) - { - memcpy(ip, cbuf, AES_BLOCK_SIZE); - ctr_inc(cbuf); - ip += AES_BLOCK_SIZE; - } - - if(blen & (AES_BLOCK_SIZE - 1)) - memcpy(ip, cbuf, AES_BLOCK_SIZE), i++; - -#if defined( USE_VIA_ACE_IF_PRESENT ) - if(ctx->inf.b[1] == 0xff) - { - via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192); - via_ecb_op5((ctx->ks), cwd, buf, buf, i); - } - else -#endif - if(aes_ecb_encrypt(buf, buf, i * AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS) - return EXIT_FAILURE; - - i = 0; ip = buf; -# ifdef FAST_BUFFER_OPERATIONS - if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( ip, 4 )) - while(i + AES_BLOCK_SIZE <= blen) - { - lp32(obuf)[0] = lp32(ibuf)[0] ^ lp32(ip)[0]; - lp32(obuf)[1] = lp32(ibuf)[1] ^ lp32(ip)[1]; - lp32(obuf)[2] = lp32(ibuf)[2] ^ lp32(ip)[2]; - lp32(obuf)[3] = lp32(ibuf)[3] ^ lp32(ip)[3]; - i += AES_BLOCK_SIZE; - ip += AES_BLOCK_SIZE; - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - } - else -#endif - while(i + AES_BLOCK_SIZE <= blen) - { - obuf[ 0] = ibuf[ 0] ^ ip[ 0]; obuf[ 1] = ibuf[ 1] ^ ip[ 1]; - obuf[ 2] = ibuf[ 2] ^ ip[ 2]; obuf[ 3] = ibuf[ 3] ^ ip[ 3]; - obuf[ 4] = ibuf[ 4] ^ ip[ 4]; obuf[ 5] = ibuf[ 5] ^ ip[ 5]; - obuf[ 6] = ibuf[ 6] ^ ip[ 6]; obuf[ 7] = ibuf[ 7] ^ ip[ 7]; - obuf[ 8] = ibuf[ 8] ^ ip[ 8]; obuf[ 9] = ibuf[ 9] ^ ip[ 9]; - obuf[10] = ibuf[10] ^ ip[10]; obuf[11] = ibuf[11] ^ ip[11]; - obuf[12] = ibuf[12] ^ ip[12]; obuf[13] = ibuf[13] ^ ip[13]; - obuf[14] = ibuf[14] ^ ip[14]; obuf[15] = ibuf[15] ^ ip[15]; - i += AES_BLOCK_SIZE; - ip += AES_BLOCK_SIZE; - ibuf += AES_BLOCK_SIZE; - obuf += AES_BLOCK_SIZE; - } - - while(i++ < blen) - *obuf++ = *ibuf++ ^ ip[b_pos++]; - } - - ctx->inf.b[2] = (uint_8t)b_pos; - return EXIT_SUCCESS; -} - -#if defined(__cplusplus) -} -#endif -#endif diff --git a/jni/libzrtp/sources/cryptcommon/aescpp.h b/jni/libzrtp/sources/cryptcommon/aescpp.h deleted file mode 100644 index 9e2e24c62..000000000 --- a/jni/libzrtp/sources/cryptcommon/aescpp.h +++ /dev/null @@ -1,141 +0,0 @@ -/* ---------------------------------------------------------------------------- -Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. - -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: - - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. - -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 - - This file contains the definitions required to use AES (Rijndael) in C++. -*/ - -#ifndef _AESCPP_H -#define _AESCPP_H - -#include "aes.h" - -#if defined( AES_ENCRYPT ) - -class AESencrypt -{ -public: - aes_encrypt_ctx cx[1]; - AESencrypt(void) { aes_init(); }; -#if defined(AES_128) - AESencrypt(const unsigned char key[]) - { aes_encrypt_key128(key, cx); } - AES_RETURN key128(const unsigned char key[]) - { return aes_encrypt_key128(key, cx); } -#endif -#if defined(AES_192) - AES_RETURN key192(const unsigned char key[]) - { return aes_encrypt_key192(key, cx); } -#endif -#if defined(AES_256) - AES_RETURN key256(const unsigned char key[]) - { return aes_encrypt_key256(key, cx); } -#endif -#if defined(AES_VAR) - AES_RETURN key(const unsigned char key[], int key_len) - { return aes_encrypt_key(key, key_len, cx); } -#endif - AES_RETURN encrypt(const unsigned char in[], unsigned char out[]) const - { return aes_encrypt(in, out, cx); } -#ifndef AES_MODES - AES_RETURN ecb_encrypt(const unsigned char in[], unsigned char out[], int nb) const - { while(nb--) - { aes_encrypt(in, out, cx), in += AES_BLOCK_SIZE, out += AES_BLOCK_SIZE; } - } -#endif -#ifdef AES_MODES - AES_RETURN mode_reset(void) { return aes_mode_reset(cx); } - - AES_RETURN ecb_encrypt(const unsigned char in[], unsigned char out[], int nb) const - { return aes_ecb_encrypt(in, out, nb, cx); } - - AES_RETURN cbc_encrypt(const unsigned char in[], unsigned char out[], int nb, - unsigned char iv[]) const - { return aes_cbc_encrypt(in, out, nb, iv, cx); } - - AES_RETURN cfb_encrypt(const unsigned char in[], unsigned char out[], int nb, - unsigned char iv[]) - { return aes_cfb_encrypt(in, out, nb, iv, cx); } - - AES_RETURN cfb_decrypt(const unsigned char in[], unsigned char out[], int nb, - unsigned char iv[]) - { return aes_cfb_decrypt(in, out, nb, iv, cx); } - - AES_RETURN ofb_crypt(const unsigned char in[], unsigned char out[], int nb, - unsigned char iv[]) - { return aes_ofb_crypt(in, out, nb, iv, cx); } - - typedef void ctr_fn(unsigned char ctr[]); - - AES_RETURN ctr_crypt(const unsigned char in[], unsigned char out[], int nb, - unsigned char iv[], ctr_fn cf) - { return aes_ctr_crypt(in, out, nb, iv, cf, cx); } - -#endif - -}; - -#endif - -#if defined( AES_DECRYPT ) - -class AESdecrypt -{ -public: - aes_decrypt_ctx cx[1]; - AESdecrypt(void) { aes_init(); }; -#if defined(AES_128) - AESdecrypt(const unsigned char key[]) - { aes_decrypt_key128(key, cx); } - AES_RETURN key128(const unsigned char key[]) - { return aes_decrypt_key128(key, cx); } -#endif -#if defined(AES_192) - AES_RETURN key192(const unsigned char key[]) - { return aes_decrypt_key192(key, cx); } -#endif -#if defined(AES_256) - AES_RETURN key256(const unsigned char key[]) - { return aes_decrypt_key256(key, cx); } -#endif -#if defined(AES_VAR) - AES_RETURN key(const unsigned char key[], int key_len) - { return aes_decrypt_key(key, key_len, cx); } -#endif - AES_RETURN decrypt(const unsigned char in[], unsigned char out[]) const - { return aes_decrypt(in, out, cx); } -#ifndef AES_MODES - AES_RETURN ecb_decrypt(const unsigned char in[], unsigned char out[], int nb) const - { while(nb--) - { aes_decrypt(in, out, cx), in += AES_BLOCK_SIZE, out += AES_BLOCK_SIZE; } - } -#endif -#ifdef AES_MODES - - AES_RETURN ecb_decrypt(const unsigned char in[], unsigned char out[], int nb) const - { return aes_ecb_decrypt(in, out, nb, cx); } - - AES_RETURN cbc_decrypt(const unsigned char in[], unsigned char out[], int nb, - unsigned char iv[]) const - { return aes_cbc_decrypt(in, out, nb, iv, cx); } -#endif -}; - -#endif - -#endif diff --git a/jni/libzrtp/sources/cryptcommon/aescrypt.c b/jni/libzrtp/sources/cryptcommon/aescrypt.c deleted file mode 100644 index 6095f41a6..000000000 --- a/jni/libzrtp/sources/cryptcommon/aescrypt.c +++ /dev/null @@ -1,294 +0,0 @@ -/* ---------------------------------------------------------------------------- -Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. - -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: - - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. - -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 -*/ - -#include "aesopt.h" -#include "aestab.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) -#define so(y,x,c) word_out(y, c, s(x,c)) - -#if defined(ARRAYS) -#define locals(y,x) x[4],y[4] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 -#endif - -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) - -#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) - -/* Visual C++ .Net v7.1 provides the fastest encryption code when using - Pentium optimiation with small code but this is poor for decryption - so we need to control this with the following VC++ pragmas -*/ - -#if defined( _MSC_VER ) && !defined( _WIN64 ) -#pragma optimize( "s", on ) -#endif - -/* Given the column (c) of the output state variable, the following - macros give the input state variables which are needed in its - computation for each row (r) of the state. All the alternative - macros give the same end values but expand into different ways - of calculating these values. In particular the complex macro - used for dynamically variable block sizes is designed to expand - to a compile time constant whenever possible but will expand to - conditional clauses on some branches (I am grateful to Frank - Yellin for this construction) -*/ - -#define fwd_var(x,r,c)\ - ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ - : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ - : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ - : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) - -#if defined(FT4_SET) -#undef dec_fmvars -#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) -#elif defined(FT1_SET) -#undef dec_fmvars -#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) -#else -#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c))) -#endif - -#if defined(FL4_SET) -#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) -#elif defined(FL1_SET) -#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) -#else -#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c)) -#endif - -AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]) -{ uint_32t locals(b0, b1); - const uint_32t *kp; -#if defined( dec_fmvars ) - dec_fmvars; /* declare variables for fwd_mcol() if needed */ -#endif - - if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 ) - return EXIT_FAILURE; - - kp = cx->ks; - state_in(b0, in, kp); - -#if (ENC_UNROLL == FULL) - - switch(cx->inf.b[0]) - { - case 14 * 16: - round(fwd_rnd, b1, b0, kp + 1 * N_COLS); - round(fwd_rnd, b0, b1, kp + 2 * N_COLS); - kp += 2 * N_COLS; - case 12 * 16: - round(fwd_rnd, b1, b0, kp + 1 * N_COLS); - round(fwd_rnd, b0, b1, kp + 2 * N_COLS); - kp += 2 * N_COLS; - case 10 * 16: - round(fwd_rnd, b1, b0, kp + 1 * N_COLS); - round(fwd_rnd, b0, b1, kp + 2 * N_COLS); - round(fwd_rnd, b1, b0, kp + 3 * N_COLS); - round(fwd_rnd, b0, b1, kp + 4 * N_COLS); - round(fwd_rnd, b1, b0, kp + 5 * N_COLS); - round(fwd_rnd, b0, b1, kp + 6 * N_COLS); - round(fwd_rnd, b1, b0, kp + 7 * N_COLS); - round(fwd_rnd, b0, b1, kp + 8 * N_COLS); - round(fwd_rnd, b1, b0, kp + 9 * N_COLS); - round(fwd_lrnd, b0, b1, kp +10 * N_COLS); - } - -#else - -#if (ENC_UNROLL == PARTIAL) - { uint_32t rnd; - for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) - { - kp += N_COLS; - round(fwd_rnd, b1, b0, kp); - kp += N_COLS; - round(fwd_rnd, b0, b1, kp); - } - kp += N_COLS; - round(fwd_rnd, b1, b0, kp); -#else - { uint_32t rnd; - for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) - { - kp += N_COLS; - round(fwd_rnd, b1, b0, kp); - l_copy(b0, b1); - } -#endif - kp += N_COLS; - round(fwd_lrnd, b0, b1, kp); - } -#endif - - state_out(out, b0); - return EXIT_SUCCESS; -} - -#endif - -#if ( FUNCS_IN_C & DECRYPTION_IN_C) - -/* Visual C++ .Net v7.1 provides the fastest encryption code when using - Pentium optimiation with small code but this is poor for decryption - so we need to control this with the following VC++ pragmas -*/ - -#if defined( _MSC_VER ) && !defined( _WIN64 ) -#pragma optimize( "t", on ) -#endif - -/* Given the column (c) of the output state variable, the following - macros give the input state variables which are needed in its - computation for each row (r) of the state. All the alternative - macros give the same end values but expand into different ways - of calculating these values. In particular the complex macro - used for dynamically variable block sizes is designed to expand - to a compile time constant whenever possible but will expand to - conditional clauses on some branches (I am grateful to Frank - Yellin for this construction) -*/ - -#define inv_var(x,r,c)\ - ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ - : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\ - : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ - : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))) - -#if defined(IT4_SET) -#undef dec_imvars -#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) -#elif defined(IT1_SET) -#undef dec_imvars -#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) -#else -#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))) -#endif - -#if defined(IL4_SET) -#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) -#elif defined(IL1_SET) -#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) -#else -#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)) -#endif - -/* This code can work with the decryption key schedule in the */ -/* order that is used for encrytpion (where the 1st decryption */ -/* round key is at the high end ot the schedule) or with a key */ -/* schedule that has been reversed to put the 1st decryption */ -/* round key at the low end of the schedule in memory (when */ -/* AES_REV_DKS is defined) */ - -#ifdef AES_REV_DKS -#define key_ofs 0 -#define rnd_key(n) (kp + n * N_COLS) -#else -#define key_ofs 1 -#define rnd_key(n) (kp - n * N_COLS) -#endif - -AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]) -{ uint_32t locals(b0, b1); -#if defined( dec_imvars ) - dec_imvars; /* declare variables for inv_mcol() if needed */ -#endif - const uint_32t *kp; - - if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 ) - return EXIT_FAILURE; - - kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0); - state_in(b0, in, kp); - -#if (DEC_UNROLL == FULL) - - kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2)); - switch(cx->inf.b[0]) - { - case 14 * 16: - round(inv_rnd, b1, b0, rnd_key(-13)); - round(inv_rnd, b0, b1, rnd_key(-12)); - case 12 * 16: - round(inv_rnd, b1, b0, rnd_key(-11)); - round(inv_rnd, b0, b1, rnd_key(-10)); - case 10 * 16: - round(inv_rnd, b1, b0, rnd_key(-9)); - round(inv_rnd, b0, b1, rnd_key(-8)); - round(inv_rnd, b1, b0, rnd_key(-7)); - round(inv_rnd, b0, b1, rnd_key(-6)); - round(inv_rnd, b1, b0, rnd_key(-5)); - round(inv_rnd, b0, b1, rnd_key(-4)); - round(inv_rnd, b1, b0, rnd_key(-3)); - round(inv_rnd, b0, b1, rnd_key(-2)); - round(inv_rnd, b1, b0, rnd_key(-1)); - round(inv_lrnd, b0, b1, rnd_key( 0)); - } - -#else - -#if (DEC_UNROLL == PARTIAL) - { uint_32t rnd; - for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) - { - kp = rnd_key(1); - round(inv_rnd, b1, b0, kp); - kp = rnd_key(1); - round(inv_rnd, b0, b1, kp); - } - kp = rnd_key(1); - round(inv_rnd, b1, b0, kp); -#else - { uint_32t rnd; - for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) - { - kp = rnd_key(1); - round(inv_rnd, b1, b0, kp); - l_copy(b0, b1); - } -#endif - kp = rnd_key(1); - round(inv_lrnd, b0, b1, kp); - } -#endif - - state_out(out, b0); - return EXIT_SUCCESS; -} - -#endif - -#if defined(__cplusplus) -} -#endif diff --git a/jni/libzrtp/sources/cryptcommon/aeskey.c b/jni/libzrtp/sources/cryptcommon/aeskey.c deleted file mode 100644 index 10d3324cc..000000000 --- a/jni/libzrtp/sources/cryptcommon/aeskey.c +++ /dev/null @@ -1,550 +0,0 @@ -/* ---------------------------------------------------------------------------- -Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. - -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: - - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. - -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 -*/ - -#include "aesopt.h" -#include "aestab.h" - -/* -#ifdef USE_VIA_ACE_IF_PRESENT -# include "aes_via_ace.h" -#endif -*/ - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* Initialise the key schedule from the user supplied key. The key - length can be specified in bytes, with legal values of 16, 24 - and 32, or in bits, with legal values of 128, 192 and 256. These - values correspond with Nk values of 4, 6 and 8 respectively. - - The following macros implement a single cycle in the key - schedule generation process. The number of cycles needed - for each cx->n_col and nk value is: - - nk = 4 5 6 7 8 - ------------------------------ - cx->n_col = 4 10 9 8 7 7 - cx->n_col = 5 14 11 10 9 9 - cx->n_col = 6 19 15 12 11 11 - cx->n_col = 7 21 19 16 13 14 - cx->n_col = 8 29 23 19 17 14 -*/ - -#if defined( REDUCE_CODE_SIZE ) -# define ls_box ls_sub - uint_32t ls_sub(const uint_32t t, const uint_32t n); -# define inv_mcol im_sub - uint_32t im_sub(const uint_32t x); -# ifdef ENC_KS_UNROLL -# undef ENC_KS_UNROLL -# endif -# ifdef DEC_KS_UNROLL -# undef DEC_KS_UNROLL -# endif -#endif - -#if (FUNCS_IN_C & ENC_KEYING_IN_C) - -#if defined(AES_128) || defined( AES_VAR ) - -#define ke4(k,i) \ -{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ - k[4*(i)+5] = ss[1] ^= ss[0]; \ - k[4*(i)+6] = ss[2] ^= ss[1]; \ - k[4*(i)+7] = ss[3] ^= ss[2]; \ -} - -AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]) -{ uint_32t ss[4]; - - cx->ks[0] = ss[0] = word_in(key, 0); - cx->ks[1] = ss[1] = word_in(key, 1); - cx->ks[2] = ss[2] = word_in(key, 2); - cx->ks[3] = ss[3] = word_in(key, 3); - -#ifdef ENC_KS_UNROLL - ke4(cx->ks, 0); ke4(cx->ks, 1); - ke4(cx->ks, 2); ke4(cx->ks, 3); - ke4(cx->ks, 4); ke4(cx->ks, 5); - ke4(cx->ks, 6); ke4(cx->ks, 7); - ke4(cx->ks, 8); -#else - { uint_32t i; - for(i = 0; i < 9; ++i) - ke4(cx->ks, i); - } -#endif - ke4(cx->ks, 9); - cx->inf.l = 0; - cx->inf.b[0] = 10 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - return EXIT_SUCCESS; -} - -#endif - -#if defined(AES_192) || defined( AES_VAR ) - -#define kef6(k,i) \ -{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ - k[6*(i)+ 7] = ss[1] ^= ss[0]; \ - k[6*(i)+ 8] = ss[2] ^= ss[1]; \ - k[6*(i)+ 9] = ss[3] ^= ss[2]; \ -} - -#define ke6(k,i) \ -{ kef6(k,i); \ - k[6*(i)+10] = ss[4] ^= ss[3]; \ - k[6*(i)+11] = ss[5] ^= ss[4]; \ -} - -AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]) -{ uint_32t ss[6]; - - cx->ks[0] = ss[0] = word_in(key, 0); - cx->ks[1] = ss[1] = word_in(key, 1); - cx->ks[2] = ss[2] = word_in(key, 2); - cx->ks[3] = ss[3] = word_in(key, 3); - cx->ks[4] = ss[4] = word_in(key, 4); - cx->ks[5] = ss[5] = word_in(key, 5); - -#ifdef ENC_KS_UNROLL - ke6(cx->ks, 0); ke6(cx->ks, 1); - ke6(cx->ks, 2); ke6(cx->ks, 3); - ke6(cx->ks, 4); ke6(cx->ks, 5); - ke6(cx->ks, 6); -#else - { uint_32t i; - for(i = 0; i < 7; ++i) - ke6(cx->ks, i); - } -#endif - kef6(cx->ks, 7); - cx->inf.l = 0; - cx->inf.b[0] = 12 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - return EXIT_SUCCESS; -} - -#endif - -#if defined(AES_256) || defined( AES_VAR ) - -#define kef8(k,i) \ -{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ - k[8*(i)+ 9] = ss[1] ^= ss[0]; \ - k[8*(i)+10] = ss[2] ^= ss[1]; \ - k[8*(i)+11] = ss[3] ^= ss[2]; \ -} - -#define ke8(k,i) \ -{ kef8(k,i); \ - k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \ - k[8*(i)+13] = ss[5] ^= ss[4]; \ - k[8*(i)+14] = ss[6] ^= ss[5]; \ - k[8*(i)+15] = ss[7] ^= ss[6]; \ -} - -AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]) -{ uint_32t ss[8]; - - cx->ks[0] = ss[0] = word_in(key, 0); - cx->ks[1] = ss[1] = word_in(key, 1); - cx->ks[2] = ss[2] = word_in(key, 2); - cx->ks[3] = ss[3] = word_in(key, 3); - cx->ks[4] = ss[4] = word_in(key, 4); - cx->ks[5] = ss[5] = word_in(key, 5); - cx->ks[6] = ss[6] = word_in(key, 6); - cx->ks[7] = ss[7] = word_in(key, 7); - -#ifdef ENC_KS_UNROLL - ke8(cx->ks, 0); ke8(cx->ks, 1); - ke8(cx->ks, 2); ke8(cx->ks, 3); - ke8(cx->ks, 4); ke8(cx->ks, 5); -#else - { uint_32t i; - for(i = 0; i < 6; ++i) - ke8(cx->ks, i); - } -#endif - kef8(cx->ks, 6); - cx->inf.l = 0; - cx->inf.b[0] = 14 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - return EXIT_SUCCESS; -} - -#endif - -#if defined( AES_VAR ) - -AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]) -{ - switch(key_len) - { - case 16: case 128: return aes_encrypt_key128(key, cx); - case 24: case 192: return aes_encrypt_key192(key, cx); - case 32: case 256: return aes_encrypt_key256(key, cx); - default: return EXIT_FAILURE; - } -} - -#endif - -#endif - -#if (FUNCS_IN_C & DEC_KEYING_IN_C) - -/* this is used to store the decryption round keys */ -/* in forward or reverse order */ - -#ifdef AES_REV_DKS -#define v(n,i) ((n) - (i) + 2 * ((i) & 3)) -#else -#define v(n,i) (i) -#endif - -#if DEC_ROUND == NO_TABLES -#define ff(x) (x) -#else -#define ff(x) inv_mcol(x) -#if defined( dec_imvars ) -#define d_vars dec_imvars -#endif -#endif - -#if defined(AES_128) || defined( AES_VAR ) - -#define k4e(k,i) \ -{ k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ - k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \ - k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \ - k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \ -} - -#if 1 - -#define kdf4(k,i) \ -{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \ - ss[1] = ss[1] ^ ss[3]; \ - ss[2] = ss[2] ^ ss[3]; \ - ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ - ss[i % 4] ^= ss[4]; \ - ss[4] ^= k[v(40,(4*(i)))]; k[v(40,(4*(i))+4)] = ff(ss[4]); \ - ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \ - ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \ - ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \ -} - -#define kd4(k,i) \ -{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ - ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ - k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \ - k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \ - k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \ - k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \ -} - -#define kdl4(k,i) \ -{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ - k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \ - k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \ - k[v(40,(4*(i))+6)] = ss[0]; \ - k[v(40,(4*(i))+7)] = ss[1]; \ -} - -#else - -#define kdf4(k,i) \ -{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ff(ss[0]); \ - ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ff(ss[1]); \ - ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ff(ss[2]); \ - ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ff(ss[3]); \ -} - -#define kd4(k,i) \ -{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \ - ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[v(40,(4*(i))+ 4)] = ss[4] ^= k[v(40,(4*(i)))]; \ - ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[4] ^= k[v(40,(4*(i))+ 1)]; \ - ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[4] ^= k[v(40,(4*(i))+ 2)]; \ - ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[4] ^= k[v(40,(4*(i))+ 3)]; \ -} - -#define kdl4(k,i) \ -{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ss[0]; \ - ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[1]; \ - ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[2]; \ - ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[3]; \ -} - -#endif - -AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]) -{ uint_32t ss[5]; -#if defined( d_vars ) - d_vars; -#endif - cx->ks[v(40,(0))] = ss[0] = word_in(key, 0); - cx->ks[v(40,(1))] = ss[1] = word_in(key, 1); - cx->ks[v(40,(2))] = ss[2] = word_in(key, 2); - cx->ks[v(40,(3))] = ss[3] = word_in(key, 3); - -#ifdef DEC_KS_UNROLL - kdf4(cx->ks, 0); kd4(cx->ks, 1); - kd4(cx->ks, 2); kd4(cx->ks, 3); - kd4(cx->ks, 4); kd4(cx->ks, 5); - kd4(cx->ks, 6); kd4(cx->ks, 7); - kd4(cx->ks, 8); kdl4(cx->ks, 9); -#else - { uint_32t i; - for(i = 0; i < 10; ++i) - k4e(cx->ks, i); -#if !(DEC_ROUND == NO_TABLES) - for(i = N_COLS; i < 10 * N_COLS; ++i) - cx->ks[i] = inv_mcol(cx->ks[i]); -#endif - } -#endif - cx->inf.l = 0; - cx->inf.b[0] = 10 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - return EXIT_SUCCESS; -} - -#endif - -#if defined(AES_192) || defined( AES_VAR ) - -#define k6ef(k,i) \ -{ k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ - k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \ - k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \ - k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \ -} - -#define k6e(k,i) \ -{ k6ef(k,i); \ - k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \ - k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \ -} - -#define kdf6(k,i) \ -{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \ - ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \ - ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \ - ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \ - ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \ - ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \ -} - -#define kd6(k,i) \ -{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \ - ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \ - ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \ - ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \ - ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \ - ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \ - ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \ -} - -#define kdl6(k,i) \ -{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \ - ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \ - ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \ - ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \ -} - -AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]) -{ uint_32t ss[7]; -#if defined( d_vars ) - d_vars; -#endif - cx->ks[v(48,(0))] = ss[0] = word_in(key, 0); - cx->ks[v(48,(1))] = ss[1] = word_in(key, 1); - cx->ks[v(48,(2))] = ss[2] = word_in(key, 2); - cx->ks[v(48,(3))] = ss[3] = word_in(key, 3); - -#ifdef DEC_KS_UNROLL - cx->ks[v(48,(4))] = ff(ss[4] = word_in(key, 4)); - cx->ks[v(48,(5))] = ff(ss[5] = word_in(key, 5)); - kdf6(cx->ks, 0); kd6(cx->ks, 1); - kd6(cx->ks, 2); kd6(cx->ks, 3); - kd6(cx->ks, 4); kd6(cx->ks, 5); - kd6(cx->ks, 6); kdl6(cx->ks, 7); -#else - cx->ks[v(48,(4))] = ss[4] = word_in(key, 4); - cx->ks[v(48,(5))] = ss[5] = word_in(key, 5); - { uint_32t i; - - for(i = 0; i < 7; ++i) - k6e(cx->ks, i); - k6ef(cx->ks, 7); -#if !(DEC_ROUND == NO_TABLES) - for(i = N_COLS; i < 12 * N_COLS; ++i) - cx->ks[i] = inv_mcol(cx->ks[i]); -#endif - } -#endif - cx->inf.l = 0; - cx->inf.b[0] = 12 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - return EXIT_SUCCESS; -} - -#endif - -#if defined(AES_256) || defined( AES_VAR ) - -#define k8ef(k,i) \ -{ k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ - k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \ - k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \ - k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \ -} - -#define k8e(k,i) \ -{ k8ef(k,i); \ - k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \ - k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \ - k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \ - k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \ -} - -#define kdf8(k,i) \ -{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \ - ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \ - ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \ - ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \ - ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \ - ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \ - ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \ - ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \ -} - -#define kd8(k,i) \ -{ ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \ - ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \ - ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \ - ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \ - ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \ - ss[8] = ls_box(ss[3],0); \ - ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \ - ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \ - ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \ - ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \ -} - -#define kdl8(k,i) \ -{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \ - ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \ - ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \ - ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \ -} - -AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]) -{ uint_32t ss[9]; -#if defined( d_vars ) - d_vars; -#endif - cx->ks[v(56,(0))] = ss[0] = word_in(key, 0); - cx->ks[v(56,(1))] = ss[1] = word_in(key, 1); - cx->ks[v(56,(2))] = ss[2] = word_in(key, 2); - cx->ks[v(56,(3))] = ss[3] = word_in(key, 3); - -#ifdef DEC_KS_UNROLL - cx->ks[v(56,(4))] = ff(ss[4] = word_in(key, 4)); - cx->ks[v(56,(5))] = ff(ss[5] = word_in(key, 5)); - cx->ks[v(56,(6))] = ff(ss[6] = word_in(key, 6)); - cx->ks[v(56,(7))] = ff(ss[7] = word_in(key, 7)); - kdf8(cx->ks, 0); kd8(cx->ks, 1); - kd8(cx->ks, 2); kd8(cx->ks, 3); - kd8(cx->ks, 4); kd8(cx->ks, 5); - kdl8(cx->ks, 6); -#else - cx->ks[v(56,(4))] = ss[4] = word_in(key, 4); - cx->ks[v(56,(5))] = ss[5] = word_in(key, 5); - cx->ks[v(56,(6))] = ss[6] = word_in(key, 6); - cx->ks[v(56,(7))] = ss[7] = word_in(key, 7); - { uint_32t i; - - for(i = 0; i < 6; ++i) - k8e(cx->ks, i); - k8ef(cx->ks, 6); -#if !(DEC_ROUND == NO_TABLES) - for(i = N_COLS; i < 14 * N_COLS; ++i) - cx->ks[i] = inv_mcol(cx->ks[i]); -#endif - } -#endif - cx->inf.l = 0; - cx->inf.b[0] = 14 * 16; - -#ifdef USE_VIA_ACE_IF_PRESENT - if(VIA_ACE_AVAILABLE) - cx->inf.b[1] = 0xff; -#endif - return EXIT_SUCCESS; -} - -#endif - -#if defined( AES_VAR ) - -AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]) -{ - switch(key_len) - { - case 16: case 128: return aes_decrypt_key128(key, cx); - case 24: case 192: return aes_decrypt_key192(key, cx); - case 32: case 256: return aes_decrypt_key256(key, cx); - default: return EXIT_FAILURE; - } -} - -#endif - -#endif - -#if defined(__cplusplus) -} -#endif diff --git a/jni/libzrtp/sources/cryptcommon/aesopt.h b/jni/libzrtp/sources/cryptcommon/aesopt.h deleted file mode 100644 index 471e0c9d3..000000000 --- a/jni/libzrtp/sources/cryptcommon/aesopt.h +++ /dev/null @@ -1,742 +0,0 @@ -/* ---------------------------------------------------------------------------- -Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. - -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: - - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. - -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 - - This file contains the compilation options for AES (Rijndael) and code - that is common across encryption, key scheduling and table generation. - - OPERATION - - These source code files implement the AES algorithm Rijndael designed by - Joan Daemen and Vincent Rijmen. This version is designed for the standard - block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24 - and 32 bytes). - - This version is designed for flexibility and speed using operations on - 32-bit words rather than operations on bytes. It can be compiled with - either big or little endian internal byte order but is faster when the - native byte order for the processor is used. - - THE CIPHER INTERFACE - - The cipher interface is implemented as an array of bytes in which lower - AES bit sequence indexes map to higher numeric significance within bytes. - - uint_8t (an unsigned 8-bit type) - uint_32t (an unsigned 32-bit type) - struct aes_encrypt_ctx (structure for the cipher encryption context) - struct aes_decrypt_ctx (structure for the cipher decryption context) - AES_RETURN the function return type - - C subroutine calls: - - AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); - AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); - AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); - AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, - const aes_encrypt_ctx cx[1]); - - AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); - AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); - AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); - AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, - const aes_decrypt_ctx cx[1]); - - IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that - you call aes_init() before AES is used so that the tables are initialised. - - C++ aes class subroutines: - - Class AESencrypt for encryption - - Construtors: - AESencrypt(void) - AESencrypt(const unsigned char *key) - 128 bit key - Members: - AES_RETURN key128(const unsigned char *key) - AES_RETURN key192(const unsigned char *key) - AES_RETURN key256(const unsigned char *key) - AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const - - Class AESdecrypt for encryption - Construtors: - AESdecrypt(void) - AESdecrypt(const unsigned char *key) - 128 bit key - Members: - AES_RETURN key128(const unsigned char *key) - AES_RETURN key192(const unsigned char *key) - AES_RETURN key256(const unsigned char *key) - AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const -*/ - -#if !defined( _AESOPT_H ) -#define _AESOPT_H - -#if defined( __cplusplus ) -#include "aescpp.h" -#else -#include "aes.h" -#endif - -/* PLATFORM SPECIFIC INCLUDES */ - -#include "brg_endian.h" - -/* CONFIGURATION - THE USE OF DEFINES - - Later in this section there are a number of defines that control the - operation of the code. In each section, the purpose of each define is - explained so that the relevant form can be included or excluded by - setting either 1's or 0's respectively on the branches of the related - #if clauses. The following local defines should not be changed. -*/ - -#define ENCRYPTION_IN_C 1 -#define DECRYPTION_IN_C 2 -#define ENC_KEYING_IN_C 4 -#define DEC_KEYING_IN_C 8 - -#define NO_TABLES 0 -#define ONE_TABLE 1 -#define FOUR_TABLES 4 -#define NONE 0 -#define PARTIAL 1 -#define FULL 2 - -/* --- START OF USER CONFIGURED OPTIONS --- */ - -/* 1. BYTE ORDER WITHIN 32 BIT WORDS - - The fundamental data processing units in Rijndael are 8-bit bytes. The - input, output and key input are all enumerated arrays of bytes in which - bytes are numbered starting at zero and increasing to one less than the - number of bytes in the array in question. This enumeration is only used - for naming bytes and does not imply any adjacency or order relationship - from one byte to another. When these inputs and outputs are considered - as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to - byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. - In this implementation bits are numbered from 0 to 7 starting at the - numerically least significant end of each byte (bit n represents 2^n). - - However, Rijndael can be implemented more efficiently using 32-bit - words by packing bytes into words so that bytes 4*n to 4*n+3 are placed - into word[n]. While in principle these bytes can be assembled into words - in any positions, this implementation only supports the two formats in - which bytes in adjacent positions within words also have adjacent byte - numbers. This order is called big-endian if the lowest numbered bytes - in words have the highest numeric significance and little-endian if the - opposite applies. - - This code can work in either order irrespective of the order used by the - machine on which it runs. Normally the internal byte order will be set - to the order of the processor on which the code is to be run but this - define can be used to reverse this in special situations - - WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set. - This define will hence be redefined later (in section 4) if necessary -*/ - -#if 1 -# define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER -#elif 0 -# define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN -#elif 0 -# define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN -#else -# error The algorithm byte order is not defined -#endif - -/* 2. VIA ACE SUPPORT */ - -#if defined( __GNUC__ ) && defined( __i386__ ) \ - || defined( _WIN32 ) && defined( _M_IX86 ) \ - && !(defined( _WIN64 ) || defined( _WIN32_WCE ) || defined( _MSC_VER ) && ( _MSC_VER <= 800 )) -# define VIA_ACE_POSSIBLE -#endif - -/* Define this option if support for the VIA ACE is required. This uses - inline assembler instructions and is only implemented for the Microsoft, - Intel and GCC compilers. If VIA ACE is known to be present, then defining - ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption - code. If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if - it is detected (both present and enabled) but the normal AES code will - also be present. - - When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte - aligned; other input/output buffers do not need to be 16 byte aligned - but there are very large performance gains if this can be arranged. - VIA ACE also requires the decryption key schedule to be in reverse - order (which later checks below ensure). -*/ - -#if 1 && defined( VIA_ACE_POSSIBLE ) && !defined( USE_VIA_ACE_IF_PRESENT ) -# define USE_VIA_ACE_IF_PRESENT -#endif - -#if 0 && defined( VIA_ACE_POSSIBLE ) && !defined( ASSUME_VIA_ACE_PRESENT ) -# define ASSUME_VIA_ACE_PRESENT -# endif - -/* 3. ASSEMBLER SUPPORT - - This define (which can be on the command line) enables the use of the - assembler code routines for encryption, decryption and key scheduling - as follows: - - ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for - encryption and decryption and but with key scheduling in C - ASM_X86_V2 uses assembler (aes_x86_v2.asm) with compressed tables for - encryption, decryption and key scheduling - ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for - encryption and decryption and but with key scheduling in C - ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for - encryption and decryption and but with key scheduling in C - - Change one 'if 0' below to 'if 1' to select the version or define - as a compilation option. -*/ - -#if 0 && !defined( ASM_X86_V1C ) -# define ASM_X86_V1C -#elif 0 && !defined( ASM_X86_V2 ) -# define ASM_X86_V2 -#elif 0 && !defined( ASM_X86_V2C ) -# define ASM_X86_V2C -#elif 0 && !defined( ASM_AMD64_C ) -# define ASM_AMD64_C -#endif - -#if (defined ( ASM_X86_V1C ) || defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) \ - && !defined( _M_IX86 ) || defined( ASM_AMD64_C ) && !defined( _M_X64 ) -# error Assembler code is only available for x86 and AMD64 systems -#endif - -/* 4. FAST INPUT/OUTPUT OPERATIONS. - - On some machines it is possible to improve speed by transferring the - bytes in the input and output arrays to and from the internal 32-bit - variables by addressing these arrays as if they are arrays of 32-bit - words. On some machines this will always be possible but there may - be a large performance penalty if the byte arrays are not aligned on - the normal word boundaries. On other machines this technique will - lead to memory access errors when such 32-bit word accesses are not - properly aligned. The option SAFE_IO avoids such problems but will - often be slower on those machines that support misaligned access - (especially so if care is taken to align the input and output byte - arrays on 32-bit word boundaries). If SAFE_IO is not defined it is - assumed that access to byte arrays as if they are arrays of 32-bit - words will not cause problems when such accesses are misaligned. -*/ -#if 1 && !defined( _MSC_VER ) -# define SAFE_IO -#endif - -/* 5. LOOP UNROLLING - - The code for encryption and decrytpion cycles through a number of rounds - that can be implemented either in a loop or by expanding the code into a - long sequence of instructions, the latter producing a larger program but - one that will often be much faster. The latter is called loop unrolling. - There are also potential speed advantages in expanding two iterations in - a loop with half the number of iterations, which is called partial loop - unrolling. The following options allow partial or full loop unrolling - to be set independently for encryption and decryption -*/ -#if 1 -# define ENC_UNROLL FULL -#elif 0 -# define ENC_UNROLL PARTIAL -#else -# define ENC_UNROLL NONE -#endif - -#if 1 -# define DEC_UNROLL FULL -#elif 0 -# define DEC_UNROLL PARTIAL -#else -# define DEC_UNROLL NONE -#endif - -#if 1 -# define ENC_KS_UNROLL -#endif - -#if 1 -# define DEC_KS_UNROLL -#endif - -/* 6. FAST FINITE FIELD OPERATIONS - - If this section is included, tables are used to provide faster finite - field arithmetic (this has no effect if FIXED_TABLES is defined). -*/ -#if 1 -# define FF_TABLES -#endif - -/* 7. INTERNAL STATE VARIABLE FORMAT - - The internal state of Rijndael is stored in a number of local 32-bit - word varaibles which can be defined either as an array or as individual - names variables. Include this section if you want to store these local - varaibles in arrays. Otherwise individual local variables will be used. -*/ -#if 1 -# define ARRAYS -#endif - -/* 8. FIXED OR DYNAMIC TABLES - - When this section is included the tables used by the code are compiled - statically into the binary file. Otherwise the subroutine aes_init() - must be called to compute them before the code is first used. -*/ -#if 1 && !(defined( _MSC_VER ) && ( _MSC_VER <= 800 )) -# define FIXED_TABLES -#endif - -/* 9. MASKING OR CASTING FROM LONGER VALUES TO BYTES - - In some systems it is better to mask longer values to extract bytes - rather than using a cast. This option allows this choice. -*/ -#if 0 -# define to_byte(x) ((uint_8t)(x)) -#else -# define to_byte(x) ((x) & 0xff) -#endif - -/* 10. TABLE ALIGNMENT - - On some sytsems speed will be improved by aligning the AES large lookup - tables on particular boundaries. This define should be set to a power of - two giving the desired alignment. It can be left undefined if alignment - is not needed. This option is specific to the Microsft VC++ compiler - - it seems to sometimes cause trouble for the VC++ version 6 compiler. -*/ - -#if 1 && defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) -# define TABLE_ALIGN 32 -#endif - -/* 11. REDUCE CODE AND TABLE SIZE - - This replaces some expanded macros with function calls if AES_ASM_V2 or - AES_ASM_V2C are defined -*/ - -#if 1 && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) -# define REDUCE_CODE_SIZE -#endif - -/* 12. TABLE OPTIONS - - This cipher proceeds by repeating in a number of cycles known as 'rounds' - which are implemented by a round function which can optionally be speeded - up using tables. The basic tables are each 256 32-bit words, with either - one or four tables being required for each round function depending on - how much speed is required. The encryption and decryption round functions - are different and the last encryption and decrytpion round functions are - different again making four different round functions in all. - - This means that: - 1. Normal encryption and decryption rounds can each use either 0, 1 - or 4 tables and table spaces of 0, 1024 or 4096 bytes each. - 2. The last encryption and decryption rounds can also use either 0, 1 - or 4 tables and table spaces of 0, 1024 or 4096 bytes each. - - Include or exclude the appropriate definitions below to set the number - of tables used by this implementation. -*/ - -#if 1 /* set tables for the normal encryption round */ -# define ENC_ROUND FOUR_TABLES -#elif 0 -# define ENC_ROUND ONE_TABLE -#else -# define ENC_ROUND NO_TABLES -#endif - -#if 1 /* set tables for the last encryption round */ -# define LAST_ENC_ROUND FOUR_TABLES -#elif 0 -# define LAST_ENC_ROUND ONE_TABLE -#else -# define LAST_ENC_ROUND NO_TABLES -#endif - -#if 1 /* set tables for the normal decryption round */ -# define DEC_ROUND FOUR_TABLES -#elif 0 -# define DEC_ROUND ONE_TABLE -#else -# define DEC_ROUND NO_TABLES -#endif - -#if 1 /* set tables for the last decryption round */ -# define LAST_DEC_ROUND FOUR_TABLES -#elif 0 -# define LAST_DEC_ROUND ONE_TABLE -#else -# define LAST_DEC_ROUND NO_TABLES -#endif - -/* The decryption key schedule can be speeded up with tables in the same - way that the round functions can. Include or exclude the following - defines to set this requirement. -*/ -#if 1 -# define KEY_SCHED FOUR_TABLES -#elif 0 -# define KEY_SCHED ONE_TABLE -#else -# define KEY_SCHED NO_TABLES -#endif - -/* ---- END OF USER CONFIGURED OPTIONS ---- */ - -/* VIA ACE support is only available for VC++ and GCC */ - -#if !defined( _MSC_VER ) && !defined( __GNUC__ ) -# if defined( ASSUME_VIA_ACE_PRESENT ) -# undef ASSUME_VIA_ACE_PRESENT -# endif -# if defined( USE_VIA_ACE_IF_PRESENT ) -# undef USE_VIA_ACE_IF_PRESENT -# endif -#endif - -#if defined( ASSUME_VIA_ACE_PRESENT ) && !defined( USE_VIA_ACE_IF_PRESENT ) -# define USE_VIA_ACE_IF_PRESENT -#endif - -#if defined( USE_VIA_ACE_IF_PRESENT ) && !defined ( AES_REV_DKS ) -# define AES_REV_DKS -#endif - -/* ********** UNDEF - we don't use VIA stuff ****************** */ -#undef USE_VIA_ACE_IF_PRESENT - -/* Assembler support requires the use of platform byte order */ - -#if ( defined( ASM_X86_V1C ) || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) ) \ - && (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER) -# undef ALGORITHM_BYTE_ORDER -# define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER -#endif - -/* In this implementation the columns of the state array are each held in - 32-bit words. The state array can be held in various ways: in an array - of words, in a number of individual word variables or in a number of - processor registers. The following define maps a variable name x and - a column number c to the way the state array variable is to be held. - The first define below maps the state into an array x[c] whereas the - second form maps the state into a number of individual variables x0, - x1, etc. Another form could map individual state colums to machine - register names. -*/ - -#if defined( ARRAYS ) -# define s(x,c) x[c] -#else -# define s(x,c) x##c -#endif - -/* This implementation provides subroutines for encryption, decryption - and for setting the three key lengths (separately) for encryption - and decryption. Since not all functions are needed, masks are set - up here to determine which will be implemented in C -*/ - -#if !defined( AES_ENCRYPT ) -# define EFUNCS_IN_C 0 -#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ - || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) -# define EFUNCS_IN_C ENC_KEYING_IN_C -#elif !defined( ASM_X86_V2 ) -# define EFUNCS_IN_C ( ENCRYPTION_IN_C | ENC_KEYING_IN_C ) -#else -# define EFUNCS_IN_C 0 -#endif - -#if !defined( AES_DECRYPT ) -# define DFUNCS_IN_C 0 -#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ - || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) -# define DFUNCS_IN_C DEC_KEYING_IN_C -#elif !defined( ASM_X86_V2 ) -# define DFUNCS_IN_C ( DECRYPTION_IN_C | DEC_KEYING_IN_C ) -#else -# define DFUNCS_IN_C 0 -#endif - -#define FUNCS_IN_C ( EFUNCS_IN_C | DFUNCS_IN_C ) - -/* END OF CONFIGURATION OPTIONS */ - -#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2)) - -/* Disable or report errors on some combinations of options */ - -#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES -# undef LAST_ENC_ROUND -# define LAST_ENC_ROUND NO_TABLES -#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES -# undef LAST_ENC_ROUND -# define LAST_ENC_ROUND ONE_TABLE -#endif - -#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE -# undef ENC_UNROLL -# define ENC_UNROLL NONE -#endif - -#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES -# undef LAST_DEC_ROUND -# define LAST_DEC_ROUND NO_TABLES -#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES -# undef LAST_DEC_ROUND -# define LAST_DEC_ROUND ONE_TABLE -#endif - -#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE -# undef DEC_UNROLL -# define DEC_UNROLL NONE -#endif - -#if defined( bswap32 ) -# define aes_sw32 bswap32 -#elif defined( bswap_32 ) -# define aes_sw32 bswap_32 -#else -# define brot(x,n) (((uint_32t)(x) << n) | ((uint_32t)(x) >> (32 - n))) -# define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00)) -#endif - -/* upr(x,n): rotates bytes within words by n positions, moving bytes to - higher index positions with wrap around into low positions - ups(x,n): moves bytes by n positions to higher index positions in - words but without wrap around - bval(x,n): extracts a byte from a word - - WARNING: The definitions given here are intended only for use with - unsigned variables and with shift counts that are compile - time constants -*/ - -#if ( ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN ) -# define upr(x,n) (((uint_32t)(x) << (8 * (n))) | ((uint_32t)(x) >> (32 - 8 * (n)))) -# define ups(x,n) ((uint_32t) (x) << (8 * (n))) -# define bval(x,n) to_byte((x) >> (8 * (n))) -# define bytes2word(b0, b1, b2, b3) \ - (((uint_32t)(b3) << 24) | ((uint_32t)(b2) << 16) | ((uint_32t)(b1) << 8) | (b0)) -#endif - -#if ( ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN ) -# define upr(x,n) (((uint_32t)(x) >> (8 * (n))) | ((uint_32t)(x) << (32 - 8 * (n)))) -# define ups(x,n) ((uint_32t) (x) >> (8 * (n))) -# define bval(x,n) to_byte((x) >> (24 - 8 * (n))) -# define bytes2word(b0, b1, b2, b3) \ - (((uint_32t)(b0) << 24) | ((uint_32t)(b1) << 16) | ((uint_32t)(b2) << 8) | (b3)) -#endif - -#if defined( SAFE_IO ) -# define word_in(x,c) bytes2word(((const uint_8t*)(x)+4*c)[0], ((const uint_8t*)(x)+4*c)[1], \ - ((const uint_8t*)(x)+4*c)[2], ((const uint_8t*)(x)+4*c)[3]) -# define word_out(x,c,v) { ((uint_8t*)(x)+4*c)[0] = bval(v,0); ((uint_8t*)(x)+4*c)[1] = bval(v,1); \ - ((uint_8t*)(x)+4*c)[2] = bval(v,2); ((uint_8t*)(x)+4*c)[3] = bval(v,3); } -#elif ( ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER ) -# define word_in(x,c) (*((uint_32t*)(x)+(c))) -# define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = (v)) -#else -# define word_in(x,c) aes_sw32(*((uint_32t*)(x)+(c))) -# define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = aes_sw32(v)) -#endif - -/* the finite field modular polynomial and elements */ - -#define WPOLY 0x011b -#define BPOLY 0x1b - -/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ - -#define gf_c1 0x80808080 -#define gf_c2 0x7f7f7f7f -#define gf_mulx(x) ((((x) & gf_c2) << 1) ^ ((((x) & gf_c1) >> 7) * BPOLY)) - -/* The following defines provide alternative definitions of gf_mulx that might - give improved performance if a fast 32-bit multiply is not available. Note - that a temporary variable u needs to be defined where gf_mulx is used. - -#define gf_mulx(x) (u = (x) & gf_c1, u |= (u >> 1), ((x) & gf_c2) << 1) ^ ((u >> 3) | (u >> 6)) -#define gf_c4 (0x01010101 * BPOLY) -#define gf_mulx(x) (u = (x) & gf_c1, ((x) & gf_c2) << 1) ^ ((u - (u >> 7)) & gf_c4) -*/ - -/* Work out which tables are needed for the different options */ - -#if defined( ASM_X86_V1C ) -# if defined( ENC_ROUND ) -# undef ENC_ROUND -# endif -# define ENC_ROUND FOUR_TABLES -# if defined( LAST_ENC_ROUND ) -# undef LAST_ENC_ROUND -# endif -# define LAST_ENC_ROUND FOUR_TABLES -# if defined( DEC_ROUND ) -# undef DEC_ROUND -# endif -# define DEC_ROUND FOUR_TABLES -# if defined( LAST_DEC_ROUND ) -# undef LAST_DEC_ROUND -# endif -# define LAST_DEC_ROUND FOUR_TABLES -# if defined( KEY_SCHED ) -# undef KEY_SCHED -# define KEY_SCHED FOUR_TABLES -# endif -#endif - -#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) || defined( ASM_X86_V1C ) -# if ENC_ROUND == ONE_TABLE -# define FT1_SET -# elif ENC_ROUND == FOUR_TABLES -# define FT4_SET -# else -# define SBX_SET -# endif -# if LAST_ENC_ROUND == ONE_TABLE -# define FL1_SET -# elif LAST_ENC_ROUND == FOUR_TABLES -# define FL4_SET -# elif !defined( SBX_SET ) -# define SBX_SET -# endif -#endif - -#if ( FUNCS_IN_C & DECRYPTION_IN_C ) || defined( ASM_X86_V1C ) -# if DEC_ROUND == ONE_TABLE -# define IT1_SET -# elif DEC_ROUND == FOUR_TABLES -# define IT4_SET -# else -# define ISB_SET -# endif -# if LAST_DEC_ROUND == ONE_TABLE -# define IL1_SET -# elif LAST_DEC_ROUND == FOUR_TABLES -# define IL4_SET -# elif !defined(ISB_SET) -# define ISB_SET -# endif -#endif - -#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))) -# if ((FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C)) -# if KEY_SCHED == ONE_TABLE -# if !defined( FL1_SET ) && !defined( FL4_SET ) -# define LS1_SET -# endif -# elif KEY_SCHED == FOUR_TABLES -# if !defined( FL4_SET ) -# define LS4_SET -# endif -# elif !defined( SBX_SET ) -# define SBX_SET -# endif -# endif -# if (FUNCS_IN_C & DEC_KEYING_IN_C) -# if KEY_SCHED == ONE_TABLE -# define IM1_SET -# elif KEY_SCHED == FOUR_TABLES -# define IM4_SET -# elif !defined( SBX_SET ) -# define SBX_SET -# endif -# endif -#endif - -/* generic definitions of Rijndael macros that use tables */ - -#define no_table(x,box,vf,rf,c) bytes2word( \ - box[bval(vf(x,0,c),rf(0,c))], \ - box[bval(vf(x,1,c),rf(1,c))], \ - box[bval(vf(x,2,c),rf(2,c))], \ - box[bval(vf(x,3,c),rf(3,c))]) - -#define one_table(x,op,tab,vf,rf,c) \ - ( tab[bval(vf(x,0,c),rf(0,c))] \ - ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ - ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ - ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) - -#define four_tables(x,tab,vf,rf,c) \ - ( tab[0][bval(vf(x,0,c),rf(0,c))] \ - ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ - ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ - ^ tab[3][bval(vf(x,3,c),rf(3,c))]) - -#define vf1(x,r,c) (x) -#define rf1(r,c) (r) -#define rf2(r,c) ((8+r-c)&3) - -/* perform forward and inverse column mix operation on four bytes in long word x in */ -/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ - -#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))) - -#if defined( FM4_SET ) /* not currently used */ -# define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0) -#elif defined( FM1_SET ) /* not currently used */ -# define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0) -#else -# define dec_fmvars uint_32t g2 -# define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1)) -#endif - -#if defined( IM4_SET ) -# define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0) -#elif defined( IM1_SET ) -# define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0) -#else -# define dec_imvars uint_32t g2, g4, g9 -# define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \ - (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1)) -#endif - -#if defined( FL4_SET ) -# define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c) -#elif defined( LS4_SET ) -# define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c) -#elif defined( FL1_SET ) -# define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c) -#elif defined( LS1_SET ) -# define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c) -#else -# define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c) -#endif - -#endif - -#if defined( ASM_X86_V1C ) && defined( AES_DECRYPT ) && !defined( ISB_SET ) -# define ISB_SET -#endif - -#endif diff --git a/jni/libzrtp/sources/cryptcommon/aestab.c b/jni/libzrtp/sources/cryptcommon/aestab.c deleted file mode 100644 index e2bdb9a79..000000000 --- a/jni/libzrtp/sources/cryptcommon/aestab.c +++ /dev/null @@ -1,391 +0,0 @@ -/* ---------------------------------------------------------------------------- -Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. - -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: - - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. - -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 -*/ - -#define DO_TABLES - -#include "aes.h" -#include "aesopt.h" - -#if defined(FIXED_TABLES) - -#define sb_data(w) {\ - w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ - w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ - w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ - w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ - w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ - w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ - w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ - w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ - w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ - w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ - w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ - w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ - w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ - w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ - w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ - w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ - w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ - w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ - w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ - w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ - w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ - w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ - w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ - w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ - w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ - w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ - w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ - w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ - w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ - w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ - w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ - w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } - -#define isb_data(w) {\ - w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ - w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ - w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ - w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ - w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ - w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ - w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ - w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ - w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ - w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ - w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ - w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ - w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ - w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ - w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ - w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ - w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ - w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ - w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ - w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ - w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ - w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ - w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ - w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ - w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ - w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ - w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ - w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ - w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ - w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ - w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ - w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } - -#define mm_data(w) {\ - w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ - w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ - w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ - w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ - w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ - w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ - w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ - w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ - w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ - w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ - w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ - w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ - w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ - w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ - w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ - w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ - w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ - w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ - w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ - w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ - w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ - w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ - w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ - w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ - w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ - w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ - w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ - w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ - w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ - w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ - w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ - w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } - -#define rc_data(w) {\ - w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\ - w(0x1b), w(0x36) } - -#define h0(x) (x) - -#define w0(p) bytes2word(p, 0, 0, 0) -#define w1(p) bytes2word(0, p, 0, 0) -#define w2(p) bytes2word(0, 0, p, 0) -#define w3(p) bytes2word(0, 0, 0, p) - -#define u0(p) bytes2word(f2(p), p, p, f3(p)) -#define u1(p) bytes2word(f3(p), f2(p), p, p) -#define u2(p) bytes2word(p, f3(p), f2(p), p) -#define u3(p) bytes2word(p, p, f3(p), f2(p)) - -#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) -#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) -#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) -#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) - -#endif - -#if defined(FIXED_TABLES) || !defined(FF_TABLES) - -#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) -#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) -#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ - ^ (((x>>5) & 4) * WPOLY)) -#define f3(x) (f2(x) ^ x) -#define f9(x) (f8(x) ^ x) -#define fb(x) (f8(x) ^ f2(x) ^ x) -#define fd(x) (f8(x) ^ f4(x) ^ x) -#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) - -#else - -#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) -#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) -#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) -#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) -#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) -#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) - -#endif - -#include "aestab.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#if defined(FIXED_TABLES) - -/* implemented in case of wrong call for fixed tables */ - -AES_RETURN aes_init(void) -{ - return EXIT_SUCCESS; -} - -#else /* Generate the tables for the dynamic table option */ - -#if defined(FF_TABLES) - -#define gf_inv(x) ((x) ? pow[ 255 - log[x]] : 0) - -#else - -/* It will generally be sensible to use tables to compute finite - field multiplies and inverses but where memory is scarse this - code might sometimes be better. But it only has effect during - initialisation so its pretty unimportant in overall terms. -*/ - -/* return 2 ^ (n - 1) where n is the bit number of the highest bit - set in x with x in the range 1 < x < 0x00000200. This form is - used so that locals within fi can be bytes rather than words -*/ - -static uint_8t hibit(const uint_32t x) -{ uint_8t r = (uint_8t)((x >> 1) | (x >> 2)); - - r |= (r >> 2); - r |= (r >> 4); - return (r + 1) >> 1; -} - -/* return the inverse of the finite field element x */ - -static uint_8t gf_inv(const uint_8t x) -{ uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; - - if(x < 2) - return x; - - for( ; ; ) - { - if(n1) - while(n2 >= n1) /* divide polynomial p2 by p1 */ - { - n2 /= n1; /* shift smaller polynomial left */ - p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */ - v2 ^= v1 * n2; /* shift accumulated value and */ - n2 = hibit(p2); /* add into result */ - } - else - return v1; - - if(n2) /* repeat with values swapped */ - while(n1 >= n2) - { - n1 /= n2; - p1 ^= p2 * n1; - v1 ^= v2 * n1; - n1 = hibit(p1); - } - else - return v2; - } -} - -#endif - -/* The forward and inverse affine transformations used in the S-box */ -uint_8t fwd_affine(const uint_8t x) -{ uint_32t w = x; - w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4); - return 0x63 ^ ((w ^ (w >> 8)) & 0xff); -} - -uint_8t inv_affine(const uint_8t x) -{ uint_32t w = x; - w = (w << 1) ^ (w << 3) ^ (w << 6); - return 0x05 ^ ((w ^ (w >> 8)) & 0xff); -} - -static int init = 0; - -AES_RETURN aes_init(void) -{ uint_32t i, w; - -#if defined(FF_TABLES) - - uint_8t pow[512], log[256]; - - if(init) - return EXIT_SUCCESS; - /* log and power tables for GF(2^8) finite field with - WPOLY as modular polynomial - the simplest primitive - root is 0x03, used here to generate the tables - */ - - i = 0; w = 1; - do - { - pow[i] = (uint_8t)w; - pow[i + 255] = (uint_8t)w; - log[w] = (uint_8t)i++; - w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); - } - while (w != 1); - -#else - if(init) - return EXIT_SUCCESS; -#endif - - for(i = 0, w = 1; i < RC_LENGTH; ++i) - { - t_set(r,c)[i] = bytes2word(w, 0, 0, 0); - w = f2(w); - } - - for(i = 0; i < 256; ++i) - { uint_8t b; - - b = fwd_affine(gf_inv((uint_8t)i)); - w = bytes2word(f2(b), b, b, f3(b)); - -#if defined( SBX_SET ) - t_set(s,box)[i] = b; -#endif - -#if defined( FT1_SET ) /* tables for a normal encryption round */ - t_set(f,n)[i] = w; -#endif -#if defined( FT4_SET ) - t_set(f,n)[0][i] = w; - t_set(f,n)[1][i] = upr(w,1); - t_set(f,n)[2][i] = upr(w,2); - t_set(f,n)[3][i] = upr(w,3); -#endif - w = bytes2word(b, 0, 0, 0); - -#if defined( FL1_SET ) /* tables for last encryption round (may also */ - t_set(f,l)[i] = w; /* be used in the key schedule) */ -#endif -#if defined( FL4_SET ) - t_set(f,l)[0][i] = w; - t_set(f,l)[1][i] = upr(w,1); - t_set(f,l)[2][i] = upr(w,2); - t_set(f,l)[3][i] = upr(w,3); -#endif - -#if defined( LS1_SET ) /* table for key schedule if t_set(f,l) above is*/ - t_set(l,s)[i] = w; /* not of the required form */ -#endif -#if defined( LS4_SET ) - t_set(l,s)[0][i] = w; - t_set(l,s)[1][i] = upr(w,1); - t_set(l,s)[2][i] = upr(w,2); - t_set(l,s)[3][i] = upr(w,3); -#endif - - b = gf_inv(inv_affine((uint_8t)i)); - w = bytes2word(fe(b), f9(b), fd(b), fb(b)); - -#if defined( IM1_SET ) /* tables for the inverse mix column operation */ - t_set(i,m)[b] = w; -#endif -#if defined( IM4_SET ) - t_set(i,m)[0][b] = w; - t_set(i,m)[1][b] = upr(w,1); - t_set(i,m)[2][b] = upr(w,2); - t_set(i,m)[3][b] = upr(w,3); -#endif - -#if defined( ISB_SET ) - t_set(i,box)[i] = b; -#endif -#if defined( IT1_SET ) /* tables for a normal decryption round */ - t_set(i,n)[i] = w; -#endif -#if defined( IT4_SET ) - t_set(i,n)[0][i] = w; - t_set(i,n)[1][i] = upr(w,1); - t_set(i,n)[2][i] = upr(w,2); - t_set(i,n)[3][i] = upr(w,3); -#endif - w = bytes2word(b, 0, 0, 0); -#if defined( IL1_SET ) /* tables for last decryption round */ - t_set(i,l)[i] = w; -#endif -#if defined( IL4_SET ) - t_set(i,l)[0][i] = w; - t_set(i,l)[1][i] = upr(w,1); - t_set(i,l)[2][i] = upr(w,2); - t_set(i,l)[3][i] = upr(w,3); -#endif - } - init = 1; - return EXIT_SUCCESS; -} - -#endif - -#if defined(__cplusplus) -} -#endif - diff --git a/jni/libzrtp/sources/cryptcommon/aestab.h b/jni/libzrtp/sources/cryptcommon/aestab.h deleted file mode 100644 index de685679d..000000000 --- a/jni/libzrtp/sources/cryptcommon/aestab.h +++ /dev/null @@ -1,173 +0,0 @@ -/* ---------------------------------------------------------------------------- -Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. - -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: - - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; - - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. - -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 - - This file contains the code for declaring the tables needed to implement - AES. The file aesopt.h is assumed to be included before this header file. - If there are no global variables, the definitions here can be used to put - the AES tables in a structure so that a pointer can then be added to the - AES context to pass them to the AES routines that need them. If this - facility is used, the calling program has to ensure that this pointer is - managed appropriately. In particular, the value of the t_dec(in,it) item - in the table structure must be set to zero in order to ensure that the - tables are initialised. In practice the three code sequences in aeskey.c - that control the calls to aes_init() and the aes_init() routine itself will - have to be changed for a specific implementation. If global variables are - available it will generally be preferable to use them with the precomputed - FIXED_TABLES option that uses static global tables. - - The following defines can be used to control the way the tables - are defined, initialised and used in embedded environments that - require special features for these purposes - - the 't_dec' construction is used to declare fixed table arrays - the 't_set' construction is used to set fixed table values - the 't_use' construction is used to access fixed table values - - 256 byte tables: - - t_xxx(s,box) => forward S box - t_xxx(i,box) => inverse S box - - 256 32-bit word OR 4 x 256 32-bit word tables: - - t_xxx(f,n) => forward normal round - t_xxx(f,l) => forward last round - t_xxx(i,n) => inverse normal round - t_xxx(i,l) => inverse last round - t_xxx(l,s) => key schedule table - t_xxx(i,m) => key schedule table - - Other variables and tables: - - t_xxx(r,c) => the rcon table -*/ - -#if !defined( _AESTAB_H ) -#define _AESTAB_H - -#if defined(__cplusplus) -extern "C" { -#endif - -#define t_dec(m,n) t_##m##n -#define t_set(m,n) t_##m##n -#define t_use(m,n) t_##m##n - -#if defined(FIXED_TABLES) -# if !defined( __GNUC__ ) && (defined( __MSDOS__ ) || defined( __WIN16__ )) -/* make tables far data to avoid using too much DGROUP space (PG) */ -# define CONST const far -# else -# define CONST const -# endif -#else -# define CONST -#endif - -#if defined(DO_TABLES) -# define EXTERN -#else -# define EXTERN extern -#endif - -#if defined(_MSC_VER) && defined(TABLE_ALIGN) -#define ALIGN __declspec(align(TABLE_ALIGN)) -#else -#define ALIGN -#endif - -#if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) -# define XP_DIR __cdecl -#else -# define XP_DIR -#endif - -#if defined(DO_TABLES) && defined(FIXED_TABLES) -#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] = b(e) -#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) } -EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH] = rc_data(w0); -#else -#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] -#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] -EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH]; -#endif - -#if defined( SBX_SET ) - d_1(uint_8t, t_dec(s,box), sb_data, h0); -#endif -#if defined( ISB_SET ) - d_1(uint_8t, t_dec(i,box), isb_data, h0); -#endif - -#if defined( FT1_SET ) - d_1(uint_32t, t_dec(f,n), sb_data, u0); -#endif -#if defined( FT4_SET ) - d_4(uint_32t, t_dec(f,n), sb_data, u0, u1, u2, u3); -#endif - -#if defined( FL1_SET ) - d_1(uint_32t, t_dec(f,l), sb_data, w0); -#endif -#if defined( FL4_SET ) - d_4(uint_32t, t_dec(f,l), sb_data, w0, w1, w2, w3); -#endif - -#if defined( IT1_SET ) - d_1(uint_32t, t_dec(i,n), isb_data, v0); -#endif -#if defined( IT4_SET ) - d_4(uint_32t, t_dec(i,n), isb_data, v0, v1, v2, v3); -#endif - -#if defined( IL1_SET ) - d_1(uint_32t, t_dec(i,l), isb_data, w0); -#endif -#if defined( IL4_SET ) - d_4(uint_32t, t_dec(i,l), isb_data, w0, w1, w2, w3); -#endif - -#if defined( LS1_SET ) -#if defined( FL1_SET ) -#undef LS1_SET -#else - d_1(uint_32t, t_dec(l,s), sb_data, w0); -#endif -#endif - -#if defined( LS4_SET ) -#if defined( FL4_SET ) -#undef LS4_SET -#else - d_4(uint_32t, t_dec(l,s), sb_data, w0, w1, w2, w3); -#endif -#endif - -#if defined( IM1_SET ) - d_1(uint_32t, t_dec(i,m), mm_data, v0); -#endif -#if defined( IM4_SET ) - d_4(uint_32t, t_dec(i,m), mm_data, v0, v1, v2, v3); -#endif - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/jni/libzrtp/sources/demo/CMakeLists.txt b/jni/libzrtp/sources/demo/CMakeLists.txt index c253d9fcc..8db3c630a 100755 --- a/jni/libzrtp/sources/demo/CMakeLists.txt +++ b/jni/libzrtp/sources/demo/CMakeLists.txt @@ -1,27 +1,15 @@ +########### next target ############### -#to make sure includes are first taken - it contains config.h -include_directories(BEFORE ${CMAKE_BINARY_DIR}) -include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR}/zrtp - ${CMAKE_SOURCE_DIR}/clients/ccrtp) - -if (CCRTP) - ########### next target ############### +add_executable(zrtptest zrtptest.cpp) +target_link_libraries(zrtptest zrtpcpp) +add_dependencies(zrtptest zrtpcpp) - add_executable(zrtptest zrtptest.cpp) - target_link_libraries(zrtptest ${zrtplibName}) - add_dependencies(zrtptest ${zrtplibName}) +########### next target ############### - ########### next target ############### +add_executable(zrtptestMulti zrtptestMulti.cpp) +target_link_libraries(zrtptestMulti zrtpcpp) +add_dependencies(zrtptestMulti zrtpcpp) - add_executable(zrtptestMulti zrtptestMulti.cpp) - target_link_libraries(zrtptestMulti ${zrtplibName}) - add_dependencies(zrtptestMulti ${zrtplibName}) -else() - add_executable(sdestest sdestest.cpp) - target_link_libraries(sdestest ${zrtplibName}) - add_dependencies(sdestest ${zrtplibName}) -endif() ########### next target ############### #add_executable(wrappertest wrappertest.c) diff --git a/jni/libzrtp/sources/demo/sdestest.cpp b/jni/libzrtp/sources/demo/sdestest.cpp deleted file mode 100644 index a329e8d52..000000000 --- a/jni/libzrtp/sources/demo/sdestest.cpp +++ /dev/null @@ -1,231 +0,0 @@ -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <crypto/hmac256.h> - -/* -HKDF-Expand(PRK, info, L) - -Description in RFC 5869 - - HKDF-Expand(PRK, info, L) -> OKM - - Options: - Hash a hash function; HashLen denotes the length of the - hash function output in octets - Inputs: - PRK a pseudorandom key of at least HashLen octets - (usually, the output from the extract step) - info optional context and application specific information - (can be a zero-length string) - L length of output keying material in octets - (<= 255*HashLen) - - Output: - OKM output keying material (of L octets) - - The output OKM is calculated as follows: - - N = ceil(L/HashLen) - T = T(1) | T(2) | T(3) | ... | T(N) - OKM = first L octets of T - - where: - T(0) = empty string (zero length) - T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) - T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) - T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) - ... - - (where the constant concatenated to the end of each T(n) is a - single octet.) - - - A.1. Test Case 1 - - Basic test case with SHA-256 - - Hash = SHA-256 - IKM = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets) - salt = 0x000102030405060708090a0b0c (13 octets) - info = 0xf0f1f2f3f4f5f6f7f8f9 (10 octets) - L = 42 - - PRK = 0x077709362c2e32df0ddc3f0dc47bba63 - 90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets) - OKM = 0x3cb25f25faacd57a90434f64d0362f2a - 2d2d0a90cf1a5a4c5db02d56ecc4c5bf - 34007208d5b887185865 (42 octets) - -A.2. Test Case 2 - - Test with SHA-256 and longer inputs/outputs - - Hash = SHA-256 - IKM = 0x000102030405060708090a0b0c0d0e0f - 101112131415161718191a1b1c1d1e1f - 202122232425262728292a2b2c2d2e2f - 303132333435363738393a3b3c3d3e3f - 404142434445464748494a4b4c4d4e4f (80 octets) - salt = 0x606162636465666768696a6b6c6d6e6f - 707172737475767778797a7b7c7d7e7f - 808182838485868788898a8b8c8d8e8f - 909192939495969798999a9b9c9d9e9f - a0a1a2a3a4a5a6a7a8a9aaabacadaeaf (80 octets) - info = 0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf - c0c1c2c3c4c5c6c7c8c9cacbcccdcecf - d0d1d2d3d4d5d6d7d8d9dadbdcdddedf - e0e1e2e3e4e5e6e7e8e9eaebecedeeef - f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff (80 octets) - L = 82 - - PRK = 0x06a6b88c5853361a06104c9ceb35b45c - ef760014904671014a193f40c15fc244 (32 octets) - OKM = 0xb11e398dc80327a1c8e7f78c596a4934 - 4f012eda2d4efad8a050cc4c19afa97c - 59045a99cac7827271cb41c65e590e09 - da3275600c2f09b8367793a9aca3db71 - cc30c58179ec3e87c14c01d5c1f3434f - 1d87 (82 octets) - -A.3. Test Case 3 - - Test with SHA-256 and zero-length salt/info - - Hash = SHA-256 - IKM = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets) - salt = (0 octets) - info = (0 octets) - L = 42 - - PRK = 0x19ef24a32c717b167f33a91d6f648bdf - 96596776afdb6377ac434c1c293ccb04 (32 octets) - OKM = 0x8da4e775a563c18f715f802a063c5a31 - b8a11f5c5ee1879ec3454e5f3c738d2d - 9d201395faa4b61a96c8 (42 octets) - -*/ - -static void hexdump(const char* title, const unsigned char *s, int l) -{ - int n=0; - - if (s == NULL) return; - - fprintf(stderr, "%s",title); - for( ; n < l ; ++n) { - if((n%16) == 0) - fprintf(stderr, "\n%04x",n); - fprintf(stderr, " %02x",s[n]); - } - fprintf(stderr, "\n"); -} - - -static uint8_t info_A1[] = { - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9}; - -static int32_t L_A1 = 42; - -static uint8_t PRK_A1[] = { - 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, - 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}; - -static uint8_t OKM_A1[] = { - 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, - 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, - 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65}; // (42 octets) - - -static int32_t L_A3 = 42; - -static uint8_t PRK_A3[] = { - 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, - 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}; // (32 octets) - -static uint8_t OKM_A3[] = { - 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, - 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, - 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8}; // (42 octets) - - - -void* createSha256HmacContext(uint8_t* key, int32_t keyLength); -void freeSha256HmacContext(void* ctx); -void hmacSha256Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], uint8_t* mac, int32_t* macLength ); - - -static int expand(uint8_t* prk, uint32_t prkLen, uint8_t* info, int32_t infoLen, int32_t L, uint32_t hashLen, uint8_t* outbuffer) -{ - int32_t n; - uint8_t *T; - void* hmacCtx; - - const uint8_t* data[4]; // Data pointers for HMAC data, max. 3 plus terminating NULL - uint32_t dataLen[4]; - int32_t dataIdx = 0; - - uint8_t counter; - int32_t macLength; - - if (prkLen < hashLen) - return -1; - - n = (L + (hashLen-1)) / hashLen; - - // T points to buffer that holds concatenated T(1) || T(2) || ... T(N)) - T = reinterpret_cast<uint8_t*>(malloc(n * hashLen)); - - // Prepare the HMAC - hmacCtx = createSha256HmacContext(prk, prkLen); - - // Prepare first HMAC. T(0) has zero length, thus we ignore it in first run. - // After first run use its output (T(1)) as first data in next HMAC run. - for (int i = 1; i <= n; i++) { - if (infoLen > 0 && info != NULL) { - data[dataIdx] = info; - dataLen[dataIdx++] = infoLen; - } - counter = i & 0xff; - data[dataIdx] = &counter; - dataLen[dataIdx++] = 1; - - data[dataIdx] = NULL; - dataLen[dataIdx++] = 0; - - hmacSha256Ctx(hmacCtx, data, dataLen, T + ((i-1) * hashLen), &macLength); - - dataIdx = 0; - data[dataIdx] = T + ((i-1) * hashLen); - dataLen[dataIdx++] = hashLen; - } - freeSha256HmacContext(hmacCtx); - memcpy(outbuffer, T, L); - free(T); - return 0; -} - -int main(int argc, char *argv[]) -{ - uint8_t buffer[500]; - expand(PRK_A1, sizeof(PRK_A1), info_A1, sizeof(info_A1), L_A1, SHA256_DIGEST_LENGTH, buffer); - if (memcmp(buffer, OKM_A1, L_A1) != 0) { - fprintf(stderr, "ERROR: Test result A1 mismatch"); - hexdump("Computed result of expand A1", buffer, L_A1); - hexdump("Expected result of expand A1", OKM_A1, L_A1); - return 1; - } - - expand(PRK_A3, sizeof(PRK_A3), NULL, 0, L_A3, SHA256_DIGEST_LENGTH, buffer); - if (memcmp(buffer, OKM_A3, L_A3) != 0) { - fprintf(stderr, "ERROR: Test result A3 mismatch"); - hexdump("Computed result of expand A3", buffer, L_A3); - hexdump("Expected result of expand A3", OKM_A3, L_A3); - return 1; - } - - printf("Done\n"); - return 0; -} diff --git a/jni/libzrtp/sources/demo/zrtptest.cpp b/jni/libzrtp/sources/demo/zrtptest.cpp index 0595543f0..394d31c9d 100644 --- a/jni/libzrtp/sources/demo/zrtptest.cpp +++ b/jni/libzrtp/sources/demo/zrtptest.cpp @@ -18,7 +18,7 @@ #include <cstdlib> #include <map> -#include <zrtpccrtp.h> +#include <libzrtpcpp/zrtpccrtp.h> #include <libzrtpcpp/ZrtpUserCallback.h> using namespace ost; @@ -28,36 +28,40 @@ using namespace GnuZrtpCodes; class PacketsPattern { public: - inline const InetHostAddress& getReceiverAddress() const { return *receiverAddress; } - inline const InetHostAddress& getSenderAddress() const { return *senderAddress; } + inline const InetHostAddress& + getDestinationAddress() const + { return destinationAddress; } - inline void setReceiverAddress(InetHostAddress *addr) const { delete receiverAddress; receiverAddress = addr; } - inline void setSenderAddress(InetHostAddress *addr) const { delete senderAddress; senderAddress = addr; } + inline const tpport_t + getDestinationPort() const + { return destinationPort; } - inline const tpport_t getReceiverPort() const { return receiverPort; } - inline const tpport_t getSenderPort() const { return senderPort; } + uint32 + getPacketsNumber() const + { return packetsNumber; } - uint32 getPacketsNumber() const { return packetsNumber; } + uint32 + getSsrc() const + { return 0xdeadbeef; } - uint32 getSsrc() const { return 0xdeadbeef; } + const unsigned char* + getPacketData(uint32 i) + { return data[i%2]; } - const unsigned char*getPacketData(uint32 i) { return data[i%2]; } - - const size_t getPacketSize(uint32 i) { return strlen((char*)data[i%2]) + 1 ; } + const size_t + getPacketSize(uint32 i) + { return strlen((char*)data[i%2]) + 1 ; } private: - static const InetHostAddress *receiverAddress; - static const InetHostAddress *senderAddress; - - static const uint16 receiverPort = 5002; - static const uint16 senderPort = 5004; + static const InetHostAddress destinationAddress; + static const uint16 destinationPort = 5002; static const uint32 packetsNumber = 10; static const uint32 packetsSize = 12; static const unsigned char* data[]; }; -const InetHostAddress *PacketsPattern::receiverAddress = new InetHostAddress("localhost"); -const InetHostAddress *PacketsPattern::senderAddress = new InetHostAddress("localhost"); +const InetHostAddress PacketsPattern::destinationAddress = + InetHostAddress("localhost"); const unsigned char* PacketsPattern::data[] = { (unsigned char*)"0123456789\n", @@ -111,13 +115,6 @@ public: }; -/* - * The following classes use: - * - localAddress and destination port+2 for the sender classes - * - destinationAddress and destination port for the receiver classes. - * - */ - /** * SymmetricZRTPSession in non-security mode (RTPSession compatible). * @@ -135,7 +132,7 @@ public: int doTest() { // should be valid? //RTPSession tx(); - ExtZrtpSession tx(pattern.getSsrc(), pattern.getSenderAddress(), pattern.getSenderPort()); + ExtZrtpSession tx(pattern.getSsrc(), InetHostAddress("localhost")); // SymmetricZRTPSession tx(pattern.getSsrc(), InetHostAddress("localhost")); tx.setSchedulingTimeout(10000); tx.setExpireTimeout(1000000); @@ -143,9 +140,8 @@ public: tx.startRunning(); tx.setPayloadFormat(StaticPayloadFormat(sptPCMU)); - - // We are sender: - if (!tx.addDestination(pattern.getReceiverAddress(), pattern.getReceiverPort()) ) { + if (!tx.addDestination(pattern.getDestinationAddress(), + pattern.getDestinationPort()) ) { return 1; } @@ -178,7 +174,8 @@ public: int doTest() { - ExtZrtpSession rx(pattern.getSsrc()+1, pattern.getReceiverAddress(), pattern.getReceiverPort()); + ExtZrtpSession rx(pattern.getSsrc()+1, pattern.getDestinationAddress(), + pattern.getDestinationPort()); // SymmetricZRTPSession rx(pattern.getSsrc()+1, pattern.getDestinationAddress(), // pattern.getDestinationPort()); @@ -188,7 +185,8 @@ public: rx.startRunning(); rx.setPayloadFormat(StaticPayloadFormat(sptPCMU)); // arbitrary number of loops to provide time to start transmitter - if (!rx.addDestination(pattern.getSenderAddress(), pattern.getSenderPort()) ) { + if (!rx.addDestination(pattern.getDestinationAddress(), + pattern.getDestinationPort()+2) ) { return 1; } for ( int i = 0; i < 5000 ; i++ ) { @@ -227,8 +225,8 @@ public: int doTest() { // should be valid? //RTPSession tx(); - // Initialize with local address and Local port is detination port +2 - keep RTP/RTCP port pairs - ExtZrtpSession tx(pattern.getSsrc(), pattern.getSenderAddress(), pattern.getSenderPort()); + ExtZrtpSession tx(pattern.getSsrc(), pattern.getDestinationAddress(), + pattern.getDestinationPort()+2); tx.initialize("test_t.zid"); tx.setSchedulingTimeout(10000); @@ -237,7 +235,8 @@ public: tx.startRunning(); tx.setPayloadFormat(StaticPayloadFormat(sptPCMU)); - if (!tx.addDestination(pattern.getReceiverAddress(), pattern.getReceiverPort()) ) { + if (!tx.addDestination(pattern.getDestinationAddress(), + pattern.getDestinationPort()) ) { return 1; } tx.startZrtp(); @@ -269,7 +268,8 @@ public: int doTest() { - ExtZrtpSession rx(pattern.getSsrc()+1, pattern.getReceiverAddress(), pattern.getReceiverPort()); + ExtZrtpSession rx(pattern.getSsrc()+1, pattern.getDestinationAddress(), + pattern.getDestinationPort()); rx.initialize("test_r.zid"); @@ -279,7 +279,8 @@ public: rx.startRunning(); rx.setPayloadFormat(StaticPayloadFormat(sptPCMU)); // arbitrary number of loops to provide time to start transmitter - if (!rx.addDestination(pattern.getSenderAddress(), pattern.getSenderPort()) ) { + if (!rx.addDestination(pattern.getDestinationAddress(), + pattern.getDestinationPort()+2) ) { return 1; } rx.startZrtp(); @@ -344,8 +345,6 @@ class MyUserCallback: public ZrtpUserCallback { warningMap.insert(pair<int32, std::string*>(WarningCRCmismatch, new string("Internal ZRTP packet checksum mismatch - packet dropped"))); warningMap.insert(pair<int32, std::string*>(WarningSRTPauthError, new string("Dropping packet because SRTP authentication failed!"))); warningMap.insert(pair<int32, std::string*>(WarningSRTPreplayError, new string("Dropping packet because SRTP replay check failed!"))); - warningMap.insert(pair<int32, std::string*>(WarningNoExpectedRSMatch, new string("No RS match found - but ZRTP expected a match."))); - warningMap.insert(pair<int32, std::string*>(WarningNoExpectedAuxMatch, new string("The auxlliary secrets do not match."))); severeMap.insert(pair<int32, std::string*>(SevereHelloHMACFailed, new string("Hash HMAC check of Hello failed!"))); severeMap.insert(pair<int32, std::string*>(SevereCommitHMACFailed, new string("Hash HMAC check of Commit failed!"))); @@ -451,8 +450,6 @@ map<int32, std::string*>MyUserCallback::zrtpMap; bool MyUserCallback::initialized = false; -static unsigned char transmAuxSecret[] = {1,2,3,4,5,6,7,8,9,0}; - /** * SymmetricZRTPSession in security mode and using a callback class. * @@ -468,55 +465,26 @@ class ZrtpSendPacketTransmissionTestCB : public Thread, public TimerPort { public: - - ZrtpConfigure config; - - void run() { + void + run() + { doTest(); } - int doTest() { + int doTest() + { // should be valid? //RTPSession tx(); - ExtZrtpSession tx(/*pattern.getSsrc(),*/ pattern.getSenderAddress(), pattern.getSenderPort()); - config.clear(); -// config.setStandardConfig(); -// config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("DH2k")); -// config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("DH3k")); - - // This ordering prefers NIST - config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("EC38")); - config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("E414")); - - config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("EC25")); - config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("E255")); - - config.addAlgo(HashAlgorithm, zrtpHashes.getByName("S384")); - config.addAlgo(HashAlgorithm, zrtpHashes.getByName("SKN3")); - - config.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName("AES3")); - config.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName("2FS3")); - - config.addAlgo(SasType, zrtpSasTypes.getByName("B256")); - - config.addAlgo(AuthLength, zrtpAuthLengths.getByName("HS32")); - config.addAlgo(AuthLength, zrtpAuthLengths.getByName("HS80")); - config.addAlgo(AuthLength, zrtpAuthLengths.getByName("SK32")); - config.addAlgo(AuthLength, zrtpAuthLengths.getByName("SK64")); - - tx.initialize("test_t.zid", true, &config); + ExtZrtpSession tx(/*pattern.getSsrc(),*/ pattern.getDestinationAddress(), + pattern.getDestinationPort()+2); + tx.initialize("test_t.zid"); // At this point the Hello hash is available. See ZRTP specification // chapter 9.1 for further information when an how to use the Hello // hash. - int numSupportedVersion = tx.getNumberSupportedVersions(); - cout << "TX Hello hash 0: " << tx.getHelloHash(0) << endl; - cout << "TX Hello hash 0 length: " << tx.getHelloHash(0).length() << endl; - if (numSupportedVersion > 1) { - cout << "TX Hello hash 1: " << tx.getHelloHash(1) << endl; - cout << "TX Hello hash 1 length: " << tx.getHelloHash(1).length() << endl; - } + cout << "TX Hello hash: " << tx.getHelloHash() << endl; + cout << "TX Hello hash length: " << tx.getHelloHash().length() << endl; + tx.setUserCallback(new MyUserCallback(&tx)); - tx.setAuxSecret(transmAuxSecret, sizeof(transmAuxSecret)); tx.setSchedulingTimeout(10000); tx.setExpireTimeout(1000000); @@ -524,8 +492,8 @@ public: tx.startRunning(); tx.setPayloadFormat(StaticPayloadFormat(sptPCMU)); - - if (!tx.addDestination(pattern.getReceiverAddress(), pattern.getReceiverPort()) ) { + if (!tx.addDestination(pattern.getDestinationAddress(), + pattern.getDestinationPort()) ) { return 1; } tx.startZrtp(); @@ -549,49 +517,29 @@ public: } }; -static unsigned char recvAuxSecret[] = {1,2,3,4,5,6,7,8,9,9}; class ZrtpRecvPacketTransmissionTestCB: public Thread { public: - ZrtpConfigure config; - - void run() { + void + run() { doTest(); } - int doTest() { - ExtZrtpSession rx( /*pattern.getSsrc()+1,*/ pattern.getReceiverAddress(), pattern.getReceiverPort()); - config.clear(); -// config.setStandardConfig(); -// config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("DH3k")); - - config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("E414")); - config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("EC38")); - - config.addAlgo(HashAlgorithm, zrtpHashes.getByName("S384")); - config.addAlgo(HashAlgorithm, zrtpHashes.getByName("SKN3")); - -// config.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName("2FS3")); -// config.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName("AES3")); - - config.addAlgo(SasType, zrtpSasTypes.getByName("B256")); - + int + doTest() { + ExtZrtpSession rx( /*pattern.getSsrc()+1,*/ pattern.getDestinationAddress(), + pattern.getDestinationPort()); - rx.initialize("test_r.zid", true, &config); + rx.initialize("test_r.zid"); // At this point the Hello hash is available. See ZRTP specification // chapter 9.1 for further information when an how to use the Hello // hash. - int numSupportedVersion = rx.getNumberSupportedVersions(); - cout << "RX Hello hash 0: " << rx.getHelloHash(0) << endl; - cout << "RX Hello hash 0 length: " << rx.getHelloHash(0).length() << endl; - if (numSupportedVersion > 1) { - cout << "RX Hello hash 1: " << rx.getHelloHash(1) << endl; - cout << "RX Hello hash 1 length: " << rx.getHelloHash(1).length() << endl; - } + cout << "RX Hello hash: " << rx.getHelloHash() << endl; + cout << "RX Hello hash length: " << rx.getHelloHash().length() << endl; + rx.setUserCallback(new MyUserCallback(&rx)); - rx.setAuxSecret(recvAuxSecret, sizeof(recvAuxSecret)); rx.setSchedulingTimeout(10000); rx.setExpireTimeout(1000000); @@ -599,7 +547,8 @@ public: rx.startRunning(); rx.setPayloadFormat(StaticPayloadFormat(sptPCMU)); // arbitrary number of loops to provide time to start transmitter - if (!rx.addDestination(pattern.getSenderAddress(), pattern.getSenderPort()) ) { + if (!rx.addDestination(pattern.getDestinationAddress(), + pattern.getDestinationPort()+2) ) { return 1; } rx.startZrtp(); @@ -631,7 +580,7 @@ int main(int argc, char *argv[]) /* check args */ while (1) { - c = getopt(argc, argv, "rsR:S:"); + c = getopt(argc, argv, "rs"); if (c == -1) { break; } @@ -642,12 +591,6 @@ int main(int argc, char *argv[]) case 's': send = true; break; - case 'R': - pattern.setReceiverAddress(new InetHostAddress(optarg)); - break; - case 'S': - pattern.setSenderAddress(new InetHostAddress(optarg)); - break; default: cerr << "Wrong Arguments, only -s and -r are accepted" << endl; } diff --git a/jni/libzrtp/sources/demo/zrtptestMulti.cpp b/jni/libzrtp/sources/demo/zrtptestMulti.cpp index d7042ed0b..39e20a796 100644 --- a/jni/libzrtp/sources/demo/zrtptestMulti.cpp +++ b/jni/libzrtp/sources/demo/zrtptestMulti.cpp @@ -18,7 +18,7 @@ #include <cstdlib> #include <map> -#include <zrtpccrtp.h> +#include <libzrtpcpp/zrtpccrtp.h> #include <libzrtpcpp/ZrtpUserCallback.h> #include <libzrtpcpp/ZrtpConfigure.h> @@ -488,8 +488,7 @@ int ZrtpSendPacketTransmissionTestCB::doTest() { if (!multiParams.empty()) { tx = new SymmetricZRTPSession(pattern.getDestinationAddress(), pattern.getDestinationPort()+2+10); - - // tx->initialize("test_t.zid", true, &config); +// tx->initialize("test_t.zid", true, &config); tx->initialize("test_t.zid", true); tx->setMultiStrParams(multiParams); @@ -500,12 +499,13 @@ int ZrtpSendPacketTransmissionTestCB::doTest() { else { tx = new SymmetricZRTPSession(pattern.getDestinationAddress(), pattern.getDestinationPort()+2); + //config.addHashAlgo(Sha384); +// tx->initialize("test_t.zid", true, &config); if (mitm) { // Act as trusted MitM - could be enrolled tx->setMitmMode(true); } tx->setSignSas(signsas); -// tx->initialize("test_t.zid", true, &config); tx->initialize("test_t.zid", true); if (enroll) // act as PBX enrollement service @@ -518,13 +518,8 @@ int ZrtpSendPacketTransmissionTestCB::doTest() { // At this point the Hello hash is available. See ZRTP specification // chapter 9.1 for further information when an how to use the Hello // hash. - int numSupportedVersion = tx->getNumberSupportedVersions(); - cout << "TX Hello hash 0: " << tx->getHelloHash(0) << endl; - cout << "TX Hello hash 0 length: " << tx->getHelloHash(0).length() << endl; - if (numSupportedVersion > 1) { - cout << "TX Hello hash 1: " << tx->getHelloHash(1) << endl; - cout << "TX Hello hash 1 length: " << tx->getHelloHash(1).length() << endl; - } + cout << prefix << "Hello hash: " << tx->getHelloHash() << endl; + cout << prefix << "Hello hash length: " << tx->getHelloHash().length() << endl; tx->setUserCallback(mcb); tx->setSchedulingTimeout(10000); tx->setExpireTimeout(1000000); @@ -588,14 +583,12 @@ int ZrtpRecvPacketTransmissionTestCB::doTest() { rx = new SymmetricZRTPSession(pattern.getDestinationAddress(), pattern.getDestinationPort()); config.setStandardConfig(); -// config.clear(); -// config.addAlgo(SasType, zrtpSasTypes.getByName("B256")); - if (enroll) config.setTrustedMitM(true); // allow a trusted MitM to start enrollment process rx->setSignSas(signsas); + // config.addHashAlgo(Sha384); rx->initialize("test_r.zid", true, &config); // rx->initialize("test_r.zid", true); @@ -606,13 +599,8 @@ int ZrtpRecvPacketTransmissionTestCB::doTest() { // At this point the Hello hash is available. See ZRTP specification // chapter 9.1 for further information when an how to use the Hello // hash. - int numSupportedVersion = rx->getNumberSupportedVersions(); - cout << "RX Hello hash 0: " << rx->getHelloHash(0) << endl; - cout << "RX Hello hash 0 length: " << rx->getHelloHash(0).length() << endl; - if (numSupportedVersion > 1) { - cout << "RX Hello hash 1: " << rx->getHelloHash(1) << endl; - cout << "RX Hello hash 1 length: " << rx->getHelloHash(1).length() << endl; - } + cout << prefix << "Hello hash: " << rx->getHelloHash() << endl; + cout << prefix << "Hello hash length: " << rx->getHelloHash().length() << endl; rx->setUserCallback(mcb); rx->setSchedulingTimeout(10000); rx->setExpireTimeout(1000000); diff --git a/jni/libzrtp/sources/doc/Doxymini b/jni/libzrtp/sources/doc/Doxymini index 245ff0770..2685d6eb6 100644 --- a/jni/libzrtp/sources/doc/Doxymini +++ b/jni/libzrtp/sources/doc/Doxymini @@ -1,243 +1,211 @@ -# Doxyfile 1.7.5.1 +# Doxyfile 1.5.3 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. +# doxygen (www.doxygen.org) for a project # -# All text after a hash (#) is considered a comment and will be ignored. +# All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" "). +# Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or sequence of words) that should -# identify the project. Note that if you do not use Doxywizard you need -# to put quotes around the project name if it contains spaces. +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. -PROJECT_NAME = "ZRTP and SRTP implementation" +PROJECT_NAME = "ZRTP for ccRTP " -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = +PROJECT_NUMBER = -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = - -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = . -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" -ABBREVIATE_BRIEF = +ABBREVIATE_BRIEF = -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the # path to strip. -STRIP_FROM_PATH = +STRIP_FROM_PATH = -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = NO -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. -TAB_SIZE = 4 +TAB_SIZE = 8 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. -ALIASES = +ALIASES = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO @@ -247,542 +215,406 @@ BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields will be shown inline in the documentation -# of the scope in which they are defined (i.e. file, namespace, or group -# documentation), provided this scope is documented. If set to NO (the default), -# structs, classes, and unions are shown on a separate page (for HTML and Man -# pages) or section (for LaTeX and RTF). - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file +# If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. -EXTRACT_STATIC = YES +EXTRACT_STATIC = NO -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the +# Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES -# The ENABLED_SECTIONS tag can be used to enable conditional +# The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. -ENABLED_SECTIONS = +ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command <command> <input-file>, where <command> is the value of -# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file -# provided by doxygen. Whatever the program writes to standard output +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. The create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files -# containing the references data. This must be a list of .bib files. The -# .bib extension is automatically appended if omitted. Using this command -# requires the bibtex tool to be installed. See also -# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style -# of the bibliography can be controlled using LATEX_BIB_STYLE. - -CITE_BIB_FILES = +FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated +# The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written # to stderr. -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../zrtp \ - ../zrtp/libzrtpcpp \ - ../zrtp/crypto \ - ../srtp \ - ../srtp/crypto \ - ../clients/ccrtp +INPUT = ../src \ + ../src/libzrtpcpp \ + ../src/libzrtpcpp/crypto -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. INPUT_ENCODING = UTF-8 -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py FILE_PATTERNS = *.h -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -# Note that relative paths are relative to directory from which doxygen is run. -EXCLUDE = +EXCLUDE = -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = config.h \ macros.h \ namespace.h -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left # blank all files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = +IMAGE_PATH = -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command <filter> <input-file>, where <filter> -# is the value of the INPUT_FILTER tag, and <input-file> is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. -INPUT_FILTER = +INPUT_FILTER = -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. -FILTER_PATTERNS = +FILTER_PATTERNS = -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. - -FILTER_SOURCE_PATTERNS = - #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway SOURCE_BROWSER = NO -# Setting the INLINE_SOURCES tag to YES will include the body +# Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES @@ -790,21 +622,20 @@ REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. +# link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES @@ -813,544 +644,287 @@ VERBATIM_HEADERS = YES # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. -IGNORE_PREFIX = +IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. -HTML_OUTPUT = +HTML_OUTPUT = -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is adviced to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. - -HTML_EXTRA_FILES = +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. +HTML_HEADER = -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. -HTML_COLORSTYLE_GAMMA = 80 +HTML_FOOTER = -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! -HTML_TIMESTAMP = NO +HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = YES -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be # written to the html output directory. -CHM_FILE = +CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. -HHC_LOCATION = +HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members +# The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> -# Qt Help Project / Custom Filters</a>. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> -# Qt Help Project / Filter Attributes</a>. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. GENERATE_TREEVIEW = NO -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. - -USE_MATHJAX = NO - -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the -# mathjax.org site, so you can quickly see the result without installing -# MathJax, but it is strongly recommended to install a local copy of MathJax -# before deployment. - -MATHJAX_RELPATH = http://www.mathjax.org/mathjax - -# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension -# names that should be enabled during MathJax rendering. - -MATHJAX_EXTENSIONS = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = NO - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvantages are that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. -LATEX_OUTPUT = +LATEX_OUTPUT = -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. LATEX_CMD_NAME = latex -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, letter, legal and +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. -EXTRA_PACKAGES = +EXTRA_PACKAGES = -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! -LATEX_HEADER = - -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for -# the generated latex document. The footer should contain everything after -# the last chapter. If it is left blank doxygen will generate a -# standard footer. Notice: only use this tag if you know what you are doing! - -LATEX_FOOTER = +LATEX_HEADER = -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -# The LATEX_BIB_STYLE tag can be used to specify the style to use for the -# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See -# http://en.wikipedia.org/wiki/BibTeX for more info. - -LATEX_BIB_STYLE = plain - #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. -RTF_STYLESHEET_FILE = +RTF_STYLESHEET_FILE = -# Set optional variables used in the generation of an rtf document. +# Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. -RTF_EXTENSIONS_FILE = +RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. -MAN_OUTPUT = +MAN_OUTPUT = -# The MAN_EXTENSION tag determines the extension that is added to +# The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO @@ -1359,33 +933,33 @@ MAN_LINKS = NO # configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the # syntax of the XML files. -XML_SCHEMA = +XML_SCHEMA = -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the # syntax of the XML files. -XML_DTD = +XML_DTD = -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES @@ -1394,10 +968,10 @@ XML_PROGRAMLISTING = YES # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO @@ -1406,359 +980,319 @@ GENERATE_AUTOGEN_DEF = NO # configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. -PERLMOD_MAKEVAR_PREFIX = +PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- -# Configuration options related to the preprocessor +# Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# pointed to by INCLUDE_PATH will be searched when a #include is found. +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = . -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. -INCLUDE_FILE_PATTERNS = +INCLUDE_FILE_PATTERNS = -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = +PREDEFINED = -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition that -# overrules the definition found in the source code. +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. -EXPAND_AS_DEFINED = +EXPAND_AS_DEFINED = -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all references to function-like macros -# that are alone on a line, have an all uppercase name, and do not end with a -# semicolon, because these will confuse the parser if not removed. +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- -# Configuration::additions related to external references +# Configuration::additions related to external references #--------------------------------------------------------------------------- -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen +# If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. -TAGFILES = +TAGFILES = -# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. -GENERATE_TAGFILE = +GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES -# The PERL_PATH should be the absolute path and name of the perl script +# The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option also works with HAVE_DOT disabled, but it is recommended to -# install and use dot, since it yields more powerful graphs. +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. CLASS_DIAGRAMS = YES -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. -MSCGEN_PATH = +MSCGEN_PATH = -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -DOT_NUM_THREADS = 0 - -# By default doxygen will use the Helvetica font for all dot files that -# doxygen generates. When you want a differently looking font you can specify -# the font name using DOT_FONTNAME. You need to make sure dot is able to find -# the font, which can be done by putting it in a standard location or by setting -# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the -# directory containing the font. - -DOT_FONTNAME = Helvetica - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the Helvetica font. -# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to -# set the path where dot can find it. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES -# If set to YES, the inheritance and collaboration graphs will show the +# If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. CALL_GRAPH = NO -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. CALLER_GRAPH = NO -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will generate a graphical hierarchy of all classes instead of a textual one. +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are svg, png, jpg, or gif. -# If left blank png will be used. If you choose svg you need to set -# HTML_FILE_EXTENSION to xhtml in order to make the SVG files -# visible in IE 9+ (other browsers do not have this requirement). +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. DOT_IMAGE_FORMAT = png -# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to -# enable generation of interactive SVG images that allow zooming and panning. -# Note that this requires a modern browser other than Internet Explorer. -# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you -# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files -# visible. Older versions of IE do not have SVG support. - -INTERACTIVE_SVG = NO - -# The tag DOT_PATH can be used to specify the path where the dot tool can be +# The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. -DOT_PATH = +DOT_PATH = -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the # \dotfile command). -DOTFILE_DIRS = +DOTFILE_DIRS = -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the -# \mscfile command). - -MSCFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). DOT_TRANSPARENT = NO -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/jni/libzrtp/sources/libzrtpcpp.pc.cmake b/jni/libzrtp/sources/libzrtpcpp.pc.cmake index 655bd3064..f9f554130 100644 --- a/jni/libzrtp/sources/libzrtpcpp.pc.cmake +++ b/jni/libzrtp/sources/libzrtpcpp.pc.cmake @@ -9,7 +9,7 @@ Name: libzrtpcpp Description: GNU ZRTP core library Version: @VERSION@ Requires: @CRYPTOBACKEND@ -Libs: -L${libdir} -l@zrtplibName@ +Libs: -L${libdir} -l@zrtplib@ Cflags: -I${includedir} diff --git a/jni/libzrtp/sources/zrtp/Base32.cpp b/jni/libzrtp/sources/src/Base32.cpp similarity index 100% rename from jni/libzrtp/sources/zrtp/Base32.cpp rename to jni/libzrtp/sources/src/Base32.cpp diff --git a/jni/libzrtp/sources/src/CMakeLists.txt b/jni/libzrtp/sources/src/CMakeLists.txt new file mode 100755 index 000000000..05e57ffbc --- /dev/null +++ b/jni/libzrtp/sources/src/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required (VERSION 2.6) + +# add_subdirectory(libzrtpcpp) +# add_subdirectory(libzrtpcpp/crypto) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +set(gcrypt_src + libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp + libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp + libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp + libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp + libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp + libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp + libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp) + +set(openssl_src + libzrtpcpp/crypto/openssl/ZrtpDH.cpp + libzrtpcpp/crypto/openssl/hmac256.cpp + libzrtpcpp/crypto/openssl/sha256.cpp + libzrtpcpp/crypto/openssl/hmac384.cpp + libzrtpcpp/crypto/openssl/sha384.cpp + libzrtpcpp/crypto/openssl/AesCFB.cpp + libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp) + +if (GCRYPT_FOUND) + set(crypto_src ${gcrypt_src}) +endif() + +if (OPENSSL_FOUND) + set(crypto_src ${openssl_src}) +endif() + +if(enable_ccrtp) + set(ccrtp_src ZrtpQueue.cpp) +endif() + +set(twofish_srcs libzrtpcpp/crypto/twofish.c + libzrtpcpp/crypto/twofish_cfb.c + libzrtpcpp/crypto/TwoCFB.cpp) + +set(zrtp_src + ZrtpCallbackWrapper.cpp + ZIDFile.cpp + ZIDRecord.cpp + ZRtp.cpp + ZrtpCrc32.cpp + ZrtpPacketCommit.cpp + ZrtpPacketConf2Ack.cpp + ZrtpPacketConfirm.cpp + ZrtpPacketDHPart.cpp + ZrtpPacketGoClear.cpp + ZrtpPacketClearAck.cpp + ZrtpPacketHelloAck.cpp + ZrtpPacketHello.cpp + ZrtpPacketError.cpp + ZrtpPacketErrorAck.cpp + ZrtpPacketPingAck.cpp + ZrtpPacketPing.cpp + ZrtpPacketSASrelay.cpp + ZrtpPacketRelayAck.cpp + ZrtpStateClass.cpp + ZrtpTextData.cpp + ZrtpConfigure.cpp + ZrtpCWrapper.cpp + Base32.cpp) + +set(zrtpcpp_src ${zrtp_src} ${ccrtp_src} ${crypto_src} ${twofish_srcs}) + +if(BUILD_STATIC AND NOT BUILD_SHARED) + set(LIBRARY_BUILD_TYPE STATIC) +else() + set(LIBRARY_BUILD_TYPE SHARED) +endif() + +add_library(${zrtplib} ${LIBRARY_BUILD_TYPE} ${zrtpcpp_src}) +set_target_properties(${zrtplib} PROPERTIES VERSION ${VERSION} SOVERSION ${SOVERSION}) +target_link_libraries(${zrtplib} ${LIBS}) + +if(enable_ccrtp) + add_dependencies(${zrtplib} ccrtp) +endif() + +add_subdirectory(libzrtpcpp) + +install(TARGETS ${zrtplib} DESTINATION ${LIBDIRNAME}) + diff --git a/jni/libzrtp/sources/src/ZIDFile.cpp b/jni/libzrtp/sources/src/ZIDFile.cpp new file mode 100644 index 000000000..69b43eb38 --- /dev/null +++ b/jni/libzrtp/sources/src/ZIDFile.cpp @@ -0,0 +1,430 @@ +/* + Copyright (C) 2006-2008 Werner Dittmann + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Authors: Werner Dittmann <Werner.Dittmann@t-online.de> + */ +// #define UNIT_TEST + +#include <string> +#include <time.h> +#include <stdlib.h> +#include <unistd.h> + +#include <libzrtpcpp/ZIDFile.h> + + +static ZIDFile* instance; +static int errors = 0; // maybe we will use as member of ZIDFile later... + +void ZIDFile::createZIDFile(char* name) { + zidFile = fopen(name, "wb+"); + // New file, generate an associated random ZID and save + // it as first record + if (zidFile != NULL) { + unsigned int* ip; + ip = (unsigned int*) associatedZid; + srand(time(NULL)); + *ip++ = rand(); + *ip++ = rand(); + *ip = rand(); + + ZIDRecord rec(associatedZid); + rec.setOwnZIDRecord(); + fseek(zidFile, 0L, SEEK_SET); + if (fwrite(rec.getRecordData(), rec.getRecordLength(), 1, zidFile) < 1) + ++errors; + fflush(zidFile); + } +} + +/** + * Migrate old ZID file format to new one. + * + * If ZID file is old format: + * - close it, rename it, then re-open + * - create ZID file for new format + * - copy over contents and flags. + */ +void ZIDFile::checkDoMigration(char* name) { + FILE* fdOld; + unsigned char inb[2]; + zidrecord1_t recOld; + + fseek(zidFile, 0L, SEEK_SET); + if (fread(inb, 2, 1, zidFile) < 1) { + ++errors; + inb[0] = 0; + } + + if (inb[0] > 0) { // if it's new format just return + return; + } + fclose(zidFile); // close old ZID file + zidFile = NULL; + + // create save file name, rename and re-open + // if rename fails, just unlink old ZID file and create a brand new file + // just a little inconvenience for the user, need to verify new SAS + std::string fn = std::string(name) + std::string(".save"); + if (rename(name, fn.c_str()) < 0) { + unlink(name); + createZIDFile(name); + return; + } + fdOld = fopen(fn.c_str(), "rb"); // reopen old format in read only mode + + // Get first record from old file - is the own ZID + fseek(fdOld, 0L, SEEK_SET); + if (fread(&recOld, sizeof(zidrecord1_t), 1, fdOld) != 1) { + fclose(fdOld); + return; + } + if (recOld.ownZid != 1) { + fclose(fdOld); + return; + } + zidFile = fopen(name, "wb+"); // create new format file in binary r/w mode + if (zidFile == NULL) { + return; + } + // create ZIDRecord in new format, copy over own ZID and write the record + ZIDRecord rec(recOld.identifier); + rec.setOwnZIDRecord(); + if (fwrite(rec.getRecordData(), rec.getRecordLength(), 1, zidFile) < 1) + ++errors; + + // now copy over all valid records from old ZID file format. + // Sequentially read old records, sequentially write new records + int numRead; + do { + numRead = fread(&recOld, sizeof(zidrecord1_t), 1, fdOld); + if (numRead == 0) { // all old records processed + break; + } + // skip own ZID record and invalid records + if (recOld.ownZid == 1 || recOld.recValid == 0) { + continue; + } + ZIDRecord rec2(recOld.identifier); + rec2.setValid(); + if (recOld.rs1Valid & SASVerified) { + rec2.setSasVerified(); + } + rec2.setNewRs1(recOld.rs2Data); + rec2.setNewRs1(recOld.rs1Data); + if (fwrite(rec2.getRecordData(), rec2.getRecordLength(), 1, zidFile) < 1) + ++errors; + + } while (numRead == 1); + fflush(zidFile); +} + +ZIDFile::~ZIDFile() { + close(); +} + +ZIDFile* ZIDFile::getInstance() { + + if (instance == NULL) { + instance = new ZIDFile(); + } + return instance; +} + +int ZIDFile::open(char* name) { + + // check for an already active ZID file + if (zidFile != NULL) { + return 0; + } + if ((zidFile = fopen(name, "rb+")) == NULL) { + createZIDFile(name); + } else { + checkDoMigration(name); + if (zidFile != NULL) { + ZIDRecord rec; + fseek(zidFile, 0L, SEEK_SET); + if (fread(rec.getRecordData(), rec.getRecordLength(), 1, zidFile) != 1) { + fclose(zidFile); + zidFile = NULL; + return -1; + } + if (!rec.isOwnZIDRecord()) { + fclose(zidFile); + zidFile = NULL; + return -1; + } + memcpy(associatedZid, rec.getIdentifier(), IDENTIFIER_LEN); + } + } + return ((zidFile == NULL) ? -1 : 1); +} + +void ZIDFile::close() { + + if (zidFile != NULL) { + fclose(zidFile); + zidFile = NULL; + } +} + +unsigned int ZIDFile::getRecord(ZIDRecord* zidRecord) { + unsigned long pos; + ZIDRecord rec; + int numRead; + + // set read pointer behind first record ( + fseek(zidFile, rec.getRecordLength(), SEEK_SET); + + do { + pos = ftell(zidFile); + numRead = fread(rec.getRecordData(), rec.getRecordLength(), 1, zidFile); + if (numRead == 0) { + break; + } + + // skip own ZID record and invalid records + if (rec.isOwnZIDRecord() || !rec.isValid()) { + continue; + } + + } while (numRead == 1 && + memcmp(zidRecord->getIdentifier(), rec.getIdentifier(), IDENTIFIER_LEN) != 0); + + // If we reached end of file, then no record with the ZID + // found. We need to create a new ZID record. + if (numRead == 0) { + // create new record + ZIDRecord rec1(zidRecord->getIdentifier()); + rec1.setValid(); + if (fwrite(rec1.getRecordData(), rec1.getRecordLength(), 1, zidFile) < 1) + ++errors; + memcpy(zidRecord->getRecordData(), rec1.getRecordData(), rec1.getRecordLength()); + } else { + // Copy the read data into caller's the record storage + memcpy(zidRecord->getRecordData(), rec.getRecordData(), rec.getRecordLength()); + } + + // remember position of record in file for save operation + zidRecord->setPosition(pos); + return 1; +} + +unsigned int ZIDFile::saveRecord(ZIDRecord *zidRecord) { + + fseek(zidFile, zidRecord->getPosition(), SEEK_SET); + if (fwrite(zidRecord->getRecordData(), zidRecord->getRecordLength(), 1, zidFile) < 1) + ++errors; + fflush(zidFile); + return 1; +} + + +#ifdef UNIT_TEST + +#include <iostream> +#include <unistd.h> +using namespace std; + +static void hexdump(const char* title, const unsigned char *s, int l) { + int n=0; + + if (s == NULL) return; + + fprintf(stderr, "%s",title); + for (; n < l ; ++n) { + if ((n%16) == 0) + fprintf(stderr, "\n%04x",n); + fprintf(stderr, " %02x",s[n]); + } + fprintf(stderr, "\n"); +} + +int main(int argc, char *argv[]) { + + unsigned char myId[IDENTIFIER_LEN]; + ZIDFile *zid = ZIDFile::getInstance(); + + unlink("testzid2"); + zid->open("testzid2"); + hexdump("My ZID: ", zid->getZid(), IDENTIFIER_LEN); + memcpy(myId, zid->getZid(), IDENTIFIER_LEN); + zid->close(); + + zid->open("testzid2"); + if (memcmp(myId, zid->getZid(), IDENTIFIER_LEN) != 0) { + cerr << "Wrong ZID in testfile" << endl; + return 1; + } + + // Create a new ZID record for peer ZID "123456789012" + ZIDRecord zr3((unsigned char*) "123456789012"); + zid->getRecord(&zr3); + if (!zr3.isValid()) { + cerr << "New ZID record '123456789012' not set to valid" << endl; + return 1; + } + zid->saveRecord(&zr3); + + // create a second record with peer ZID "210987654321" + ZIDRecord zr4((unsigned char*) "210987654321"); + zid->getRecord(&zr4); + if (!zr4.isValid()) { + cerr << "New ZID record '210987654321' not set to valid" << endl; + return 1; + } + zid->saveRecord(&zr4); + + // now set a first RS1 with default expiration interval, check + // if set correctly, valid flag and expiration interval + zr3.setNewRs1((unsigned char*) "11122233344455566677788899900012"); + if (memcmp(zr3.getRs1(), "11122233344455566677788899900012", RS_LENGTH) != 0) { + cerr << "RS1 was not set (111...012)" << endl; + return 1; + } + if (!zr3.isRs1Valid()) { + cerr << "RS1 was not set to valid state (111...012)" << endl; + return 1; + } + if (!zr3.isRs1NotExpired()) { + cerr << "RS1 expired (111...012)" << endl; + return 1; + } + if (zr3.isRs2Valid()) { + cerr << "RS2 was set to valid state (111...012)" << endl; + return 1; + } + zid->saveRecord(&zr3); + + // create a second RS1, RS2 will become the first RS1, check + // if set correctly, valid flag and expiration interval for both + // RS1 and RS2 + zr3.setNewRs1((unsigned char*) "00099988877766655544433322211121"); + if (memcmp(zr3.getRs1(), "00099988877766655544433322211121", RS_LENGTH) != 0) { + cerr << "RS1 was not set (000...121)" << endl; + return 1; + } + if (!zr3.isRs1Valid()) { + cerr << "RS1 was not set to valid state (000...121)" << endl; + return 1; + } + if (!zr3.isRs1NotExpired()) { + cerr << "RS1 expired (000...121)" << endl; + return 1; + } + if (memcmp(zr3.getRs2(), "11122233344455566677788899900012", RS_LENGTH) != 0) { + cerr << "RS2 was not set (111...012)" << endl; + return 1; + } + if (!zr3.isRs2Valid()) { + cerr << "RS2 was not set to valid state (111...012)" << endl; + return 1; + } + if (!zr3.isRs2NotExpired()) { + cerr << "RS2 expired (111...012)" << endl; + return 1; + } + zid->saveRecord(&zr3); + + zid->close(); + + // Reopen, check if first record is still valid, RSx vaild and + // not expired. Then manipulate 2nd record. + zid->open("testzid2"); + + ZIDRecord zr3a((unsigned char*) "123456789012"); + zid->getRecord(&zr3a); + if (!zr3a.isValid()) { + cerr << "Re-read ZID record '123456789012' not set to valid" << endl; + return 1; + } + if (memcmp(zr3a.getRs1(), "00099988877766655544433322211121", RS_LENGTH) != 0) { + cerr << "re-read RS1 was not set (000...121)" << endl; + return 1; + } + if (!zr3a.isRs1Valid()) { + cerr << "Re-read RS1 was not set to valid state (000...121)" << endl; + return 1; + } + if (!zr3a.isRs1NotExpired()) { + cerr << "re-read RS1 expired (000...121)" << endl; + return 1; + } + if (memcmp(zr3a.getRs2(), "11122233344455566677788899900012", RS_LENGTH) != 0) { + cerr << "re-read RS2 was not set (111...012)" << endl; + return 1; + } + if (!zr3a.isRs2Valid()) { + cerr << "Re-read RS2 was not set to valid state (111...012)" << endl; + return 1; + } + if (!zr3a.isRs2NotExpired()) { + cerr << "Re-read RS2 expired (111...012)" << endl; + return 1; + } + + ZIDRecord zr5((unsigned char*) "210987654321"); + zid->getRecord(&zr5); + + + // set new RS1 with expire interval of 5 second, then check immediatly + zr5.setNewRs1((unsigned char*) "aaa22233344455566677788899900012", 5); + if (!zr5.isValid()) { + cerr << "Re-read ZID record '210987654321' not set to valid" << endl; + return 1; + } + if (memcmp(zr5.getRs1(), "aaa22233344455566677788899900012", RS_LENGTH) != 0) { + cerr << "RS1 (2) was not set (aaa...012)" << endl; + return 1; + } + if (!zr5.isRs1Valid()) { + cerr << "RS1 (2) was not set to valid state (aaa...012)" << endl; + return 1; + } + if (!zr5.isRs1NotExpired()) { + cerr << "RS1 (2) expired (aaa...012)" << endl; + return 1; + } + + // wait for 6 second, now the expire check shall fail + sleep(6); + if (zr5.isRs1NotExpired()) { + cerr << "RS1 (2) is not expired after defined interval (aaa...012)" << endl; + return 1; + } + + zr5.setNewRs1((unsigned char*) "bbb99988877766655544433322211121", 256); + zid->saveRecord(&zr5); + + zid->close(); + + // Test migration + zid->open("testzidOld"); + zid->close(); + +} + +#endif + +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ diff --git a/jni/libzrtp/sources/zrtp/ZIDRecordFile.cpp b/jni/libzrtp/sources/src/ZIDRecord.cpp similarity index 57% rename from jni/libzrtp/sources/zrtp/ZIDRecordFile.cpp rename to jni/libzrtp/sources/src/ZIDRecord.cpp index fd25dec12..d62c2e378 100644 --- a/jni/libzrtp/sources/zrtp/ZIDRecordFile.cpp +++ b/jni/libzrtp/sources/src/ZIDRecord.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -21,81 +21,93 @@ #include <time.h> -#include <libzrtpcpp/ZIDRecordFile.h> +#include <libzrtpcpp/ZIDRecord.h> -void ZIDRecordFile::setNewRs1(const unsigned char* data, int32_t expire) { +void ZIDRecord::setNewRs1(const unsigned char* data, int32_t expire) { // shift RS1 data into RS2 position memcpy(record.rs2Data, record.rs1Data, RS_LENGTH); memcpy(record.rs2Interval, record.rs1Interval, TIME_LENGTH); + // now propagate flags as well + if (isRs1Valid()) { + setRs2Valid(); + } + // set new RS1 data memcpy(record.rs1Data, data, RS_LENGTH); time_t validThru; if (expire == -1) { - validThru = -1; + validThru = -1; } else if (expire <= 0) { - validThru = 0; + validThru = 0; } else { - validThru = time(NULL) + expire; + validThru = time(NULL) + expire; } if (sizeof(time_t) == 4) { - long long temp = validThru; - memcpy(record.rs1Interval, (unsigned char*)&temp, TIME_LENGTH); + long long temp = validThru; + memcpy(record.rs1Interval, (unsigned char*)&temp, TIME_LENGTH); } else { - memcpy(record.rs1Interval, (unsigned char*)&validThru, TIME_LENGTH); + memcpy(record.rs1Interval, (unsigned char*)&validThru, TIME_LENGTH); } - resetRs2Valid(); setRs1Valid(); } -bool ZIDRecordFile::isRs1NotExpired() { +const bool ZIDRecord::isRs1NotExpired() { time_t current = time(NULL); time_t validThru; if (sizeof(time_t) == 4) { - long long temp; - memcpy((unsigned char*)&temp, record.rs1Interval, TIME_LENGTH); - validThru = temp; + long long temp; + memcpy((unsigned char*)&temp, record.rs1Interval, TIME_LENGTH); + validThru = temp; } else { - memcpy((unsigned char*)&validThru, record.rs1Interval, TIME_LENGTH); + memcpy((unsigned char*)&validThru, record.rs1Interval, TIME_LENGTH); } if (validThru == -1) - return true; + return true; if (validThru == 0) - return false; + return false; return (current <= validThru) ? true : false; } -bool ZIDRecordFile::isRs2NotExpired() { +const bool ZIDRecord::isRs2NotExpired() { time_t current = time(NULL); time_t validThru; if (sizeof(time_t) == 4) { - long long temp; - memcpy((unsigned char*)&temp, record.rs2Interval, TIME_LENGTH); - validThru = temp; + long long temp; + memcpy((unsigned char*)&temp, record.rs2Interval, TIME_LENGTH); + validThru = temp; } else { - memcpy((unsigned char*)&validThru, record.rs2Interval, TIME_LENGTH); + memcpy((unsigned char*)&validThru, record.rs2Interval, TIME_LENGTH); } if (validThru == -1) - return true; + return true; if (validThru == 0) - return false; + return false; return (current <= validThru) ? true : false; } -void ZIDRecordFile::setMiTMData(const unsigned char* data) { +void ZIDRecord::setMiTMData(const unsigned char* data) { memcpy(record.mitmKey, data, RS_LENGTH); setMITMKeyAvailable(); } + +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ diff --git a/jni/libzrtp/sources/zrtp/ZRtp.cpp b/jni/libzrtp/sources/src/ZRtp.cpp similarity index 69% rename from jni/libzrtp/sources/zrtp/ZRtp.cpp rename to jni/libzrtp/sources/src/ZRtp.cpp index c7d2a464e..50c29a9ad 100755 --- a/jni/libzrtp/sources/zrtp/ZRtp.cpp +++ b/jni/libzrtp/sources/src/ZRtp.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2009 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -15,28 +15,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* +/*F * Authors: Werner Dittmann <Werner.Dittmann@t-online.de> */ #include <sstream> -#include <crypto/zrtpDH.h> -#include <crypto/hmac256.h> -#include <crypto/sha256.h> -#include <crypto/hmac384.h> -#include <crypto/sha384.h> - -#include <crypto/skeinMac256.h> -#include <crypto/skein256.h> -#include <crypto/skeinMac384.h> -#include <crypto/skein384.h> - -#include <crypto/aesCFB.h> -#include <crypto/twoCFB.h> +#include <libzrtpcpp/crypto/ZrtpDH.h> +#include <libzrtpcpp/crypto/hmac256.h> +#include <libzrtpcpp/crypto/sha256.h> +#include <libzrtpcpp/crypto/hmac384.h> +#include <libzrtpcpp/crypto/sha384.h> +#include <libzrtpcpp/crypto/aesCFB.h> +#include <libzrtpcpp/crypto/twoCFB.h> #include <libzrtpcpp/ZRtp.h> #include <libzrtpcpp/ZrtpStateClass.h> -#include <libzrtpcpp/ZIDCache.h> +#include <libzrtpcpp/ZIDFile.h> +#include <libzrtpcpp/ZIDRecord.h> #include <libzrtpcpp/Base32.h> using namespace GnuZrtpCodes; @@ -58,7 +53,7 @@ static void hexdump(const char* title, const unsigned char *s, int l) { } fprintf(stderr, "\n"); } - * */ + */ /* * This method simplifies detection of libzrtpcpp inside Automake, configure @@ -77,12 +72,10 @@ extern "C" { ZRtp::ZRtp(uint8_t *myZid, ZrtpCallback *cb, std::string id, ZrtpConfigure* config, bool mitmm, bool sasSignSupport): callback(cb), dhContext(NULL), DHss(NULL), auxSecret(NULL), auxSecretLength(0), rs1Valid(false), - rs2Valid(false), msgShaContext(NULL), hash(NULL), cipher(NULL), pubKey(NULL), sasType(NULL), authLength(NULL), - multiStream(false), multiStreamAvailable(false), peerIsEnrolled(false), mitmSeen(false), pbxSecretTmp(NULL), - enrollmentMode(false), configureAlgos(*config), zidRec(NULL), saveZidRecord(true) { + rs2Valid(false), msgShaContext(NULL), multiStream(false), multiStreamAvailable(false), pbxSecretTmp(NULL), + configureAlgos(*config) { enableMitmEnrollment = config->isTrustedMitM(); - signatureData = NULL; paranoidMode = config->isParanoidMode(); // setup the implicit hash function pointers and length @@ -93,8 +86,6 @@ ZRtp::ZRtp(uint8_t *myZid, ZrtpCallback *cb, std::string id, ZrtpConfigure* conf hmacFunctionImpl = hmac_sha256; hmacListFunctionImpl = hmac_sha256; - memcpy(ownZid, myZid, ZID_SIZE); // save the ZID - /* * Generate H0 as a random number (256 bits, 32 bytes) and then * the hash chain, refer to chapter 9. Use the implicit hash function. @@ -104,39 +95,19 @@ ZRtp::ZRtp(uint8_t *myZid, ZrtpCallback *cb, std::string id, ZrtpConfigure* conf sha256(H1, HASH_IMAGE_SIZE, H2); // H2 sha256(H2, HASH_IMAGE_SIZE, H3); // H3 - // configure all supported Hello packet versions - zrtpHello_11.configureHello(&configureAlgos); - zrtpHello_11.setH3(H3); // set H3 in Hello, included in helloHash - zrtpHello_11.setZid(ownZid); - zrtpHello_11.setVersion((uint8_t*)zrtpVersion_11); + zrtpHello.configureHello(&configureAlgos); + zrtpHello.setH3(H3); // set H3 in Hello, included in helloHash + memcpy(zid, myZid, ZID_SIZE); + zrtpHello.setZid(zid); - zrtpHello_12.configureHello(&configureAlgos); - zrtpHello_12.setH3(H3); // set H3 in Hello, included in helloHash - zrtpHello_12.setZid(ownZid); - zrtpHello_12.setVersion((uint8_t*)zrtpVersion_12); + if (mitmm) // this session acts for a trusted MitM (PBX) + zrtpHello.setMitmMode(); - if (mitmm) { // this session acts for a trusted MitM (PBX) - zrtpHello_11.setMitmMode(); - zrtpHello_12.setMitmMode(); - } - if (sasSignSupport) { // the application supports SAS signing - zrtpHello_11.setSasSign(); - zrtpHello_12.setSasSign(); - } - - // Keep array in ascending order (greater index -> greater version) - helloPackets[0].packet = &zrtpHello_11; - helloPackets[0].version = zrtpHello_11.getVersionInt(); - setClientId(id, &helloPackets[0]); // set id, compute HMAC and final helloHash + if (sasSignSupport) // the application supports SAS signing + zrtpHello.setSasSign(); - helloPackets[1].packet = &zrtpHello_12; - helloPackets[1].version = zrtpHello_12.getVersionInt(); - setClientId(id, &helloPackets[1]); // set id, compute HMAC and final helloHash - - currentHelloPacket = helloPackets[SUPPORTED_ZRTP_VERSIONS-1].packet; // start with highest supported version - helloPackets[SUPPORTED_ZRTP_VERSIONS].packet = NULL; - peerHelloVersion[0] = 0; + setClientId(id); // set id, compute HMAC and final helloHash stateEngine = new ZrtpStateClass(this); } @@ -164,10 +135,6 @@ ZRtp::~ZRtp() { auxSecret = NULL; auxSecretLength = 0; } - if (zidRec != NULL) { - delete zidRec; - zidRec = NULL; - } memset(hmacKeyI, 0, MAX_DIGEST_LENGTH); memset(hmacKeyR, 0, MAX_DIGEST_LENGTH); @@ -187,12 +154,11 @@ ZRtp::~ZRtp() { memset(zrtpSession, 0, MAX_DIGEST_LENGTH); } -void ZRtp::processZrtpMessage(uint8_t *message, uint32_t pSSRC, size_t length) { +void ZRtp::processZrtpMessage(uint8_t *message, uint32_t pSSRC) { Event_t ev; peerSSRC = pSSRC; ev.type = ZrtpPacket; - ev.length = length; ev.packet = message; if (stateEngine != NULL) { @@ -263,7 +229,7 @@ bool ZRtp::inState(int32_t state) } ZrtpPacketHello* ZRtp::prepareHello() { - return currentHelloPacket; + return &zrtpHello; } ZrtpPacketHelloAck* ZRtp::prepareHelloAck() { @@ -277,33 +243,20 @@ ZrtpPacketHelloAck* ZRtp::prepareHelloAck() { */ ZrtpPacketCommit* ZRtp::prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg) { - myRole = Initiator; + sendInfo(Info, InfoHelloReceived); - if (!hello->isLengthOk()) { - *errMsg = CriticalSWError; + if (memcmp(hello->getVersion(), zrtpVersion, ZRTP_WORD_SIZE-1) != 0) { + *errMsg = UnsuppZRTPVersion; return NULL; } - // Save data before detailed checks - may aid in analysing problems - peerClientId.assign((char*)hello->getClientId(), ZRTP_WORD_SIZE * 4); - memcpy(peerHelloVersion, hello->getVersion(), ZRTP_WORD_SIZE); - peerHelloVersion[ZRTP_WORD_SIZE] = 0; - // Save our peer's (presumably the Responder) ZRTP id memcpy(peerZid, hello->getZid(), ZID_SIZE); - if (memcmp(peerZid, ownZid, ZID_SIZE) == 0) { // peers have same ZID???? + if (memcmp(peerZid, zid, ZID_SIZE) == 0) { // peers have same ZID???? *errMsg = EqualZIDHello; return NULL; } memcpy(peerH3, hello->getH3(), HASH_IMAGE_SIZE); - int32_t helloLen = hello->getLength() * ZRTP_WORD_SIZE; - - // calculate hash over the received Hello packet - is peer's hello hash. - // Use implicit hash algorithm - hashFunctionImpl((unsigned char*)hello->getHeaderBase(), helloLen, peerHelloHash); - - sendInfo(Info, InfoHelloReceived); - /* * The Following section extracts the algorithm from the peer's Hello * packet. Always the preferend offered algorithms are @@ -320,15 +273,10 @@ ZrtpPacketCommit* ZRtp::prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg) sasType = findBestSASType(hello); if (!multiStream) { - pubKey = findBestPubkey(hello); // Check for public key algorithm first, must set 'hash' as well - if (hash == NULL) { - *errMsg = UnsuppHashType; - return NULL; - } - if (cipher == NULL) // public key selection may have set the cipher already - cipher = findBestCipher(hello, pubKey); - if (authLength == NULL) // public key selection may have set the SRTP authLen already - authLength = findBestAuthLen(hello); + authLength = findBestAuthLen(hello); + pubKey = findBestPubkey(hello); + cipher = findBestCipher(hello, pubKey); + hash = findBestHash(hello); multiStreamAvailable = checkMultiStream(hello); } else { @@ -358,16 +306,22 @@ ZrtpPacketCommit* ZRtp::prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg) /* * Prepare our DHPart2 packet here. Required to compute HVI. If we stay * in Initiator role then we reuse this packet later in prepareDHPart2(). - * To create this DH packet we have to compute the retained secret ids, - * thus get our peer's retained secret data first. + * To create this DH packet we have to compute the retained secret ids + * first. Thus get our peer's retained secret data first. */ - zidRec = getZidCacheInstance()->getRecord(peerZid); + ZIDRecord zidRec(peerZid); + ZIDFile *zidFile = ZIDFile::getInstance(); + zidFile->getRecord(&zidRec); //Compute the Initator's and Responder's retained secret ids. computeSharedSecretSet(zidRec); // Check if a PBX application set the MitM flag. - mitmSeen = hello->isMitmMode(); + if (hello->isMitmMode()) { + mitmSeen = true; + } + // Flag to record that fact that we have a MitM key of the other peer. + peerIsEnrolled = zidRec.isMITMKeyAvailable(); signSasSeen = hello->isSasSign(); // Construct a DHPart2 message (Initiator's DH message). This packet @@ -397,7 +351,7 @@ ZrtpPacketCommit* ZRtp::prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg) // Compute the HVI, refer to chapter 5.4.1.1 of the specification computeHvi(&zrtpDH2, hello); - zrtpCommit.setZid(ownZid); + zrtpCommit.setZid(zid); zrtpCommit.setHashType((uint8_t*)hash->getName()); zrtpCommit.setCipherType((uint8_t*)cipher->getName()); zrtpCommit.setAuthLen((uint8_t*)authLength->getName()); @@ -417,6 +371,7 @@ ZrtpPacketCommit* ZRtp::prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg) // hash first messages to produce overall message hash // First the Responder's Hello message, second the Commit (always Initator's). // Must use negotiated hash. + int32_t helloLen = hello->getLength() * ZRTP_WORD_SIZE; msgShaContext = createHashCtx(); hashCtxFunction(msgShaContext, (unsigned char*)hello->getHeaderBase(), helloLen); hashCtxFunction(msgShaContext, (unsigned char*)zrtpCommit.getHeaderBase(), len); @@ -425,6 +380,12 @@ ZrtpPacketCommit* ZRtp::prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg) // Responder or DHPart1 as Initiator storeMsgTemp(hello); + // calculate hash over the received Hello packet - is peer's hello hash. + // Use implicit hash algorithm + hashFunctionImpl((unsigned char*)hello->getHeaderBase(), helloLen, peerHelloHash); + memcpy(peerHelloVersion, hello->getVersion(), ZRTP_WORD_SIZE); + peerHelloVersion[ZRTP_WORD_SIZE] = 0; + return &zrtpCommit; } @@ -432,11 +393,11 @@ ZrtpPacketCommit* ZRtp::prepareCommitMultiStream(ZrtpPacketHello *hello) { randomZRTP(hvi, ZRTP_WORD_SIZE*4); // This is the Multi-Stream NONCE size - zrtpCommit.setZid(ownZid); + zrtpCommit.setZid(zid); zrtpCommit.setHashType((uint8_t*)hash->getName()); zrtpCommit.setCipherType((uint8_t*)cipher->getName()); zrtpCommit.setAuthLen((uint8_t*)authLength->getName()); - zrtpCommit.setPubKeyType((uint8_t*)mult); // this is fixed because of Multi Stream mode + zrtpCommit.setPubKeyType((uint8_t*)"Mult"); // this is fixed because of Multi Stream mode zrtpCommit.setSasType((uint8_t*)sasType->getName()); zrtpCommit.setNonce(hvi); zrtpCommit.setH2(H2); @@ -466,11 +427,17 @@ ZrtpPacketCommit* ZRtp::prepareCommitMultiStream(ZrtpPacketHello *hello) { // Responder or DHPart1 as Initiator storeMsgTemp(hello); + // calculate hash over the received Hello packet - is peer's hello hash. + // Use implicit hash algorithm + hashFunctionImpl((unsigned char*)hello->getHeaderBase(), helloLen, peerHelloHash); + memcpy(peerHelloVersion, hello->getVersion(), ZRTP_WORD_SIZE); + peerHelloVersion[ZRTP_WORD_SIZE] = 0; + return &zrtpCommit; } /* - * At this point we will take the role of the Responder. We have been in + * At this point we will take the role of the Responder. We may have been in * the role of the Initiator before and already sent a commit packet that * clashed with a commit packet from our peer. If our HVI was lower than our * peer's HVI then we switched to Responder and handle our peer's commit packet @@ -482,21 +449,8 @@ ZrtpPacketDHPart* ZRtp::prepareDHPart1(ZrtpPacketCommit *commit, uint32_t* errMs sendInfo(Info, InfoRespCommitReceived); - if (!commit->isLengthOk(ZrtpPacketCommit::DhExchange)) { - *errMsg = CriticalSWError; - return NULL; - } - - // Check if ZID in Commit is the same as we got in Hello - uint8_t tmpZid[ZID_SIZE]; - memcpy(tmpZid, commit->getZid(), ZID_SIZE); - if (memcmp(peerZid, tmpZid, ZID_SIZE) != 0) { // ZIDs do not match???? - sendInfo(Severe, SevereProtocolError); - *errMsg = CriticalSWError; - return NULL; - } - - // The following code checks the hash chain according chapter 10 to detect false ZRTP packets. + // The following code check the hash chain according chapter 10 to detect + // false ZRTP packets. // Must use the implicit hash function. uint8_t tmpH3[IMPL_MAX_DIGEST_LENGTH]; memcpy(peerH2, commit->getH2(), HASH_IMAGE_SIZE); @@ -544,22 +498,22 @@ ZrtpPacketDHPart* ZRtp::prepareDHPart1(ZrtpPacketCommit *commit, uint32_t* errMs if (*(int32_t*)(hash->getName()) != *(int32_t*)(cp->getName())) { hash = cp; setNegotiatedHash(hash); + + ZIDRecord zidRec(peerZid); + ZIDFile *zidFile = ZIDFile::getInstance(); + zidFile->getRecord(&zidRec); + // Compute the Initator's and Responder's retained secret ids // with the committed hash. computeSharedSecretSet(zidRec); } + // check if we support the commited pub key type cp = &zrtpPubKeys.getByName((const char*)commit->getPubKeysType()); if (!cp->isValid()) { // no match - something went wrong *errMsg = UnsuppPKExchange; return NULL; } - if (*(int32_t*)(cp->getName()) == *(int32_t*)ec38 || *(int32_t*)(cp->getName()) == *(int32_t*)e414) { - if (!(*(int32_t*)(hash->getName()) == *(int32_t*)s384 || *(int32_t*)(hash->getName()) == *(int32_t*)skn3)) { - *errMsg = UnsuppHashType; - return NULL; - } - } pubKey = cp; // check if we support the commited SAS type @@ -571,7 +525,7 @@ ZrtpPacketDHPart* ZRtp::prepareDHPart1(ZrtpPacketCommit *commit, uint32_t* errMs sasType = cp; // dhContext cannot be NULL - always setup during prepareCommit() - // check if we can use the dhContext prepared by prepareCommit(), + // check if we can use the dhContext prepared by prepareCOmmit(), // if not delete old DH context and generate new one // The algorithm names are 4 chars only, thus we can cast to int32_t if (*(int32_t*)(dhContext->getDHtype()) != *(int32_t*)(pubKey->getName())) { @@ -583,11 +537,7 @@ ZrtpPacketDHPart* ZRtp::prepareDHPart1(ZrtpPacketCommit *commit, uint32_t* errMs dhContext->getPubKeyBytes(pubKeyBytes); - // Re-compute auxSecretIDr because we changed roles *IDr with my H3, *IDi with peer's H3 // Setup a DHPart1 packet. - myRole = Responder; - computeAuxSecretIds(); // recompute AUX secret ids because we are now Responder, use different H3 - zrtpDH1.setPubKeyType(pubKey->getName()); zrtpDH1.setMessageType((uint8_t*)DHPart1Msg); zrtpDH1.setRs1Id(rs1IDr); @@ -608,20 +558,22 @@ ZrtpPacketDHPart* ZRtp::prepareDHPart1(ZrtpPacketCommit *commit, uint32_t* errMs zrtpDH1.setHMAC(hmac); // We are definitly responder. Save the peer's hvi for later compare. + myRole = Responder; memcpy(peerHvi, commit->getHvi(), HVI_SIZE); - // We are responder. Release the pre-computed SHA context because it was prepared for Initiator. - // Setup and compute for Responder. + // We are responder. Release a possibly pre-computed SHA context + // because this was prepared for Initiator. Then create a new one. if (msgShaContext != NULL) { closeHashCtx(msgShaContext, NULL); } msgShaContext = createHashCtx(); // Hash messages to produce overall message hash: - // First the Responder's (my) Hello message, second the Commit (always Initator's), - // then the DH1 message (which is always a Responder's message). - // Must use negotiated hash. - hashCtxFunction(msgShaContext, (unsigned char*)currentHelloPacket->getHeaderBase(), currentHelloPacket->getLength() * ZRTP_WORD_SIZE); + // First the Responder's (my) Hello message, second the Commit + // (always Initator's), then the DH1 message (which is always a + // Responder's message). + // Must use negotiated hash + hashCtxFunction(msgShaContext, (unsigned char*)zrtpHello.getHeaderBase(), zrtpHello.getLength() * ZRTP_WORD_SIZE); hashCtxFunction(msgShaContext, (unsigned char*)commit->getHeaderBase(), commit->getLength() * ZRTP_WORD_SIZE); hashCtxFunction(msgShaContext, (unsigned char*)zrtpDH1.getHeaderBase(), zrtpDH1.getLength() * ZRTP_WORD_SIZE); @@ -640,10 +592,6 @@ ZrtpPacketDHPart* ZRtp::prepareDHPart2(ZrtpPacketDHPart *dhPart1, uint32_t* errM sendInfo(Info, InfoInitDH1Received); - if (!dhPart1->isLengthOk()) { - *errMsg = CriticalSWError; - return NULL; - } // Because we are initiator the protocol engine didn't receive Commit // thus could not store a peer's H2. A two step SHA256 is required to // re-compute H3. Then compare with peer's H3 from peer's Hello packet. @@ -682,6 +630,8 @@ ZrtpPacketDHPart* ZRtp::prepareDHPart2(ZrtpPacketDHPart *dhPart1, uint32_t* errM } dhContext->computeSecretKey(pvr, DHss); + myRole = Initiator; + // We are Initiator: the Responder's Hello and the Initiator's (our) Commit // are already hashed in the context. Now hash the Responder's DH1 and then // the Initiator's (our) DH2 in that order. @@ -692,9 +642,17 @@ ZrtpPacketDHPart* ZRtp::prepareDHPart2(ZrtpPacketDHPart *dhPart1, uint32_t* errM // Compute the message Hash closeHashCtx(msgShaContext, messageHash); msgShaContext = NULL; + + // To compute the keys for the Initiator we need the retained secrets of our + // peer. Get them from the storage. + ZIDRecord zidRec(peerZid); + ZIDFile *zid = ZIDFile::getInstance(); + zid->getRecord(&zidRec); + // Now compute the S0, all dependend keys and the new RS1. The function // also performs sign SAS callback if it's active. generateKeysInitiator(dhPart1, zidRec); + zid->saveRecord(&zidRec); delete dhContext; dhContext = NULL; @@ -714,10 +672,6 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm1(ZrtpPacketDHPart* dhPart2, uint32_t* er sendInfo(Info, InfoRespDH2Received); - if (!dhPart2->isLengthOk()) { - *errMsg = CriticalSWError; - return NULL; - } // Because we are responder we received a Commit and stored its H2. // Now re-compute H2 from received H1 and compare with stored peer's H2. // Use implicit hash function @@ -740,7 +694,7 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm1(ZrtpPacketDHPart* dhPart2, uint32_t* er // using my Hello packet and the Initiator's DHPart2 and compare with // hvi sent in commit packet. If it doesn't macht then a MitM attack // may have occured. - computeHvi(dhPart2, currentHelloPacket); + computeHvi(dhPart2, &zrtpHello); if (memcmp(hvi, peerHvi, HVI_SIZE) != 0) { *errMsg = DHErrorWrongHVI; return NULL; @@ -757,20 +711,27 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm1(ZrtpPacketDHPart* dhPart2, uint32_t* er return NULL; } dhContext->computeSecretKey(pvi, DHss); - - // Hash the Initiator's DH2 into the message Hash (other messages already prepared, see method prepareDHPart1(). + // Hash the Initiator's DH2 into the message Hash (other messages already + // prepared, see method prepareDHPart1(). // Use neotiated hash function hashCtxFunction(msgShaContext, (unsigned char*)dhPart2->getHeaderBase(), dhPart2->getLength() * ZRTP_WORD_SIZE); closeHashCtx(msgShaContext, messageHash); msgShaContext = NULL; + + // To compute the Keys for the Initiator we need the retained secrets of our + // peer. Get them from the storage. + ZIDRecord zidRec(peerZid); + ZIDFile *zid = ZIDFile::getInstance(); + zid->getRecord(&zidRec); + /* * The expected shared secret Ids were already computed when we built the * DHPart1 packet. Generate s0, all depended keys, and the new RS1 value - * for the ZID record. The functions also performs sign SAS callback if it's - * active. May reset the verify flag in ZID record. + * for the ZID record. The functions also performs sign SAS callback if it's active. */ generateKeysResponder(dhPart2, zidRec); + zid->saveRecord(&zidRec); delete dhContext; dhContext = NULL; @@ -780,24 +741,19 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm1(ZrtpPacketDHPart* dhPart2, uint32_t* er // Check if user verfied the SAS in a previous call and thus verfied // the retained secret. Don't set the verified flag if paranoidMode is true. - if (zidRec->isSasVerified() && !paranoidMode) { + if (zidRec.isSasVerified() && !paranoidMode) { zrtpConfirm1.setSASFlag(); } zrtpConfirm1.setExpTime(0xFFFFFFFF); zrtpConfirm1.setIv(randomIV); zrtpConfirm1.setHashH0(H0); - // if this runs at PBX user agent enrollment service then set flag in confirm + // if this run at PBX user agent enrollment service then set flag in confirm // packet and store the MitM key if (enrollmentMode) { - // As clarification to RFC6189: store new PBX secret only if we don't have - // a matching PBX secret for the peer's ZID. - if (!peerIsEnrolled) { - computePBXSecret(); - zidRec->setMiTMData(pbxSecretTmp); - } - // Set flag to enable user's client to ask for confirmation or re-confirmation. + computePBXSecret(); zrtpConfirm1.setPBXEnrollment(); + writeEnrollmentPBX(); } uint8_t confMac[MAX_DIGEST_LENGTH]; uint32_t macLen; @@ -821,10 +777,6 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm1MultiStream(ZrtpPacketCommit* commit, ui sendInfo(Info, InfoRespCommitReceived); - if (!commit->isLengthOk(ZrtpPacketCommit::MultiStream)) { - *errMsg = CriticalSWError; - return NULL; - } // The following code checks the hash chain according chapter 10 to detect // false ZRTP packets. // Use implicit hash function @@ -895,7 +847,7 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm1MultiStream(ZrtpPacketCommit* commit, ui // First the Responder's (my) Hello message, second the Commit // (always Initator's) // use negotiated hash - hashCtxFunction(msgShaContext, (unsigned char*)currentHelloPacket->getHeaderBase(), currentHelloPacket->getLength() * ZRTP_WORD_SIZE); + hashCtxFunction(msgShaContext, (unsigned char*)zrtpHello.getHeaderBase(), zrtpHello.getLength() * ZRTP_WORD_SIZE); hashCtxFunction(msgShaContext, (unsigned char*)commit->getHeaderBase(), commit->getLength() * ZRTP_WORD_SIZE); closeHashCtx(msgShaContext, messageHash); @@ -933,10 +885,6 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* sendInfo(Info, InfoInitConf1Received); - if (!confirm1->isLengthOk()) { - *errMsg = CriticalSWError; - return NULL; - } uint8_t confMac[MAX_DIGEST_LENGTH]; uint32_t macLen; @@ -951,7 +899,10 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* *errMsg = ConfirmHMACWrong; return NULL; } - cipher->getDecrypt()(zrtpKeyR, cipher->getKeylen(), (uint8_t*)confirm1->getIv(), confirm1->getHashH0(), hmlen); + cipher->getDecrypt()(zrtpKeyR, cipher->getKeylen(), confirm1->getIv(), confirm1->getHashH0(), hmlen); + + std::string cs(cipher->getReadable()); + cs.append("/").append(pubKey->getName()); // Check HMAC of DHPart1 packet stored in temporary buffer. The // HMAC key of the DHPart1 packet is peer's H0 that is contained in @@ -962,7 +913,7 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* return NULL; } signatureLength = confirm1->getSignatureLength(); - if (signSasSeen && signatureLength > 0 && confirm1->isSignatureLengthOk()) { + if (signSasSeen && signatureLength > 0) { signatureData = confirm1->getSignatureData(); callback->checkSASSignature(sasHash); // TODO: error handling if checkSASSignature returns false. @@ -973,18 +924,27 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* */ bool sasFlag = confirm1->isSASFlag(); + // Initialize a ZID record to get peer's retained secrets + ZIDRecord zidRec(peerZid); + + ZIDFile *zid = ZIDFile::getInstance(); + zid->getRecord(&zidRec); + // Our peer did not confirm the SAS in last session, thus reset // our SAS flag too. Reset the flag also if paranoidMode is true. if (!sasFlag || paranoidMode) { - zidRec->resetSasVerified(); + zidRec.resetSasVerified(); } // get verified flag from current RS1 before set a new RS1. This // may not be set even if peer's flag is set in confirm1 message. - sasFlag = zidRec->isSasVerified(); + sasFlag = zidRec.isSasVerified(); + + callback->srtpSecretsOn(cs, SAS, sasFlag); // now we are ready to save the new RS1 which inherits the verified // flag from old RS1 - zidRec->setNewRs1((const uint8_t*)newRs1); + zidRec.setNewRs1((const uint8_t*)newRs1); + zid->saveRecord(&zidRec); // now generate my Confirm2 message zrtpConfirm2.setMessageType((uint8_t*)Confirm2Msg); @@ -1005,19 +965,10 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* // packet and store the MitM key. The PBX user agent service always stores // its MitM key. if (enrollmentMode) { - // As clarification to RFC6189: store new PBX secret only if we don't have - // a matching PBX secret for the peer's ZID. - if (!peerIsEnrolled) { - computePBXSecret(); - zidRec->setMiTMData(pbxSecretTmp); - } - // Set flag to enable user's client to ask for confirmation or re-confirmation. zrtpConfirm2.setPBXEnrollment(); + writeEnrollmentPBX(); } } - if (saveZidRecord) - getZidCacheInstance()->saveRecord(zidRec); - // Encrypt and HMAC with Initiator's key - we are Initiator here hmlen = (zrtpConfirm2.getLength() - 9) * ZRTP_WORD_SIZE; cipher->getEncrypt()(zrtpKeyI, cipher->getKeylen(), randomIV, zrtpConfirm2.getHashH0(), hmlen); @@ -1032,18 +983,27 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* // agent stores the MitM key only if the user accepts the enrollment // request. if (enableMitmEnrollment && confirm1->isPBXEnrollment()) { - // As clarification to RFC6189: if already enrolled (having a matching PBX secret) - // ask for reconfirmation. - if (!peerIsEnrolled) { - callback->zrtpAskEnrollment(EnrollmentRequest); - } - else { - callback->zrtpAskEnrollment(EnrollmentReconfirm); - } + callback->zrtpAskEnrollment(EnrollmentRequest); } return &zrtpConfirm2; } +/** + * Save the computed MitM secret to the ZID record of the peer + */ +void ZRtp::writeEnrollmentPBX() { + // Initialize a ZID record to get peer's retained secrets + ZIDRecord zidRec(peerZid); + + ZIDFile *zid = ZIDFile::getInstance(); + zid->getRecord(&zidRec); + + if (pbxSecretTmp != NULL) { + zidRec.setMiTMData(pbxSecretTmp); + } + zid->saveRecord(&zidRec); +} + /* * At this point we are Initiator. */ @@ -1054,10 +1014,6 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm2MultiStream(ZrtpPacketConfirm* confirm1, // don't update SAS, RS sendInfo(Info, InfoInitConf1Received); - if (!confirm1->isLengthOk()) { - *errMsg = CriticalSWError; - return NULL; - } uint8_t confMac[MAX_DIGEST_LENGTH]; uint32_t macLen; @@ -1078,8 +1034,8 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm2MultiStream(ZrtpPacketConfirm* confirm1, *errMsg = ConfirmHMACWrong; return NULL; } - // Cast away the const for the IV - the standalone AES CFB modifies IV on return - cipher->getDecrypt()(zrtpKeyR, cipher->getKeylen(), (uint8_t*)confirm1->getIv(), confirm1->getHashH0(), hmlen); + cipher->getDecrypt()(zrtpKeyR, cipher->getKeylen(), confirm1->getIv(), confirm1->getHashH0(), hmlen); + std::string cs(cipher->getReadable()); // Because we are initiator the protocol engine didn't receive Commit and // because we are using multi-stream mode here we also did not receive a DHPart1 and @@ -1099,6 +1055,12 @@ ZrtpPacketConfirm* ZRtp::prepareConfirm2MultiStream(ZrtpPacketConfirm* confirm1, *errMsg = CriticalSWError; return NULL; } + // TODO: here we have a SAS signature from reponder, call checkSASsignature (save / compare in case of resend) + + // Inform GUI about security state, don't show SAS and its state + std::string cs1(""); + callback->srtpSecretsOn(cs, cs1, true); + // now generate my Confirm2 message zrtpConfirm2.setMessageType((uint8_t*)Confirm2Msg); zrtpConfirm2.setHashH0(H0); @@ -1123,10 +1085,6 @@ ZrtpPacketConf2Ack* ZRtp::prepareConf2Ack(ZrtpPacketConfirm *confirm2, uint32_t* sendInfo(Info, InfoRespConf2Received); - if (!confirm2->isLengthOk()) { - *errMsg = CriticalSWError; - return NULL; - } uint8_t confMac[MAX_DIGEST_LENGTH]; uint32_t macLen; @@ -1143,8 +1101,9 @@ ZrtpPacketConf2Ack* ZRtp::prepareConf2Ack(ZrtpPacketConfirm *confirm2, uint32_t* *errMsg = ConfirmHMACWrong; return NULL; } - // Cast away the const for the IV - the standalone AES CFB modifies IV on return - cipher->getDecrypt()(zrtpKeyI, cipher->getKeylen(), (uint8_t*)confirm2->getIv(), confirm2->getHashH0(), hmlen); + cipher->getDecrypt()(zrtpKeyI, cipher->getKeylen(), confirm2->getIv(), confirm2->getHashH0(), hmlen); + + std::string cs(cipher->getReadable()); if (!multiStream) { // Check HMAC of DHPart2 packet stored in temporary buffer. The @@ -1156,7 +1115,7 @@ ZrtpPacketConf2Ack* ZRtp::prepareConf2Ack(ZrtpPacketConfirm *confirm2, uint32_t* return NULL; } signatureLength = confirm2->getSignatureLength(); - if (signSasSeen && signatureLength > 0 && confirm2->isSignatureLengthOk() ) { + if (signSasSeen && signatureLength > 0) { signatureData = confirm2->getSignatureData(); callback->checkSASSignature(sasHash); // TODO: error handling if checkSASSignature returns false. @@ -1166,16 +1125,29 @@ ZrtpPacketConf2Ack* ZRtp::prepareConf2Ack(ZrtpPacketConfirm *confirm2, uint32_t* * GUI about state. */ bool sasFlag = confirm2->isSASFlag(); + + // Initialize a ZID record to get peer's retained secrets + ZIDRecord zidRec(peerZid); + + ZIDFile *zid = ZIDFile::getInstance(); + zid->getRecord(&zidRec); + // Our peer did not confirm the SAS in last session, thus reset // our SAS flag too. Reset the flag also if paranoidMode is true. if (!sasFlag || paranoidMode) { - zidRec->resetSasVerified(); + zidRec.resetSasVerified(); } + // Now get the resulting SAS verified flag from current RS1 before setting a new RS1. + // It's a combination of our SAS verfied flag and peer's verified flag. Only if both + // were set (true) then sasFlag becomes true. + sasFlag = zidRec.isSasVerified(); + cs.append("/").append(pubKey->getName()); + callback->srtpSecretsOn(cs, SAS, sasFlag); + // save new RS1, this inherits the verified flag from old RS1 - zidRec->setNewRs1((const uint8_t*)newRs1); - if (saveZidRecord) - getZidCacheInstance()->saveRecord(zidRec); + zidRec.setNewRs1((const uint8_t*)newRs1); + zid->saveRecord(&zidRec); // Ask for enrollment only if enabled via configuration and the // confirm packet contains the enrollment flag. The enrolling user @@ -1183,14 +1155,7 @@ ZrtpPacketConf2Ack* ZRtp::prepareConf2Ack(ZrtpPacketConfirm *confirm2, uint32_t* // request. if (enableMitmEnrollment && confirm2->isPBXEnrollment()) { computePBXSecret(); - // As clarification to RFC6189: if already enrolled (having a matching PBX secret) - // ask for reconfirmation. - if (!peerIsEnrolled) { - callback->zrtpAskEnrollment(EnrollmentRequest); - } - else { - callback->zrtpAskEnrollment(EnrollmentReconfirm); - } + callback->zrtpAskEnrollment(EnrollmentRequest); } } else { @@ -1205,15 +1170,16 @@ ZrtpPacketConf2Ack* ZRtp::prepareConf2Ack(ZrtpPacketConfirm *confirm2, uint32_t* *errMsg = CriticalSWError; return NULL; } + std::string cs1(""); + + // Inform GUI about security state, don't show SAS and its state + callback->srtpSecretsOn(cs, cs1, true); } return &zrtpConf2Ack; } ZrtpPacketErrorAck* ZRtp::prepareErrorAck(ZrtpPacketError* epkt) { - if (epkt->getLength() < 4) - sendInfo(ZrtpError, CriticalSWError * -1); - else - sendInfo(ZrtpError, epkt->getErrorCode() * -1); + sendInfo(ZrtpError, epkt->getErrorCode() * -1); return &zrtpErrorAck; } @@ -1223,12 +1189,11 @@ ZrtpPacketError* ZRtp::prepareError(uint32_t errMsg) { } ZrtpPacketPingAck* ZRtp::preparePingAck(ZrtpPacketPing* ppkt) { - if (ppkt->getLength() != 6) // A PING packet must have a length of 6 words - return NULL; + // Because we do not support ZRTP proxy mode use the truncated ZID. // If this code shall be used in ZRTP proxy implementation the computation // of the endpoint hash must be enhanced (see chaps 5.15ff and 5.16) - zrtpPingAck.setLocalEpHash(ownZid); + zrtpPingAck.setLocalEpHash(zid); zrtpPingAck.setRemoteEpHash(ppkt->getEpHash()); zrtpPingAck.setSSRC(peerSSRC); return &zrtpPingAck; @@ -1240,10 +1205,6 @@ ZrtpPacketRelayAck* ZRtp::prepareRelayAck(ZrtpPacketSASrelay* srly, uint32_t* er if (!mitmSeen || paranoidMode) return &zrtpRelayAck; - if (!srly->isLengthOk()) { - *errMsg = CriticalSWError; - return NULL; - } uint8_t* hkey, *ekey; // If we are responder then the PBX used it's Initiator keys if (myRole == Responder) { @@ -1258,6 +1219,8 @@ ZrtpPacketRelayAck* ZRtp::prepareRelayAck(ZrtpPacketSASrelay* srly, uint32_t* er uint8_t confMac[MAX_DIGEST_LENGTH]; uint32_t macLen; + // Use the Initiator's keys here because we are Responder here and + // reveice packets from Initiator int16_t hmlen = (srly->getLength() - 9) * ZRTP_WORD_SIZE; // Use negotiated HMAC (hash) @@ -1267,10 +1230,11 @@ ZrtpPacketRelayAck* ZRtp::prepareRelayAck(ZrtpPacketSASrelay* srly, uint32_t* er *errMsg = ConfirmHMACWrong; return NULL; // TODO - check error handling } - // Cast away the const for the IV - the standalone AES CFB modifies IV on return - cipher->getDecrypt()(ekey, cipher->getKeylen(), (uint8_t*)srly->getIv(), (uint8_t*)srly->getFiller(), hmlen); + cipher->getDecrypt()(ekey, cipher->getKeylen(), srly->getIv(), (uint8_t*)srly->getFiller(), hmlen); + const uint8_t* render = srly->getSas(); const uint8_t* newSasHash = srly->getTrustedSas(); + bool sasHashNull = true; for (int i = 0; i < HASH_IMAGE_SIZE; i++) { if (newSasHash[i] != 0) { @@ -1278,38 +1242,27 @@ ZrtpPacketRelayAck* ZRtp::prepareRelayAck(ZrtpPacketSASrelay* srly, uint32_t* er break; } } - std::string cs(cipher->getReadable()); - cs.append("/").append(pubKey->getName()); - // Check if new SAS is null or a trusted MitM relationship doesn't exist. // If this is the case then don't render and don't show the new SAS - use - // our computed SAS hash but we may use a different SAS rendering algorithm to + // the computed SAS hash but we may use a different SAS rendering algorithm to // render the computed SAS. if (sasHashNull || !peerIsEnrolled) { - cs.append("/MitM"); newSasHash = sasHash; } - else { - cs.append("/SASviaMitM"); - } // If other SAS schemes required - check here and use others - const uint8_t* render = srly->getSasAlgo(); AlgorithmEnum* renderAlgo = &zrtpSasTypes.getByName((const char*)render); - uint8_t sasBytes[4]; + uint8_t sasBytes[4];; if (renderAlgo->isValid()) { sasBytes[0] = newSasHash[0]; sasBytes[1] = newSasHash[1]; sasBytes[2] = newSasHash[2] & 0xf0; sasBytes[3] = 0; - if (*(int32_t*)b32 == *(int32_t*)(renderAlgo->getName())) { - SAS = Base32(sasBytes, 20).getEncoded(); - } - else { - SAS.assign(sas256WordsEven[sasBytes[0]]).append(":").append(sas256WordsOdd[sasBytes[1]]); - } } - bool verify = zidRec->isSasVerified() && srly->isSASFlag(); - callback->srtpSecretsOn(cs, SAS, verify); + SAS = Base32(sasBytes, 20).getEncoded(); + std::string cs(cipher->getReadable()); + cs.append("/").append(pubKey->getName()).append("/MitM"); + + callback->srtpSecretsOn(cs, SAS, false); return &zrtpRelayAck; } @@ -1359,26 +1312,42 @@ AlgorithmEnum* ZRtp::findBestHash(ZrtpPacketHello *hello) { int numAlgosConf; AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1]; + bool mandatoryFound = false; + // If Hello does not contain any hash names return Sha256, its mandatory int num = hello->getNumHashes(); if (num == 0) { return &zrtpHashes.getByName(mandatoryHash); } - // Build list of configured hash algorithm names. + // Build list of configured hash algorithm names, append mandatory algos + // if necessary. numAlgosConf = configureAlgos.getNumConfiguredAlgos(HashAlgorithm); for (i = 0; i < numAlgosConf; i++) { algosConf[i] = &configureAlgos.getAlgoAt(HashAlgorithm, i); + if (*(int32_t*)(algosConf[i]->getName()) == *(int32_t*)mandatoryHash) { + mandatoryFound = true; + } + } + if (!mandatoryFound) { + algosConf[numAlgosConf++] = &zrtpHashes.getByName(mandatoryHash); } // Build list of offered known algos in Hello, append mandatory algos if necessary + mandatoryFound = false; for (numAlgosOffered = 0, i = 0; i < num; i++) { algosOffered[numAlgosOffered] = &zrtpHashes.getByName((const char*)hello->getHashType(i)); if (!algosOffered[numAlgosOffered]->isValid()) continue; - numAlgosOffered++; + if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatoryHash) { + mandatoryFound = true; + } + } + if (!mandatoryFound) { + algosOffered[numAlgosOffered++] = &zrtpHashes.getByName(mandatoryHash); } - // Lookup offered algos in configured algos. + // Lookup offered algos in configured algos. Because of appended + // mandatory algorithms at least one match will happen for (i = 0; i < numAlgosOffered; i++) { for (ii = 0; ii < numAlgosConf; ii++) { if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) { @@ -1389,7 +1358,6 @@ AlgorithmEnum* ZRtp::findBestHash(ZrtpPacketHello *hello) { return &zrtpHashes.getByName(mandatoryHash); } - AlgorithmEnum* ZRtp::findBestCipher(ZrtpPacketHello *hello, AlgorithmEnum* pk) { int i; @@ -1400,24 +1368,44 @@ AlgorithmEnum* ZRtp::findBestCipher(ZrtpPacketHello *hello, AlgorithmEnum* pk) { int numAlgosConf; AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1]; + bool mandatoryFound = false; + int num = hello->getNumCiphers(); if (num == 0 || (*(int32_t*)(pk->getName()) == *(int32_t*)dh2k)) { return &zrtpSymCiphers.getByName(aes1); } - // Build list of configured cipher algorithm names. + // Build list of configured cipher algorithm names, append mandatory algos + // if necessary. numAlgosConf = configureAlgos.getNumConfiguredAlgos(CipherAlgorithm); for (i = 0; i < numAlgosConf; i++) { algosConf[i] = &configureAlgos.getAlgoAt(CipherAlgorithm, i); + if (*(int32_t*)(algosConf[i]->getName()) == *(int32_t*)mandatoryCipher) { + mandatoryFound = true; + } + } + if (!mandatoryFound) { + algosConf[numAlgosConf++] = &zrtpSymCiphers.getByName(mandatoryCipher); } - // Build list of offered known algos names in Hello. + + // Build list of offered known algos names in Hello, append mandatory algos if + // necessary + mandatoryFound = false; for (numAlgosOffered = 0, i = 0; i < num; i++) { algosOffered[numAlgosOffered] = &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i)); if (!algosOffered[numAlgosOffered]->isValid()) continue; - numAlgosOffered++; + if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatoryCipher) { + mandatoryFound = true; + } + } + + if (!mandatoryFound) { + algosOffered[numAlgosOffered++] = &zrtpSymCiphers.getByName(mandatoryCipher); } - // Lookup offered algos in configured algos. Prefer algorithms that appear first in Hello packet (offered). + + // Lookup offered algos in configured algos. Because of appended + // mandatory algorithms at least one match will happen for (i = 0; i < numAlgosOffered; i++) { for (ii = 0; ii < numAlgosConf; ii++) { if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) { @@ -1425,106 +1413,70 @@ AlgorithmEnum* ZRtp::findBestCipher(ZrtpPacketHello *hello, AlgorithmEnum* pk) { } } } - // If we don't have a match - use the mandatory algorithm return &zrtpSymCiphers.getByName(mandatoryCipher); } -// We can have the non-NIST in the list of orderedAlgos even if they are not available -// in the code (refer to ZrtpConfigure.cpp). If they are not build in they cannot appear -// in'configureAlgos' and thus not in the intersection lists. Thus a ZRTP build that -// does not include the non-NIST curves also works without problems. -// AlgorithmEnum* ZRtp::findBestPubkey(ZrtpPacketHello *hello) { - AlgorithmEnum* peerIntersect[ZrtpConfigure::maxNoOfAlgos+1]; - AlgorithmEnum* ownIntersect[ZrtpConfigure::maxNoOfAlgos+1]; + int i; + int ii; + int numAlgosOffered; + AlgorithmEnum* algosOffered[ZrtpConfigure::maxNoOfAlgos+1]; + + int numAlgosConf; + AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1]; - // Build list of own pubkey algorithm names, must follow the order - // defined in RFC 6189, chapter 4.1.2. - const char *orderedAlgos[] = {dh2k, e255, ec25, dh3k, e414, ec38}; - int numOrderedAlgos = sizeof(orderedAlgos) / sizeof(const char*); + bool mandatoryFound = false; - int numAlgosPeer = hello->getNumPubKeys(); - if (numAlgosPeer == 0) { - hash = findBestHash(hello); // find a hash algorithm + int num = hello->getNumPubKeys(); + if (num == 0) { return &zrtpPubKeys.getByName(mandatoryPubKey); } - // Build own list of intersecting algos, keep own order or algorithms - // The list must include real public key algorithms only, so skip mult-stream mode, - // preshared and alike. - int numAlgosOwn = configureAlgos.getNumConfiguredAlgos(PubKeyAlgorithm); - int numOwnIntersect = 0; - for (int i = 0; i < numAlgosOwn; i++) { - ownIntersect[numOwnIntersect] = &configureAlgos.getAlgoAt(PubKeyAlgorithm, i); - if (*(int32_t*)(ownIntersect[numOwnIntersect]->getName()) == *(int32_t*)mult) { + // Build list of configured pubkey algorithm names, append mandatory algos + // if necessary. + // The list must include real public key algorithms only, so skip + // mult-stream mode, preshared and alike. + numAlgosConf = configureAlgos.getNumConfiguredAlgos(PubKeyAlgorithm); + for (i = 0, ii = 0; i < numAlgosConf; i++) { + algosConf[ii] = &configureAlgos.getAlgoAt(PubKeyAlgorithm, ii); + if (*(int32_t*)(algosConf[ii]->getName()) == *(int32_t*)mult) { continue; // skip multi-stream mode } - for (int ii = 0; ii < numAlgosPeer; ii++) { - if (*(int32_t*)(ownIntersect[numOwnIntersect]->getName()) == *(int32_t*)(zrtpPubKeys.getByName((const char*)hello->getPubKeyType(ii)).getName())) { - numOwnIntersect++; - break; - } - } - } - // Build list of peer's intersecting algos: take own list as input and build a - // list of algorithms that we have in common. The order of the list is according - // to peer's Hello packet (peer's preferences). - int numPeerIntersect = 0; - for (int i = 0; i < numAlgosPeer; i++) { - peerIntersect[numPeerIntersect] = &zrtpPubKeys.getByName((const char*)hello->getPubKeyType(i)); - for (int ii = 0; ii < numOwnIntersect; ii++) { - if (*(int32_t*)(ownIntersect[ii]->getName()) == *(int32_t*)(peerIntersect[numPeerIntersect]->getName())) { - numPeerIntersect++; - break; - } + if (*(int32_t*)(algosConf[ii++]->getName()) == *(int32_t*)mandatoryPubKey) { + mandatoryFound = true; } } - if (numPeerIntersect == 0) { // If we don't have a common algorithm - use mandatory algorithms - hash = findBestHash(hello); - return &zrtpPubKeys.getByName(mandatoryPubKey); - } - // If we have only one algorithm in common or if the first entry matches - take it. - // Otherwise determine which algorithm from the intersection lists is first in the - // list of ordered algorithms and select it (RFC6189, section 4.1.2). - AlgorithmEnum* useAlgo; - if (numPeerIntersect > 1 && *(int32_t*)(ownIntersect[0]->getName()) != *(int32_t*)(peerIntersect[0]->getName())) { - int own, peer; + numAlgosConf = ii; + if (!mandatoryFound) { + algosConf[numAlgosConf++] = &zrtpPubKeys.getByName(mandatoryPubKey); + } - const int32_t *name = (int32_t*)ownIntersect[0]->getName(); - for (own = 0; own < numOrderedAlgos; own++) { - if (*name == *(int32_t*)orderedAlgos[own]) - break; - } - name = (int32_t*)peerIntersect[0]->getName(); - for (peer = 0; peer < numOrderedAlgos; peer++) { - if (*name == *(int32_t*)orderedAlgos[peer]) - break; - } - if (own < peer) { - useAlgo = ownIntersect[0]; - } - else { - useAlgo = peerIntersect[0]; + // Build list of offered known algos in Hello, append mandatory algos if necessary + mandatoryFound = false; + for (numAlgosOffered = 0, i = 0; i < num; i++) { + algosOffered[numAlgosOffered] = &zrtpPubKeys.getByName((const char*)hello->getPubKeyType(i)); + if (!algosOffered[numAlgosOffered]->isValid()) + continue; + if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatoryPubKey) { + mandatoryFound = true; } - // find fastest of conf vs intersecting } - else { - useAlgo = peerIntersect[0]; - } - int32_t algoName = *(int32_t*)(useAlgo->getName()); - // select a corresponding strong hash if necessary. - if (algoName == *(int32_t*)ec38 || algoName == *(int32_t*)e414) { - hash = getStrongHashOffered(hello, algoName); - cipher = getStrongCipherOffered(hello, algoName); + if (!mandatoryFound) { + algosOffered[numAlgosOffered++] = &zrtpPubKeys.getByName(mandatoryPubKey); } - else { - hash = getHashOffered(hello, algoName);; - cipher = getCipherOffered(hello, algoName); + + // Lookup offered algos in configured algos. Because of appended + // mandatory algorithms at least one match will happen + for (i = 0; i < numAlgosOffered; i++) { + for (ii = 0; ii < numAlgosConf; ii++) { + if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) { + return algosConf[ii]; + } + } } - authLength = getAuthLenOffered(hello, algoName); - return useAlgo; + return &zrtpPubKeys.getByName(mandatoryPubKey); } AlgorithmEnum* ZRtp::findBestSASType(ZrtpPacketHello *hello) { @@ -1537,23 +1489,42 @@ AlgorithmEnum* ZRtp::findBestSASType(ZrtpPacketHello *hello) { int numAlgosConf; AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1]; + bool mandatoryFound = false; + int num = hello->getNumSas(); if (num == 0) { return &zrtpSasTypes.getByName(mandatorySasType); } - // Build list of configured SAS algorithm names + // Buildlist of configured SAS algorithm names, append mandatory algos + // if necessary. numAlgosConf = configureAlgos.getNumConfiguredAlgos(SasType); for (i = 0; i < numAlgosConf; i++) { algosConf[i] = &configureAlgos.getAlgoAt(SasType, i); + if (*(int32_t*)(algosConf[i]->getName()) == *(int32_t*)mandatorySasType) { + mandatoryFound = true; + } + } + + if (!mandatoryFound) { + algosConf[numAlgosConf++] = &zrtpSasTypes.getByName(mandatorySasType); } - // Build list of offered known algos in Hello, + + // Build list of offered known algos in Hello, append mandatory algos if necessary for (numAlgosOffered = 0, i = 0; i < num; i++) { - algosOffered[numAlgosOffered] = &zrtpSasTypes.getByName((const char*)hello->getSasType(i)); + algosOffered[numAlgosOffered] = &zrtpSasTypes.getByName((const char*)hello->getSasType(i++)); if (!algosOffered[numAlgosOffered]->isValid()) continue; - numAlgosOffered++; + if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatorySasType) { + mandatoryFound = true; + } + } + + if (!mandatoryFound) { + algosOffered[numAlgosOffered++] = &zrtpSasTypes.getByName(mandatorySasType); } - // Lookup offered algos in configured algos. Prefer algorithms that appear first in Hello packet (offered). + + // Lookup offered algos in configured algos. Because of appended + // mandatory algorithms at least one match will happen for (i = 0; i < numAlgosOffered; i++) { for (ii = 0; ii < numAlgosConf; ii++) { if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) { @@ -1561,7 +1532,6 @@ AlgorithmEnum* ZRtp::findBestSASType(ZrtpPacketHello *hello) { } } } - // If we don't have a match - use the mandatory algorithm return &zrtpSasTypes.getByName(mandatorySasType); } @@ -1575,26 +1545,55 @@ AlgorithmEnum* ZRtp::findBestAuthLen(ZrtpPacketHello *hello) { int numAlgosConf; AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+2]; + bool mandatoryFound_1 = false; + bool mandatoryFound_2 = false; + int num = hello->getNumAuth(); if (num == 0) { return &zrtpAuthLengths.getByName(mandatoryAuthLen_1); } - // Build list of configured Authentication tag length algorithm names. + // Build list of configured SAS algorithm names, append mandatory algos + // if necessary. numAlgosConf = configureAlgos.getNumConfiguredAlgos(AuthLength); for (i = 0; i < numAlgosConf; i++) { algosConf[i] = &configureAlgos.getAlgoAt(AuthLength, i); + if (*(int32_t*)(algosConf[i]->getName()) == *(int32_t*)mandatoryAuthLen_1) { + mandatoryFound_1 = true; + } + if (*(int32_t*)(algosConf[i]->getName()) == *(int32_t*)mandatoryAuthLen_2) { + mandatoryFound_2 = true; + } } - // Build list of offered known algos in Hello. + if (!mandatoryFound_1) { + algosConf[numAlgosConf++] = &zrtpAuthLengths.getByName(mandatoryAuthLen_1); + } + + if (!mandatoryFound_2) { + algosConf[numAlgosConf++] = &zrtpAuthLengths.getByName(mandatoryAuthLen_2); + } + + // Build list of offered known algos in Hello, append mandatory algos if necessary for (numAlgosOffered = 0, i = 0; i < num; i++) { algosOffered[numAlgosOffered] = &zrtpAuthLengths.getByName((const char*)hello->getAuthLen(i)); if (!algosOffered[numAlgosOffered]->isValid()) continue; - numAlgosOffered++; + if (*(int32_t*)(algosOffered[numAlgosOffered]->getName()) == *(int32_t*)mandatoryAuthLen_1) { + mandatoryFound_1 = true; + } + if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatoryAuthLen_2) { + mandatoryFound_2 = true; + } } - - // Lookup offered algos in configured algos. Prefer algorithms that appear first in Hello packet (offered). + if (!mandatoryFound_1) { + algosOffered[numAlgosOffered++] = &zrtpAuthLengths.getByName(mandatoryAuthLen_1); + } + if (!mandatoryFound_2) { + algosOffered[numAlgosOffered++] = &zrtpAuthLengths.getByName(mandatoryAuthLen_2); + } + // Lookup offered algos in configured algos. Because of appended + // mandatory algorithms at least one match will happen for (i = 0; i < numAlgosOffered; i++) { for (ii = 0; ii < numAlgosConf; ii++) { if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) { @@ -1602,115 +1601,9 @@ AlgorithmEnum* ZRtp::findBestAuthLen(ZrtpPacketHello *hello) { } } } - // If we don't have a match - use the mandatory algorithm return &zrtpAuthLengths.getByName(mandatoryAuthLen_1); } -// The following set of functions implement a 'non-NIST first policy' if nonNist computes -// to true. They prefer nonNist algorithms if these are available. Otherwise they use the NIST -// counterpart or simply call the according findBest*(...) function. -// -// Only the findBestPubkey(...) function calls them after it selected the public key algorithm. -// If the public key algorithm is non-NIST and if the policy is set to PreferNonNist then -// nonNist becomes true. -// -// The functions work according to the RFC6189 spec: the initiator can select every algorithm -// that both parties support. Thus the Initiator can even select an algorithm the wasn't offered -// in its own Hello packet but that the Initiator found in the peer's Hello and that is available -// for it. -// -AlgorithmEnum* ZRtp::getStrongHashOffered(ZrtpPacketHello *hello, int32_t algoName) { - - int numHash = hello->getNumHashes(); - bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist; - - if (nonNist) { - for (int i = 0; i < numHash; i++) { - int32_t nm = *(int32_t*)(hello->getHashType(i)); - if (nm == *(int32_t*)skn3) { - return &zrtpHashes.getByName((const char*)hello->getHashType(i)); - } - } - } - for (int i = 0; i < numHash; i++) { - int32_t nm = *(int32_t*)(hello->getHashType(i)); - if (nm == *(int32_t*)s384 || nm == *(int32_t*)skn3) { - return &zrtpHashes.getByName((const char*)hello->getHashType(i)); - } - } - return NULL; // returning NULL -> prepareCommit(...) terminates ZRTP, missing strong hash is an error -} - -AlgorithmEnum* ZRtp::getStrongCipherOffered(ZrtpPacketHello *hello, int32_t algoName) { - - int num = hello->getNumCiphers(); - bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist; - - if (nonNist) { - for (int i = 0; i < num; i++) { - int32_t nm = *(int32_t*)(hello->getCipherType(i)); - if (nm == *(int32_t*)two3) { - return &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i)); - } - } - } - for (int i = 0; i < num; i++) { - int32_t nm = *(int32_t*)(hello->getCipherType(i)); - if (nm == *(int32_t*)aes3 || nm == *(int32_t*)two3) { - return &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i)); - } - } - return NULL; // returning NULL -> prepareCommit(...) finds the best cipher -} - -AlgorithmEnum* ZRtp::getHashOffered(ZrtpPacketHello *hello, int32_t algoName) { - - int num = hello->getNumHashes(); - bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist; - - if (nonNist) { - for (int i = 0; i < num; i++) { - int32_t nm = *(int32_t*)(hello->getHashType(i)); - if (nm == *(int32_t*)skn2 || nm == *(int32_t*)skn3) { - return &zrtpHashes.getByName((const char*)hello->getHashType(i)); - } - } - } - return findBestHash(hello); -} - -AlgorithmEnum* ZRtp::getCipherOffered(ZrtpPacketHello *hello, int32_t algoName) { - - int num = hello->getNumCiphers(); - bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist; - - if (nonNist) { - for (int i = 0; i < num; i++) { - int32_t nm = *(int32_t*)(hello->getCipherType(i)); - if (nm == *(int32_t*)two2 || nm == *(int32_t*)two3) { - return &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i)); - } - } - } - return NULL; // returning NULL -> prepareCommit(...) finds the best cipher -} - -AlgorithmEnum* ZRtp::getAuthLenOffered(ZrtpPacketHello *hello, int32_t algoName) { - - int num = hello->getNumAuth(); - bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist; - - if (nonNist) { - for (int i = 0; i < num; i++) { - int32_t nm = *(int32_t*)(hello->getAuthLen(i)); - if (nm == *(int32_t*)sk32 || nm == *(int32_t*)sk64) { - return &zrtpAuthLengths.getByName((const char*)hello->getAuthLen(i)); - } - } - } - return findBestAuthLen(hello); -} - bool ZRtp::checkMultiStream(ZrtpPacketHello *hello) { int i; @@ -1731,10 +1624,6 @@ bool ZRtp::checkMultiStream(ZrtpPacketHello *hello) { bool ZRtp::verifyH2(ZrtpPacketCommit *commit) { uint8_t tmpH3[IMPL_MAX_DIGEST_LENGTH]; - // packet does not have the correct size, treat H2 verfication as failed. - if (!commit->isLengthOk(multiStream ? ZrtpPacketCommit::MultiStream : ZrtpPacketCommit::DhExchange)) - return false; - sha256(commit->getH2(), HASH_IMAGE_SIZE, tmpH3); if (memcmp(tmpH3, peerH3, HASH_IMAGE_SIZE) != 0) { return false; @@ -1761,7 +1650,7 @@ void ZRtp::computeHvi(ZrtpPacketDHPart* dh, ZrtpPacketHello *hello) { return; } -void ZRtp:: computeSharedSecretSet(ZIDRecord *zidRec) { +void ZRtp:: computeSharedSecretSet(ZIDRecord &zidRec) { /* * Compute the Initiator's and Reponder's retained shared secret Ids. @@ -1770,64 +1659,45 @@ void ZRtp:: computeSharedSecretSet(ZIDRecord *zidRec) { uint8_t randBuf[RS_LENGTH]; uint32_t macLen; - fprintf(stderr, "Compute shared secrets\n"); - detailInfo.secretsCached = 0; - if (!zidRec->isRs1Valid()) { + if (!zidRec.isRs1Valid()) { randomZRTP(randBuf, RS_LENGTH); hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs1IDi, &macLen); hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), rs1IDr, &macLen); } else { rs1Valid = true; - hmacFunction((unsigned char*)zidRec->getRs1(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs1IDi, &macLen); - hmacFunction((unsigned char*)zidRec->getRs1(), RS_LENGTH, (unsigned char*)responder, strlen(responder), rs1IDr, &macLen); - detailInfo.secretsCached = Rs1; + hmacFunction((unsigned char*)zidRec.getRs1(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs1IDi, &macLen); + hmacFunction((unsigned char*)zidRec.getRs1(), RS_LENGTH, (unsigned char*)responder, strlen(responder), rs1IDr, &macLen); } - if (!zidRec->isRs2Valid()) { + if (!zidRec.isRs2Valid()) { randomZRTP(randBuf, RS_LENGTH); hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs2IDi, &macLen); hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), rs2IDr, &macLen); } else { rs2Valid = true; - hmacFunction((unsigned char*)zidRec->getRs2(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs2IDi, &macLen); - hmacFunction((unsigned char*)zidRec->getRs2(), RS_LENGTH, (unsigned char*)responder, strlen(responder), rs2IDr, &macLen); - detailInfo.secretsCached |= Rs2; + hmacFunction((unsigned char*)zidRec.getRs2(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs2IDi, &macLen); + hmacFunction((unsigned char*)zidRec.getRs2(), RS_LENGTH, (unsigned char*)responder, strlen(responder), rs2IDr, &macLen); } - if (!zidRec->isMITMKeyAvailable()) { + /* + * For the time being we don't support this types of shared secrect. Could be + * easily done: somebody sets some data into our ZRtp object, check it here + * and use it. Otherwise use the random data. + */ + randomZRTP(randBuf, RS_LENGTH); + hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), auxSecretIDi, &macLen); + hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), auxSecretIDr, &macLen); + + if (!zidRec.isMITMKeyAvailable()) { randomZRTP(randBuf, RS_LENGTH); hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), pbxSecretIDi, &macLen); hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), pbxSecretIDr, &macLen); - - } - else { - hmacFunction((unsigned char*)zidRec->getMiTMData(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), pbxSecretIDi, &macLen); - hmacFunction((unsigned char*)zidRec->getMiTMData(), RS_LENGTH, (unsigned char*)responder, strlen(responder), pbxSecretIDr, &macLen); - detailInfo.secretsCached |= Pbx; - } - computeAuxSecretIds(); -} - -void ZRtp::computeAuxSecretIds() { - uint8_t randBuf[RS_LENGTH]; - uint32_t macLen; - - if (auxSecret == NULL) { - randomZRTP(randBuf, RS_LENGTH); - hmacFunction(randBuf, RS_LENGTH, H3, HASH_IMAGE_SIZE, auxSecretIDi, &macLen); - hmacFunction(randBuf, RS_LENGTH, H3, HASH_IMAGE_SIZE, auxSecretIDr, &macLen); } else { - if (myRole == Initiator) { // I'm initiator thus use my H3 for initiator's IDi, peerH3 for respnder's IDr - hmacFunction(auxSecret, auxSecretLength, H3, HASH_IMAGE_SIZE, auxSecretIDi, &macLen); - hmacFunction(auxSecret, auxSecretLength, peerH3, HASH_IMAGE_SIZE, auxSecretIDr, &macLen); - } - else { - hmacFunction(auxSecret, auxSecretLength, peerH3, HASH_IMAGE_SIZE, auxSecretIDi, &macLen); - hmacFunction(auxSecret, auxSecretLength, H3, HASH_IMAGE_SIZE, auxSecretIDr, &macLen); - } + hmacFunction((unsigned char*)zidRec.getMiTMData(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), pbxSecretIDi, &macLen); + hmacFunction((unsigned char*)zidRec.getMiTMData(), RS_LENGTH, (unsigned char*)responder, strlen(responder), pbxSecretIDr, &macLen); } } @@ -1837,70 +1707,49 @@ void ZRtp::computeAuxSecretIds() { * to chapter 5.3 in the specification). * When using this method then we are in Initiator role. */ -void ZRtp::generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { +void ZRtp::generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec) { const uint8_t* setD[3]; int32_t rsFound = 0; setD[0] = setD[1] = setD[2] = NULL; - detailInfo.secretsMatchedDH = 0; - if (memcmp(rs1IDr, dhPart->getRs1Id(), HMAC_SIZE) == 0 || memcmp(rs1IDr, dhPart->getRs2Id(), HMAC_SIZE) == 0) - detailInfo.secretsMatchedDH |= Rs1; - if (memcmp(rs2IDr, dhPart->getRs1Id(), HMAC_SIZE) == 0 || memcmp(rs2IDr, dhPart->getRs2Id(), HMAC_SIZE) == 0) - detailInfo.secretsMatchedDH |= Rs2; /* * Select the real secrets into setD. The dhPart is DHpart1 message * received from responder. rs1IDr and rs2IDr are the expected ids using * the initator's cached retained secrets. */ - // Check which RS we shall use for first place (s1) - detailInfo.secretsMatched = 0; + int matchingSecrets = 0; if (memcmp(rs1IDr, dhPart->getRs1Id(), HMAC_SIZE) == 0) { - setD[0] = zidRec->getRs1(); + setD[matchingSecrets++] = zidRec.getRs1(); rsFound = 0x1; - detailInfo.secretsMatched = Rs1; } else if (memcmp(rs1IDr, dhPart->getRs2Id(), HMAC_SIZE) == 0) { - setD[0] = zidRec->getRs1(); + setD[matchingSecrets++] = zidRec.getRs1(); rsFound = 0x2; - detailInfo.secretsMatched = Rs1; } else if (memcmp(rs2IDr, dhPart->getRs1Id(), HMAC_SIZE) == 0) { - setD[0] = zidRec->getRs2(); + setD[matchingSecrets++] = zidRec.getRs2(); rsFound = 0x4; - detailInfo.secretsMatched = Rs2; } else if (memcmp(rs2IDr, dhPart->getRs2Id(), HMAC_SIZE) == 0) { - setD[0] = zidRec->getRs2(); + setD[matchingSecrets++] = zidRec.getRs2(); rsFound = 0x8; - detailInfo.secretsMatched = Rs2; } - + /* *** Not yet supported if (memcmp(auxSecretIDr, dhPart->getAuxSecretId(), 8) == 0) { - DEBUGOUT((fprintf(stdout, "Initiator: Match for aux secret found\n"))); - setD[1] = auxSecret; - detailInfo.secretsMatched |= Aux; - detailInfo.secretsMatchedDH |= Aux; + DEBUGOUT((fprintf(stdout, "%c: Match for aux secret found\n", zid[0]))); + setD[matchingSecrets++] = auxSecret; } - if (auxSecret != NULL && (detailInfo.secretsMatched & Aux) == 0) { - sendInfo(Warning, WarningNoExpectedAuxMatch); - } - - // check if we have a matching PBX secret and place it third (s3) - if (memcmp(pbxSecretIDr, dhPart->getPbxSecretId(), HMAC_SIZE) == 0) { + */ + if (memcmp(pbxSecretIDr, dhPart->getPbxSecretId(), 8) == 0) { DEBUGOUT((fprintf(stdout, "%c: Match for Other_secret found\n", zid[0]))); - setD[2] = zidRec->getMiTMData(); - detailInfo.secretsMatched |= Pbx; - detailInfo.secretsMatchedDH |= Pbx; - // Flag to record that fact that we have a MitM key of the other peer. - peerIsEnrolled = true; + setD[matchingSecrets++] = zidRec.getMiTMData(); } // Check if some retained secrets found if (rsFound == 0) { // no RS matches found if (rs1Valid || rs2Valid) { // but valid RS records in cache sendInfo(Warning, WarningNoExpectedRSMatch); - zidRec->resetSasVerified(); - saveZidRecord = false; // Don't save RS until user verfied/confirmed SAS + zidRec.resetSasVerified(); } else { // No valid RS record in cache sendInfo(Warning, WarningNoRSMatch); @@ -1934,7 +1783,7 @@ void ZRtp::generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { //Very first element is a fixed counter, big endian counter = 1; - counter = zrtpHtonl(counter); + counter = htonl(counter); data[pos] = (unsigned char*)&counter; length[pos++] = sizeof(uint32_t); @@ -1948,7 +1797,7 @@ void ZRtp::generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { // Next is Initiator's id (ZIDi), in this case as Initiator // it is zid - data[pos] = ownZid; + data[pos] = zid; length[pos++] = ZID_SIZE; // Next is Responder's id (ZIDr), in this case our peer's id @@ -1969,7 +1818,7 @@ void ZRtp::generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { * this length stuff again. */ int secretHashLen = RS_LENGTH; - secretHashLen = zrtpHtonl(secretHashLen); // prepare 32 bit big-endian number + secretHashLen = htonl(secretHashLen); // prepare 32 bit big-endian number for (int32_t i = 0; i < 3; i++) { if (setD[i] != NULL) { // a matching secret, set length, then secret @@ -1977,7 +1826,7 @@ void ZRtp::generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { data[pos] = (unsigned char*)&sLen[i]; length[pos++] = sizeof(uint32_t); data[pos] = (unsigned char*)setD[i]; - length[pos++] = (i != 1) ? RS_LENGTH : auxSecretLength; + length[pos++] = RS_LENGTH; } else { // no machting secret, set length 0, skip secret sLen[i] = 0; @@ -2002,68 +1851,47 @@ void ZRtp::generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { * retained secret ids. Compare them with the expected secret ids (refer * to chapter 5.3.1 in the specification). */ -void ZRtp::generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { +void ZRtp::generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec) { const uint8_t* setD[3]; int32_t rsFound = 0; setD[0] = setD[1] = setD[2] = NULL; - detailInfo.secretsMatchedDH = 0; - if (memcmp(rs1IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0 || memcmp(rs1IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0) - detailInfo.secretsMatchedDH |= Rs1; - if (memcmp(rs2IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0 || memcmp(rs2IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0) - detailInfo.secretsMatchedDH |= Rs2; - /* * Select the real secrets into setD */ - // Check which RS we shall use for first place (s1) - detailInfo.secretsMatched = 0; + int matchingSecrets = 0; if (memcmp(rs1IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0) { - setD[0] = zidRec->getRs1(); + setD[matchingSecrets++] = zidRec.getRs1(); rsFound = 0x1; - detailInfo.secretsMatched = Rs1; } else if (memcmp(rs1IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0) { - setD[0] = zidRec->getRs1(); + setD[matchingSecrets++] = zidRec.getRs1(); rsFound = 0x2; - detailInfo.secretsMatched = Rs1; } - else if (memcmp(rs2IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0) { - setD[0] = zidRec->getRs2(); + else if (memcmp(rs2IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0) { + setD[matchingSecrets++] = zidRec.getRs2(); rsFound |= 0x4; - detailInfo.secretsMatched = Rs2; } - else if (memcmp(rs2IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0) { - setD[0] = zidRec->getRs2(); + else if (memcmp(rs2IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0) { + setD[matchingSecrets++] = zidRec.getRs2(); rsFound |= 0x8; - detailInfo.secretsMatched = Rs2; } - - if (memcmp(auxSecretIDi, dhPart->getAuxSecretId(), 8) == 0) { - DEBUGOUT((fprintf(stdout, "Responder: Match for aux secret found\n"))); - setD[1] = auxSecret; - detailInfo.secretsMatched |= Aux; - detailInfo.secretsMatchedDH |= Aux; - } - // If we have an auxSecret but no match from peer - report this. - if (auxSecret != NULL && (detailInfo.secretsMatched & Aux) == 0) { - sendInfo(Warning, WarningNoExpectedAuxMatch); + /* ***** not yet supported + if (memcmp(auxSecretIDi, dhPart->getauxSecretId(), 8) == 0) { + DEBUGOUT((fprintf(stdout, "%c: Match for aux secret found\n", zid[0]))); + setD[matchingSecrets++] = ; } - + */ if (memcmp(pbxSecretIDi, dhPart->getPbxSecretId(), 8) == 0) { - DEBUGOUT((fprintf(stdout, "%c: Match for PBX secret found\n", ownZid[0]))); - setD[2] = zidRec->getMiTMData(); - detailInfo.secretsMatched |= Pbx; - detailInfo.secretsMatchedDH |= Pbx; - peerIsEnrolled = true; + DEBUGOUT((fprintf(stdout, "%c: Match for PBX secret found\n", zid[0]))); + setD[matchingSecrets++] = zidRec.getMiTMData(); } // Check if some retained secrets found if (rsFound == 0) { // no RS matches found if (rs1Valid || rs2Valid) { // but valid RS records in cache sendInfo(Warning, WarningNoExpectedRSMatch); - zidRec->resetSasVerified(); - saveZidRecord = false; // Don't save RS until user verfied/confirmed SAS + zidRec.resetSasVerified(); } else { // No valid RS record in cache sendInfo(Warning, WarningNoRSMatch); @@ -2099,7 +1927,7 @@ void ZRtp::generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { //Very first element is a fixed counter, big endian counter = 1; - counter = zrtpHtonl(counter); + counter = htonl(counter); data[pos] = (unsigned char*)&counter; length[pos++] = sizeof(uint32_t); @@ -2117,7 +1945,7 @@ void ZRtp::generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { length[pos++] = ZID_SIZE; // Next is Responder's id (ZIDr), in this case our own zid - data[pos] = ownZid; + data[pos] = zid; length[pos++] = ZID_SIZE; // Next ist total hash (messageHash) itself @@ -2134,7 +1962,7 @@ void ZRtp::generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { * this length stuff again. */ int secretHashLen = RS_LENGTH; - secretHashLen = zrtpHtonl(secretHashLen); // prepare 32 bit big-endian number + secretHashLen = htonl(secretHashLen); // prepare 32 bit big-endian number for (int32_t i = 0; i < 3; i++) { if (setD[i] != NULL) { // a matching secret, set length, then secret @@ -2142,7 +1970,7 @@ void ZRtp::generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) { data[pos] = (unsigned char*)&sLen[i]; length[pos++] = sizeof(uint32_t); data[pos] = (unsigned char*)setD[i]; - length[pos++] = (i != 1) ? RS_LENGTH : auxSecretLength; + length[pos++] = RS_LENGTH; } else { // no machting secret, set length 0, skip secret sLen[i] = 0; @@ -2174,7 +2002,7 @@ void ZRtp::KDF(uint8_t* key, uint32_t keyLength, uint8_t* label, int32_t labelLe // Very first element is a fixed counter, big endian uint32_t counter = 1; - counter = zrtpHtonl(counter); + counter = htonl(counter); data[pos] = (unsigned char*)&counter; length[pos++] = sizeof(uint32_t); @@ -2187,7 +2015,7 @@ void ZRtp::KDF(uint8_t* key, uint32_t keyLength, uint8_t* label, int32_t labelLe length[pos++] = contextLength; // last element is HMAC length in bits, big endian - uint32_t len = zrtpHtonl(L); + uint32_t len = htonl(L); data[pos] = (unsigned char*)&len; length[pos++] = sizeof(uint32_t); @@ -2201,18 +2029,18 @@ void ZRtp::KDF(uint8_t* key, uint32_t keyLength, uint8_t* label, int32_t labelLe void ZRtp::generateKeysMultiStream() { // allocate the maximum size, compute real size to use - uint8_t KDFcontext[sizeof(peerZid)+sizeof(ownZid)+sizeof(messageHash)]; - int32_t kdfSize = sizeof(peerZid)+sizeof(ownZid)+hashLength; + uint8_t KDFcontext[sizeof(peerZid)+sizeof(zid)+sizeof(messageHash)]; + int32_t kdfSize = sizeof(peerZid)+sizeof(zid)+hashLength; if (myRole == Responder) { memcpy(KDFcontext, peerZid, sizeof(peerZid)); - memcpy(KDFcontext+sizeof(peerZid), ownZid, sizeof(ownZid)); + memcpy(KDFcontext+sizeof(peerZid), zid, sizeof(zid)); } else { - memcpy(KDFcontext, ownZid, sizeof(ownZid)); - memcpy(KDFcontext+sizeof(ownZid), peerZid, sizeof(peerZid)); + memcpy(KDFcontext, zid, sizeof(zid)); + memcpy(KDFcontext+sizeof(zid), peerZid, sizeof(peerZid)); } - memcpy(KDFcontext+sizeof(ownZid)+sizeof(peerZid), messageHash, hashLength); + memcpy(KDFcontext+sizeof(zid)+sizeof(peerZid), messageHash, hashLength); KDF(zrtpSession, hashLength, (unsigned char*)zrtpMsk, strlen(zrtpMsk)+1, KDFcontext, kdfSize, hashLength*8, s0); @@ -2224,16 +2052,16 @@ void ZRtp::generateKeysMultiStream() { void ZRtp::computePBXSecret() { // Construct the KDF context as per ZRTP specification chap 7.3.1: // ZIDi || ZIDr - uint8_t KDFcontext[sizeof(peerZid)+sizeof(ownZid)]; - int32_t kdfSize = sizeof(peerZid)+sizeof(ownZid); + uint8_t KDFcontext[sizeof(peerZid)+sizeof(zid)]; + int32_t kdfSize = sizeof(peerZid)+sizeof(zid); if (myRole == Responder) { memcpy(KDFcontext, peerZid, sizeof(peerZid)); - memcpy(KDFcontext+sizeof(peerZid), ownZid, sizeof(ownZid)); + memcpy(KDFcontext+sizeof(peerZid), zid, sizeof(zid)); } else { - memcpy(KDFcontext, ownZid, sizeof(ownZid)); - memcpy(KDFcontext+sizeof(ownZid), peerZid, sizeof(peerZid)); + memcpy(KDFcontext, zid, sizeof(zid)); + memcpy(KDFcontext+sizeof(zid), peerZid, sizeof(peerZid)); } KDF(zrtpSession, hashLength, (unsigned char*)zrtpTrustedMitm, strlen(zrtpTrustedMitm)+1, KDFcontext, @@ -2246,20 +2074,20 @@ void ZRtp::computePBXSecret() { void ZRtp::computeSRTPKeys() { // allocate the maximum size, compute real size to use - uint8_t KDFcontext[sizeof(peerZid)+sizeof(ownZid)+sizeof(messageHash)]; - int32_t kdfSize = sizeof(peerZid)+sizeof(ownZid)+hashLength; + uint8_t KDFcontext[sizeof(peerZid)+sizeof(zid)+sizeof(messageHash)]; + int32_t kdfSize = sizeof(peerZid)+sizeof(zid)+hashLength; int32_t keyLen = cipher->getKeylen() * 8; if (myRole == Responder) { memcpy(KDFcontext, peerZid, sizeof(peerZid)); - memcpy(KDFcontext+sizeof(peerZid), ownZid, sizeof(ownZid)); + memcpy(KDFcontext+sizeof(peerZid), zid, sizeof(zid)); } else { - memcpy(KDFcontext, ownZid, sizeof(ownZid)); - memcpy(KDFcontext+sizeof(ownZid), peerZid, sizeof(peerZid)); + memcpy(KDFcontext, zid, sizeof(zid)); + memcpy(KDFcontext+sizeof(zid), peerZid, sizeof(peerZid)); } - memcpy(KDFcontext+sizeof(ownZid)+sizeof(peerZid), messageHash, hashLength); + memcpy(KDFcontext+sizeof(zid)+sizeof(peerZid), messageHash, hashLength); // Inititiator key and salt KDF(s0, hashLength, (unsigned char*)iniMasterKey, strlen(iniMasterKey)+1, KDFcontext, kdfSize, keyLen, srtpKeyI); @@ -2271,13 +2099,13 @@ void ZRtp::computeSRTPKeys() { // The HMAC keys for GoClear KDF(s0, hashLength, (unsigned char*)iniHmacKey, strlen(iniHmacKey)+1, KDFcontext, kdfSize, hashLength*8, hmacKeyI); + KDF(s0, hashLength, (unsigned char*)respHmacKey, strlen(respHmacKey)+1, KDFcontext, kdfSize, hashLength*8, hmacKeyR); // The keys for Confirm messages KDF(s0, hashLength, (unsigned char*)iniZrtpKey, strlen(iniZrtpKey)+1, KDFcontext, kdfSize, keyLen, zrtpKeyI); KDF(s0, hashLength, (unsigned char*)respZrtpKey, strlen(respZrtpKey)+1, KDFcontext, kdfSize, keyLen, zrtpKeyR); - detailInfo.pubKey = detailInfo.sasType = NULL; if (!multiStream) { // Compute the new Retained Secret KDF(s0, hashLength, (unsigned char*)retainedSec, strlen(retainedSec)+1, KDFcontext, kdfSize, SHA256_DIGEST_LENGTH*8, newRs1); @@ -2285,7 +2113,7 @@ void ZRtp::computeSRTPKeys() { // Compute the ZRTP Session Key KDF(s0, hashLength, (unsigned char*)zrtpSessionKey, strlen(zrtpSessionKey)+1, KDFcontext, kdfSize, hashLength*8, zrtpSession); - // perform generation according to chapter 5.5 and 8. + // perform SAS generation according to chapter 5.5 and 8. // we don't need a speciai sasValue filed. sasValue are the first // (leftmost) 32 bits (4 bytes) of sasHash uint8_t sasBytes[4]; @@ -2298,24 +2126,10 @@ void ZRtp::computeSRTPKeys() { sasBytes[1] = sasHash[1]; sasBytes[2] = sasHash[2] & 0xf0; sasBytes[3] = 0; - if (*(int32_t*)b32 == *(int32_t*)(sasType->getName())) { - SAS = Base32(sasBytes, 20).getEncoded(); - } - else { - SAS.assign(sas256WordsEven[sasBytes[0]]).append(":").append(sas256WordsOdd[sasBytes[1]]); - } - + SAS = Base32(sasBytes, 20).getEncoded(); if (signSasSeen) callback->signSAS(sasHash); - - detailInfo.pubKey = pubKey->getReadable(); - detailInfo.sasType = sasType->getReadable(); } - // set algorithm names into detailInfo structure - detailInfo.authLength = authLength->getReadable(); - detailInfo.cipher = cipher->getReadable(); - detailInfo.hash = hash->getReadable(); - memset(KDFcontext, 0, sizeof(KDFcontext)); } @@ -2341,25 +2155,7 @@ bool ZRtp::srtpSecretsReady(EnableSecurity part) { sec.sas = SAS; sec.role = myRole; - bool rc = callback->srtpSecretsReady(&sec, part); - - // The call state engine calls ForSender always after ForReceiver. - if (part == ForSender) { - std::string cs(cipher->getReadable()); - if (!multiStream) { - cs.append("/").append(pubKey->getName()); - if (mitmSeen) - cs.append("/EndAtMitM"); - callback->srtpSecretsOn(cs, SAS, zidRec->isSasVerified()); - } - else { - std::string cs1(""); - if (mitmSeen) - cs.append("/EndAtMitM"); - callback->srtpSecretsOn(cs, cs1, true); - } - } - return rc; + return callback->srtpSecretsReady(&sec, part); } @@ -2392,34 +2188,6 @@ void ZRtp::setNegotiatedHash(AlgorithmEnum* hash) { hashCtxFunction = sha384Ctx; hashCtxListFunction = sha384Ctx; break; - - case 2: - hashLength = SKEIN256_DIGEST_LENGTH; - hashFunction = skein256; - hashListFunction = skein256; - - hmacFunction = macSkein256; - hmacListFunction = macSkein256; - - createHashCtx = createSkein256Context; - closeHashCtx = closeSkein256Context; - hashCtxFunction = skein256Ctx; - hashCtxListFunction = skein256Ctx; - break; - - case 3: - hashLength = SKEIN384_DIGEST_LENGTH; - hashFunction = skein384; - hashListFunction = skein384; - - hmacFunction = macSkein384; - hmacListFunction = macSkein384; - - createHashCtx = createSkein384Context; - closeHashCtx = closeSkein384Context; - hashCtxFunction = skein384Ctx; - hashCtxListFunction = skein384Ctx; - break; } } @@ -2432,25 +2200,25 @@ void ZRtp::SASVerified() { if (paranoidMode) return; - zidRec->setSasVerified(); - saveZidRecord = true; - getZidCacheInstance()->saveRecord(zidRec); + // Initialize a ZID record to get peer's retained secrets + ZIDRecord zidRec(peerZid); + ZIDFile *zid = ZIDFile::getInstance(); + + zid->getRecord(&zidRec); + zidRec.setSasVerified(); + zid->saveRecord(&zidRec); } void ZRtp::resetSASVerified() { + // Initialize a ZID record to get peer's retained secrets + ZIDRecord zidRec(peerZid); + ZIDFile *zid = ZIDFile::getInstance(); - zidRec->resetSasVerified(); - getZidCacheInstance()->saveRecord(zidRec); + zid->getRecord(&zidRec); + zidRec.resetSasVerified(); + zid->saveRecord(&zidRec); } -void ZRtp::setRs2Valid() { - - if (zidRec != NULL) { - zidRec->setRs2Valid(); - if (saveZidRecord) - getZidCacheInstance()->saveRecord(zidRec); - } -} void ZRtp::sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) { @@ -2502,32 +2270,33 @@ void ZRtp::setAuxSecret(uint8_t* data, int32_t length) { } } -void ZRtp::setClientId(std::string id, HelloPacketVersion* hpv) { - - unsigned char tmp[CLIENT_ID_SIZE +1] = {' '}; - memcpy(tmp, id.c_str(), id.size() > CLIENT_ID_SIZE ? CLIENT_ID_SIZE : id.size()); - tmp[CLIENT_ID_SIZE] = 0; - - hpv->packet->setClientId(tmp); +void ZRtp::setClientId(std::string id) { + if (id.size() < CLIENT_ID_SIZE) { + unsigned char tmp[CLIENT_ID_SIZE +1] = {' '}; + memcpy(tmp, id.c_str(), id.size()); + tmp[CLIENT_ID_SIZE] = 0; + zrtpHello.setClientId(tmp); + } else { + zrtpHello.setClientId((unsigned char*)id.c_str()); + } - int32_t len = hpv->packet->getLength() * ZRTP_WORD_SIZE; + int32_t len = zrtpHello.getLength() * ZRTP_WORD_SIZE; - // Hello packets are ready now, compute its HMAC + // Hello packet is ready now, compute its HMAC // (excluding the HMAC field (2*ZTP_WORD_SIZE)) and store in Hello // use the implicit hash function uint8_t hmac[IMPL_MAX_DIGEST_LENGTH]; uint32_t macLen; - hmacFunctionImpl(H2, HASH_IMAGE_SIZE, (uint8_t*)hpv->packet->getHeaderBase(), len-(2*ZRTP_WORD_SIZE), hmac, &macLen); - hpv->packet->setHMAC(hmac); + hmacFunctionImpl(H2, HASH_IMAGE_SIZE, (uint8_t*)zrtpHello.getHeaderBase(), len-(2*ZRTP_WORD_SIZE), hmac, &macLen); + zrtpHello.setHMAC(hmac); // calculate hash over the final Hello packet, refer to chap 9.1 how to // use this hash in SIP/SDP. - hashFunctionImpl((uint8_t*)hpv->packet->getHeaderBase(), len, hpv->helloHash); + hashFunctionImpl((uint8_t*)zrtpHello.getHeaderBase(), len, helloHash); } void ZRtp::storeMsgTemp(ZrtpPacketBase* pkt) { - uint32_t length = pkt->getLength() * ZRTP_WORD_SIZE; - length = (length > sizeof(tempMsgBuffer)) ? sizeof(tempMsgBuffer) : length; + int32_t length = pkt->getLength() * ZRTP_WORD_SIZE; memset(tempMsgBuffer, 0, sizeof(tempMsgBuffer)); memcpy(tempMsgBuffer, (uint8_t*)pkt->getHeaderBase(), length); lengthOfMsgData = length; @@ -2543,18 +2312,12 @@ bool ZRtp::checkMsgHmac(uint8_t* key) { return (memcmp(hmac, tempMsgBuffer+len, (HMAC_SIZE)) == 0 ? true : false); } -std::string ZRtp::getHelloHash(int32_t index) { +std::string ZRtp::getHelloHash() { std::ostringstream stm; - if (index < 0 || index >= MAX_ZRTP_VERSIONS) - return std::string(); - - uint8_t* hp = helloPackets[index].helloHash; - - char version[5] = {'\0'}; - strncpy(version, (const char*)helloPackets[index].packet->getVersion(), ZRTP_WORD_SIZE); + uint8_t* hp = helloHash; - stm << version; + stm << zrtpVersion; stm << " "; stm.fill('0'); stm << hex; @@ -2634,19 +2397,24 @@ bool ZRtp::isMultiStreamAvailable() { void ZRtp::acceptEnrollment(bool accepted) { if (!accepted) { - zidRec->resetMITMKeyAvailable(); callback->zrtpInformEnrollment(EnrollmentCanceled); - getZidCacheInstance()->saveRecord(zidRec); return; } + // Get peer's zid record to store the pbx (MitM) secret + // Initialize a ZID record to get peer's retained secrets + ZIDRecord zidRec(peerZid); + ZIDFile* zid = ZIDFile::getInstance(); + zid->getRecord(&zidRec); + if (pbxSecretTmp != NULL) { - zidRec->setMiTMData(pbxSecretTmp); - getZidCacheInstance()->saveRecord(zidRec); + zidRec.setMiTMData(pbxSecretTmp); callback->zrtpInformEnrollment(EnrollmentOk); } else { callback->zrtpInformEnrollment(EnrollmentFailed); + return; } + zid->saveRecord(&zidRec); return; } @@ -2671,8 +2439,7 @@ void ZRtp::conf2AckSecure() { Event_t ev; ev.type = ZrtpPacket; - ev.packet = (uint8_t*)zrtpConf2Ack.getHeaderBase(); - ev.length = sizeof (Conf2AckPacket_t) + 12; // 12 is fixed ZRTP (RTP) header size + ev.packet = (uint8_t*)&zrtpConf2Ack; if (stateEngine != NULL) { stateEngine->processEvent(&ev); @@ -2680,8 +2447,7 @@ void ZRtp::conf2AckSecure() { } int32_t ZRtp::compareCommit(ZrtpPacketCommit *commit) { - // TODO: enhance to compare according to rules defined in chapter 4.2, - // but we don't support Preshared. + // TODO: enhance to compare according to rules defined in chapter 4.2 int32_t len = 0; len = !multiStream ? HVI_SIZE : (4 * ZRTP_WORD_SIZE); return (memcmp(hvi, commit->getHvi(), len)); @@ -2720,8 +2486,9 @@ bool ZRtp::sendSASRelayPacket(uint8_t* sh, std::string render) { randomZRTP(randomIV, sizeof(randomIV)); zrtpSasRelay.setIv(randomIV); zrtpSasRelay.setTrustedSas(sh); - zrtpSasRelay.setSasAlgo((uint8_t*)render.c_str()); + zrtpSasRelay.setSas((uint8_t*)render.c_str()); + // Encrypt and HMAC with Initiator's key - we are Initiator here int16_t hmlen = (zrtpSasRelay.getLength() - 9) * ZRTP_WORD_SIZE; cipher->getEncrypt()(ekey, cipher->getKeylen(), randomIV, (uint8_t*)zrtpSasRelay.getFiller(), hmlen); @@ -2748,22 +2515,6 @@ int32_t ZRtp::getPeerZid(uint8_t* data) { return IDENTIFIER_LEN; } -const ZRtp::zrtpInfo* ZRtp::getDetailInfo() { - return &detailInfo; -} - -std::string ZRtp::getPeerClientId() { - if (peerClientId.empty()) - return std::string(); - return peerClientId; -} - -std::string ZRtp::getPeerProtcolVersion() { - if (peerHelloVersion[0] == 0) - return std::string(); - return std::string((char*)peerHelloVersion); -} - /** EMACS ** * Local variables: * mode: c++ diff --git a/jni/libzrtp/sources/zrtp/ZrtpCWrapper.cpp b/jni/libzrtp/sources/src/ZrtpCWrapper.cpp similarity index 94% rename from jni/libzrtp/sources/zrtp/ZrtpCWrapper.cpp rename to jni/libzrtp/sources/src/ZrtpCWrapper.cpp index 7f7c3dd7c..1e1d2c882 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpCWrapper.cpp +++ b/jni/libzrtp/sources/src/ZrtpCWrapper.cpp @@ -1,9 +1,9 @@ /* This class maps the ZRTP C calls to ZRTP C++ methods. - Copyright (C) 2010-2013 Werner Dittmann + Copyright (C) 2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -19,7 +19,7 @@ #include <libzrtpcpp/ZrtpCallback.h> #include <libzrtpcpp/ZrtpConfigure.h> -#include <libzrtpcpp/ZIDCache.h> +#include <libzrtpcpp/ZIDFile.h> #include <libzrtpcpp/ZRtp.h> #include <libzrtpcpp/ZrtpCallbackWrapper.h> #include <libzrtpcpp/ZrtpCWrapper.h> @@ -55,7 +55,8 @@ void zrtp_initializeZrtpEngine(ZrtpContext* zrtpContext, // Initialize ZID file (cache) and get my own ZID zrtp_initZidFile(zidFilename); - const unsigned char* myZid = getZidCacheInstance()->getZid(); + ZIDFile* zf = ZIDFile::getInstance(); + const unsigned char* myZid = zf->getZid(); zrtpContext->zrtpEngine = new ZRtp((uint8_t*)myZid, zrtpContext->zrtpCallback, clientIdString, zrtpContext->configure, mitmMode == 0 ? false : true); @@ -79,7 +80,7 @@ void zrtp_DestroyWrapper(ZrtpContext* zrtpContext) { } static int32_t zrtp_initZidFile(const char* zidFilename) { - ZIDCache* zf = getZidCacheInstance(); + ZIDFile* zf = ZIDFile::getInstance(); if (!zf->isOpen()) { std::string fname; @@ -124,9 +125,9 @@ void zrtp_stopZrtpEngine(ZrtpContext* zrtpContext) { zrtpContext->zrtpEngine->stopZrtp(); } -void zrtp_processZrtpMessage(ZrtpContext* zrtpContext, uint8_t *extHeader, uint32_t peerSSRC, size_t length) { +void zrtp_processZrtpMessage(ZrtpContext* zrtpContext, uint8_t *extHeader, uint32_t peerSSRC) { if (zrtpContext && zrtpContext->zrtpEngine) - zrtpContext->zrtpEngine->processZrtpMessage(extHeader, peerSSRC, length); + zrtpContext->zrtpEngine->processZrtpMessage(extHeader, peerSSRC); } void zrtp_processTimeout(ZrtpContext* zrtpContext) { @@ -164,10 +165,10 @@ void zrtp_resetSASVerified(ZrtpContext* zrtpContext) { zrtpContext->zrtpEngine->resetSASVerified(); } -char* zrtp_getHelloHash(ZrtpContext* zrtpContext, int32_t index) { +char* zrtp_getHelloHash(ZrtpContext* zrtpContext) { std::string ret; if (zrtpContext && zrtpContext->zrtpEngine) - ret = zrtpContext->zrtpEngine->getHelloHash(index); + ret = zrtpContext->zrtpEngine->getHelloHash(); else return NULL; @@ -324,13 +325,6 @@ int32_t zrtp_getPeerZid(ZrtpContext* zrtpContext, uint8_t* data) { return 0; } -int32_t zrtp_getNumberSupportedVersions(ZrtpContext* zrtpContext) { - return zrtpContext->zrtpEngine->getNumberSupportedVersions(); -} - -int32_t zrtp_getCurrentProtocolVersion(ZrtpContext* zrtpContext) { - return zrtpContext->zrtpEngine->getCurrentProtocolVersion(); -} /* * The following methods wrap the ZRTP Configure functions */ diff --git a/jni/libzrtp/sources/zrtp/ZrtpCallbackWrapper.cpp b/jni/libzrtp/sources/src/ZrtpCallbackWrapper.cpp similarity index 97% rename from jni/libzrtp/sources/zrtp/ZrtpCallbackWrapper.cpp rename to jni/libzrtp/sources/src/ZrtpCallbackWrapper.cpp index fed2c0453..ca2dce6bc 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpCallbackWrapper.cpp +++ b/jni/libzrtp/sources/src/ZrtpCallbackWrapper.cpp @@ -1,9 +1,9 @@ /* This class maps the ZRTP C++ callback methods to C callback methods. - Copyright (C) 2010-2013 Werner Dittmann + Copyright (C) 2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/ZrtpConfigure.cpp b/jni/libzrtp/sources/src/ZrtpConfigure.cpp similarity index 82% rename from jni/libzrtp/sources/zrtp/ZrtpConfigure.cpp rename to jni/libzrtp/sources/src/ZrtpConfigure.cpp index 6a22983b5..560466f3a 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpConfigure.cpp +++ b/jni/libzrtp/sources/src/ZrtpConfigure.cpp @@ -1,26 +1,5 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Authors: Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#include <crypto/aesCFB.h> -#include <crypto/twoCFB.h> +#include <libzrtpcpp/crypto/aesCFB.h> +#include <libzrtpcpp/crypto/twoCFB.h> #include <libzrtpcpp/ZrtpConfigure.h> #include <libzrtpcpp/ZrtpTextData.h> @@ -154,10 +133,8 @@ std::list<std::string>* EnumBase::getAllNames() { * Set up the enumeration list for available hash algorithms */ HashEnum::HashEnum() : EnumBase(HashAlgorithm) { - insert(s256, 0, "SHA-256", NULL, NULL, None); - insert(s384, 0, "SHA-384", NULL, NULL, None); - insert(skn2, 0, "Skein-256", NULL, NULL, None); - insert(skn3, 0, "Skein-384", NULL, NULL, None); + insert(s256); + insert(s384); } HashEnum::~HashEnum() {} @@ -166,10 +143,10 @@ HashEnum::~HashEnum() {} * Set up the enumeration list for available symmetric cipher algorithms */ SymCipherEnum::SymCipherEnum() : EnumBase(CipherAlgorithm) { - insert(aes3, 32, "AES-256", aesCfbEncrypt, aesCfbDecrypt, Aes); - insert(aes1, 16, "AES-128", aesCfbEncrypt, aesCfbDecrypt, Aes); - insert(two3, 32, "Twofish-256", twoCfbEncrypt, twoCfbDecrypt, TwoFish); - insert(two1, 16, "TwoFish-128", twoCfbEncrypt, twoCfbDecrypt, TwoFish); + insert(aes3, 32, "AES-CM-256", aesCfbEncrypt, aesCfbDecrypt, Aes); + insert(aes1, 16, "AES-CM-128", aesCfbEncrypt, aesCfbDecrypt, Aes); + insert(two3, 32, "TWO-CM-256", twoCfbEncrypt, twoCfbDecrypt, TwoFish); + insert(two1, 16, "TWO-CM-128", twoCfbEncrypt, twoCfbDecrypt, TwoFish); } SymCipherEnum::~SymCipherEnum() {} @@ -178,15 +155,11 @@ SymCipherEnum::~SymCipherEnum() {} * Set up the enumeration list for available public key algorithms */ PubKeyEnum::PubKeyEnum() : EnumBase(PubKeyAlgorithm) { - insert(dh2k, 0, "DH-2048", NULL, NULL, None); - insert(ec25, 0, "NIST ECDH-256", NULL, NULL, None); - insert(dh3k, 0, "DH-3072", NULL, NULL, None); - insert(ec38, 0, "NIST ECDH-384", NULL, NULL, None); - insert(mult, 0, "Multi-stream", NULL, NULL, None); -#ifdef SUPPORT_NON_NIST - insert(e255, 0, "ECDH-255", NULL, NULL, None); - insert(e414, 0, "ECDH-414", NULL, NULL, None); -#endif + insert(dh2k); + insert(dh3k); + insert(mult); + insert(ec25); + insert(ec38); } PubKeyEnum::~PubKeyEnum() {} @@ -196,7 +169,6 @@ PubKeyEnum::~PubKeyEnum() {} */ SasTypeEnum::SasTypeEnum() : EnumBase(SasType) { insert(b32); - insert(b256); } SasTypeEnum::~SasTypeEnum() {} @@ -205,10 +177,10 @@ SasTypeEnum::~SasTypeEnum() {} * Set up the enumeration list for available SRTP authentications */ AuthLengthEnum::AuthLengthEnum() : EnumBase(AuthLength) { - insert(hs32, 32, "HMAC-SHA1 32 bit", NULL, NULL, Sha1); - insert(hs80, 80, "HMAC-SHA1 80 bit", NULL, NULL, Sha1); - insert(sk32, 32, "Skein-MAC 32 bit", NULL, NULL, Skein); - insert(sk64, 64, "Skein-MAC 64 bit", NULL, NULL, Skein); + insert(hs32, 32, "", NULL, NULL, Sha1); + insert(hs80, 80, "", NULL, NULL, Sha1); + insert(sk32, 32, "", NULL, NULL, Skein); + insert(sk64, 64, "", NULL, NULL, Skein); } AuthLengthEnum::~AuthLengthEnum() {} @@ -225,8 +197,7 @@ AuthLengthEnum zrtpAuthLengths; /* * The public methods are mainly a facade to the private methods. */ -ZrtpConfigure::ZrtpConfigure(): enableTrustedMitM(false), enableSasSignature(false), enableParanoidMode(false), -selectionPolicy(Standard){} +ZrtpConfigure::ZrtpConfigure() : enableTrustedMitM(false), enableSasSignature(false), enableParanoidMode(false) {} ZrtpConfigure::~ZrtpConfigure() {} diff --git a/jni/libzrtp/sources/zrtp/ZrtpCrc32.cpp b/jni/libzrtp/sources/src/ZrtpCrc32.cpp similarity index 74% rename from jni/libzrtp/sources/zrtp/ZrtpCrc32.cpp rename to jni/libzrtp/sources/src/ZrtpCrc32.cpp index 060656143..c65b19a5c 100755 --- a/jni/libzrtp/sources/zrtp/ZrtpCrc32.cpp +++ b/jni/libzrtp/sources/src/ZrtpCrc32.cpp @@ -1,7 +1,46 @@ +/* SCTP kernel reference Implementation + * Copyright (c) 1999-2001 Motorola, Inc. + * Copyright (c) 2001-2003 International Business Machines, Corp. + * + * SCTP Checksum functions + * + * The SCTP reference implementation is free software; + * you can redistribute it and/or modify it under the terms of + * the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * The SCTP reference implementation is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * ************************ + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU CC; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Please send any bug reports or fixes you make to the + * email address(es): + * lksctp developers <lksctp-developers@lists.sourceforge.net> + * + * Or submit a bug report through the following website: + * http://www.sf.net/projects/lksctp + * + * Written or modified by: + * Dinakaran Joseph + * Jon Grimm <jgrimm@us.ibm.com> + * Sridhar Samudrala <sri@us.ibm.com> + * + * Any bugs reported given to us we will try to fix... any fixes shared will + * be incorporated into the next SCTP release. + */ + /* The following code has been taken directly from * draft-ietf-tsvwg-sctpcsum-03.txt * - * The code has now been modified by Werner.Dittmann@t-online.de for use + * The code has now been modified by Werner.Dittmann@t-online.de for use * inside the ZRTP implementation. */ @@ -145,10 +184,40 @@ uint32_t zrtpEndCksum(uint32_t crc32) byte3 = (result>>24) & 0xff; crc32 = ((byte0 << 24) | - (byte1 << 16) | - (byte2 << 8) | - byte3); + (byte1 << 16) | + (byte2 << 8) | + byte3); // fprintf(stderr, "Computed crc32: %x\n", crc32); return crc32; } +#ifdef UNIT_TEST +uint8_t test_data[48] = { + 0x01, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x01, 0xFE, 0x60, 0xAC, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x09, + 0x25, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +int main( int argc, char * argv[] ) +{ + crc32c = sctp_update_cksum(test_data, 48); + printf("Hello World, expected result: 0x664f75eb\n"); + printf("Result is: 0x%x\n", crc32c); +} +#endif +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketClearAck.cpp b/jni/libzrtp/sources/src/ZrtpPacketClearAck.cpp similarity index 91% rename from jni/libzrtp/sources/zrtp/ZrtpPacketClearAck.cpp rename to jni/libzrtp/sources/src/ZrtpPacketClearAck.cpp index 5a96f5299..85f14844f 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketClearAck.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketClearAck.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketCommit.cpp b/jni/libzrtp/sources/src/ZrtpPacketCommit.cpp similarity index 93% rename from jni/libzrtp/sources/zrtp/ZrtpPacketCommit.cpp rename to jni/libzrtp/sources/src/ZrtpPacketCommit.cpp index b58277742..af4bb0915 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketCommit.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketCommit.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketConf2Ack.cpp b/jni/libzrtp/sources/src/ZrtpPacketConf2Ack.cpp similarity index 91% rename from jni/libzrtp/sources/zrtp/ZrtpPacketConf2Ack.cpp rename to jni/libzrtp/sources/src/ZrtpPacketConf2Ack.cpp index 67a51eed2..f35dc8221 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketConf2Ack.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketConf2Ack.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketConfirm.cpp b/jni/libzrtp/sources/src/ZrtpPacketConfirm.cpp similarity index 84% rename from jni/libzrtp/sources/zrtp/ZrtpPacketConfirm.cpp rename to jni/libzrtp/sources/src/ZrtpPacketConfirm.cpp index 6f13caebf..f5587592a 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketConfirm.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketConfirm.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -66,17 +66,6 @@ bool ZrtpPacketConfirm::setSignatureData(uint8_t* data, int32_t length) { return true; } -bool ZrtpPacketConfirm::isSignatureLengthOk() { - int32_t actualLen = getLength(); - int32_t expectedLen = 19; // Confirm packet fixed part is 19 ZRTP words - int32_t sigLen = getSignatureLength(); - - if (sigLen > 0) { // We have a signature - expectedLen += sigLen + 1; // +1 for the signature length field - } - return (expectedLen == actualLen); -} - int32_t ZrtpPacketConfirm::getSignatureLength() { int32_t sl = confirmHeader->sigLength & 0xff; if (confirmHeader->filler[1] == 1) { // do we have a 9th bit diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketDHPart.cpp b/jni/libzrtp/sources/src/ZrtpPacketDHPart.cpp similarity index 83% rename from jni/libzrtp/sources/zrtp/ZrtpPacketDHPart.cpp rename to jni/libzrtp/sources/src/ZrtpPacketDHPart.cpp index 1a89e163c..8c59233f8 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketDHPart.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketDHPart.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -59,12 +59,6 @@ void ZrtpPacketDHPart::setPubKeyType(const char* pkt) { else if (*(int32_t*)pkt == *(int32_t*)ec38) { dhLength = 96; } - else if (*(int32_t*)pkt == *(int32_t*)e255) { - dhLength = 32; - } - else if (*(int32_t*)pkt == *(int32_t*)e414) { - dhLength = 104; - } else return; @@ -80,24 +74,18 @@ ZrtpPacketDHPart::ZrtpPacketDHPart(uint8_t *data) { int16_t len = getLength(); DEBUGOUT((fprintf(stdout, "DHPart length: %d\n", len))); - if (len == 85) { // Dh2k + if (len == 85) { dhLength = 256; } - else if (len == 117) { // Dh3k + else if (len == 117) { dhLength = 384; } - else if (len == 37) { // EC256 + else if (len == 37) { dhLength = 64; } - else if (len == 45) { // EC384 + else if (len == 45) { dhLength = 96; } - else if (len == 29) { // E255 - dhLength = 32; - } - else if (len == 47) { // E414 - dhLength = 104; - } else { pv = NULL; return; diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketError.cpp b/jni/libzrtp/sources/src/ZrtpPacketError.cpp similarity index 92% rename from jni/libzrtp/sources/zrtp/ZrtpPacketError.cpp rename to jni/libzrtp/sources/src/ZrtpPacketError.cpp index 94d4dc199..a9d881e84 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketError.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketError.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketErrorAck.cpp b/jni/libzrtp/sources/src/ZrtpPacketErrorAck.cpp similarity index 91% rename from jni/libzrtp/sources/zrtp/ZrtpPacketErrorAck.cpp rename to jni/libzrtp/sources/src/ZrtpPacketErrorAck.cpp index d0d0f336e..3a3097799 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketErrorAck.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketErrorAck.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketGoClear.cpp b/jni/libzrtp/sources/src/ZrtpPacketGoClear.cpp similarity index 100% rename from jni/libzrtp/sources/zrtp/ZrtpPacketGoClear.cpp rename to jni/libzrtp/sources/src/ZrtpPacketGoClear.cpp diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketHello.cpp b/jni/libzrtp/sources/src/ZrtpPacketHello.cpp similarity index 81% rename from jni/libzrtp/sources/zrtp/ZrtpPacketHello.cpp rename to jni/libzrtp/sources/src/ZrtpPacketHello.cpp index bc885ef18..1a0b701bd 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketHello.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketHello.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -19,7 +19,6 @@ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de> */ -#include <ctype.h> #include <libzrtpcpp/ZrtpPacketHello.h> @@ -63,6 +62,8 @@ void ZrtpPacketHello::configureHello(ZrtpConfigure* config) { setLength(length / ZRTP_WORD_SIZE); setMessageType((uint8_t*)HelloMsg); + setVersion((uint8_t*)zrtpVersion); + uint32_t lenField = nHash << 16; for (int32_t i = 0; i < nHash; i++) { AlgorithmEnum& hash = config->getAlgoAt(HashAlgorithm, i); @@ -92,7 +93,7 @@ void ZrtpPacketHello::configureHello(ZrtpConfigure* config) { AlgorithmEnum& sas = config->getAlgoAt(SasType, i); setSasType(i, (int8_t*)sas.getName()); } - *((uint32_t*)&helloHeader->flags) = zrtpHtonl(lenField); + *((uint32_t*)&helloHeader->flags) = htonl(lenField); } ZrtpPacketHello::ZrtpPacketHello(uint8_t *data) { @@ -101,28 +102,14 @@ ZrtpPacketHello::ZrtpPacketHello(uint8_t *data) { zrtpHeader = (zrtpPacketHeader_t *)&((HelloPacket_t *)data)->hdr; // the standard header helloHeader = (Hello_t *)&((HelloPacket_t *)data)->hello; - // Force the isLengthOk() check to fail when we process the packet. - if (getLength() < HELLO_FIXED_PART_LEN) { - computedLength = 0; - return; - } - uint32_t t = *((uint32_t*)&helloHeader->flags); - uint32_t temp = zrtpNtohl(t); + uint32_t temp = ntohl(t); nHash = (temp & (0xf << 16)) >> 16; - nHash &= 0x7; // restrict to max 7 algorithms nCipher = (temp & (0xf << 12)) >> 12; - nCipher &= 0x7; nAuth = (temp & (0xf << 8)) >> 8; - nAuth &= 0x7; nPubkey = (temp & (0xf << 4)) >> 4; - nPubkey &= 0x7; nSas = temp & 0xf; - nSas &= 0x7; - - // +2 : the MAC at the end of the packet - computedLength = nHash + nCipher + nAuth + nPubkey + nSas + sizeof(HelloPacket_t)/ZRTP_WORD_SIZE + 2; oHash = sizeof(Hello_t); oCipher = oHash + (nHash * ZRTP_WORD_SIZE); @@ -135,14 +122,3 @@ ZrtpPacketHello::ZrtpPacketHello(uint8_t *data) { ZrtpPacketHello::~ZrtpPacketHello() { DEBUGOUT((fprintf(stdout, "Deleting Hello packet: alloc: %x\n", allocated))); } - -int32_t ZrtpPacketHello::getVersionInt() { - uint8_t* vp = getVersion(); - int32_t version = 0; - - if (isdigit(*vp) && isdigit(*vp+2)) { - version = (*vp - '0') * 10; - version += *(vp+2) - '0'; - } - return version; -} diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketHelloAck.cpp b/jni/libzrtp/sources/src/ZrtpPacketHelloAck.cpp similarity index 91% rename from jni/libzrtp/sources/zrtp/ZrtpPacketHelloAck.cpp rename to jni/libzrtp/sources/src/ZrtpPacketHelloAck.cpp index 2849f2d6f..2d752b752 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketHelloAck.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketHelloAck.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketPing.cpp b/jni/libzrtp/sources/src/ZrtpPacketPing.cpp similarity index 86% rename from jni/libzrtp/sources/zrtp/ZrtpPacketPing.cpp rename to jni/libzrtp/sources/src/ZrtpPacketPing.cpp index b79e4ac3e..9a1f90f81 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketPing.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketPing.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2009 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -30,7 +30,7 @@ ZrtpPacketPing::ZrtpPacketPing() { setZrtpId(); setLength((sizeof(PingPacket_t) / ZRTP_WORD_SIZE) - 1); setMessageType((uint8_t*)PingMsg); - setVersion((uint8_t*)zrtpVersion_11); // TODO: fix version string after clarification + setVersion((uint8_t*)zrtpVersion); } ZrtpPacketPing::ZrtpPacketPing(uint8_t *data) { diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketPingAck.cpp b/jni/libzrtp/sources/src/ZrtpPacketPingAck.cpp similarity index 87% rename from jni/libzrtp/sources/zrtp/ZrtpPacketPingAck.cpp rename to jni/libzrtp/sources/src/ZrtpPacketPingAck.cpp index 0bee991a5..23316409a 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketPingAck.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketPingAck.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2009 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -30,7 +30,7 @@ ZrtpPacketPingAck::ZrtpPacketPingAck() { setZrtpId(); setLength((sizeof(PingAckPacket_t) / ZRTP_WORD_SIZE) - 1); setMessageType((uint8_t*)PingAckMsg); - setVersion((uint8_t*)zrtpVersion_11); // TODO: fix version string after clarification + setVersion((uint8_t*)zrtpVersion); } ZrtpPacketPingAck::ZrtpPacketPingAck(uint8_t *data) { diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketRelayAck.cpp b/jni/libzrtp/sources/src/ZrtpPacketRelayAck.cpp similarity index 91% rename from jni/libzrtp/sources/zrtp/ZrtpPacketRelayAck.cpp rename to jni/libzrtp/sources/src/ZrtpPacketRelayAck.cpp index a531e2f09..6ff0c7a15 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketRelayAck.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketRelayAck.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-20013 Werner Dittmann + Copyright (C) 2006-20011 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketSASrelay.cpp b/jni/libzrtp/sources/src/ZrtpPacketSASrelay.cpp similarity index 95% rename from jni/libzrtp/sources/zrtp/ZrtpPacketSASrelay.cpp rename to jni/libzrtp/sources/src/ZrtpPacketSASrelay.cpp index c8b7f5473..d132e2885 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpPacketSASrelay.cpp +++ b/jni/libzrtp/sources/src/ZrtpPacketSASrelay.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/ZrtpQueue.cpp b/jni/libzrtp/sources/src/ZrtpQueue.cpp similarity index 96% rename from jni/libzrtp/sources/zrtp/ZrtpQueue.cpp rename to jni/libzrtp/sources/src/ZrtpQueue.cpp index fef847e75..73cb22838 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpQueue.cpp +++ b/jni/libzrtp/sources/src/ZrtpQueue.cpp @@ -22,8 +22,8 @@ #include <string> #include <stdio.h> -#include <ZrtpQueue.h> -#include <libzrtpcpp/ZIDCache.h> +#include <libzrtpcpp/ZrtpQueue.h> +#include <libzrtpcpp/ZIDFile.h> #include <libzrtpcpp/ZRtp.h> #include <libzrtpcpp/ZrtpStateClass.h> #include <libzrtpcpp/ZrtpUserCallback.h> @@ -90,7 +90,7 @@ ZrtpQueue::initialize(const char *zidFilename, bool autoEnable, ZrtpConfigure* c staticTimeoutProvider = new TimeoutProvider<std::string, ZrtpQueue*>(); staticTimeoutProvider->start(); } - ZIDCache* zf = getZidCacheInstance(); + ZIDFile* zf = ZIDFile::getInstance(); if (!zf->isOpen()) { std::string fname; if (zidFilename == NULL) { @@ -119,15 +119,12 @@ ZrtpQueue::initialize(const char *zidFilename, bool autoEnable, ZrtpConfigure* c void ZrtpQueue::startZrtp() { if (zrtpEngine != NULL) { zrtpEngine->startZrtpEngine(); - zrtpUnprotect = 0; started = true; } } void ZrtpQueue::stopZrtp() { if (zrtpEngine != NULL) { - if (zrtpUnprotect < 50 && !zrtpEngine->isMultiStream()) - zrtpEngine->setRs2Valid(); delete zrtpEngine; zrtpEngine = NULL; started = false; @@ -161,10 +158,6 @@ ZrtpQueue::takeInDataPacket(void) // if ZRTP processing is enabled. Because valid RTP packets are // already handled we delete any packets here after processing. if (enableZrtp && zrtpEngine != NULL) { - // Fixed header length + smallest ZRTP packet (includes CRC) - if (rtn < (int32)(12 + sizeof(HelloAckPacket_t))) // data too small, dismiss - return 0; - // Get CRC value into crc (see above how to compute the offset) uint16_t temp = rtn - CRC_SIZE; uint32_t crc = *(uint32_t*)(buffer + temp); @@ -199,7 +192,7 @@ ZrtpQueue::takeInDataPacket(void) // store peer's SSRC, used when creating the CryptoContext peerSSRC = packet->getSSRC(); - zrtpEngine->processZrtpMessage(extHeader, peerSSRC, rtn); + zrtpEngine->processZrtpMessage(extHeader, peerSSRC); } delete packet; return 0; @@ -686,9 +679,9 @@ void ZrtpQueue::setClientId(std::string id) { clientIdString = id; } -std::string ZrtpQueue::getHelloHash(int32_t index) { +std::string ZrtpQueue::getHelloHash() { if (zrtpEngine != NULL) - return zrtpEngine->getHelloHash(index); + return zrtpEngine->getHelloHash(); else return std::string(); } @@ -818,21 +811,6 @@ int32 ZrtpQueue::getPeerZid(uint8* data) { return 0; } -int32_t ZrtpQueue::getNumberSupportedVersions() { - if (zrtpEngine != NULL) - return zrtpEngine->getNumberSupportedVersions(); - - return 0; -} - -int32_t ZrtpQueue::getCurrentProtocolVersion() { - if (zrtpEngine != NULL) - return zrtpEngine->getCurrentProtocolVersion(); - - return 0; -} - - IncomingZRTPPkt::IncomingZRTPPkt(const unsigned char* const block, size_t len) : IncomingRTPPkt(block,len) { } diff --git a/jni/libzrtp/sources/zrtp/ZrtpStateClass.cpp b/jni/libzrtp/sources/src/ZrtpStateClass.cpp similarity index 85% rename from jni/libzrtp/sources/zrtp/ZrtpStateClass.cpp rename to jni/libzrtp/sources/src/ZrtpStateClass.cpp index 2c46a4f12..f77f9f925 100644 --- a/jni/libzrtp/sources/zrtp/ZrtpStateClass.cpp +++ b/jni/libzrtp/sources/src/ZrtpStateClass.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2008 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -46,9 +46,14 @@ state_t states[numberOfStates] = { }; -ZrtpStateClass::ZrtpStateClass(ZRtp *p) : parent(p), commitPkt(NULL), multiStream(false), secSubstate(Normal), sentVersion(0) { +ZrtpStateClass::ZrtpStateClass(ZRtp *p) { + parent = p; + secSubstate = Normal; engine = new ZrtpStates(states, numberOfStates, Initial); + commitPkt = NULL; + multiStream = false; + // Set up timers according to ZRTP spec T1.start = 50; T1.maxResend = 20; @@ -77,35 +82,21 @@ ZrtpStateClass::~ZrtpStateClass(void) { void ZrtpStateClass::processEvent(Event_t *ev) { + event = ev; char *msg, first, middle, last; uint8_t *pkt; parent->synchEnter(); - event = ev; if (event->type == ZrtpPacket) { - pkt = event->packet; - msg = (char *)pkt + 4; - first = tolower(*msg); - middle = tolower(*(msg+4)); + pkt = event->packet; + msg = (char *)pkt + 4; + first = tolower(*msg); + middle = tolower(*(msg+4)); last = tolower(*(msg+7)); - // Sanity check of packet size for all states except WaitErrorAck. - if (!inState(WaitErrorAck)) { - uint16_t totalLength = *(uint16_t*)(pkt+2); - totalLength = zrtpNtohs(totalLength) * ZRTP_WORD_SIZE; - totalLength += 12 + sizeof(uint32_t); // 12 bytes is fixed header, uint32_t is CRC - - if (totalLength != ev->length) { - fprintf(stderr, "Total length does not match received length: %d - %ld\n", totalLength, (long int)(ev->length & 0xffff)); - sendErrorPacket(MalformedPacket); - parent->synchLeave(); - return; - } - } - // Check if this is an Error packet. - if (first == 'e' && middle =='r' && last == ' ') { + if (first == 'e' && middle =='r' && last == ' ') { /* * Process a received Error packet. * @@ -123,9 +114,7 @@ void ZrtpStateClass::processEvent(Event_t *ev) { else if (first == 'p' && middle == ' ' && last == ' ') { ZrtpPacketPing ppkt(pkt); ZrtpPacketPingAck* ppktAck = parent->preparePingAck(&ppkt); - if (ppktAck != NULL) { // ACK only to valid PING packet, otherwise ignore it - parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(ppktAck)); - } + parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(ppktAck)); parent->synchLeave(); return; } @@ -137,6 +126,7 @@ void ZrtpStateClass::processEvent(Event_t *ev) { parent->synchLeave(); return; } + } /* * Shut down protocol state engine: cancel outstanding timer, further @@ -154,11 +144,10 @@ void ZrtpStateClass::evInitial(void) { DEBUGOUT((cout << "Checking for match in Initial.\n")); if (event->type == ZrtpInitial) { - ZrtpPacketHello* hello = parent->prepareHello(); - sentVersion = hello->getVersionInt(); + ZrtpPacketHello* hello = parent->prepareHello(); - // remember packet for easy resend in case timer triggers - sentPacket = static_cast<ZrtpPacketBase *>(hello); + // remember packet for easy resend in case timer triggers + sentPacket = static_cast<ZrtpPacketBase *>(hello); if (!parent->sendPacketZRTP(sentPacket)) { sendFailed(); // returns to state Initial @@ -168,7 +157,7 @@ void ZrtpStateClass::evInitial(void) { timerFailed(SevereNoTimer); // returns to state Initial return; } - nextState(Detect); + nextState(Detect); } } @@ -236,8 +225,6 @@ void ZrtpStateClass::evDetect(void) { * - our peer acknowledged our Hello packet, we have not seen the peer's Hello yet * - cancel timer T1 to stop resending Hello * - switch to state AckDetected, wait for peer's Hello (F3) - * - * When we receive an HelloAck this also means that out partner accepted our protocol version. */ if (first == 'h' && last =='k') { cancelTimer(); @@ -247,8 +234,7 @@ void ZrtpStateClass::evDetect(void) { } /* * Hello: - * - send HelloAck packet to acknowledge the received Hello packet if versions match. - * Otherweise negotiate ZRTP versions. + * - send HelloAck packet to acknowledge the received Hello packet * - use received Hello packet to prepare own Commit packet. We need to * do it at this point because we need the hash value computed from * peer's Hello packet. Follwing states my use the prepared Commit. @@ -257,58 +243,7 @@ void ZrtpStateClass::evDetect(void) { * - Don't clear sentPacket, points to Hello */ if (first == 'h' && last ==' ') { - ZrtpPacketHello hpkt(pkt); - cancelTimer(); - - /* - * Check and negotiate the ZRTP protocol version first. - * - * This selection mechanism relies on the fact that we sent the highest supported protocol version in - * the initial Hello packet with as stated in RFC6189, section 4.1.1 - */ - int32_t recvVersion = hpkt.getVersionInt(); - if (recvVersion > sentVersion) { // We don't support this version, stay in state with timer active - if (startTimer(&T1) <= 0) { - timerFailed(SevereNoTimer); // returns to state Initial - } - return; - } - - /* - * The versions don't match. Start negotiating versions. This negotiation stays in the Detect state. - * Only if the received version matches our own sent version we start to send a HelloAck. - */ - if (recvVersion != sentVersion) { - ZRtp::HelloPacketVersion* hpv = parent->helloPackets; - - int32_t index; - for (index = 0; hpv->packet && hpv->packet != parent->currentHelloPacket; hpv++, index++) // Find current sent Hello - ; - - for(; index >= 0 && hpv->version > recvVersion; hpv--, index--) // find a supported version less-equal to received version - ; - - if (index < 0) { - sendErrorPacket(UnsuppZRTPVersion); - return; - } - parent->currentHelloPacket = hpv->packet; - sentVersion = parent->currentHelloPacket->getVersionInt(); - - // remember packet for easy resend in case timer triggers - sentPacket = static_cast<ZrtpPacketBase *>(parent->currentHelloPacket); - - if (!parent->sendPacketZRTP(sentPacket)) { - sendFailed(); // returns to state Initial - return; - } - if (startTimer(&T1) <= 0) { - timerFailed(SevereNoTimer); // returns to state Initial - return; - } - return; - } ZrtpPacketHelloAck* helloAck = parent->prepareHelloAck(); if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) { @@ -317,6 +252,7 @@ void ZrtpStateClass::evDetect(void) { } // Use peer's Hello packet to create my commit packet, store it // for possible later usage in state AckSent + ZrtpPacketHello hpkt(pkt); commitPkt = parent->prepareCommit(&hpkt, &errorCode); nextState(AckSent); @@ -343,7 +279,7 @@ void ZrtpStateClass::evDetect(void) { nextState(Detect); } } - // If application calls zrtpStart() to restart discovery + // If application call zrtpStart() to restart discovery else if (event->type == ZrtpInitial) { cancelTimer(); if (!parent->sendPacketZRTP(sentPacket)) { @@ -368,7 +304,7 @@ void ZrtpStateClass::evDetect(void) { * * The protocol engine got a Hello packet from peer and answered with a * HelloAck response. According to the protocol we must also send a - * Hello after HelloAck (refer to figure 1 in ZRTP RFC 6189, message + * Hello after HelloAck (refer to figure 1 in ZRTP RFC xxxx, message * HelloACK (F2) must be followed by Hello (F3)). We use the timeout in * this state to send the required Hello (F3). * @@ -411,36 +347,36 @@ void ZrtpStateClass::evAckSent(void) { */ if (event->type == ZrtpPacket) { pkt = event->packet; - msg = (char *)pkt + 4; + msg = (char *)pkt + 4; - first = tolower(*msg); - last = tolower(*(msg+7)); + first = tolower(*msg); + last = tolower(*(msg+7)); - /* + /* * HelloAck: * The peer answers with HelloAck to own HelloAck/Hello. Send Commit * and try Initiator mode. The requirement defined in chapter 4.1 to * have a complete Hello/HelloAck is fulfilled. - * - stop Hello timer T1 - * - send own Commit message - * - switch state to CommitSent, start Commit timer, assume Initiator - */ - if (first == 'h' && last =='k') { - cancelTimer(); + * - stop Hello timer T1 + * - send own Commit message + * - switch state to CommitSent, start Commit timer, assume Initiator + */ + if (first == 'h' && last =='k') { + cancelTimer(); // remember packet for easy resend in case timer triggers // Timer trigger received in new state CommitSend sentPacket = static_cast<ZrtpPacketBase *>(commitPkt); commitPkt = NULL; // now stored in sentPacket - nextState(CommitSent); + nextState(CommitSent); if (!parent->sendPacketZRTP(sentPacket)) { sendFailed(); // returns to state Initial return; } if (startTimer(&T2) <= 0) { timerFailed(SevereNoTimer); // returns to state Initial - } - return; + } + return; } /* * Hello: @@ -472,7 +408,7 @@ void ZrtpStateClass::evAckSent(void) { * - switch to state WaitDHPart2 and wait for peer's DHPart2 * - don't start timer, we are responder */ - if (first == 'c' && last == ' ') { + if (first == 'c') { cancelTimer(); ZrtpPacketCommit cpkt(pkt); @@ -510,7 +446,7 @@ void ZrtpStateClass::evAckSent(void) { } /* * Timer: - * - resend Hello packet, stay in state, restart timer until repeat + * - resend Hello packet, stay in state, restart timer until repeat * counter triggers * - if repeat counter triggers switch to state Detect, con't clear * sentPacket, Detect requires it to point to own Hello message @@ -540,7 +476,7 @@ void ZrtpStateClass::evAckSent(void) { * AckDetected state. * * The protocol engine received a HelloAck in state Detect, thus the peer - * acknowledged our the Hello. According to ZRT RFC 6189 our peer must send + * acknowledged our the Hello. According to ZRT RFC xxxx our peer must send * its Hello until our protocol engine sees it (refer also to comment for * state AckSent). This protocol sequence gurantees that both peers got at * least one Hello. @@ -575,7 +511,7 @@ void ZrtpStateClass::evAckDetected(void) { /* * Implementation for choice 1) * Hello: - * - Acknowledge peer's Hello, sending HelloACK (F4) + * - Acknowledge peers Hello, sending HelloACK (F4) * - switch to state WaitCommit, wait for peer's Commit * - we are going to be in the Responder role */ @@ -606,13 +542,13 @@ void ZrtpStateClass::evAckDetected(void) { /* * Implementation for choice 2) * Hello: - * - Acknowledge peer's Hello by sending Commit (F5) + * - Acknowledge peers Hello by sending Commit (F5) * instead of HelloAck (F4) * - switch to state CommitSent * - Initiator role, thus start timer T2 to monitor timeout for Commit */ - if (first == 'h' && last == ' ') { + if (first == 'h') { // Parse peer's packet data into a Hello packet ZrtpPacketHello hpkt(pkt); ZrtpPacketCommit* commit = parent->prepareCommit(&hpkt, &errorCode); @@ -662,7 +598,7 @@ void ZrtpStateClass::evWaitCommit(void) { DEBUGOUT((cout << "Checking for match in WaitCommit.\n")); - char *msg, first, last; + char *msg, first; uint8_t *pkt; uint32_t errorCode = 0; @@ -671,13 +607,12 @@ void ZrtpStateClass::evWaitCommit(void) { msg = (char *)pkt + 4; first = tolower(*msg); - last = tolower(*(msg+7)); /* * Hello: * - resend HelloAck * - stay in WaitCommit */ - if (first == 'h' && last == ' ') { + if (first == 'h') { if (!parent->sendPacketZRTP(sentPacket)) { sendFailed(); // returns to state Initial } @@ -690,7 +625,7 @@ void ZrtpStateClass::evWaitCommit(void) { * - switch state to WaitDHPart2 or WaitConfirm2 if multi stream mode * - don't start timer, we are responder */ - if (first == 'c' && last == ' ') { + if (first == 'c') { ZrtpPacketCommit cpkt(pkt); if (!multiStream) { @@ -758,7 +693,7 @@ void ZrtpStateClass::evCommitSent(void) { DEBUGOUT((cout << "Checking for match in CommitSend.\n")); - char *msg, first, middle, last, secondLast; + char *msg, first, last; uint8_t *pkt; uint32_t errorCode = 0; @@ -767,9 +702,7 @@ void ZrtpStateClass::evCommitSent(void) { msg = (char *)pkt + 4; first = tolower(*msg); - middle = tolower(*(msg+4)); last = tolower(*(msg+7)); - secondLast = tolower(*(msg+6)); /* * HelloAck or Hello: @@ -777,7 +710,7 @@ void ZrtpStateClass::evCommitSent(void) { * ignore it * - no switch in state, leave timer as it is */ - if (first == 'h' && middle == 'o' && (last =='k' || last == ' ')) { + if (first == 'h' && (last =='k' || last == ' ')) { return; } @@ -802,11 +735,6 @@ void ZrtpStateClass::evCommitSent(void) { } cancelTimer(); // this cancels the Commit timer T2 - if (!zpCo.isLengthOk(multiStream ? ZrtpPacketCommit::MultiStream : ZrtpPacketCommit::DhExchange)) { - sendErrorPacket(CriticalSWError); - return; - } - // if our hvi is less than peer's hvi: switch to Responder mode and // send DHPart1 or Confirm1 packet. Peer (as Initiator) will retrigger if // necessary @@ -859,7 +787,7 @@ void ZrtpStateClass::evCommitSent(void) { * - switch to WaitConfirm1 * - start timer to resend DHPart2 if necessary, we are Initiator */ - if (first == 'd' && secondLast == '1') { + if (first == 'd') { cancelTimer(); sentPacket = NULL; ZrtpPacketDHPart dpkt(pkt); @@ -891,11 +819,6 @@ void ZrtpStateClass::evCommitSent(void) { return; } - /* - * Confirm1 and multi-stream mode - * - switch off resending commit - * - prepare Confirm2 - */ if (multiStream && (first == 'c' && last == '1')) { cancelTimer(); ZrtpPacketConfirm cpkt(pkt); @@ -966,7 +889,7 @@ void ZrtpStateClass::evWaitDHPart2(void) { DEBUGOUT((cout << "Checking for match in DHPart2.\n")); - char *msg, first, secondLast, last; + char *msg, first; uint8_t *pkt; uint32_t errorCode = 0; @@ -975,14 +898,12 @@ void ZrtpStateClass::evWaitDHPart2(void) { msg = (char *)pkt + 4; first = tolower(*msg); - last = tolower(*(msg+7)); - secondLast = tolower(*(msg+6)); /* * Commit: * - resend DHPart1 * - stay in state */ - if (first == 'c' && last == ' ') { + if (first == 'c') { if (!parent->sendPacketZRTP(sentPacket)) { return sendFailed(); // returns to state Initial } @@ -994,7 +915,7 @@ void ZrtpStateClass::evWaitDHPart2(void) { * - switch to WaitConfirm2 * - No timer, we are responder */ - if (first == 'd' && secondLast == '2') { + if (first == 'd') { ZrtpPacketDHPart dpkt(pkt); ZrtpPacketConfirm* confirm = parent->prepareConfirm1(&dpkt, &errorCode); @@ -1073,14 +994,6 @@ void ZrtpStateClass::evWaitConfirm1(void) { sendErrorPacket(errorCode); return; } - // according to chap 5.8: after sending Confirm2 the Initiator must - // be ready to receive SRTP data. SRTP sender will be enabled in WaitConfAck - // state. - if (!parent->srtpSecretsReady(ForReceiver)) { - parent->sendInfo(Severe, CriticalSWError); - sendErrorPacket(CriticalSWError); - return; - } nextState(WaitConfAck); sentPacket = static_cast<ZrtpPacketBase *>(confirm); @@ -1089,7 +1002,15 @@ void ZrtpStateClass::evWaitConfirm1(void) { return; } if (startTimer(&T2) <= 0) { - timerFailed(SevereNoTimer); // returns to state Initial + timerFailed(SevereNoTimer); // returns to state Initial TODO check for return following this line + } + // according to chap 5.8: after sending Confirm2 the Initiator must + // be ready to receive SRTP data. SRTP sender will be enabled in WaitConfAck + // state. + if (!parent->srtpSecretsReady(ForReceiver)) { + parent->sendInfo(Severe, CriticalSWError); + sendErrorPacket(CriticalSWError); + return; } } } @@ -1135,7 +1056,7 @@ void ZrtpStateClass::evWaitConfirm2(void) { DEBUGOUT((cout << "Checking for match in WaitConfirm2.\n")); - char *msg, first, secondLast, last; + char *msg, first, last; uint8_t *pkt; uint32_t errorCode = 0; @@ -1144,7 +1065,6 @@ void ZrtpStateClass::evWaitConfirm2(void) { msg = (char *)pkt + 4; first = tolower(*msg); - secondLast = tolower(*(msg+6)); last = tolower(*(msg+7)); /* @@ -1152,7 +1072,7 @@ void ZrtpStateClass::evWaitConfirm2(void) { * - resend Confirm1 packet * - stay in state */ - if ((first == 'd' && secondLast == '2') || (multiStream && (first == 'c' && last == ' '))) { + if (first == 'd' || (multiStream && (first == 'c' && last == ' '))) { if (!parent->sendPacketZRTP(sentPacket)) { sendFailed(); // returns to state Initial } @@ -1179,7 +1099,8 @@ void ZrtpStateClass::evWaitConfirm2(void) { sendFailed(); // returns to state Initial return; } - if (!parent->srtpSecretsReady(ForReceiver) || !parent->srtpSecretsReady(ForSender)) { + if (!parent->srtpSecretsReady(ForSender) || + !parent->srtpSecretsReady(ForReceiver)) { parent->sendInfo(Severe, CriticalSWError); sendErrorPacket(CriticalSWError); return; @@ -1218,7 +1139,7 @@ void ZrtpStateClass::evWaitConfAck(void) { DEBUGOUT((cout << "Checking for match in WaitConfAck.\n")); - char *msg, first, last; + char *msg, first; uint8_t *pkt; if (event->type == ZrtpPacket) { @@ -1226,13 +1147,12 @@ void ZrtpStateClass::evWaitConfAck(void) { msg = (char *)pkt + 4; first = tolower(*msg); - last = tolower(*(msg+7)); /* * ConfAck: * - Switch off resending Confirm2 * - switch to SecureState */ - if (first == 'c' && last == 'k') { + if (first == 'c') { cancelTimer(); sentPacket = NULL; // Receiver was already enabled after sending Confirm2 packet @@ -1276,45 +1196,44 @@ void ZrtpStateClass::evWaitConfAck(void) { void ZrtpStateClass::evWaitClearAck(void) { DEBUGOUT((cout << "Checking for match in ClearAck.\n")); -// char *msg, first, last, middle; -// uint8_t *pkt; -// -// if (event->type == ZrtpPacket) { -// pkt = event->packet; -// msg = (char *)pkt + 4; -// -// first = tolower(*msg); -// middle = tolower(*(msg+4)); -// last = tolower(*(msg+7)); -// -// /* -// * ClearAck: -// * - stop resending GoClear, -// * - switch to state AckDetected, wait for peer's Hello -// */ -// if (first == 'c' && middle == 'r' && last =='k') { -// cancelTimer(); -// sentPacket = NULL; -// nextState(Initial); -// } -// } -// // Timer event triggered - this is Timer T2 to resend GoClear w/o HMAC -// else if (event->type == Timer) { -// if (!parent->sendPacketZRTP(sentPacket)) { -// sendFailed(); // returns to state Initial -// return; -// } -// if (nextTimer(&T2) <= 0) { -// timerFailed(SevereTooMuchRetries); // returns to state Initial -// } -// } -// else { // unknown Event type for this state (covers Error and ZrtpClose) -// if (event->type != ZrtpClose) { -// parent->zrtpNegotiationFailed(Severe, SevereProtocolError); -// } -// sentPacket = NULL; -// nextState(Initial); -// } + char *msg, first, last; + uint8_t *pkt; + + if (event->type == ZrtpPacket) { + pkt = event->packet; + msg = (char *)pkt + 4; + + first = tolower(*msg); + last = tolower(*(msg+7)); + + /* + * ClearAck: + * - stop resending GoClear, + * - switch to state AckDetected, wait for peer's Hello + */ + if (first == 'c' && last =='k') { + cancelTimer(); + sentPacket = NULL; + nextState(Initial); + } + } + // Timer event triggered - this is Timer T2 to resend GoClear w/o HMAC + else if (event->type == Timer) { + if (!parent->sendPacketZRTP(sentPacket)) { + sendFailed(); // returns to state Initial + return; + } + if (nextTimer(&T2) <= 0) { + timerFailed(SevereTooMuchRetries); // returns to state Initial + } + } + else { // unknown Event type for this state (covers Error and ZrtpClose) + if (event->type != ZrtpClose) { + parent->zrtpNegotiationFailed(Severe, SevereProtocolError); + } + sentPacket = NULL; + nextState(Initial); + } } @@ -1418,7 +1337,7 @@ void ZrtpStateClass::evSecureState(void) { } /* * GoClear received, handle it. TODO fix go clear handling - * + */ if (first == 'g' && last == 'r') { ZrtpPacketGoClear gpkt(pkt); ZrtpPacketClearAck* clearAck = parent->prepareClearAck(&gpkt); @@ -1428,18 +1347,8 @@ void ZrtpStateClass::evSecureState(void) { } // TODO Timeout to resend clear ack until user user confirmation } - */ - } - else if (event->type == Timer) { - // Ignore stray timeout in this state - ; } - // unknown Event type for this state (covers Error and ZrtpClose) - else { - // If in secure state ingnore error events to avoid Error packet injection - // attack - found by Dmitry Monakhov (dmonakhov@openvz.org) - if (event->type == ErrorPkt) - return; + else { // unknown Event type for this state (covers Error and ZrtpClose) sentPacket = NULL; parent->srtpSecretsOff(ForSender); parent->srtpSecretsOff(ForReceiver); diff --git a/jni/libzrtp/sources/src/ZrtpTextData.cpp b/jni/libzrtp/sources/src/ZrtpTextData.cpp new file mode 100644 index 000000000..586109913 --- /dev/null +++ b/jni/libzrtp/sources/src/ZrtpTextData.cpp @@ -0,0 +1,97 @@ +/* + Copyright (C) 2006-2008 Werner Dittmann + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Authors: Werner Dittmann <Werner.Dittmann@t-online.de> + */ +#include <stdint.h> +#include <libzrtpcpp/ZrtpConfigure.h> +// 1 +// 1234567890123456 +char clientId[] = "GNU ZRTP 2.1.0 "; // 16 chars max. +char zrtpVersion[] = "1.10"; // must be 4 chars +/** + * + */ +char HelloMsg[] = "Hello "; +char HelloAckMsg[] = "HelloACK"; +char CommitMsg[] = "Commit "; +char DHPart1Msg[] = "DHPart1 "; +char DHPart2Msg[] = "DHPart2 "; +char Confirm1Msg[] = "Confirm1"; +char Confirm2Msg[] = "Confirm2"; +char Conf2AckMsg[] = "Conf2ACK"; +char ErrorMsg[] = "Error "; +char ErrorAckMsg[] = "ErrorACK"; +char GoClearMsg[] = "GoClear "; +char ClearAckMsg[] = "ClearACK"; +char PingMsg[] = "Ping "; +char PingAckMsg[] = "PingACK "; +char SasRelayMsg[] = "SASrelay"; +char RelayAckMsg[] = "RelayACK"; + +char responder[] = "Responder"; +char initiator[] = "Initiator"; +char iniMasterKey[] = "Initiator SRTP master key"; +char iniMasterSalt[] = "Initiator SRTP master salt"; +char respMasterKey[] = "Responder SRTP master key"; +char respMasterSalt[] = "Responder SRTP master salt"; + +char iniHmacKey[] = "Initiator HMAC key"; +char respHmacKey[] = "Responder HMAC key"; +char retainedSec[] = "retained secret"; + +char iniZrtpKey[] = "Initiator ZRTP key"; +char respZrtpKey[] = "Responder ZRTP key"; + +char sasString[] = "SAS"; + +char KDFString[] = "ZRTP-HMAC-KDF"; + +char zrtpSessionKey[] = "ZRTP Session Key"; + +char zrtpMsk[] = "ZRTP MSK"; +char zrtpTrustedMitm[] = "Trusted MiTM key"; + +char s256[] = "S256"; +char s384[] = "S384"; +const char* mandatoryHash = s256; + +char aes3[] = "AES3"; +char aes2[] = "AES2"; +char aes1[] = "AES1"; +char two3[] = "2FS3"; +char two2[] = "2FS2"; +char two1[] = "2FS1"; +const char* mandatoryCipher = aes1; + +char dh2k[] = "DH2k"; +char ec25[] = "EC25"; +char dh3k[] = "DH3k"; +char ec38[] = "EC38"; +char mult[] = "Mult"; +const char* mandatoryPubKey = dh3k; + +char b32[] = "B32 "; +const char* mandatorySasType = b32; + +char hs32[] = "HS32"; +char hs80[] = "HS80"; +char sk32[] = "SK32"; +char sk64[] = "SK64"; +const char* mandatoryAuthLen_1 = hs32; +const char* mandatoryAuthLen_2 = hs80; diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/Base32.h b/jni/libzrtp/sources/src/libzrtpcpp/Base32.h similarity index 100% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/Base32.h rename to jni/libzrtp/sources/src/libzrtpcpp/Base32.h diff --git a/jni/libzrtp/sources/src/libzrtpcpp/CMakeLists.txt b/jni/libzrtp/sources/src/libzrtpcpp/CMakeLists.txt new file mode 100755 index 000000000..099a23322 --- /dev/null +++ b/jni/libzrtp/sources/src/libzrtpcpp/CMakeLists.txt @@ -0,0 +1,9 @@ + +if(enable_ccrtp) + set(ccrtp_inst ZrtpQueue.h zrtpccrtp.h ZrtpUserCallback.h TimeoutProvider.h) +endif() + +install(FILES + ZrtpCodes.h ZrtpConfigure.h ZrtpCallback.h ZrtpCWrapper.h + ${ccrtp_inst} DESTINATION include/libzrtpcpp) + diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/CcrtpTimeoutProvider.h b/jni/libzrtp/sources/src/libzrtpcpp/TimeoutProvider.h similarity index 71% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/CcrtpTimeoutProvider.h rename to jni/libzrtp/sources/src/libzrtpcpp/TimeoutProvider.h index 7aa3405d9..9f0edf7a3 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/CcrtpTimeoutProvider.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/TimeoutProvider.h @@ -55,14 +55,14 @@ class TPRequest public: TPRequest( TOSubscriber tsi, int timeoutMs, const TOCommand &command): - subscriber(tsi) + subscriber(tsi) { struct timeval tv; gettimeofday(&tv, NULL ); when_ms = ((uint64)tv.tv_sec) * (uint64)1000 + ((uint64)tv.tv_usec) / (uint64)1000; - when_ms += timeoutMs; - this->command = command; + when_ms += timeoutMs; + this->command = command; } /** @@ -70,18 +70,18 @@ public: */ bool happensBefore(uint64 t) { - if (when_ms < t) { - return true; - } - if (when_ms > t) { - return false; - } - return false; // if equal it does not "happens_before" + if (when_ms < t) { + return true; + } + if (when_ms > t) { + return false; + } + return false; // if equal it does not "happens_before" } bool happensBefore(const TPRequest *req){ - return happensBefore(req->when_ms); + return happensBefore(req->when_ms); } /** @@ -95,22 +95,22 @@ public: uint64 now = ((uint64)tv.tv_sec) * (uint64)1000 + ((uint64)tv.tv_usec) / (uint64)1000; - if (happensBefore(now)) { - return 0; - } - else { - return (int)(when_ms - now); - } + if (happensBefore(now)) { + return 0; + } + else { + return (int)(when_ms - now); + } } TOCommand getCommand() { - return command; + return command; } TOSubscriber getSubscriber() { - return subscriber; + return subscriber; } /** @@ -121,9 +121,9 @@ public: */ bool operator==(const TPRequest<TOCommand, TOSubscriber> &req) { - if (req.subscriber == subscriber && - req.command == command && - req.when_ms == when_ms) { + if (req.subscriber == subscriber && + req.command == command && + req.when_ms == when_ms) { return true; } return false; @@ -132,10 +132,10 @@ public: private: TOSubscriber subscriber; uint64 when_ms; // Time since Epoch in ms when the timeout - // will happen + // will happen TOCommand command; // Command that will be delivered to the - // receiver (subscriber) of the timeout. + // receiver (subscriber) of the timeout. }; /** @@ -145,7 +145,7 @@ private: * @author Werner Dittmann */ template<class TOCommand, class TOSubscriber> -class TimeoutProvider : public ost::Thread, ost::Event { + class TimeoutProvider : public ost::Thread, ost::Event { public: @@ -158,15 +158,15 @@ public: * Destructor also terminates the Timeout thread. */ ~TimeoutProvider() { - terminate(); + terminate(); } /** * Terminates the Timeout provider thread. */ void stopThread(){ - stop = true; - signal(); // signal event to waiting thread + stop = true; + signal(); // signal event to waiting thread } /** @@ -183,28 +183,28 @@ public: void requestTimeout(int32_t time_ms, TOSubscriber subscriber, const TOCommand &command) { TPRequest<TOCommand, TOSubscriber>* request = - new TPRequest<TOCommand, TOSubscriber>(subscriber, time_ms, command); + new TPRequest<TOCommand, TOSubscriber>(subscriber, time_ms, command); synchLock.enter(); - if (requests.size()==0) { - requests.push_front(request); - signal(); - synchLock.leave(); - return; - } + if (requests.size()==0) { + requests.push_front(request); + signal(); + synchLock.leave(); + return; + } if (request->happensBefore(requests.front())) { - requests.push_front(request); - signal(); + requests.push_front(request); + signal(); synchLock.leave(); - return; - } + return; + } if (requests.back()->happensBefore(request)){ - requests.push_back(request); - signal(); + requests.push_back(request); + signal(); synchLock.leave(); - return; - } + return; + } typename std::list<TPRequest<TOCommand, TOSubscriber>* >::iterator i; for(i = requests.begin(); i != requests.end(); i++ ) { @@ -213,8 +213,8 @@ public: break; } } - signal(); - synchLock.leave(); + signal(); + synchLock.leave(); } /** @@ -234,48 +234,48 @@ public: } i++; } - synchLock.leave(); + synchLock.leave(); } protected: void run() { - do { - synchLock.enter(); - int32_t time = 3600000; - int32_t size = 0; - if ((size = requests.size()) > 0) { + do { + synchLock.enter(); + int32_t time = 3600000; + int32_t size = 0; + if ((size = requests.size()) > 0) { time = requests.front()->getMsToTimeout(); } - if (time == 0 && size > 0) { - if (stop){ // This must be checked so that we will - // stop even if we have timeouts to deliver. + if (time == 0 && size > 0) { + if (stop){ // This must be checked so that we will + // stop even if we have timeouts to deliver. synchLock.leave(); - return; - } + return; + } TPRequest<TOCommand, TOSubscriber>* req = requests.front(); - TOSubscriber subs = req->getSubscriber(); - TOCommand command = req->getCommand(); + TOSubscriber subs = req->getSubscriber(); + TOCommand command = req->getCommand(); requests.pop_front(); - synchLock.leave(); // call the command with free Mutex - subs->handleTimeout(command); - continue; - } - synchLock.leave(); - if (stop) { // If we were told to stop while delivering - // a timeout we will exit here - return; - } - reset(); // ready to receive triggers again + synchLock.leave(); // call the command with free Mutex + subs->handleTimeout(command); + continue; + } + synchLock.leave(); + if (stop) { // If we were told to stop while delivering + // a timeout we will exit here + return; + } + reset(); // ready to receive triggers again wait(time); - if (stop) { // If we are told to exit while waiting we - // will exit - return; - } - } while(true); + if (stop) { // If we are told to exit while waiting we + // will exit + return; + } + } while(true); } private: @@ -287,9 +287,17 @@ private: ost::Mutex synchLock; // Protects the internal data structures bool stop; // Flag to tell the worker thread - // to terminate. Set to true and - // wake the worker thread to - // terminate it. + // to terminate. Set to true and + // wake the worker thread to + // terminate it. }; #endif + +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ diff --git a/jni/libzrtp/sources/src/libzrtpcpp/ZIDFile.h b/jni/libzrtp/sources/src/libzrtpcpp/ZIDFile.h new file mode 100644 index 000000000..0637c270d --- /dev/null +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZIDFile.h @@ -0,0 +1,157 @@ +/* + Copyright (C) 2006-2010 Werner Dittmann + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> + +#include <libzrtpcpp/ZIDRecord.h> + +#ifndef _ZIDFILE_H_ +#define _ZIDFILE_H_ +/** + * @file ZIDFile.h + * @brief ZID file management + * + * A ZID file stores (caches) some data that helps ZRTP to achives its + * key continuity feature. See @c ZIDRecord for further info which data + * the ZID file contains. + * + * @ingroup GNU_ZRTP + * @{ + */ + +/** + * This class implements a ZID (ZRTP Identifiers) file. + * + * The ZID file holds information about peers. + * + * @author: Werner Dittmann <Werner.Dittmann@t-online.de> + */ + +class __EXPORT ZIDFile { + +private: + + FILE* zidFile; + unsigned char associatedZid[IDENTIFIER_LEN]; + /** + * The private ZID file constructor. + * + */ + ZIDFile(): zidFile(NULL) {}; + ~ZIDFile(); + void createZIDFile(char* name); + void checkDoMigration(char* name); + +public: + + /** + * Get the an instance of ZIDFile. + * + * This method just creates an instance an store a pointer to it + * in a static variable. The ZIDFile is a singleton, thus only + * <em>one</em> ZID file can be open at one time. + * + * @return + * A pointer to the global ZIDFile singleton instance. + */ + static ZIDFile* getInstance(); + /** + * Open the named ZID file and return a ZID file class. + * + * This static function either opens an existing ZID file or + * creates a new ZID file with the given name. The ZIDFile is a + * singleton, thus only <em>one</em> ZID file can be open at one + * time. + * + * To open another ZID file you must close the active ZID file + * first. + * + * @param name + * The name of the ZID file to open or create + * @return + * 1 if file could be opened/created, 0 if the ZID instance + * already has an open file, -1 if open/creation of file failed. + */ + int open(char *name); + + /** + * Check if ZIDFile has an active (open) file. + * + * @return + * True if ZIDFile has an active file, false otherwise + */ + bool isOpen() { return (zidFile != NULL); }; + + /** + * Close the ZID file. + * Closes the ZID file, and prepares to open a new ZID file. + */ + void close(); + + /** + * Get a ZID record from the active ZID file. + * + * The method get the identifier data from the ZID record parameter, + * locates the record in the ZID file and fills in the RS1, RS2, and + * other data. + * + * If no matching record exists in the ZID file the method creates + * it and fills it with default values. + * + * @param zidRecord + * The ZID record that contains the identifier data. The method + * fills in data . + * @return + * Currently always 1 to indicate sucess + */ + unsigned int getRecord(ZIDRecord* zidRecord); + + /** + * Save a ZID record into the active ZID file. + * + * This method saves the content of a ZID record into the ZID file. Before + * you can save the ZID record you must have performed a getRecord() + * first. + * + * @param zidRecord + * The ZID record to save. + * @return + * 1 on success + */ + unsigned int saveRecord(ZIDRecord *zidRecord); + + /** + * Get the ZID associated with this ZID file. + * + * @return + * Pointer to the ZID + */ + const unsigned char* getZid() { return associatedZid; }; +}; + +/** + * @} + */ +#endif + +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordFile.h b/jni/libzrtp/sources/src/libzrtpcpp/ZIDRecord.h similarity index 81% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordFile.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZIDRecord.h index 74cc8a0cc..dc4691ffb 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordFile.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZIDRecord.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -15,13 +15,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _ZIDRECORDFILE_H_ -#define _ZIDRECORDFILE_H_ +#ifndef _ZIDRECORD_H_ +#define _ZIDRECORD_H_ /** - * @file ZIDRecordFile.h - * @brief ZID cache record management + * @file ZIDRecord.h + * @brief ZID record management * * A ZID record stores (caches) ZID (ZRTP ID) specific data that helps ZRTP * to achives its key continuity feature. Please refer to the ZRTP @@ -33,8 +33,9 @@ #include <string.h> #include <stdint.h> -#include <libzrtpcpp/ZIDRecord.h> +#define IDENTIFIER_LEN 12 +#define RS_LENGTH 32 #define TIME_LENGTH 8 // 64 bit, can hold time on 64 bit systems /** @@ -67,6 +68,21 @@ typedef struct zidrecord2 { unsigned char mitmKey[RS_LENGTH]; ///< MiTM key if available } zidrecord2_t; + +#ifndef __EXPORT + #if defined _WIN32 || defined __CYGWIN__ + #define __EXPORT __declspec(dllimport) + #define __LOCAL + #endif + #if __GNUC__ >= 4 + #define __EXPORT __attribute__ ((visibility("default"))) + #define __LOCAL __attribute__ ((visibility("hidden"))) + #else + #define __EXPORT + #define __LOCAL + #endif +#endif + static const int Valid = 0x1; static const int SASVerified = 0x2; static const int RS1Valid = 0x4; @@ -86,13 +102,20 @@ static const int OwnZIDRecord = 0x20; * * @author: Werner Dittmann <Werner.Dittmann@t-online.de> */ -class __EXPORT ZIDRecordFile: public ZIDRecord { - friend class ZIDCacheFile; +class __EXPORT ZIDRecord { + friend class ZIDFile; private: zidrecord2_t record; unsigned long position; + /* + * The default constructor is private + */ + ZIDRecord() { + record.version = 2; + } + /** * Functions for I/O availabe for ZID file handling * @@ -108,21 +131,25 @@ private: void setValid() { record.flags |= Valid; } public: - /* - * @brief The default constructor, - */ - ZIDRecordFile() { - memset(&record, 0, sizeof(zidrecord2_t)); - record.version = 2; - } - /** - * Set the @c ZID in the record. + * Create a ZID Record with given ZID data + * + * The method creates a new ZID record and initializes its ZID + * data field. All other fields are set to null. * - * Set the ZID in this record before calling read or save. + * An application can use this pre-initialized record to look + * up the associated record in the ZID file. If the record is + * available, the ZID record fields are filled with the stored + * data. + * + * @param idData + * Pointer to the fixed length ZID data + * @see ZIDFile::getRecord */ - void setZid(const unsigned char *zid) { - memcpy(record.identifier, zid, IDENTIFIER_LEN); + ZIDRecord(const unsigned char *idData) { + memset(&record, 0, sizeof(zidrecord2_t)); + memcpy(record.identifier, idData, IDENTIFIER_LEN); + record.version = 2; } /** @@ -211,7 +238,7 @@ public: * @return * Returns true is RS1 is not expired (valid), false otherwise. */ - bool isRs1NotExpired(); + const bool isRs1NotExpired(); /** * Returns pointer to RS1 data. @@ -226,7 +253,7 @@ public: * @return * Returns true is RS2 is not expired (valid), false otherwise. */ - bool isRs2NotExpired(); + const bool isRs2NotExpired(); /** * Returns pointer to RS1 data. @@ -269,5 +296,13 @@ public: const unsigned char* getMiTMData() {return record.mitmKey; } }; -#endif // ZIDRECORDSMALL +#endif // ZIDRECORD + +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZRtp.h b/jni/libzrtp/sources/src/libzrtpcpp/ZRtp.h similarity index 82% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZRtp.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZRtp.h index a20b59945..4e03f28b4 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZRtp.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZRtp.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -41,7 +41,7 @@ #include <libzrtpcpp/ZrtpPacketSASrelay.h> #include <libzrtpcpp/ZrtpPacketRelayAck.h> #include <libzrtpcpp/ZrtpCallback.h> -#include <libzrtpcpp/ZIDCache.h> +#include <libzrtpcpp/ZIDRecord.h> #ifndef SHA256_DIGEST_LENGTH #define SHA256_DIGEST_LENGTH 32 @@ -51,15 +51,6 @@ #define MAX_DIGEST_LENGTH 64 #define IMPL_MAX_DIGEST_LENGTH 64 -// max. number of parallel supported ZRTP protocol versions. -#define MAX_ZRTP_VERSIONS 2 - -// currently only 1.10 supported -#define SUPPORTED_ZRTP_VERSIONS 1 - -// Integer representation of highest supported ZRTP protocol version -#define HIGHEST_ZRTP_VERION 12 - class __EXPORT ZrtpStateClass; class ZrtpDH; @@ -99,33 +90,6 @@ class __EXPORT ZRtp { public: - typedef enum _secrets { - Rs1 = 1, - Rs2 = 2, - Pbx = 4, - Aux = 8 - } secrets; - - typedef struct _zrtpInfo { - int32_t secretsCached; - int32_t secretsMatched; - int32_t secretsMatchedDH; - const char *hash; - const char *cipher; - const char *pubKey; - const char *sasType; - const char *authLength; - } zrtpInfo; - - /** - * Faster access to Hello packets with different versions. - */ - typedef struct _HelloPacketVersion { - int32_t version; - ZrtpPacketHello* packet; - uint8_t helloHash[IMPL_MAX_DIGEST_LENGTH]; - } HelloPacketVersion; - /** * Constructor intializes all relevant data but does not start the * engine. @@ -154,24 +118,26 @@ class __EXPORT ZRtp { void stopZrtp(); /** - * Process ZRTP message. + * Process RTP extension header. * - * The method takes the data and forwards it to the ZRTP state engine for further - * processing. It's the caller's duty to check the ZRTP CRC and the ZRTP magic - * cookie before calling this function. + * This method expects to get a pointer to the extension header of + * a RTP packet. The method checks if this is really a ZRTP + * packet. If this check fails the method returns 0 (false) in + * case this is not a ZRTP packet. We return a 1 if we processed + * the ZRTP extension header and the caller may process RTP data + * after the extension header as usual. The method return -1 the + * call shall dismiss the packet and shall not forward it to + * further RTP processing. * * @param extHeader - * A pointer to the first byte of the ZRTP message. Refer to RFC6189. + * A pointer to the first byte of the extension header. Refer to + * RFC3550. * @param peerSSRC * The peer's SSRC. - * @param length - * of the received data packet, this includes the RTP like header - * and the ZRTP CRC field - used to do santity checks. - * * @return * Code indicating further packet handling, see description above. */ - void processZrtpMessage(uint8_t *extHeader, uint32_t peerSSRC, size_t length); + void processZrtpMessage(uint8_t *extHeader, uint32_t peerSSRC); /** * Process a timeout event. @@ -236,25 +202,17 @@ class __EXPORT ZRtp { /** * Get the ZRTP Hello Hash data. * - * Use this method to get the ZRTP Hello hash data. The method + * Use this method to get the ZRTP Hello Hash data. The method * returns the data as a string containing the ZRTP protocol version and * hex-digits. - * - * The index defines which Hello packet to use. Each supported ZRTP procol version - * uses a different Hello packet and thus computes different hashes. * * Refer to ZRTP specification, chapter 8. - * - * @param index - * Hello hash of the Hello packet identfied by index. Index must be 0 <= index < MAX_ZRTP_VERSIONS. * * @return - * a std::string formatted according to RFC6189 section 8 without the leading 'a=zrtp-hash:' - * SDP attribute identifier. The hello hash is available immediately after class instantiation. - * - * @see getNumberSupportedVersions() + * a std:string containing the Hello hash value as hex-digits. The + * hello hash is available immediately after class instantiation. */ - std::string getHelloHash(int index); + std::string getHelloHash(); /** * Get the peer's ZRTP Hello Hash data. @@ -493,50 +451,6 @@ class __EXPORT ZRtp { */ int32_t getPeerZid(uint8_t* data); - /** - * Returns a pointer to the gather detailed information structure. - * - * This structure contains some detailed information about the negotiated - * algorithms, the chached and matched shared secrets. - */ - const zrtpInfo *getDetailInfo(); - - /** - * Get peer's client id. - * - * @return the peer's client id or an empty @c string if not set. - */ - std::string getPeerClientId(); - - /** - * Get peer's protocl version string. - * - * @return the peer's protocol version or an empty @c string if not set. - */ - std::string getPeerProtcolVersion(); - - /** - * Get number of supported ZRTP protocol versions. - * - * @return the number of supported ZRTP protocol versions. - */ - int32_t getNumberSupportedVersions() {return SUPPORTED_ZRTP_VERSIONS;} - - /** - * Get negotiated ZRTP protocol version. - * - * @return the integer representation of the negotiated ZRTP protocol version. - */ - int32_t getCurrentProtocolVersion() {return currentHelloPacket->getVersionInt();} - - /** - * Validate the RS2 data if necessary. - * - * The cache functions stores the RS2 data but does not set its valid flag. The - * application may decide to set this flag. - */ - void setRs2Valid(); - private: friend class ZrtpStateClass; @@ -548,7 +462,7 @@ private: /** * This is my ZID that I send to the peer. */ - uint8_t ownZid[IDENTIFIER_LEN]; + uint8_t zid[IDENTIFIER_LEN]; /** * The peer's ZID @@ -659,6 +573,7 @@ private: uint8_t H1[IMPL_MAX_DIGEST_LENGTH]; uint8_t H2[IMPL_MAX_DIGEST_LENGTH]; uint8_t H3[IMPL_MAX_DIGEST_LENGTH]; + uint8_t helloHash[IMPL_MAX_DIGEST_LENGTH]; uint8_t peerHelloHash[IMPL_MAX_DIGEST_LENGTH]; uint8_t peerHelloVersion[ZRTP_WORD_SIZE + 1]; // +1 for nul byte @@ -816,9 +731,7 @@ private: /** * Pre-initialized packets. */ - ZrtpPacketHello zrtpHello_11; - ZrtpPacketHello zrtpHello_12; // Prepare for ZRTP protocol version 1.2 - + ZrtpPacketHello zrtpHello; ZrtpPacketHelloAck zrtpHelloAck; ZrtpPacketConf2Ack zrtpConf2Ack; ZrtpPacketClearAck zrtpClearAck; @@ -834,23 +747,6 @@ private: ZrtpPacketSASrelay zrtpSasRelay; ZrtpPacketRelayAck zrtpRelayAck; - HelloPacketVersion helloPackets[MAX_ZRTP_VERSIONS + 1]; - int32_t highestZrtpVersion; - - /// Pointer to Hello packet sent to partner, initialized in ZRtp, modified by ZrtpStateClass - ZrtpPacketHello* currentHelloPacket; - - /** - * ZID cache record - */ - ZIDRecord *zidRec; - - /** - * Save record - * - * If false don't save record until user vrified and confirmed the SAS. - */ - bool saveZidRecord; /** * Random IV data to encrypt the confirm data, 128 bit for AES */ @@ -870,11 +766,7 @@ private: */ bool signSasSeen; - uint32_t peerSSRC; // peer's SSRC, required to setup PingAck packet - - zrtpInfo detailInfo; // filled with some more detailded information if application would like to know - - std::string peerClientId; // store the peer's client Id + uint32_t peerSSRC; // peer's SSRC, required to setup PingAck packet /** * Enable or disable paranoid mode. @@ -917,8 +809,9 @@ private: * The Hello packet. * @return * The Enum that identifies the best offered Hash algortihm. Return - * mandatory algorithm if no match was found. - */ + * <code>NumSupportedHashes</code> to signal that no matching Hash algorithm + * was found at all. + */ AlgorithmEnum* findBestHash(ZrtpPacketHello *hello); /** @@ -932,8 +825,9 @@ private: * @param pk * The id of the selected public key algorithm * @return - * The Enum that identifies the best offered Cipher algorithm. Return - * mandatory algorithm if no match was found. + * The Enum that identifies the best offered Cipher algortihm. Return + * <code>NumSupportedSymCiphers</code> to signal that no matching Cipher algorithm + * was found at all. */ AlgorithmEnum* findBestCipher(ZrtpPacketHello *hello, AlgorithmEnum* pk); @@ -946,8 +840,9 @@ private: * @param hello * The Hello packet. * @return - * The Enum that identifies the best offered Public Key algorithm. Return - * mandatory algorithm if no match was found. + * The Enum that identifies the best offered Public Key algortihm. Return + * <code>NumSupportedPubKeys</code> to signal that no matching Public Key algorithm + * was found at all. */ AlgorithmEnum* findBestPubkey(ZrtpPacketHello *hello); @@ -955,18 +850,14 @@ private: * Find the best SAS algorithm that is offered in Hello. * * Find the best, that is the strongest, SAS algorithm that our peer - * offers in its Hello packet. The method works as definied in RFC 6189, - * chapter 4.1.2. - * - * The list of own supported public key algorithms must follow the rules - * defined in RFC 6189, chapter 4.1.2, thus the order in the list must go - * from fastest to slowest. + * offers in its Hello packet. * * @param hello * The Hello packet. * @return - * The Enum that identifies the best offered SAS algorithm. Return - * mandatory algorithm if no match was found. + * The Enum that identifies the best offered SAS algortihm. Return + * <code>NumSupportedSASTypes</code> to signal that no matching SAS algorithm + * was found at all. */ AlgorithmEnum* findBestSASType(ZrtpPacketHello* hello); @@ -980,7 +871,8 @@ private: * The Hello packet. * @return * The Enum that identifies the best offered authentication length. Return - * mandatory algorithm if no match was found. + * <code>NumSupportedAuthLenghts</code> to signal that no matching length + * was found at all. */ AlgorithmEnum* findBestAuthLen(ZrtpPacketHello* hello); @@ -997,77 +889,6 @@ private: */ bool checkMultiStream(ZrtpPacketHello* hello); - /** - * Checks if Hello packet contains a strong (384bit) hash based on selection policy. - * - * The function currently implements the nonNist policy only: - * If the public key algorithm is a non-NIST ECC algorithm this function prefers - * non-NIST HASH algorithms (Skein etc). - * - * If Hello packet does not contain a strong hash then this functions returns @c NULL. - * - * @param hello The Hello packet. - * @param algoName name of selected PK algorithm - * @return @c hash algorithm if found in Hello packet, @c NULL otherwise. - */ - AlgorithmEnum* getStrongHashOffered(ZrtpPacketHello *hello, int32_t algoName); - - /** - * Checks if Hello packet offers a strong (256bit) symmetric cipher based on selection policy. - * - * The function currently implements the nonNist policy only: - * If the public key algorithm is a non-NIST ECC algorithm this function prefers - * non-NIST symmetric cipher algorithms (Twofish etc). - * - * If Hello packet does not contain a symmetric cipher then this functions returns @c NULL. - - * @param hello The Hello packet. - * @param algoName name of selected PK algorithm - * @return @c hash algorithm if found in Hello packet, @c NULL otherwise. - * - * @return @c cipher algorithm if found in Hello packet, @c NULL otherwise. - */ - AlgorithmEnum* getStrongCipherOffered(ZrtpPacketHello *hello, int32_t algoName); - - /** - * Checks if Hello packet contains a hash based on selection policy. - * - * The function currently implements the nonNist policy only: - * If the public key algorithm is a non-NIST ECC algorithm this function prefers - * non-NIST HASH algorithms (Skein etc). - * - * @param hello The Hello packet. - * @param algoName name of selected PK algorithm - * @return @c hash algorithm found in Hello packet. - */ - AlgorithmEnum* getHashOffered(ZrtpPacketHello *hello, int32_t algoName); - - /** - * Checks if Hello packet offers a symmetric cipher based on selection policy. - * - * The function currently implements the nonNist policy only: - * If the public key algorithm is a non-NIST ECC algorithm this function prefers - * non-NIST symmetric cipher algorithms (Twofish etc). - * - * @param hello The Hello packet. - * @param algoName name of selected PK algorithm - * @return non-NIST @c cipher algorithm if found in Hello packet, @c NULL otherwise - */ - AlgorithmEnum* getCipherOffered(ZrtpPacketHello *hello, int32_t algoName); - - /** - * Checks if Hello packet offers a SRTP authentication length based on selection policy. - * - * The function currently implements the nonNist policy only: - * If the public key algorithm is a non-NIST ECC algorithm this function prefers - * non-NIST algorithms (Skein etc). - * - * @param hello The Hello packet. - * @param algoName algoName name of selected PK algorithm - * @return @c authLen algorithm found in Hello packet - */ - AlgorithmEnum* getAuthLenOffered(ZrtpPacketHello *hello, int32_t algoName); - /** * Save the computed MitM secret to the ZID record of the peer */ @@ -1078,18 +899,16 @@ private: */ void computeHvi(ZrtpPacketDHPart* dh, ZrtpPacketHello *hello); - void computeSharedSecretSet(ZIDRecord *zidRec); - - void computeAuxSecretIds(); + void computeSharedSecretSet(ZIDRecord& zidRec); void computeSRTPKeys(); void KDF(uint8_t* key, uint32_t keyLength, uint8_t* label, int32_t labelLength, uint8_t* context, int32_t contextLength, int32_t L, uint8_t* output); - void generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec); + void generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec); - void generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec); + void generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec); void generateKeysMultiStream(); @@ -1462,10 +1281,8 @@ private: * * @param id * The client's id - * @param hpv - * Pointer to hello packet version structure. */ - void setClientId(std::string id, HelloPacketVersion* hpv); + void setClientId(std::string id); }; /** diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCWrapper.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpCWrapper.h similarity index 96% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCWrapper.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpCWrapper.h index 0ad5b955f..01265459b 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCWrapper.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpCWrapper.h @@ -1,9 +1,9 @@ /* This file defines the GNU ZRTP C-to-C++ wrapper. - Copyright (C) 2013 Werner Dittmann + Copyright (C) 2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -565,7 +565,7 @@ extern "C" * @returns * Pointer to the ZrtpContext */ - ZrtpContext* zrtp_CreateWrapper(void); + ZrtpContext* zrtp_CreateWrapper(); /** * Initialize the ZRTP protocol engine. @@ -690,12 +690,10 @@ extern "C" * A pointer to the first byte of the ZRTP message part. * @param peerSSRC * The peer's SSRC. - * @param length of the received data packet - used to do santity checks. - * * @return * Code indicating further packet handling, see description above. */ - void zrtp_processZrtpMessage(ZrtpContext* zrtpContext, uint8_t *extHeader, uint32_t peerSSRC, size_t length); + void zrtp_processZrtpMessage(ZrtpContext* zrtpContext, uint8_t *extHeader, uint32_t peerSSRC); /** * Process a timeout event. @@ -782,28 +780,21 @@ extern "C" * * Use this method to get the ZRTP Hello Hash data. The method * returns the data as a string containing the ZRTP protocol version and - * hex-digits. - - * The index defines which Hello packet to use. Each supported ZRTP procol version - * uses a different Hello packet and thus computes different hashes. - * - * Refer to ZRTP specification, chapter 8. + * hex-digits. Refer to ZRTP specification, chapter 8. * - * @param index - * Hello hash of the Hello packet identfied by index. Index must be 0 <= index < zrtp_getNumberSupportedVersions(). + * <b>NOTE: An application may call this method if it needs this information. + * Usually it is not necessary.</b> * * @param zrtpContext * Pointer to the opaque ZrtpContext structure. - * * @return - * a pointer to a C-string that contains the Hello hash formatted according to RFC6189 section 8 - * without the leading 'a=zrtp-hash:' SDP attribute identifier. The hello hash is available - * immediately after @c zrtp_CreateWrapper. The caller must @c free() if it does not use the + * a pointer to a C-string that contains the Hello hash value as + * hex-digits. The hello hash is available immediately after + * @c zrtp_CreateWrapper . + * The caller must @c free() if it does not use the * hello hash C-string anymore. - * - * @see zrtp_getNumberSupportedVersions() */ - char* zrtp_getHelloHash(ZrtpContext* zrtpContext, int32_t index); + char* zrtp_getHelloHash(ZrtpContext* zrtpContext); /** * Get the peer's ZRTP Hello Hash data. @@ -1077,27 +1068,7 @@ extern "C" int32_t zrtp_getPeerZid(ZrtpContext* zrtpContext, uint8_t* data); - /** - * Get number of supported ZRTP protocol versions. - * - * @param zrtpContext - * Pointer to the opaque ZrtpContext structure. - * - * @return the number of supported ZRTP protocol versions. - */ - int32_t zrtp_getNumberSupportedVersions(ZrtpContext* zrtpContext); - - /** - * Get negotiated ZRTP protocol versions. - * - * @param zrtpContext - * Pointer to the opaque ZrtpContext structure. - * - * @return the integer representation of the negotiated ZRTP protocol version. - */ - int32_t zrtp_getCurrentProtocolVersion(ZrtpContext* zrtpContext); - - /** + /** * This enumerations list all configurable algorithm types. */ diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallback.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpCallback.h similarity index 95% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallback.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpCallback.h index 0ad18a9ae..23e9ca380 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallback.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpCallback.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -28,7 +28,20 @@ #include <string> #include <stdint.h> #include <libzrtpcpp/ZrtpCodes.h> -#include <common/osSpecifics.h> + +#ifndef __EXPORT + #if defined _WIN32 || defined __CYGWIN__ + #define __EXPORT __declspec(dllimport) + #define __LOCAL + #endif + #if __GNUC__ >= 4 + #define __EXPORT __attribute__ ((visibility("default"))) + #define __LOCAL __attribute__ ((visibility("hidden"))) + #else + #define __EXPORT + #define __LOCAL + #endif +#endif /** * This enum defines which role a ZRTP peer has. @@ -46,7 +59,6 @@ * </ul> */ typedef enum { - NoRole = 0, ///< ZRTP role not yet set Responder = 1, ///< This client is in ZRTP Responder mode Initiator ///< This client is in ZRTP Initiator mode } Role; @@ -118,10 +130,9 @@ protected: * ZRTP calls this method to send a ZRTP packet via the RTP session. * * @param data - * Points to ZRTP packet to send. The packet already contains a 4 bytes - * storage at the end to store CRC. + * Points to ZRTP packet to send. * @param length - * The length in bytes of the data, including the CRC storage. + * The length in bytes of the data * @return * zero if sending failed, one if packet was send */ diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallbackWrapper.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpCallbackWrapper.h similarity index 95% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallbackWrapper.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpCallbackWrapper.h index 098ec062b..dd739e01f 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallbackWrapper.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpCallbackWrapper.h @@ -1,9 +1,9 @@ /* This class maps the ZRTP C++ callback methods to C callback methods. - Copyright (C) 2010-2013 Werner Dittmann + Copyright (C) 2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCodes.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpCodes.h similarity index 90% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCodes.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpCodes.h index 1a7dd5f12..a1bb6fc9c 100755 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCodes.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpCodes.h @@ -1,10 +1,10 @@ /** @file ZrtpCodes.h */ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the Lesser GNU General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -73,7 +73,7 @@ enum MessageSeverity { * Sub-codes for Info */ enum InfoCodes { - InfoHelloReceived = 1, //!< Hello received and prepared a Commit, ready to get peer's hello hash + InfoHelloReceived = 1, //!< Hello received, preparing a Commit InfoCommitDHGenerated, //!< Commit: Generated a public DH key InfoRespCommitReceived, //!< Responder: Commit received, preparing DHPart1 InfoDH1DHGenerated, //!< DH1Part: Generated a public DH key @@ -90,15 +90,14 @@ enum InfoCodes { * Sub-codes for Warning */ enum WarningCodes { - WarningDHAESmismatch = 1, //!< Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096 - not used DH4096 was discarded + WarningDHAESmismatch = 1, //!< Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096 WarningGoClearReceived, //!< Received a GoClear message - WarningDHShort, //!< Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096- not used DH4096 was discarded + WarningDHShort, //!< Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096 WarningNoRSMatch, //!< No retained shared secrets available - must verify SAS WarningCRCmismatch, //!< Internal ZRTP packet checksum mismatch - packet dropped WarningSRTPauthError, //!< Dropping packet because SRTP authentication failed! WarningSRTPreplayError, //!< Dropping packet because SRTP replay check failed! - WarningNoExpectedRSMatch, //!< Valid retained shared secrets availabe but no matches found - must verify SAS - WarningNoExpectedAuxMatch //!< Our AUX secret was set but the other peer's AUX secret does not match ours + WarningNoExpectedRSMatch //!< Valid retained shared secrets availabe but no matches found - must verify SAS }; /** @@ -151,8 +150,7 @@ enum ZrtpErrorCodes { * Information codes for the Enrollment user callbacks. */ enum InfoEnrollment { - EnrollmentRequest = 0, //!< Aks user to confirm or deny an Enrollemnt request - EnrollmentReconfirm, //!< User already enrolled, ask re-confirmation + EnrollmentRequest, //!< Aks user to confirm or deny an Enrollemnt request EnrollmentCanceled, //!< User did not confirm the PBX enrollement EnrollmentFailed, //!< Enrollment process failed, no PBX secret available EnrollmentOk //!< Enrollment process for this PBX was ok diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpConfigure.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpConfigure.h similarity index 93% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpConfigure.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpConfigure.h index bb78cef79..33a824f51 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpConfigure.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpConfigure.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2009 - 2013 Werner Dittmann + Copyright (C) 2009 - 2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -47,7 +47,7 @@ enum AlgoTypes { }; typedef void(*encrypt_t)(uint8_t*, int32_t, uint8_t*, uint8_t*, int32_t); -typedef void(*decrypt_t)(uint8_t*, int32_t, uint8_t*, uint8_t*, int32_t); +typedef void(*decrypt_t)(uint8_t*, int32_t, const uint8_t*, uint8_t*, int32_t); /** * The algorithm enumration class. @@ -182,7 +182,7 @@ private: * @see zrtpSasTypes * @see zrtpAuthLengths */ -class __EXPORT EnumBase { +class EnumBase { public: /** * Get an AlgorithmEnum by its name @@ -257,41 +257,41 @@ private: /** * The enumaration subclasses that contain the supported algorithm enumerations. */ -class __EXPORT HashEnum : public EnumBase { +class HashEnum : public EnumBase { public: HashEnum(); ~HashEnum(); }; -class __EXPORT SymCipherEnum : public EnumBase { +class SymCipherEnum : public EnumBase { public: SymCipherEnum(); ~SymCipherEnum(); }; -class __EXPORT PubKeyEnum : public EnumBase { +class PubKeyEnum : public EnumBase { public: PubKeyEnum(); ~PubKeyEnum(); }; -class __EXPORT SasTypeEnum : public EnumBase { +class SasTypeEnum : public EnumBase { public: SasTypeEnum(); ~SasTypeEnum(); }; -class __EXPORT AuthLengthEnum : public EnumBase { +class AuthLengthEnum : public EnumBase { public: AuthLengthEnum(); ~AuthLengthEnum(); }; -extern __EXPORT HashEnum zrtpHashes; -extern __EXPORT SymCipherEnum zrtpSymCiphers; -extern __EXPORT PubKeyEnum zrtpPubKeys; -extern __EXPORT SasTypeEnum zrtpSasTypes; -extern __EXPORT AuthLengthEnum zrtpAuthLengths; +extern HashEnum zrtpHashes; +extern SymCipherEnum zrtpSymCiphers; +extern PubKeyEnum zrtpPubKeys; +extern SasTypeEnum zrtpSasTypes; +extern AuthLengthEnum zrtpAuthLengths; /** * ZRTP configuration data. @@ -314,14 +314,6 @@ public: ZrtpConfigure(); /* Creates Configuration data */ ~ZrtpConfigure(); - /** - * Define the algorithm selection policies. - */ - typedef enum _policies { - Standard = 1, - PreferNonNist = 2 - } Policy; - /** * Set the maximum number of algorithms per algorithm type that an application can * configure. @@ -518,9 +510,6 @@ public: /// Helper function to print some internal data void printConfiguredAlgos(AlgoTypes algoTyp); - Policy getSelectionPolicy() {return selectionPolicy;} - void setSelectionPolicy(Policy pol) {selectionPolicy = pol;} - private: std::vector<AlgorithmEnum* > hashes; std::vector<AlgorithmEnum* > symCiphers; @@ -543,8 +532,6 @@ public: void printConfiguredAlgos(std::vector<AlgorithmEnum* >& a); - Policy selectionPolicy; - protected: public: diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCrc32.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpCrc32.h similarity index 93% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCrc32.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpCrc32.h index 49eec83d1..ad57edd98 100755 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCrc32.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpCrc32.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketBase.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketBase.h similarity index 87% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketBase.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketBase.h index a5826c768..8beab7e1c 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketBase.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketBase.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -37,8 +37,7 @@ #include <stdint.h> #include <string.h> #include <stdlib.h> - -#include <common/osSpecifics.h> +#include <netinet/in.h> #include <libzrtpcpp/zrtpPacket.h> #include <libzrtpcpp/ZrtpTextData.h> @@ -96,7 +95,7 @@ class __EXPORT ZrtpPacketBase { * @return * @c true if check was ok */ - bool isZrtpPacket() { return (zrtpNtohs(zrtpHeader->zrtpId) == zrtpId); }; + bool isZrtpPacket() { return (ntohs(zrtpHeader->zrtpId) == zrtpId); }; /** * Get the length in words of the ZRTP message @@ -104,7 +103,7 @@ class __EXPORT ZrtpPacketBase { * @return * The length in words */ - uint16_t getLength() { return zrtpNtohs(zrtpHeader->length); }; + uint16_t getLength() { return ntohs(zrtpHeader->length); }; /** * Return pointer to fixed length message type ASCII data @@ -120,7 +119,7 @@ class __EXPORT ZrtpPacketBase { * @param len * The length of the ZRTP message in words, host order */ - void setLength(uint16_t len) { zrtpHeader->length = zrtpHtons(len); }; + void setLength(uint16_t len) { zrtpHeader->length = htons(len); }; /** * Copy the message type ASCII data to ZRTP message type field @@ -134,7 +133,7 @@ class __EXPORT ZrtpPacketBase { /** * Initializes the ZRTP Id field */ - void setZrtpId() { zrtpHeader->zrtpId = zrtpHtons(zrtpId); } + void setZrtpId() { zrtpHeader->zrtpId = htons(zrtpId); } }; /** diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketClearAck.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketClearAck.h similarity index 92% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketClearAck.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketClearAck.h index 91ca4c438..992f6d8fa 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketClearAck.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketClearAck.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketCommit.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketCommit.h similarity index 88% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketCommit.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketCommit.h index 4b6e1eb23..b23b23dd5 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketCommit.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketCommit.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -31,11 +31,6 @@ #include <libzrtpcpp/ZrtpPacketBase.h> -// PRSH here only for completeness. We don't support PRSH in the other ZRTP parts. -#define COMMIT_DH_EX 29 -#define COMMIT_MULTI 25 -#define COMMIT_PRSH 27 - /** * Implement the Commit packet. * @@ -53,11 +48,6 @@ class __EXPORT ZrtpPacketCommit : public ZrtpPacketBase { Commit_t* commitHeader; ///< Points to Commit message part public: - typedef enum _commitType { - DhExchange = 1, - MultiStream = 2 - } commitType; - /// Creates a Commit packet with default data ZrtpPacketCommit(); @@ -100,10 +90,6 @@ class __EXPORT ZrtpPacketCommit : public ZrtpPacketBase { /// Get pointer to MAC field during multi-stream mode, a fixed length byte array uint8_t* getHMACMulti() { return commitHeader->hmac-4*ZRTP_WORD_SIZE; }; - /// Check if packet length makes sense. - bool isLengthOk(commitType type) {int32_t len = getLength(); - return ((type == DhExchange) ? len == COMMIT_DH_EX : len == COMMIT_MULTI);} - /// Set hash algorithm type field, fixed length character field void setHashType(uint8_t* text) { memcpy(commitHeader->hash, text, ZRTP_WORD_SIZE); }; diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConf2Ack.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketConf2Ack.h similarity index 92% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConf2Ack.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketConf2Ack.h index a6f85f56a..a7c256724 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConf2Ack.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketConf2Ack.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConfirm.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketConfirm.h similarity index 91% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConfirm.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketConfirm.h index 283861d08..b2dfbf47c 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConfirm.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketConfirm.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -73,7 +73,7 @@ class __EXPORT ZrtpPacketConfirm : public ZrtpPacketBase { const uint8_t* getHmac() { return confirmHeader->hmac; } /// Get Expiration time data - const uint32_t getExpTime() { return zrtpNtohl(confirmHeader->expTime); } + const uint32_t getExpTime() { return ntohl(confirmHeader->expTime); } /// Get pointer to initial hash chain (H0) data, fixed byte array uint8_t* getHashH0() { return confirmHeader->hashH0; } @@ -84,11 +84,6 @@ class __EXPORT ZrtpPacketConfirm : public ZrtpPacketBase { /// get the signature length in words int32_t getSignatureLength(); - /// Check if packet length makes sense. Confirm packets are 19 words at minumum - bool isLengthOk() {return (getLength() >= 19); } - - bool isSignatureLengthOk(); - /// set SAS verified flag void setSASFlag() { confirmHeader->flags |= 0x4; } @@ -102,7 +97,7 @@ class __EXPORT ZrtpPacketConfirm : public ZrtpPacketBase { void setIv(uint8_t* text) { memcpy(confirmHeader->iv, text, sizeof(confirmHeader->iv)); } /// Set expiration time data - void setExpTime(uint32_t t) { confirmHeader->expTime = zrtpHtonl(t); } + void setExpTime(uint32_t t) { confirmHeader->expTime = htonl(t); } /// Set initial hash chain (H0) data, fixed length byte array void setHashH0(uint8_t* t) { memcpy(confirmHeader->hashH0, t, sizeof(confirmHeader->hashH0)); } diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketDHPart.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketDHPart.h similarity index 93% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketDHPart.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketDHPart.h index 08737a56b..d0ea4ba19 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketDHPart.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketDHPart.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -79,9 +79,6 @@ class __EXPORT ZrtpPacketDHPart : public ZrtpPacketBase { /// Get pointer to HMAC, fixed length byte array uint8_t* getHMAC() { return pv+dhLength; }; - /// Check if packet length makes sense. DHPart packets are 29 words at minumum, using E255 - bool isLengthOk() {return (getLength() >= 29);} - /// Setpublic key value, variable length byte array void setPv(uint8_t* text) { memcpy(pv, text, dhLength); }; diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketError.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketError.h similarity index 83% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketError.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketError.h index 679a80396..d7758013a 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketError.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketError.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -52,10 +52,10 @@ class __EXPORT ZrtpPacketError : public ZrtpPacketBase { virtual ~ZrtpPacketError(); /// Get the error code from Error message - uint32_t getErrorCode() { return zrtpNtohl(errorHeader->errorCode); }; + uint32_t getErrorCode() { return ntohl(errorHeader->errorCode); }; /// Set error code in Error message - void setErrorCode(uint32_t code) {errorHeader->errorCode = zrtpHtonl(code); }; + void setErrorCode(uint32_t code) {errorHeader->errorCode = htonl(code); }; private: ErrorPacket_t data; diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketErrorAck.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketErrorAck.h similarity index 91% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketErrorAck.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketErrorAck.h index cfd435c00..e64c8a6e9 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketErrorAck.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketErrorAck.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2007-2013 Werner Dittmann + Copyright (C) 2007 - 2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketGoClear.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketGoClear.h similarity index 100% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketGoClear.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketGoClear.h diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHello.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketHello.h similarity index 91% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHello.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketHello.h index f5394afda..0cc740355 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHello.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketHello.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -28,8 +28,6 @@ #include <libzrtpcpp/ZrtpPacketBase.h> -#define HELLO_FIXED_PART_LEN 22 - /** * Implement the Hello packet. * @@ -85,9 +83,6 @@ class __EXPORT ZrtpPacketHello : public ZrtpPacketBase { /// Get version number from Hello message, fixed ASCII character array uint8_t* getVersion() { return helloHeader->version; }; - /// Get version number from Hello message as integer, only relvant digits converted - int32_t getVersionInt(); - /// Get client id from Hello message, fixed ASCII character array uint8_t* getClientId() { return helloHeader->clientId; }; @@ -98,7 +93,7 @@ class __EXPORT ZrtpPacketHello : public ZrtpPacketBase { uint8_t* getZid() { return helloHeader->zid; }; /// Set version sting in Hello message, fixed ASCII character array - void setVersion(const uint8_t *text) { memcpy(helloHeader->version, text,ZRTP_WORD_SIZE ); } + void setVersion(uint8_t *text) { memcpy(helloHeader->version, text,ZRTP_WORD_SIZE ); } /// Set client id in Hello message, fixed ASCII character array void setClientId(const uint8_t *t) { memcpy(helloHeader->clientId, t, sizeof(helloHeader->clientId)); } @@ -176,20 +171,16 @@ class __EXPORT ZrtpPacketHello : public ZrtpPacketBase { int32_t getNumAuth() {return nAuth; } /// set MitM flag - void setMitmMode() {helloHeader->flags |= 0x20; } + void setMitmMode() { helloHeader->flags |= 0x20; } /// set SAS sign flag - void setSasSign() {helloHeader->flags |= 0x40; } - - /// Check if packet length matches - bool isLengthOk() {return (computedLength == getLength());} + void setSasSign() { helloHeader->flags |= 0x40; } private: - uint32_t computedLength; // Hello packet is of variable length. It maximum size is 46 words: - // - 20 words fixed sizze + // - 11 words fixed sizze // - up to 35 words variable part, depending on number of algorithms - // leads to a maximum of 4*55=220 bytes. + // leads to a maximum of 4*46=184 bytes. uint8_t data[256]; // large enough to hold a full blown Hello packet }; diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHelloAck.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketHelloAck.h similarity index 91% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHelloAck.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketHelloAck.h index d3e138ee5..345a071e4 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHelloAck.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketHelloAck.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPing.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketPing.h similarity index 93% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPing.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketPing.h index 32fb2f95e..840df6246 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPing.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketPing.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2009 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPingAck.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketPingAck.h similarity index 87% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPingAck.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketPingAck.h index eb2924f39..51ad8c8ff 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPingAck.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketPingAck.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2009 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -49,13 +49,13 @@ class __EXPORT ZrtpPacketPingAck : public ZrtpPacketBase { virtual ~ZrtpPacketPingAck(); /// Get SSRC from PingAck message - uint32_t getSSRC() { return zrtpNtohl(pingAckHeader->ssrc); }; + uint32_t getSSRC() { return ntohl(pingAckHeader->ssrc); }; /// Set ZRTP protocol version field, fixed ASCII character array void setVersion(uint8_t *text) { memcpy(pingAckHeader->version, text, ZRTP_WORD_SIZE ); } /// Set SSRC in PingAck message - void setSSRC(uint32_t data) {pingAckHeader->ssrc = zrtpHtonl(data); }; + void setSSRC(uint32_t data) {pingAckHeader->ssrc = htonl(data); }; /// Set remote endpoint hash, fixed byte array void setRemoteEpHash(uint8_t *hash) { memcpy(pingAckHeader->remoteEpHash, hash, sizeof(pingAckHeader->remoteEpHash)); } diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketRelayAck.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketRelayAck.h similarity index 91% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketRelayAck.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketRelayAck.h index 7fe373bc1..93437e6d1 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketRelayAck.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketRelayAck.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2007-2013 Werner Dittmann + Copyright (C) 2007 - 2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketSASrelay.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketSASrelay.h similarity index 86% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketSASrelay.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketSASrelay.h index 22739ff15..427ac2821 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketSASrelay.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpPacketSASrelay.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2011 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -70,17 +70,14 @@ class __EXPORT ZrtpPacketSASrelay : public ZrtpPacketBase { const uint8_t* getHmac() { return sasRelayHeader->hmac; } /// Get pointer to new SAS rendering algorithm, fixed byte array - const uint8_t* getSasAlgo() {return sasRelayHeader->sas; } + const uint8_t* getSas() {return sasRelayHeader->sas; } /// Get pointer to new SAS hash data, fixed byte array - const uint8_t* getTrustedSas() { return sasRelayHeader->trustedSasHash; } + const uint8_t* getTrustedSas() { return sasRelayHeader->trustedSasHash; } /// get the signature length in words uint32_t getSignatureLength(); - /// Check if packet length makes sense. SAS rely packets are 19 words at minumum, they are similar to Confirm - bool isLengthOk() {return (getLength() >= 19);} - /// set SAS verified flag void setSASFlag() { sasRelayHeader->flags |= 0x4; } @@ -91,7 +88,7 @@ class __EXPORT ZrtpPacketSASrelay : public ZrtpPacketBase { void setIv(uint8_t* text) { memcpy(sasRelayHeader->iv, text, sizeof(sasRelayHeader->iv)); } /// Set SAS rendering algorithm, fixed length byte array - void setSasAlgo(uint8_t* text) { memcpy(sasRelayHeader->sas, text, sizeof(sasRelayHeader->sas)); } + void setSas(uint8_t* text) { memcpy(sasRelayHeader->sas, text, sizeof(sasRelayHeader->sas)); } /// Set SAS hash data, fixed length byte array void setTrustedSas(uint8_t* text) { memcpy(sasRelayHeader->trustedSasHash, text, sizeof(sasRelayHeader->trustedSasHash)); } diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpQueue.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpQueue.h similarity index 96% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpQueue.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpQueue.h index 512d8c84b..b979ada46 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpQueue.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpQueue.h @@ -21,8 +21,8 @@ #include <ccrtp/cqueue.h> #include <ccrtp/rtppkt.h> #include <libzrtpcpp/ZrtpCallback.h> +#include <libzrtpcpp/TimeoutProvider.h> #include <libzrtpcpp/ZrtpConfigure.h> -#include <CcrtpTimeoutProvider.h> class __EXPORT ZrtpUserCallback; class __EXPORT ZRtp; @@ -368,28 +368,20 @@ public: */ void setClientId(std::string id); - /** + /** * Get the ZRTP Hello Hash data. * - * Use this method to get the ZRTP Hello hash data. The method - * returns the data as a string containing the ZRTP protocol version and - * hex-digits. - * - * The index defines which Hello packet to use. Each supported ZRTP procol version - * uses a different Hello packet and thus computes different hashes. - * - * Refer to ZRTP specification, chapter 8. - * - * @param index - * Hello hash of the Hello packet identfied by index. Index must be 0 <= index < getNumberSupportedVersions(). + * Use this method to get the ZRTP Hello Hash data. The method + * returns the data as a string containing hex-digits. Refer + * to ZRTP specification, chapter 9.1. * * @return - * a std::string formatted according to RFC6189 section 8 without the leading 'a=zrtp-hash:' - * SDP attribute identifier. The hello hash is available immediatly after class instantiation. - * - * @see getNumberSupportedVersions() + * a std:string containing the Hello hash value as hex-digits. The + * hello hash is available immediatly after calling + * ZrtpQueue#startZrtp. If ZRTP was not started the method returns + * an empty string. */ - std::string getHelloHash(int32_t index); + std::string getHelloHash(); /** * Get the peer's ZRTP Hello Hash data. @@ -751,20 +743,6 @@ public: */ int32 getPeerZid(uint8* data); - /** - * Get number of supported ZRTP protocol versions. - * - * @return the number of supported ZRTP protocol versions. - */ - int32_t getNumberSupportedVersions(); - - /** - * Get negotiated ZRTP protocol version. - * - * @return the integer representation of the negotiated ZRTP protocol version. - */ - int32_t getCurrentProtocolVersion(); - protected: friend class TimeoutProvider<std::string, ost::ZrtpQueue*>; @@ -873,7 +851,6 @@ private: int16 senderZrtpSeqNo; ost::Mutex synchLock; // Mutex for ZRTP (used by ZrtpStateClass) uint32 peerSSRC; - uint64 zrtpUnprotect; bool started; bool mitmMode; bool signSas; diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStateClass.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpStateClass.h similarity index 97% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStateClass.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpStateClass.h index 5c163139e..fba061d68 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStateClass.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpStateClass.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -74,7 +74,6 @@ enum SecureSubStates { /// A ZRTP state event typedef struct Event { EventDataType type; ///< Type of event - size_t length; ///< length of the message data uint8_t* packet; ///< Event data if availabe, usually a ZRTP message } Event_t; @@ -161,11 +160,6 @@ private: */ bool subEvWaitRelayAck(); - /** - * Hello packet version sent to other partner - */ - int32_t sentVersion; - public: /// Create a ZrtpStateClass ZrtpStateClass(ZRtp *p); diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStates.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpStates.h similarity index 94% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStates.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpStates.h index e90a54398..44662a0a8 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStates.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpStates.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpTextData.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpTextData.h similarity index 86% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpTextData.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpTextData.h index 0be1e5657..e79cb9871 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpTextData.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpTextData.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -37,12 +37,8 @@ * * @author Werner Dittmann <Werner.Dittmann@t-online.de> */ - -extern char zrtpBuildInfo[]; - extern char clientId[]; -extern char zrtpVersion_11[]; -extern char zrtpVersion_12[]; +extern char zrtpVersion[]; /** * @@ -91,8 +87,6 @@ extern char zrtpTrustedMitm[]; extern char s256[]; extern char s384[]; -extern char skn2[]; -extern char skn3[]; extern const char* mandatoryHash; extern char aes3[]; @@ -108,15 +102,12 @@ extern char dh2k[]; extern char dh3k[]; extern char ec25[]; extern char ec38[]; -extern char e255[]; -extern char e414[]; extern char mult[]; extern const char* mandatoryPubKey; extern char b32[]; -extern char b256[]; extern const char* mandatorySasType; extern char hs32[]; @@ -126,9 +117,6 @@ extern char sk64[]; extern const char* mandatoryAuthLen_1; extern const char* mandatoryAuthLen_2; -extern const char* sas256WordsOdd[]; -extern const char* sas256WordsEven[]; - /** * @} */ diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpUserCallback.h b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpUserCallback.h similarity index 95% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpUserCallback.h rename to jni/libzrtp/sources/src/libzrtpcpp/ZrtpUserCallback.h index d3c9f9db6..3e4871cf8 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpUserCallback.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/ZrtpUserCallback.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2008 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/crypto/twoCFB.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/TwoCFB.cpp similarity index 90% rename from jni/libzrtp/sources/zrtp/crypto/twoCFB.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/TwoCFB.cpp index d4f7042f5..be3dda418 100755 --- a/jni/libzrtp/sources/zrtp/crypto/twoCFB.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/TwoCFB.cpp @@ -36,12 +36,13 @@ #include <string.h> -#include <zrtp/crypto/twoCFB.h> -#include <cryptcommon/twofish.h> +#include <libzrtpcpp/crypto/twoCFB.h> +#include <libzrtpcpp/crypto/twofish.h> static int initialized = 0; -void twoCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, int32_t dataLength) +void twoCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, + int32_t dataLength) { Twofish_key keyCtx; int usedBytes = 0; @@ -59,7 +60,8 @@ void twoCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, } -void twoCfbDecrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, int32_t dataLength) +void twoCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data, + int32_t dataLength) { Twofish_key keyCtx; int usedBytes = 0; diff --git a/jni/libzrtp/sources/zrtp/crypto/zrtpDH.h b/jni/libzrtp/sources/src/libzrtpcpp/crypto/ZrtpDH.h similarity index 95% rename from jni/libzrtp/sources/zrtp/crypto/zrtpDH.h rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/ZrtpDH.h index d2a3a404c..bd32f7fa8 100644 --- a/jni/libzrtp/sources/zrtp/crypto/zrtpDH.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/ZrtpDH.h @@ -23,9 +23,10 @@ #define _ZRTPDH_H__ #include <stdint.h> +#include <libzrtpcpp/ZrtpConfigure.h> /** - * @file zrtpDH.h + * @file ZrtpDH.h * @brief Class that implemets Diffie-Helman key agreement for ZRTP * * @ingroup GNU_ZRTP @@ -42,25 +43,12 @@ * @param length * Number of random bytes to produce. */ -#if defined(__cplusplus) -extern "C" -{ -#endif void randomZRTP(uint8_t *buf, int32_t length); -#if defined(__cplusplus) -} -#endif - -#if defined(__cplusplus) - -#include <libzrtpcpp/ZrtpConfigure.h> const int32_t DH2K = 0; const int32_t DH3K = 1; const int32_t EC25 = 2; const int32_t EC38 = 3; -const int32_t E255 = 4; -const int32_t E414 = 5; /** @@ -164,8 +152,8 @@ public: */ const char* getDHtype(); }; -#endif /*__cpluscplus */ -#endif + +#endif // ZRTPDH_H /** * @} diff --git a/jni/libzrtp/sources/zrtp/crypto/aesCFB.h b/jni/libzrtp/sources/src/libzrtpcpp/crypto/aesCFB.h similarity index 91% rename from jni/libzrtp/sources/zrtp/crypto/aesCFB.h rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/aesCFB.h index 7223bdff5..6b4ab6ef1 100644 --- a/jni/libzrtp/sources/zrtp/crypto/aesCFB.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/aesCFB.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -79,7 +79,7 @@ void aesCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, * Length of the data in bytes */ -void aesCfbDecrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, +void aesCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data, int32_t dataLength); /** * @} diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/InitializeGcrypt.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp similarity index 96% rename from jni/libzrtp/sources/zrtp/crypto/gcrypt/InitializeGcrypt.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp index 1c743d2f9..78fad51c6 100644 --- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/InitializeGcrypt.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -17,7 +17,7 @@ #include <stdio.h> -#include <string.h> +#include <malloc.h> #include <pthread.h> #include <errno.h> #include <gcrypt.h> diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptAesCFB.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp similarity index 89% rename from jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptAesCFB.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp index 066035fa9..8d06a890d 100644 --- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptAesCFB.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -21,7 +21,7 @@ */ #include <gcrypt.h> -#include <crypto/aesCFB.h> +#include <libzrtpcpp/crypto/aesCFB.h> extern void initializeGcrypt(); @@ -51,7 +51,7 @@ void aesCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, gcry_cipher_close(tmp); } -void aesCfbDecrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, +void aesCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data, int32_t dataLength); { gcry_error_t err = 0; diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptZrtpDH.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp similarity index 98% rename from jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptZrtpDH.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp index bc8897a25..1aba68023 100644 --- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptZrtpDH.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006, 2013 Werner Dittmann + Copyright (C) 2006, 2009 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -21,8 +21,8 @@ */ #include <gcrypt.h> -#include <zrtp/crypto/zrtpDH.h> -#include <zrtp/libzrtpcpp/ZrtpTextData.h> +#include <libzrtpcpp/crypto/ZrtpDH.h> +#include <libzrtpcpp/ZrtpTextData.h> #include <sstream> struct gcryptCtx { diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcrypthmac256.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp similarity index 92% rename from jni/libzrtp/sources/zrtp/crypto/gcrypt/gcrypthmac256.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp index a0ecc65ca..3a445044f 100644 --- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcrypthmac256.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -21,7 +21,7 @@ */ #include <gcrypt.h> -#include <crypto/hmac256.h> +#include <libzrtpcpp/crypto/hmac256.h> void hmac_sha256(uint8_t* key, uint32_t keyLength, uint8_t* data, int32_t dataLength, diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcrypthmac384.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp similarity index 98% rename from jni/libzrtp/sources/zrtp/crypto/gcrypt/gcrypthmac384.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp index aa852c4d9..c48813c41 100644 --- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcrypthmac384.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp @@ -21,7 +21,7 @@ */ #include <gcrypt.h> -#include <crypto/hmac384.h> +#include <libzrtpcpp/crypto/hmac384.h> void hmac_sha384(uint8_t* key, uint32_t keyLength, uint8_t* data, int32_t dataLength, diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha256.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp similarity index 93% rename from jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha256.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp index b20bfe62b..0c32bd8ab 100644 --- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha256.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -22,7 +22,7 @@ */ #include <gcrypt.h> -#include <crypto/sha256.h> +#include <libzrtpcpp/crypto/sha256.h> void sha256(unsigned char* data, unsigned int dataLength, unsigned char* mac) diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha384.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp similarity index 93% rename from jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha384.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp index c26a23c5f..19c8c5b6f 100644 --- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha384.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -22,7 +22,7 @@ */ #include <gcrypt.h> -#include <crypto/sha384.h> +#include <libzrtpcpp/crypto/sha384.h> void sha384(unsigned char* data, unsigned int dataLength, unsigned char* mac) diff --git a/jni/libzrtp/sources/zrtp/crypto/hmac256.h b/jni/libzrtp/sources/src/libzrtpcpp/crypto/hmac256.h similarity index 100% rename from jni/libzrtp/sources/zrtp/crypto/hmac256.h rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/hmac256.h diff --git a/jni/libzrtp/sources/zrtp/crypto/hmac384.h b/jni/libzrtp/sources/src/libzrtpcpp/crypto/hmac384.h similarity index 100% rename from jni/libzrtp/sources/zrtp/crypto/hmac384.h rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/hmac384.h diff --git a/jni/libzrtp/sources/zrtp/crypto/openssl/aesCFB.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/AesCFB.cpp similarity index 93% rename from jni/libzrtp/sources/zrtp/crypto/openssl/aesCFB.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/AesCFB.cpp index bac29f5ce..595d1ff09 100644 --- a/jni/libzrtp/sources/zrtp/crypto/openssl/aesCFB.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/AesCFB.cpp @@ -38,7 +38,7 @@ #include <openssl/aes.h> #include <string.h> -#include <zrtp/crypto/aesCFB.h> +#include <libzrtpcpp/crypto/aesCFB.h> // extern void initializeOpenSSL(); @@ -66,7 +66,7 @@ void aesCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, } -void aesCfbDecrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, +void aesCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data, int32_t dataLength) { AES_KEY aesKey; @@ -85,5 +85,5 @@ void aesCfbDecrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, return; } AES_cfb128_encrypt(data, data, dataLength, &aesKey, - IV, &usedBytes, AES_DECRYPT); + (unsigned char*)IV, &usedBytes, AES_DECRYPT); } diff --git a/jni/libzrtp/sources/zrtp/crypto/openssl/InitializeOpenSSL.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp similarity index 97% rename from jni/libzrtp/sources/zrtp/crypto/openssl/InitializeOpenSSL.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp index 2c5c8de40..ef0c926be 100755 --- a/jni/libzrtp/sources/zrtp/crypto/openssl/InitializeOpenSSL.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006 Werner Dittmann This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/crypto/openssl/zrtpDH.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp similarity index 99% rename from jni/libzrtp/sources/zrtp/crypto/openssl/zrtpDH.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp index d5b8cc9ba..fbd623caf 100644 --- a/jni/libzrtp/sources/zrtp/crypto/openssl/zrtpDH.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp @@ -46,8 +46,8 @@ #include <openssl/ec.h> #include <openssl/ecdh.h> -#include <zrtp/crypto/zrtpDH.h> -#include <zrtp/libzrtpcpp/ZrtpTextData.h> +#include <libzrtpcpp/crypto/ZrtpDH.h> +#include <libzrtpcpp/ZrtpTextData.h> // extern void initializeOpenSSL(); diff --git a/jni/libzrtp/sources/zrtp/crypto/openssl/hmac256.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/hmac256.cpp similarity index 98% rename from jni/libzrtp/sources/zrtp/crypto/openssl/hmac256.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/hmac256.cpp index 40e4e8230..a054c0216 100644 --- a/jni/libzrtp/sources/zrtp/crypto/openssl/hmac256.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/hmac256.cpp @@ -36,7 +36,7 @@ */ #include <openssl/hmac.h> -#include <crypto/hmac256.h> +#include <libzrtpcpp/crypto/hmac256.h> void hmac_sha256(uint8_t* key, uint32_t key_length, uint8_t* data, int32_t data_length, diff --git a/jni/libzrtp/sources/zrtp/crypto/openssl/hmac384.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/hmac384.cpp similarity index 92% rename from jni/libzrtp/sources/zrtp/crypto/openssl/hmac384.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/hmac384.cpp index 8181cd66e..10d6fbca7 100644 --- a/jni/libzrtp/sources/zrtp/crypto/openssl/hmac384.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/hmac384.cpp @@ -36,9 +36,11 @@ */ #include <openssl/hmac.h> -#include <zrtp/crypto/hmac256.h> +#include <libzrtpcpp/crypto/hmac256.h> -void hmac_sha384(uint8_t* key, uint32_t key_length, uint8_t* data, int32_t data_length, uint8_t* mac, uint32_t* mac_length) +void hmac_sha384(uint8_t* key, uint32_t key_length, + uint8_t* data, int32_t data_length, + uint8_t* mac, uint32_t* mac_length) { unsigned int tmp; HMAC( EVP_sha384(), key, key_length, data, data_length, mac, &tmp ); diff --git a/jni/libzrtp/sources/zrtp/crypto/openssl/sha256.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/sha256.cpp similarity index 98% rename from jni/libzrtp/sources/zrtp/crypto/openssl/sha256.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/sha256.cpp index bc2e222e6..2163a6d26 100644 --- a/jni/libzrtp/sources/zrtp/crypto/openssl/sha256.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/sha256.cpp @@ -38,7 +38,7 @@ #include <openssl/crypto.h> #include <openssl/sha.h> -#include <crypto/sha256.h> +#include <libzrtpcpp/crypto/sha256.h> void sha256(unsigned char *data, unsigned int data_length, unsigned char *digest ) diff --git a/jni/libzrtp/sources/zrtp/crypto/openssl/sha384.cpp b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/sha384.cpp similarity index 98% rename from jni/libzrtp/sources/zrtp/crypto/openssl/sha384.cpp rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/sha384.cpp index 9fcf3169f..9d166e757 100644 --- a/jni/libzrtp/sources/zrtp/crypto/openssl/sha384.cpp +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/openssl/sha384.cpp @@ -38,7 +38,7 @@ #include <openssl/crypto.h> #include <openssl/sha.h> -#include <crypto/sha384.h> +#include <libzrtpcpp/crypto/sha384.h> void sha384(unsigned char *data, unsigned int data_length, unsigned char *digest ) diff --git a/jni/libzrtp/sources/zrtp/crypto/sha256.h b/jni/libzrtp/sources/src/libzrtpcpp/crypto/sha256.h similarity index 97% rename from jni/libzrtp/sources/zrtp/crypto/sha256.h rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/sha256.h index 36127b9df..959a620ef 100644 --- a/jni/libzrtp/sources/zrtp/crypto/sha256.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/sha256.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/crypto/sha384.h b/jni/libzrtp/sources/src/libzrtpcpp/crypto/sha384.h similarity index 97% rename from jni/libzrtp/sources/zrtp/crypto/sha384.h rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/sha384.h index d4ccce5ef..6cb7a7092 100644 --- a/jni/libzrtp/sources/zrtp/crypto/sha384.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/sha384.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/crypto/twoCFB.h b/jni/libzrtp/sources/src/libzrtpcpp/crypto/twoCFB.h similarity index 88% rename from jni/libzrtp/sources/zrtp/crypto/twoCFB.h rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/twoCFB.h index 595d19d68..593a59c45 100755 --- a/jni/libzrtp/sources/zrtp/crypto/twoCFB.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/twoCFB.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -56,7 +56,8 @@ * Length of the data in bytes */ -void twoCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, int32_t dataLength); +void twoCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, + int32_t dataLength); /** * Decrypt data with Twofish CFB mode, full block feedback size. @@ -78,7 +79,8 @@ void twoCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, * Length of the data in bytes */ -void twoCfbDecrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data, int32_t dataLength); +void twoCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data, + int32_t dataLength); /** * @} */ diff --git a/jni/libzrtp/sources/cryptcommon/twofish.c b/jni/libzrtp/sources/src/libzrtpcpp/crypto/twofish.c similarity index 97% rename from jni/libzrtp/sources/cryptcommon/twofish.c rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/twofish.c index 03d277003..3d390eaf4 100644 --- a/jni/libzrtp/sources/cryptcommon/twofish.c +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/twofish.c @@ -1,1742 +1,1733 @@ -/* - * Fast, portable, and easy-to-use Twofish implementation, - * Version 0.3. - * Copyright (c) 2002 by Niels Ferguson. - * (See further down for the almost-unrestricted licensing terms.) - * - * -------------------------------------------------------------------------- - * There are two files for this implementation: - * - twofish.h, the header file. - * - twofish.c, the code file. - * - * To incorporate this code into your program you should: - * - Check the licensing terms further down in this comment. - * - Fix the two type definitions in twofish.h to suit your platform. - * - Fix a few definitions in twofish.c in the section marked - * PLATFORM FIXES. There is one important ones that affects - * functionality, and then a few definitions that you can optimise - * for efficiency but those have no effect on the functionality. - * Don't change anything else. - * - Put the code in your project and compile it. - * - * To use this library you should: - * - Call Twofish_initialise() in your program before any other function in - * this library. - * - Use Twofish_prepare_key(...) to convert a key to internal form. - * - Use Twofish_encrypt(...) and Twofish_decrypt(...) to encrypt and decrypt - * data. - * See the comments in the header file for details on these functions. - * -------------------------------------------------------------------------- - * - * There are many Twofish implementation available for free on the web. - * Most of them are hard to integrate into your own program. - * As we like people to use our cipher, I thought I would make it easier. - * Here is a free and easy-to-integrate Twofish implementation in C. - * The latest version is always available from my personal home page at - * http://niels.ferguson.net/ - * - * Integrating library code into a project is difficult because the library - * header files interfere with the project's header files and code. - * And of course the project's header files interfere with the library code. - * I've tried to resolve these problems here. - * The header file of this implementation is very light-weight. - * It contains two typedefs, a structure, and a few function declarations. - * All names it defines start with "Twofish_". - * The header file is therefore unlikely to cause problems in your project. - * The code file of this implementation doesn't need to include the header - * files of the project. There is thus no danger of the project interfering - * with all the definitions and macros of the Twofish code. - * In most situations, all you need to do is fill in a few platform-specific - * definitions in the header file and code file, - * and you should be able to run the Twofish code in your project. - * I estimate it should take you less than an hour to integrate this code - * into your project, most of it spent reading the comments telling you what - * to do. - * - * For people using C++: it is very easy to wrap this library into a - * TwofishKey class. One of the big advantages is that you can automate the - * wiping of the key material in the destructor. I have not provided a C++ - * class because the interface depends too much on the abstract base class - * you use for block ciphers in your program, which I don't know about. - * - * This implementation is designed for use on PC-class machines. It uses the - * Twofish 'full' keying option which uses large tables. Total table size is - * around 5-6 kB for static tables plus 4.5 kB for each pre-processed key. - * If you need an implementation that uses less memory, - * take a look at Brian Gladman's code on his web site: - * http://fp.gladman.plus.com/cryptography_technology/aes/ - * He has code for all AES candidates. - * His Twofish code has lots of options trading off table size vs. speed. - * You can also take a look at the optimised code by Doug Whiting on the - * Twofish web site - * http://www.counterpane.com/twofish.html - * which has loads of options. - * I believe these existing implementations are harder to re-use because they - * are not clean libraries and they impose requirements on the environment. - * This implementation is very careful to minimise those, - * and should be easier to integrate into any larger program. - * - * The default mode of this implementation is fully portable as it uses no - * behaviour not defined in the C standard. (This is harder than you think.) - * If you have any problems porting the default mode, please let me know - * so that I can fix the problem. (But only if this code is at fault, I - * don't fix compilers.) - * Most of the platform fixes are related to non-portable but faster ways - * of implementing certain functions. - * - * In general I've tried to make the code as fast as possible, at the expense - * of memory and code size. However, C does impose limits, and this - * implementation will be slower than an optimised assembler implementation. - * But beware of assembler implementations: a good Pentium implementation - * uses completely different code than a good Pentium II implementation. - * You basically have to re-write the assembly code for every generation of - * processor. Unless you are severely pressed for speed, stick with C. - * - * The initialisation routine of this implementation contains a self-test. - * If initialisation succeeds without calling the fatal routine, then - * the implementation works. I don't think you can break the implementation - * in such a way that it still passes the tests, unless you are malicious. - * In other words: if the initialisation routine returns, - * you have successfully ported the implementation. - * (Or not implemented the fatal routine properly, but that is your problem.) - * - * I'm indebted to many people who helped me in one way or another to write - * this code. During the design of Twofish and the AES process I had very - * extensive discussions of all implementation issues with various people. - * Doug Whiting in particular provided a wealth of information. The Twofish - * team spent untold hours discussion various cipher features, and their - * implementation. Brian Gladman implemented all AES candidates in C, - * and we had some fruitful discussions on how to implement Twofish in C. - * Jan Nieuwenhuizen tested this code on Linux using GCC. - * - * Now for the license: - * The author hereby grants a perpetual license to everybody to - * use this code for any purpose as long as the copyright message is included - * in the source code of this or any derived work. - * - * Yes, this means that you, your company, your club, and anyone else - * can use this code anywhere you want. You can change it and distribute it - * under the GPL, include it in your commercial product without releasing - * the source code, put it on the web, etc. - * The only thing you cannot do is remove my copyright message, - * or distribute any source code based on this implementation that does not - * include my copyright message. - * - * I appreciate a mention in the documentation or credits, - * but I understand if that is difficult to do. - * I also appreciate it if you tell me where and why you used my code. - * - * Please send any questions or comments to niels@ferguson.net - * - * Have Fun! - * - * Niels - */ - -/* - * DISCLAIMER: As I'm giving away my work for free, I'm of course not going - * to accept any liability of any form. This code, or the Twofish cipher, - * might very well be flawed; you have been warned. - * This software is provided as-is, without any kind of warrenty or - * guarantee. And that is really all you can expect when you download - * code for free from the Internet. - * - * I think it is really sad that disclaimers like this seem to be necessary. - * If people only had a little bit more common sense, and didn't come - * whining like little children every time something happens.... - */ - -/* - * Version history: - * Version 0.0, 2002-08-30 - * First written. - * Version 0.1, 2002-09-03 - * Added disclaimer. Improved self-tests. - * Version 0.2, 2002-09-09 - * Removed last non-portabilities. Default now works completely within - * the C standard. UInt32 can be larger than 32 bits without problems. - * Version 0.3, 2002-09-28 - * Bugfix: use instead of to adhere to ANSI/ISO. - * Rename BIG_ENDIAN macro to CPU_IS_BIG_ENDIAN. The gcc library - * header already defines BIG_ENDIAN, even though it is not - * supposed to. - */ - - -/* - * Minimum set of include files. - * You should not need any application-specific include files for this code. - * In fact, adding you own header files could break one of the many macros or - * functions in this file. Be very careful. - * Standard include files will probably be ok. - */ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -/* #include * for memset(), memcpy(), and memcmp() */ -#include "twofish.h" - - -/* - * PLATFORM FIXES - * ============== - * - * Fix the type definitions in twofish.h first! - * - * The following definitions have to be fixed for each particular platform - * you work on. If you have a multi-platform program, you no doubt have - * portable definitions that you can substitute here without changing the - * rest of the code. - */ - - -/* - * Function called if something is fatally wrong with the implementation. - * This fatal function is called when a coding error is detected in the - * Twofish implementation, or when somebody passes an obviously erroneous - * parameter to this implementation. There is not much you can do when - * the code contains bugs, so we just stop. - * - * The argument is a string. Ideally the fatal function prints this string - * as an error message. Whatever else this function does, it should never - * return. A typical implementation would stop the program completely after - * printing the error message. - * - * This default implementation is not very useful, - * but does not assume anything about your environment. - * It will at least let you know something is wrong.... - * I didn't want to include any libraries to print and error or so, - * as this makes the code much harder to integrate in a project. - * - * Note that the Twofish_fatal function may not return to the caller. - * Unfortunately this is not something the self-test can test for, - * so you have to make sure of this yourself. - * - * If you want to call an external function, be careful about including - * your own header files here. This code uses a lot of macros, and your - * header file could easily break it. Maybe the best solution is to use - * a separate extern statement for your fatal function. - */ -/* #define Twofish_fatal(pmsgx) { fprintf(stderr, pmsgx); exit(1); } */ -#define Twofish_fatal(pmsgx, code) { return(code); } - - -/* - * The rest of the settings are not important for the functionality - * of this Twofish implementation. That is, their default settings - * work on all platforms. You can change them to improve the - * speed of the implementation on your platform. Erroneous settings - * will result in erroneous implementations, but the self-test should - * catch those. - */ - - -/* - * Macros to rotate a Twofish_UInt32 value left or right by the - * specified number of bits. This should be a 32-bit rotation, - * and not rotation of, say, 64-bit values. - * - * Every encryption or decryption operation uses 32 of these rotations, - * so it is a good idea to make these macros efficient. - * - * This fully portable definition has one piece of tricky stuff. - * The UInt32 might be larger than 32 bits, so we have to mask - * any higher bits off. The simplest way to do this is to 'and' the - * value first with 0xffffffff and then shift it right. An optimising - * compiler that has a 32-bit type can optimise this 'and' away. - * - * Unfortunately there is no portable way of writing the constant - * 0xffffffff. You don't know which suffix to use (U, or UL?) - * The UINT32_MASK definition uses a bit of trickery. Shift-left - * is only defined if the shift amount is strictly less than the size - * of the UInt32, so we can't use (1<<32). The answer it to take the value - * 2, cast it to a UInt32, shift it left 31 positions, and subtract one. - * Another example of how to make something very simple extremely difficult. - * I hate C. - * - * The rotation macros are straightforward. - * They are only applied to UInt32 values, which are _unsigned_ - * so the >> operator must do a logical shift that brings in zeroes. - * On most platforms you will only need to optimise the ROL32 macro; the - * ROR32 macro is not inefficient on an optimising compiler as all rotation - * amounts in this code are known at compile time. - * - * On many platforms there is a faster solution. - * For example, MS compilers have the __rotl and __rotr functions - * that generate x86 rotation instructions. - */ -#define UINT32_MASK ( (((Twofish_UInt32)2)<<31) - 1 ) - -#ifndef _MSC_VER -#define ROL32(x,n) ( (x)<<(n) | ((x) & UINT32_MASK) >> (32-(n)) ) -#define ROR32(x,n) ( (x)>>(n) | ((x) & UINT32_MASK) << (32-(n)) ) -#else -#define ROL32(x,n) (_lrotl((x), (n))) -#define ROR32(x,n) (_lrotr((x), (n))) -#endif - -/* - * Select data type for q-table entries. - * - * Larger entry types cost more memory (1.5 kB), and might be faster - * or slower depending on the CPU and compiler details. - * - * This choice only affects the static data size and the key setup speed. - * Functionality, expanded key size, or encryption speed are not affected. - * Define to 1 to get large q-table entries. - */ -#define LARGE_Q_TABLE 0 /* default = 0 */ - - -/* - * Method to select a single byte from a UInt32. - * WARNING: non-portable code if set; might not work on all platforms. - * - * Inside the inner loop of Twofish it is necessary to access the 4 - * individual bytes of a UInt32. This can be done using either shifts - * and masks, or memory accesses. - * - * Set to 0 to use shift and mask operations for the byte selection. - * This is more ALU intensive. It is also fully portable. - * - * Set to 1 to use memory accesses. The UInt32 is stored in memory and - * the individual bytes are read from memory one at a time. - * This solution is more memory-intensive, and not fully portable. - * It might be faster on your platform, or not. If you use this option, - * make sure you set the CPU_IS_BIG_ENDIAN flag appropriately. - * - * This macro does not affect the conversion of the inputs and outputs - * of the cipher. See the CONVERT_USING_CASTS macro for that. - */ -#define SELECT_BYTE_FROM_UINT32_IN_MEMORY 0 /* default = 0 */ - - -/* - * Method used to read the input and write the output. - * WARNING: non-portable code if set; might not work on all platforms. - * - * Twofish operates on 32-bit words. The input to the cipher is - * a byte array, as is the output. The portable method of doing the - * conversion is a bunch of rotate and mask operations, but on many - * platforms it can be done faster using a cast. - * This only works if your CPU allows UInt32 accesses to arbitrary Byte - * addresses. - * - * Set to 0 to use the shift and mask operations. This is fully - * portable. . - * - * Set to 1 to use a cast. The Byte * is cast to a UInt32 *, and a - * UInt32 is read. If necessary (as indicated by the CPU_IS_BIG_ENDIAN - * macro) the byte order in the UInt32 is swapped. The reverse is done - * to write the output of the encryption/decryption. Make sure you set - * the CPU_IS_BIG_ENDIAN flag appropriately. - * This option does not work unless a UInt32 is exactly 32 bits. - * - * This macro only changes the reading/writing of the plaintext/ciphertext. - * See the SELECT_BYTE_FROM_UINT32_IN_MEMORY to affect the way in which - * a UInt32 is split into 4 bytes for the S-box selection. - */ -#define CONVERT_USING_CASTS 0 /* default = 0 */ - - -/* - * Endianness switch. - * Only relevant if SELECT_BYTE_FROM_UINT32_IN_MEMORY or - * CONVERT_USING_CASTS is set. - * - * Set to 1 on a big-endian machine, and to 0 on a little-endian machine. - * Twofish uses the little-endian convention (least significant byte first) - * and big-endian machines (using most significant byte first) - * have to do a few conversions. - * - * CAUTION: This code has never been tested on a big-endian machine, - * because I don't have access to one. Feedback appreciated. - */ -#define CPU_IS_BIG_ENDIAN 0 - - -/* - * Macro to reverse the order of the bytes in a UInt32. - * Used to convert to little-endian on big-endian machines. - * This macro is always tested, but only used in the encryption and - * decryption if CONVERT_USING_CASTS, and CPU_IS_BIG_ENDIAN - * are both set. In other words: this macro is only speed-critical if - * both these flags have been set. - * - * This default definition of SWAP works, but on many platforms there is a - * more efficient implementation. - */ -#define BSWAP(x) ((ROL32((x),8)&0x00ff00ff) | (ROR32((x),8) & 0xff00ff00)) - - -/* - * END OF PLATFORM FIXES - * ===================== - * - * You should not have to touch the rest of this file. - */ - - -/* - * Convert the external type names to some that are easier to use inside - * this file. I didn't want to use the names Byte and UInt32 in the - * header file, because many programs already define them and using two - * conventions at once can be very difficult. - * Don't change these definitions! Change the originals - * in twofish.h instead. - */ -/* A Byte must be an unsigned integer, 8 bits long. */ -/* typedef Twofish_Byte Byte; */ -/* A UInt32 must be an unsigned integer at least 32 bits long. */ -/* typedef Twofish_UInt32 UInt32; */ - - -/* - * Define a macro ENDIAN_CONVERT. - * - * We define a macro ENDIAN_CONVERT that performs a BSWAP on big-endian - * machines, and is the identity function on little-endian machines. - * The code then uses this macro without considering the endianness. - */ - -#if CPU_IS_BIG_ENDIAN -#define ENDIAN_CONVERT(x) BSWAP(x) -#else -#define ENDIAN_CONVERT(x) (x) -#endif - - -/* - * Compute byte offset within a UInt32 stored in memory. - * - * This is only used when SELECT_BYTE_FROM_UINT32_IN_MEMORY is set. - * - * The input is the byte number 0..3, 0 for least significant. - * Note the use of sizeof() to support UInt32 types that are larger - * than 4 bytes. - */ -#if CPU_IS_BIG_ENDIAN -#define BYTE_OFFSET( n ) (sizeof(Twofish_UInt32) - 1 - (n) ) -#else -#define BYTE_OFFSET( n ) (n) -#endif - - -/* - * Macro to get Byte no. b from UInt32 value X. - * We use two different definition, depending on the settings. - */ -#if SELECT_BYTE_FROM_UINT32_IN_MEMORY - /* Pick the byte from the memory in which X is stored. */ -#define SELECT_BYTE( X, b ) (((Twofish_Byte *)(&(X)))[BYTE_OFFSET(b)]) -#else - /* Portable solution: Pick the byte directly from the X value. */ -#define SELECT_BYTE( X, b ) (((X) >> (8*(b))) & 0xff) -#endif - - -/* Some shorthands because we use byte selection in large formulae. */ -#define b0(X) SELECT_BYTE((X),0) -#define b1(X) SELECT_BYTE((X),1) -#define b2(X) SELECT_BYTE((X),2) -#define b3(X) SELECT_BYTE((X),3) - - -/* - * We need macros to load and store UInt32 from/to byte arrays - * using the least-significant-byte-first convention. - * - * GET32( p ) gets a UInt32 in lsb-first form from four bytes pointed to - * by p. - * PUT32( v, p ) writes the UInt32 value v at address p in lsb-first form. - */ -#if CONVERT_USING_CASTS - - /* Get UInt32 from four bytes pointed to by p. */ -#define GET32( p ) ENDIAN_CONVERT( *((Twofish_UInt32 *)(p)) ) - /* Put UInt32 into four bytes pointed to by p */ -#define PUT32( v, p ) *((Twofish_UInt32 *)(p)) = ENDIAN_CONVERT(v) - -#else - - /* Get UInt32 from four bytes pointed to by p. */ -#define GET32( p ) \ - ( \ - (Twofish_UInt32)((p)[0]) \ - | (Twofish_UInt32)((p)[1])<< 8 \ - | (Twofish_UInt32)((p)[2])<<16 \ - | (Twofish_UInt32)((p)[3])<<24 \ - ) - /* Put UInt32 into four bytes pointed to by p */ -#define PUT32( v, p ) \ - (p)[0] = (Twofish_Byte)(((v) ) & 0xff); \ - (p)[1] = (Twofish_Byte)(((v) >> 8) & 0xff); \ - (p)[2] = (Twofish_Byte)(((v) >> 16) & 0xff); \ - (p)[3] = (Twofish_Byte)(((v) >> 24) & 0xff) - -#endif - -#ifdef ANDROID -/** - * Dummy function to disable some compiler optimizations. - * - * See comment in Twofish_cfb128_encrypt(). - */ -void Two_debugDummy(Twofish_Byte* in, Twofish_Byte* out, Twofish_Byte* ivec) -{ -} -#endif -/* - * Test the platform-specific macros. - * This function tests the macros defined so far to make sure the - * definitions are appropriate for this platform. - * If you make any mistake in the platform configuration, this should detect - * that and inform you what went wrong. - * Somewhere, someday, this is going to save somebody a lot of time, - * because misbehaving macros are hard to debug. - */ -static int test_platform() - { - /* Buffer with test values. */ - Twofish_Byte buf[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0}; - Twofish_UInt32 C; - Twofish_UInt32 x,y; - int i; - - /* - * Some sanity checks on the types that can't be done in compile time. - * A smart compiler will just optimise these tests away. - * The pre-processor doesn't understand different types, so we cannot - * do these checks in compile-time. - * - * I hate C. - * - * The first check in each case is to make sure the size is correct. - * The second check is to ensure that it is an unsigned type. - */ - if( ((Twofish_UInt32)((Twofish_UInt32)1 << 31) == 0) || ((Twofish_UInt32)-1 < 0 )) - { - Twofish_fatal( "Twofish code: Twofish_UInt32 type not suitable", ERR_UINT32 ); - } - if( (sizeof( Twofish_Byte ) != 1) || (((Twofish_Byte)-1) < 0) ) - { - Twofish_fatal( "Twofish code: Twofish_Byte type not suitable", ERR_BYTE ); - } - - /* - * Sanity-check the endianness conversions. - * This is just an aid to find problems. If you do the endianness - * conversion macros wrong you will fail the full cipher test, - * but that does not help you find the error. - * Always make it easy to find the bugs! - * - * Detail: There is no fully portable way of writing UInt32 constants, - * as you don't know whether to use the U or UL suffix. Using only U you - * might only be allowed 16-bit constants. Using UL you might get 64-bit - * constants which cannot be stored in a UInt32 without warnings, and - * which generally behave subtly different from a true UInt32. - * As long as we're just comparing with the constant, - * we can always use the UL suffix and at worst lose some efficiency. - * I use a separate '32-bit constant' macro in most of my other code. - * - * I hate C. - * - * Start with testing GET32. We test it on all positions modulo 4 - * to make sure we can handly any position of inputs. (Some CPUs - * do not allow non-aligned accesses which we would do if you used - * the CONVERT_USING_CASTS option. - */ - if( (GET32( buf ) != 0x78563412UL) || (GET32(buf+1) != 0x9a785634UL) - || (GET32( buf+2 ) != 0xbc9a7856UL) || (GET32(buf+3) != 0xdebc9a78UL) ) - { - Twofish_fatal( "Twofish code: GET32 not implemented properly", ERR_GET32 ); - } - - /* - * We can now use GET32 to test PUT32. - * We don't test the shifted versions. If GET32 can do that then - * so should PUT32. - */ - C = GET32( buf ); - PUT32( 3*C, buf ); - if( GET32( buf ) != 0x69029c36UL ) - { - Twofish_fatal( "Twofish code: PUT32 not implemented properly", ERR_PUT32 ); - } - - - /* Test ROL and ROR */ - for( i=1; i<32; i++ ) - { - /* Just a simple test. */ - x = ROR32( C, i ); - y = ROL32( C, i ); - x ^= (C>>i) ^ (C<<(32-i)); - /*y ^= (C<>(32-i)); */ - y ^= (C<<i) ^ (C>>(32-i)); - x |= y; - /* - * Now all we check is that x is zero in the least significant - * 32 bits. Using the UL suffix is safe here, as it doesn't matter - * if we get a larger type. - */ - if( (x & 0xffffffffUL) != 0 ) - { - Twofish_fatal( "Twofish ROL or ROR not properly defined.", ERR_ROLR ); - } - } - - /* Test the BSWAP macro */ - if( BSWAP(C) != 0x12345678UL ) - { - /* - * The BSWAP macro should always work, even if you are not using it. - * A smart optimising compiler will just remove this entire test. - */ - Twofish_fatal( "BSWAP not properly defined.", ERR_BSWAP ); - } - - /* And we can test the b macros which use SELECT_BYTE. */ - if( (b0(C)!=0x12) || (b1(C) != 0x34) || (b2(C) != 0x56) || (b3(C) != 0x78) ) - { - /* - * There are many reasons why this could fail. - * Most likely is that CPU_IS_BIG_ENDIAN has the wrong value. - */ - Twofish_fatal( "Twofish code: SELECT_BYTE not implemented properly", ERR_SELECTB ); - } - return SUCCESS; - } - - -/* - * Finally, we can start on the Twofish-related code. - * You really need the Twofish specifications to understand this code. The - * best source is the Twofish book: - * "The Twofish Encryption Algorithm", by Bruce Schneier, John Kelsey, - * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson. - * you can also use the AES submission document of Twofish, which is - * available from my list of publications on my personal web site at - * http://niels.ferguson.net/. - * - * The first thing we do is write the testing routines. This is what the - * implementation has to satisfy in the end. We only test the external - * behaviour of the implementation of course. - */ - - -/* - * Perform a single self test on a (plaintext,ciphertext,key) triple. - * Arguments: - * key array of key bytes - * key_len length of key in bytes - * p plaintext - * c ciphertext - */ -static int test_vector( Twofish_Byte key[], int key_len, Twofish_Byte p[16], Twofish_Byte c[16] ) - { - Twofish_Byte tmp[16]; /* scratch pad. */ - Twofish_key xkey; /* The expanded key */ - int i; - - - /* Prepare the key */ - if ((i = Twofish_prepare_key( key, key_len, &xkey)) < 0) - return i; - - /* - * We run the test twice to ensure that the xkey structure - * is not damaged by the first encryption. - * Those are hideous bugs to find if you get them in an application. - */ - for( i=0; i<2; i++ ) - { - /* Encrypt and test */ - Twofish_encrypt( &xkey, p, tmp ); - if( memcmp( c, tmp, 16 ) != 0 ) - { - Twofish_fatal( "Twofish encryption failure", ERR_TEST_ENC ); - } - - /* Decrypt and test */ - Twofish_decrypt( &xkey, c, tmp ); - if( memcmp( p, tmp, 16 ) != 0 ) - { - Twofish_fatal( "Twofish decryption failure", ERR_TEST_DEC ); - } - } - - /* The test keys are not secret, so we don't need to wipe xkey. */ - return SUCCESS; - } - - -/* - * Check implementation using three (key,plaintext,ciphertext) - * test vectors, one for each major key length. - * - * This is an absolutely minimal self-test. - * This routine does not test odd-sized keys. - */ -static int test_vectors() - { - /* - * We run three tests, one for each major key length. - * These test vectors come from the Twofish specification. - * One encryption and one decryption using randomish data and key - * will detect almost any error, especially since we generate the - * tables ourselves, so we don't have the problem of a single - * damaged table entry in the source. - */ - - /* 128-bit test is the I=3 case of section B.2 of the Twofish book. */ - static Twofish_Byte k128[] = { - 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, - 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A, - }; - static Twofish_Byte p128[] = { - 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, - 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 - }; - static Twofish_Byte c128[] = { - 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, - 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 - }; - - /* 192-bit test is the I=4 case of section B.2 of the Twofish book. */ - static Twofish_Byte k192[] = { - 0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, - 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88, - 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44 - }; - static Twofish_Byte p192[] = { - 0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, - 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2 - }; - static Twofish_Byte c192[] = { - 0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, - 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65 - }; - - /* 256-bit test is the I=4 case of section B.2 of the Twofish book. */ - static Twofish_Byte k256[] = { - 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, - 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, - 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, - 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F - }; - static Twofish_Byte p256[] = { - 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, - 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 - }; - static Twofish_Byte c256[] = { - 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, - 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA - }; - - int ret; - - /* Run the actual tests. */ - if ((ret = test_vector( k128, 16, p128, c128 )) < 0) - return ret; - if ((ret = test_vector( k192, 24, p192, c192 )) < 0) - return ret; - if ((ret = test_vector( k256, 32, p256, c256 )) < 0) - return ret; - return SUCCESS; - } - - -/* - * Perform extensive test for a single key size. - * - * Test a single key size against the test vectors from section - * B.2 in the Twofish book. This is a sequence of 49 encryptions - * and decryptions. Each plaintext is equal to the ciphertext of - * the previous encryption. The key is made up from the ciphertext - * two and three encryptions ago. Both plaintext and key start - * at the zero value. - * We should have designed a cleaner recurrence relation for - * these tests, but it is too late for that now. At least we learned - * how to do it better next time. - * For details see appendix B of the book. - * - * Arguments: - * key_len Number of bytes of key - * final_value Final plaintext value after 49 iterations - */ -static int test_sequence( int key_len, Twofish_Byte final_value[] ) - { - Twofish_Byte buf[ (50+3)*16 ]; /* Buffer to hold our computation values. */ - Twofish_Byte tmp[16]; /* Temp for testing the decryption. */ - Twofish_key xkey; /* The expanded key */ - int i, ret; - Twofish_Byte * p; - - /* Wipe the buffer */ - memset( buf, 0, sizeof( buf ) ); - - /* - * Because the recurrence relation is done in an inconvenient manner - * we end up looping backwards over the buffer. - */ - - /* Pointer in buffer points to current plaintext. */ - p = &buf[50*16]; - for( i=1; i<50; i++ ) - { - /* - * Prepare a key. - * This automatically checks that key_len is valid. - */ - if ((ret = Twofish_prepare_key( p+16, key_len, &xkey)) < 0) - return ret; - - /* Compute the next 16 bytes in the buffer */ - Twofish_encrypt( &xkey, p, p-16 ); - - /* Check that the decryption is correct. */ - Twofish_decrypt( &xkey, p-16, tmp ); - if( memcmp( tmp, p, 16 ) != 0 ) - { - Twofish_fatal( "Twofish decryption failure in sequence", ERR_SEQ_DEC ); - } - /* Move on to next 16 bytes in the buffer. */ - p -= 16; - } - - /* And check the final value. */ - if( memcmp( p, final_value, 16 ) != 0 ) - { - Twofish_fatal( "Twofish encryption failure in sequence", ERR_SEQ_ENC ); - } - - /* None of the data was secret, so there is no need to wipe anything. */ - return SUCCESS; - } - - -/* - * Run all three sequence tests from the Twofish test vectors. - * - * This checks the most extensive test vectors currently available - * for Twofish. The data is from the Twofish book, appendix B.2. - */ -static int test_sequences() - { - static Twofish_Byte r128[] = { - 0x5D, 0x9D, 0x4E, 0xEF, 0xFA, 0x91, 0x51, 0x57, - 0x55, 0x24, 0xF1, 0x15, 0x81, 0x5A, 0x12, 0xE0 - }; - static Twofish_Byte r192[] = { - 0xE7, 0x54, 0x49, 0x21, 0x2B, 0xEE, 0xF9, 0xF4, - 0xA3, 0x90, 0xBD, 0x86, 0x0A, 0x64, 0x09, 0x41 - }; - static Twofish_Byte r256[] = { - 0x37, 0xFE, 0x26, 0xFF, 0x1C, 0xF6, 0x61, 0x75, - 0xF5, 0xDD, 0xF4, 0xC3, 0x3B, 0x97, 0xA2, 0x05 - }; - - /* Run the three sequence test vectors */ - int ret; - if ((ret = test_sequence( 16, r128)) < 0) - return ret; - if ((ret = test_sequence( 24, r192)) < 0) - return ret; - if ((ret = test_sequence( 32, r256)) < 0) - return ret; - return SUCCESS; - } - - -/* - * Test the odd-sized keys. - * - * Every odd-sized key is equivalent to a one of 128, 192, or 256 bits. - * The equivalent key is found by padding at the end with zero bytes - * until a regular key size is reached. - * - * We just test that the key expansion routine behaves properly. - * If the expanded keys are identical, then the encryptions and decryptions - * will behave the same. - */ -static int test_odd_sized_keys() - { - Twofish_Byte buf[32]; - Twofish_key xkey; - Twofish_key xkey_two; - int i, ret; - - /* - * We first create an all-zero key to use as PRNG key. - * Normally we would not have to fill the buffer with zeroes, as we could - * just pass a zero key length to the Twofish_prepare_key function. - * However, this relies on using odd-sized keys, and those are just the - * ones we are testing here. We can't use an untested function to test - * itself. - */ - memset( buf, 0, sizeof( buf ) ); - if ((ret = Twofish_prepare_key( buf, 16, &xkey)) < 0) - return ret; - - /* Fill buffer with pseudo-random data derived from two encryptions */ - Twofish_encrypt( &xkey, buf, buf ); - Twofish_encrypt( &xkey, buf, buf+16 ); - - /* Create all possible shorter keys that are prefixes of the buffer. */ - for( i=31; i>=0; i-- ) - { - /* Set a byte to zero. This is the new padding byte */ - buf[i] = 0; - - /* Expand the key with only i bytes of length */ - if ((ret = Twofish_prepare_key( buf, i, &xkey)) < 0) - return ret; - - /* Expand the corresponding padded key of regular length */ - if ((ret = Twofish_prepare_key( buf, i<=16 ? 16 : (i<= 24 ? 24 : 32), &xkey_two )) < 0) - return ret; - - /* Compare the two */ - if( memcmp( &xkey, &xkey_two, sizeof( xkey ) ) != 0 ) - { - Twofish_fatal( "Odd sized keys do not expand properly", ERR_ODD_KEY ); - } - } - - /* None of the key values are secret, so we don't need to wipe them. */ - return SUCCESS; - } - - -/* - * Test the Twofish implementation. - * - * This routine runs all the self tests, in order of importance. - * It is called by the Twofish_initialise routine. - * - * In almost all applications the cost of running the self tests during - * initialisation is insignificant, especially - * compared to the time it takes to load the application from disk. - * If you are very pressed for initialisation performance, - * you could remove some of the tests. Make sure you did run them - * once in the software and hardware configuration you are using. - */ -static int self_test() - { - int ret; - /* The three test vectors form an absolute minimal test set. */ - if ((ret = test_vectors()) < 0) - return ret; - - /* - * If at all possible you should run these tests too. They take - * more time, but provide a more thorough coverage. - */ - if ((ret = test_sequences()) < 0) - return ret; - - /* Test the odd-sized keys. */ - if ((ret = test_odd_sized_keys()) < 0) - return ret; - return SUCCESS; - } - - -/* - * And now, the actual Twofish implementation. - * - * This implementation generates all the tables during initialisation. - * I don't like large tables in the code, especially since they are easily - * damaged in the source without anyone noticing it. You need code to - * generate them anyway, and this way all the code is close together. - * Generating them in the application leads to a smaller executable - * (the code is smaller than the tables it generates) and a - * larger static memory footprint. - * - * Twofish can be implemented in many ways. I have chosen to - * use large tables with a relatively long key setup time. - * If you encrypt more than a few blocks of data it pays to pre-compute - * as much as possible. This implementation is relatively inefficient for - * applications that need to re-key every block or so. - */ - -/* - * We start with the t-tables, directly from the Twofish definition. - * These are nibble-tables, but merging them and putting them two nibbles - * in one byte is more work than it is worth. - */ -static Twofish_Byte t_table[2][4][16] = { - { - {0x8,0x1,0x7,0xD,0x6,0xF,0x3,0x2,0x0,0xB,0x5,0x9,0xE,0xC,0xA,0x4}, - {0xE,0xC,0xB,0x8,0x1,0x2,0x3,0x5,0xF,0x4,0xA,0x6,0x7,0x0,0x9,0xD}, - {0xB,0xA,0x5,0xE,0x6,0xD,0x9,0x0,0xC,0x8,0xF,0x3,0x2,0x4,0x7,0x1}, - {0xD,0x7,0xF,0x4,0x1,0x2,0x6,0xE,0x9,0xB,0x3,0x0,0x8,0x5,0xC,0xA} - }, - { - {0x2,0x8,0xB,0xD,0xF,0x7,0x6,0xE,0x3,0x1,0x9,0x4,0x0,0xA,0xC,0x5}, - {0x1,0xE,0x2,0xB,0x4,0xC,0x3,0x7,0x6,0xD,0xA,0x5,0xF,0x9,0x0,0x8}, - {0x4,0xC,0x7,0x5,0x1,0x6,0x9,0xA,0x0,0xE,0xD,0x8,0x2,0xB,0x3,0xF}, - {0xB,0x9,0x5,0x1,0xC,0x3,0xD,0xE,0x6,0x4,0x7,0xF,0x2,0x0,0x8,0xA} - } -}; - - -/* A 1-bit rotation of 4-bit values. Input must be in range 0..15 */ -#define ROR4BY1( x ) (((x)>>1) | (((x)<<3) & 0x8) ) - -/* - * The q-boxes are only used during the key schedule computations. - * These are 8->8 bit lookup tables. Some CPUs prefer to have 8->32 bit - * lookup tables as it is faster to load a 32-bit value than to load an - * 8-bit value and zero the rest of the register. - * The LARGE_Q_TABLE switch allows you to choose 32-bit entries in - * the q-tables. Here we just define the Qtype which is used to store - * the entries of the q-tables. - */ -#if LARGE_Q_TABLE -typedef Twofish_UInt32 Qtype; -#else -typedef Twofish_Byte Qtype; -#endif - -/* - * The actual q-box tables. - * There are two q-boxes, each having 256 entries. - */ -static Qtype q_table[2][256]; - - -/* - * Now the function that converts a single t-table into a q-table. - * - * Arguments: - * t[4][16] : four 4->4bit lookup tables that define the q-box - * q[256] : output parameter: the resulting q-box as a lookup table. - */ -static void make_q_table( Twofish_Byte t[4][16], Qtype q[256] ) - { - int ae,be,ao,bo; /* Some temporaries. */ - int i; - /* Loop over all input values and compute the q-box result. */ - for( i=0; i<256; i++ ) { - /* - * This is straight from the Twofish specifications. - * - * The ae variable is used for the a_i values from the specs - * with even i, and ao for the odd i's. Similarly for the b's. - */ - ae = i>>4; be = i&0xf; - ao = ae ^ be; bo = ae ^ ROR4BY1(be) ^ ((ae<<3)&8); - ae = t[0][ao]; be = t[1][bo]; - ao = ae ^ be; bo = ae ^ ROR4BY1(be) ^ ((ae<<3)&8); - ae = t[2][ao]; be = t[3][bo]; - - /* Store the result in the q-box table, the cast avoids a warning. */ - q[i] = (Qtype) ((be<<4) | ae); - } - } - - -/* - * Initialise both q-box tables. - */ -static void initialise_q_boxes() { - /* Initialise each of the q-boxes using the t-tables */ - make_q_table( t_table[0], q_table[0] ); - make_q_table( t_table[1], q_table[1] ); - } - - -/* - * Next up is the MDS matrix multiplication. - * The MDS matrix multiplication operates in the field - * GF(2)[x]/p(x) with p(x)=x^8+x^6+x^5+x^3+1. - * If you don't understand this, read a book on finite fields. You cannot - * follow the finite-field computations without some background. - * - * In this field, multiplication by x is easy: shift left one bit - * and if bit 8 is set then xor the result with 0x169. - * - * The MDS coefficients use a multiplication by 1/x, - * or rather a division by x. This is easy too: first make the - * value 'even' (i.e. bit 0 is zero) by xorring with 0x169 if necessary, - * and then shift right one position. - * Even easier: shift right and xor with 0xb4 if the lsbit was set. - * - * The MDS coefficients are 1, EF, and 5B, and we use the fact that - * EF = 1 + 1/x + 1/x^2 - * 5B = 1 + 1/x^2 - * in this field. This makes multiplication by EF and 5B relatively easy. - * - * This property is no accident, the MDS matrix was designed to allow - * this implementation technique to be used. - * - * We have four MDS tables, each mapping 8 bits to 32 bits. - * Each table performs one column of the matrix multiplication. - * As the MDS is always preceded by q-boxes, each of these tables - * also implements the q-box just previous to that column. - */ - -/* The actual MDS tables. */ -static Twofish_UInt32 MDS_table[4][256]; - -/* A small table to get easy conditional access to the 0xb4 constant. */ -static Twofish_UInt32 mds_poly_divx_const[] = {0,0xb4}; - -/* Function to initialise the MDS tables. */ -static void initialise_mds_tables() - { - int i; - Twofish_UInt32 q,qef,q5b; /* Temporary variables. */ - - /* Loop over all 8-bit input values */ - for( i=0; i<256; i++ ) - { - /* - * To save some work during the key expansion we include the last - * of the q-box layers from the h() function in these MDS tables. - */ - - /* We first do the inputs that are mapped through the q0 table. */ - q = q_table[0][i]; - /* - * Here we divide by x, note the table to get 0xb4 only if the - * lsbit is set. - * This sets qef = (1/x)*q in the finite field - */ - qef = (q >> 1) ^ mds_poly_divx_const[ q & 1 ]; - /* - * Divide by x again, and add q to get (1+1/x^2)*q. - * Note that (1+1/x^2) = 5B in the field, and addition in the field - * is exclusive or on the bits. - */ - q5b = (qef >> 1) ^ mds_poly_divx_const[ qef & 1 ] ^ q; - /* - * Add q5b to qef to set qef = (1+1/x+1/x^2)*q. - * Again, (1+1/x+1/x^2) = EF in the field. - */ - qef ^= q5b; - - /* - * Now that we have q5b = 5B * q and qef = EF * q - * we can fill two of the entries in the MDS matrix table. - * See the Twofish specifications for the order of the constants. - */ - MDS_table[1][i] = (q <<24) | (q5b<<16) | (qef<<8) | qef; - MDS_table[3][i] = (q5b<<24) | (qef<<16) | (q <<8) | q5b; - - /* Now we do it all again for the two columns that have a q1 box. */ - q = q_table[1][i]; - qef = (q >> 1) ^ mds_poly_divx_const[ q & 1 ]; - q5b = (qef >> 1) ^ mds_poly_divx_const[ qef & 1 ] ^ q; - qef ^= q5b; - - /* The other two columns use the coefficient in a different order. */ - MDS_table[0][i] = (qef<<24) | (qef<<16) | (q5b<<8) | q ; - MDS_table[2][i] = (qef<<24) | (q <<16) | (qef<<8) | q5b; - } - } - - -/* - * The h() function is the heart of the Twofish cipher. - * It is a complicated sequence of q-box lookups, key material xors, - * and finally the MDS matrix. - * We use lots of macros to make this reasonably fast. - */ - -/* First a shorthand for the two q-tables */ -#define q0 q_table[0] -#define q1 q_table[1] - -/* - * Each macro computes one column of the h for either 2, 3, or 4 stages. - * As there are 4 columns, we have 12 macros in all. - * - * The key bytes are stored in the Byte array L at offset - * 0,1,2,3, 8,9,10,11, [16,17,18,19, [24,25,26,27]] as this is the - * order we get the bytes from the user. If you look at the Twofish - * specs, you'll see that h() is applied to the even key words or the - * odd key words. The bytes of the even words appear in this spacing, - * and those of the odd key words too. - * - * These macros are the only place where the q-boxes and the MDS table - * are used. - */ -#define H02( y, L ) MDS_table[0][q0[q0[y]^L[ 8]]^L[0]] -#define H12( y, L ) MDS_table[1][q0[q1[y]^L[ 9]]^L[1]] -#define H22( y, L ) MDS_table[2][q1[q0[y]^L[10]]^L[2]] -#define H32( y, L ) MDS_table[3][q1[q1[y]^L[11]]^L[3]] -#define H03( y, L ) H02( q1[y]^L[16], L ) -#define H13( y, L ) H12( q1[y]^L[17], L ) -#define H23( y, L ) H22( q0[y]^L[18], L ) -#define H33( y, L ) H32( q0[y]^L[19], L ) -#define H04( y, L ) H03( q1[y]^L[24], L ) -#define H14( y, L ) H13( q0[y]^L[25], L ) -#define H24( y, L ) H23( q0[y]^L[26], L ) -#define H34( y, L ) H33( q1[y]^L[27], L ) - -/* - * Now we can define the h() function given an array of key bytes. - * This function is only used in the key schedule, and not to pre-compute - * the keyed S-boxes. - * - * In the key schedule, the input is always of the form k*(1+2^8+2^16+2^24) - * so we only provide k as an argument. - * - * Arguments: - * k input to the h() function. - * L pointer to array of key bytes at - * offsets 0,1,2,3, ... 8,9,10,11, [16,17,18,19, [24,25,26,27]] - * kCycles # key cycles, 2, 3, or 4. - */ -static Twofish_UInt32 h( int k, Twofish_Byte L[], int kCycles ) - { - switch( kCycles ) { - /* We code all 3 cases separately for speed reasons. */ - case 2: - return H02(k,L) ^ H12(k,L) ^ H22(k,L) ^ H32(k,L); - case 3: - return H03(k,L) ^ H13(k,L) ^ H23(k,L) ^ H33(k,L); - case 4: - return H04(k,L) ^ H14(k,L) ^ H24(k,L) ^ H34(k,L); - default: - /* This is always a coding error, which is fatal. */ - Twofish_fatal( "Twofish h(): Illegal argument", ERR_ILL_ARG ); - return ERR_ILL_ARG; - } - } - - -/* - * Pre-compute the keyed S-boxes. - * Fill the pre-computed S-box array in the expanded key structure. - * Each pre-computed S-box maps 8 bits to 32 bits. - * - * The S argument contains half the number of bytes of the full key, but is - * derived from the full key. (See Twofish specifications for details.) - * S has the weird byte input order used by the Hxx macros. - * - * This function takes most of the time of a key expansion. - * - * Arguments: - * S pointer to array of 8*kCycles Bytes containing the S vector. - * kCycles number of key words, must be in the set {2,3,4} - * xkey pointer to Twofish_key structure that will contain the S-boxes. - */ -static int fill_keyed_sboxes( Twofish_Byte S[], int kCycles, Twofish_key * xkey ) - { - int i; - switch( kCycles ) { - /* We code all 3 cases separately for speed reasons. */ - case 2: - for( i=0; i<256; i++ ) - { - xkey->s[0][i]= H02( i, S ); - xkey->s[1][i]= H12( i, S ); - xkey->s[2][i]= H22( i, S ); - xkey->s[3][i]= H32( i, S ); - } - break; - case 3: - for( i=0; i<256; i++ ) - { - xkey->s[0][i]= H03( i, S ); - xkey->s[1][i]= H13( i, S ); - xkey->s[2][i]= H23( i, S ); - xkey->s[3][i]= H33( i, S ); - } - break; - case 4: - for( i=0; i<256; i++ ) - { - xkey->s[0][i]= H04( i, S ); - xkey->s[1][i]= H14( i, S ); - xkey->s[2][i]= H24( i, S ); - xkey->s[3][i]= H34( i, S ); - } - break; - default: - /* This is always a coding error, which is fatal. */ - Twofish_fatal( "Twofish fill_keyed_sboxes(): Illegal argument", ERR_ILL_ARG ); - } - return SUCCESS; - } - - -/* A flag to keep track of whether we have been initialised or not. */ -static int Twofish_initialised = 0; - -/* - * Initialise the Twofish implementation. - * This function must be called before any other function in the - * Twofish implementation is called. - * This routine also does some sanity checks, to make sure that - * all the macros behave, and it tests the whole cipher. - */ -int Twofish_initialise() - { - int ret; - /* First test the various platform-specific definitions. */ - if ((ret = test_platform()) < 0) - return ret; - - /* We can now generate our tables, in the right order of course. */ - initialise_q_boxes(); - initialise_mds_tables(); - - /* We're finished with the initialisation itself. */ - Twofish_initialised = 1; - - /* - * And run some tests on the whole cipher. - * Yes, you need to do this every time you start your program. - * It is called assurance; you have to be certain that your program - * still works properly. - */ - return self_test(); - } - - -/* - * The Twofish key schedule uses an Reed-Solomon code matrix multiply. - * Just like the MDS matrix, the RS-matrix is designed to be easy - * to implement. Details are below in the code. - * - * These constants make it easy to compute in the finite field used - * for the RS code. - * - * We use Bytes for the RS computation, but these are automatically - * widened to unsigned integers in the expressions. Having unsigned - * ints in these tables therefore provides the fastest access. - */ -static unsigned int rs_poly_const[] = {0, 0x14d}; -static unsigned int rs_poly_div_const[] = {0, 0xa6 }; - - -/* - * Prepare a key for use in encryption and decryption. - * Like most block ciphers, Twofish allows the key schedule - * to be pre-computed given only the key. - * Twofish has a fairly 'heavy' key schedule that takes a lot of time - * to compute. The main work is pre-computing the S-boxes used in the - * encryption and decryption. We feel that this makes the cipher much - * harder to attack. The attacker doesn't even know what the S-boxes - * contain without including the entire key schedule in the analysis. - * - * Unlike most Twofish implementations, this one allows any key size from - * 0 to 32 bytes. Odd key sizes are defined for Twofish (see the - * specifications); the key is simply padded with zeroes to the next real - * key size of 16, 24, or 32 bytes. - * Each odd-sized key is thus equivalent to a single normal-sized key. - * - * Arguments: - * key array of key bytes - * key_len number of bytes in the key, must be in the range 0,...,32. - * xkey Pointer to an Twofish_key structure that will be filled - * with the internal form of the cipher key. - */ -int Twofish_prepare_key( Twofish_Byte key[], int key_len, Twofish_key * xkey ) - { - /* We use a single array to store all key material in, - * to simplify the wiping of the key material at the end. - * The first 32 bytes contain the actual (padded) cipher key. - * The next 32 bytes contain the S-vector in its weird format, - * and we have 4 bytes of overrun necessary for the RS-reduction. - */ - Twofish_Byte K[32+32+4]; - - int kCycles; /* # key cycles, 2,3, or 4. */ - - int i; - Twofish_UInt32 A, B; /* Used to compute the round keys. */ - - Twofish_Byte * kptr; /* Three pointers for the RS computation. */ - Twofish_Byte * sptr; - Twofish_Byte * t; - - Twofish_Byte b,bx,bxx; /* Some more temporaries for the RS computation. */ - - /* Check that the Twofish implementation was initialised. */ - if( Twofish_initialised == 0 ) - { - /* - * You didn't call Twofish_initialise before calling this routine. - * This is a programming error, and therefore we call the fatal - * routine. - * - * I could of course call the initialisation routine here, - * but there are a few reasons why I don't. First of all, the - * self-tests have to be done at startup. It is no good to inform - * the user that the cipher implementation fails when he wants to - * write his data to disk in encrypted form. You have to warn him - * before he spends time typing his data. Second, the initialisation - * and self test are much slower than a single key expansion. - * Calling the initialisation here makes the performance of the - * cipher unpredictable. This can lead to really weird problems - * if you use the cipher for a real-time task. Suddenly it fails - * once in a while the first time you try to use it. Things like - * that are almost impossible to debug. - */ - /* Twofish_fatal( "Twofish implementation was not initialised.", ERR_INIT ); */ - - /* - * There is always a danger that the Twofish_fatal routine returns, - * in spite of the specifications that it should not. - * (A good programming rule: don't trust the rest of the code.) - * This would be disasterous. If the q-tables and MDS-tables have - * not been initialised, they are probably still filled with zeroes. - * Suppose the MDS-tables are all zero. The key expansion would then - * generate all-zero round keys, and all-zero s-boxes. The danger - * is that nobody would notice as the encry - * mangles the input, and the decryption still 'decrypts' it, - * but now in a completely key-independent manner. - * To stop such security disasters, we use blunt force. - * If your program hangs here: fix the fatal routine! - */ - for(;;); /* Infinite loop, which beats being insecure. */ - } - - /* Check for valid key length. */ - if( key_len < 0 || key_len > 32 ) - { - /* - * This can only happen if a programmer didn't read the limitations - * on the key size. - */ - Twofish_fatal( "Twofish_prepare_key: illegal key length", ERR_KEY_LEN ); - /* - * A return statement just in case the fatal macro returns. - * The rest of the code assumes that key_len is in range, and would - * buffer-overflow if it wasn't. - * - * Why do we still use a programming language that has problems like - * buffer overflows, when these problems were solved in 1960 with - * the development of Algol? Have we not leared anything? - */ - return ERR_KEY_LEN; - } - - /* Pad the key with zeroes to the next suitable key length. */ - memcpy( K, key, key_len ); - memset( K+key_len, 0, sizeof(K)-key_len ); - - /* - * Compute kCycles: the number of key cycles used in the cipher. - * 2 for 128-bit keys, 3 for 192-bit keys, and 4 for 256-bit keys. - */ - kCycles = (key_len + 7) >> 3; - /* Handle the special case of very short keys: minimum 2 cycles. */ - if( kCycles < 2 ) - { - kCycles = 2; - } - - /* - * From now on we just pretend to have 8*kCycles bytes of - * key material in K. This handles all the key size cases. - */ - - /* - * We first compute the 40 expanded key words, - * formulas straight from the Twofish specifications. - */ - for( i=0; i<40; i+=2 ) - { - /* - * Due to the byte spacing expected by the h() function - * we can pick the bytes directly from the key K. - * As we use bytes, we never have the little/big endian - * problem. - * - * Note that we apply the rotation function only to simple - * variables, as the rotation macro might evaluate its argument - * more than once. - */ - A = h( i , K , kCycles ); - B = h( i+1, K+4, kCycles ); - B = ROL32( B, 8 ); - - /* Compute and store the round keys. */ - A += B; - B += A; - xkey->K[i] = A; - xkey->K[i+1] = ROL32( B, 9 ); - } - - /* Wipe variables that contained key material. */ - A=B=0; - - /* - * And now the dreaded RS multiplication that few seem to understand. - * The RS matrix is not random, and is specially designed to compute the - * RS matrix multiplication in a simple way. - * - * We work in the field GF(2)[x]/x^8+x^6+x^3+x^2+1. Note that this is a - * different field than used for the MDS matrix. - * (At least, it is a different representation because all GF(2^8) - * representations are equivalent in some form.) - * - * We take 8 consecutive bytes of the key and interpret them as - * a polynomial k_0 + k_1 y + k_2 y^2 + ... + k_7 y^7 where - * the k_i bytes are the key bytes and are elements of the finite field. - * We multiply this polynomial by y^4 and reduce it modulo - * y^4 + (x + 1/x)y^3 + (x)y^2 + (x + 1/x)y + 1. - * using straightforward polynomial modulo reduction. - * The coefficients of the result are the result of the RS - * matrix multiplication. When we wrote the Twofish specification, - * the original RS definition used the polynomials, - * but that requires much more mathematical knowledge. - * We were already using matrix multiplication in a finite field for - * the MDS matrix, so I re-wrote the RS operation as a matrix - * multiplication to reduce the difficulty of understanding it. - * Some implementors have not picked up on this simpler method of - * computing the RS operation, even though it is mentioned in the - * specifications. - * - * It is possible to perform these computations faster by using 32-bit - * word operations, but that is not portable and this is not a speed- - * critical area. - * - * We explained the 1/x computation when we did the MDS matrix. - * - * The S vector is stored in K[32..64]. - * The S vector has to be reversed, so we loop cross-wise. - * - * Note the weird byte spacing of the S-vector, to match the even - * or odd key words arrays. See the discussion at the Hxx macros for - * details. - */ - kptr = K + 8*kCycles; /* Start at end of key */ - sptr = K + 32; /* Start at start of S */ - - /* Loop over all key material */ - while( kptr > K ) - { - kptr -= 8; - /* - * Initialise the polynimial in sptr[0..12] - * The first four coefficients are 0 as we have to multiply by y^4. - * The next 8 coefficients are from the key material. - */ - memset( sptr, 0, 4 ); - memcpy( sptr+4, kptr, 8 ); - - /* - * The 12 bytes starting at sptr are now the coefficients of - * the polynomial we need to reduce. - */ - - /* Loop over the polynomial coefficients from high to low */ - t = sptr+11; - /* Keep looping until polynomial is degree 3; */ - while( t > sptr+3 ) - { - /* Pick up the highest coefficient of the poly. */ - b = *t; - - /* - * Compute x and (x+1/x) times this coefficient. - * See the MDS matrix implementation for a discussion of - * multiplication by x and 1/x. We just use different - * constants here as we are in a - * different finite field representation. - * - * These two statements set - * bx = (x) * b - * bxx= (x + 1/x) * b - */ - bx = (Twofish_Byte)((b<<1) ^ rs_poly_const[ b>>7 ]); - bxx= (Twofish_Byte)((b>>1) ^ rs_poly_div_const[ b&1 ] ^ bx); - - /* - * Subtract suitable multiple of - * y^4 + (x + 1/x)y^3 + (x)y^2 + (x + 1/x)y + 1 - * from the polynomial, except that we don't bother - * updating t[0] as it will become zero anyway. - */ - t[-1] ^= bxx; - t[-2] ^= bx; - t[-3] ^= bxx; - t[-4] ^= b; - - /* Go to the next coefficient. */ - t--; - } - - /* Go to next S-vector word, obeying the weird spacing rules. */ - sptr += 8; - } - - /* Wipe variables that contained key material. */ - b = bx = bxx = 0; - - /* And finally, we can compute the key-dependent S-boxes. */ - fill_keyed_sboxes( &K[32], kCycles, xkey ); - - /* Wipe array that contained key material. */ - memset( K, 0, sizeof( K ) ); - return SUCCESS; - } - - -/* - * We can now start on the actual encryption and decryption code. - * As these are often speed-critical we will use a lot of macros. - */ - -/* - * The g() function is the heart of the round function. - * We have two versions of the g() function, one without an input - * rotation and one with. - * The pre-computed S-boxes make this pretty simple. - */ -#define g0(X,xkey) \ - (xkey->s[0][b0(X)]^xkey->s[1][b1(X)]^xkey->s[2][b2(X)]^xkey->s[3][b3(X)]) - -#define g1(X,xkey) \ - (xkey->s[0][b3(X)]^xkey->s[1][b0(X)]^xkey->s[2][b1(X)]^xkey->s[3][b2(X)]) - -/* - * A single round of Twofish. The A,B,C,D are the four state variables, - * T0 and T1 are temporaries, xkey is the expanded key, and r the - * round number. - * - * Note that this macro does not implement the swap at the end of the round. - */ -#define ENCRYPT_RND( A,B,C,D, T0, T1, xkey, r ) \ - T0 = g0(A,xkey); T1 = g1(B,xkey);\ - C ^= T0+T1+xkey->K[8+2*(r)]; C = ROR32(C,1);\ - D = ROL32(D,1); D ^= T0+2*T1+xkey->K[8+2*(r)+1] - -/* - * Encrypt a single cycle, consisting of two rounds. - * This avoids the swapping of the two halves. - * Parameter r is now the cycle number. - */ -#define ENCRYPT_CYCLE( A, B, C, D, T0, T1, xkey, r ) \ - ENCRYPT_RND( A,B,C,D,T0,T1,xkey,2*(r) );\ - ENCRYPT_RND( C,D,A,B,T0,T1,xkey,2*(r)+1 ) - -/* Full 16-round encryption */ -#define ENCRYPT( A,B,C,D,T0,T1,xkey ) \ - ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 0 );\ - ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 1 );\ - ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 2 );\ - ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 3 );\ - ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 4 );\ - ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 5 );\ - ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 6 );\ - ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 7 ) - -/* - * A single round of Twofish for decryption. It differs from - * ENCRYTP_RND only because of the 1-bit rotations. - */ -#define DECRYPT_RND( A,B,C,D, T0, T1, xkey, r ) \ - T0 = g0(A,xkey); T1 = g1(B,xkey);\ - C = ROL32(C,1); C ^= T0+T1+xkey->K[8+2*(r)];\ - D ^= T0+2*T1+xkey->K[8+2*(r)+1]; D = ROR32(D,1) - -/* - * Decrypt a single cycle, consisting of two rounds. - * This avoids the swapping of the two halves. - * Parameter r is now the cycle number. - */ -#define DECRYPT_CYCLE( A, B, C, D, T0, T1, xkey, r ) \ - DECRYPT_RND( A,B,C,D,T0,T1,xkey,2*(r)+1 );\ - DECRYPT_RND( C,D,A,B,T0,T1,xkey,2*(r) ) - -/* Full 16-round decryption. */ -#define DECRYPT( A,B,C,D,T0,T1, xkey ) \ - DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 7 );\ - DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 6 );\ - DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 5 );\ - DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 4 );\ - DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 3 );\ - DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 2 );\ - DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 1 );\ - DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 0 ) - -/* - * A macro to read the state from the plaintext and do the initial key xors. - * The koff argument allows us to use the same macro - * for the decryption which uses different key words at the start. - */ -#define GET_INPUT( src, A,B,C,D, xkey, koff ) \ - A = GET32(src )^xkey->K[ koff]; B = GET32(src+ 4)^xkey->K[1+koff]; \ - C = GET32(src+ 8)^xkey->K[2+koff]; D = GET32(src+12)^xkey->K[3+koff] - -/* - * Similar macro to put the ciphertext in the output buffer. - * We xor the keys into the state variables before we use the PUT32 - * macro as the macro might use its argument multiple times. - */ -#define PUT_OUTPUT( A,B,C,D, dst, xkey, koff ) \ - A ^= xkey->K[ koff]; B ^= xkey->K[1+koff]; \ - C ^= xkey->K[2+koff]; D ^= xkey->K[3+koff]; \ - PUT32( A, dst ); PUT32( B, dst+ 4 ); \ - PUT32( C, dst+8 ); PUT32( D, dst+12 ) - - -/* - * Twofish block encryption - * - * Arguments: - * xkey expanded key array - * p 16 bytes of plaintext - * c 16 bytes in which to store the ciphertext - */ -void Twofish_encrypt( Twofish_key * xkey, Twofish_Byte p[16], Twofish_Byte c[16]) - { - Twofish_UInt32 A,B,C,D,T0,T1; /* Working variables */ - - /* Get the four plaintext words xorred with the key */ - GET_INPUT( p, A,B,C,D, xkey, 0 ); - - /* Do 8 cycles (= 16 rounds) */ - ENCRYPT( A,B,C,D,T0,T1,xkey ); - - /* Store them with the final swap and the output whitening. */ - PUT_OUTPUT( C,D,A,B, c, xkey, 4 ); - } - - -/* - * Twofish block decryption. - * - * Arguments: - * xkey expanded key array - * p 16 bytes of plaintext - * c 16 bytes in which to store the ciphertext - */ -void Twofish_decrypt( Twofish_key * xkey, Twofish_Byte c[16], Twofish_Byte p[16]) - { - Twofish_UInt32 A,B,C,D,T0,T1; /* Working variables */ - - /* Get the four plaintext words xorred with the key */ - GET_INPUT( c, A,B,C,D, xkey, 4 ); - - /* Do 8 cycles (= 16 rounds) */ - DECRYPT( A,B,C,D,T0,T1,xkey ); - - /* Store them with the final swap and the output whitening. */ - PUT_OUTPUT( C,D,A,B, p, xkey, 0 ); - } - -/* - * Using the macros it is easy to make special routines for - * CBC mode, CTR mode etc. The only thing you might want to - * add is a XOR_PUT_OUTPUT which xors the outputs into the - * destinationa instead of overwriting the data. This requires - * a XOR_PUT32 macro as well, but that should all be trivial. - * - * I thought about including routines for the separate cipher - * modes here, but it is unclear which modes should be included, - * and each encryption or decryption routine takes up a lot of code space. - * Also, I don't have any test vectors for any cipher modes - * with Twofish. - */ - - +/* + * Fast, portable, and easy-to-use Twofish implementation, + * Version 0.3. + * Copyright (c) 2002 by Niels Ferguson. + * (See further down for the almost-unrestricted licensing terms.) + * + * -------------------------------------------------------------------------- + * There are two files for this implementation: + * - twofish.h, the header file. + * - twofish.c, the code file. + * + * To incorporate this code into your program you should: + * - Check the licensing terms further down in this comment. + * - Fix the two type definitions in twofish.h to suit your platform. + * - Fix a few definitions in twofish.c in the section marked + * PLATFORM FIXES. There is one important ones that affects + * functionality, and then a few definitions that you can optimise + * for efficiency but those have no effect on the functionality. + * Don't change anything else. + * - Put the code in your project and compile it. + * + * To use this library you should: + * - Call Twofish_initialise() in your program before any other function in + * this library. + * - Use Twofish_prepare_key(...) to convert a key to internal form. + * - Use Twofish_encrypt(...) and Twofish_decrypt(...) to encrypt and decrypt + * data. + * See the comments in the header file for details on these functions. + * -------------------------------------------------------------------------- + * + * There are many Twofish implementation available for free on the web. + * Most of them are hard to integrate into your own program. + * As we like people to use our cipher, I thought I would make it easier. + * Here is a free and easy-to-integrate Twofish implementation in C. + * The latest version is always available from my personal home page at + * http://niels.ferguson.net/ + * + * Integrating library code into a project is difficult because the library + * header files interfere with the project's header files and code. + * And of course the project's header files interfere with the library code. + * I've tried to resolve these problems here. + * The header file of this implementation is very light-weight. + * It contains two typedefs, a structure, and a few function declarations. + * All names it defines start with "Twofish_". + * The header file is therefore unlikely to cause problems in your project. + * The code file of this implementation doesn't need to include the header + * files of the project. There is thus no danger of the project interfering + * with all the definitions and macros of the Twofish code. + * In most situations, all you need to do is fill in a few platform-specific + * definitions in the header file and code file, + * and you should be able to run the Twofish code in your project. + * I estimate it should take you less than an hour to integrate this code + * into your project, most of it spent reading the comments telling you what + * to do. + * + * For people using C++: it is very easy to wrap this library into a + * TwofishKey class. One of the big advantages is that you can automate the + * wiping of the key material in the destructor. I have not provided a C++ + * class because the interface depends too much on the abstract base class + * you use for block ciphers in your program, which I don't know about. + * + * This implementation is designed for use on PC-class machines. It uses the + * Twofish 'full' keying option which uses large tables. Total table size is + * around 5-6 kB for static tables plus 4.5 kB for each pre-processed key. + * If you need an implementation that uses less memory, + * take a look at Brian Gladman's code on his web site: + * http://fp.gladman.plus.com/cryptography_technology/aes/ + * He has code for all AES candidates. + * His Twofish code has lots of options trading off table size vs. speed. + * You can also take a look at the optimised code by Doug Whiting on the + * Twofish web site + * http://www.counterpane.com/twofish.html + * which has loads of options. + * I believe these existing implementations are harder to re-use because they + * are not clean libraries and they impose requirements on the environment. + * This implementation is very careful to minimise those, + * and should be easier to integrate into any larger program. + * + * The default mode of this implementation is fully portable as it uses no + * behaviour not defined in the C standard. (This is harder than you think.) + * If you have any problems porting the default mode, please let me know + * so that I can fix the problem. (But only if this code is at fault, I + * don't fix compilers.) + * Most of the platform fixes are related to non-portable but faster ways + * of implementing certain functions. + * + * In general I've tried to make the code as fast as possible, at the expense + * of memory and code size. However, C does impose limits, and this + * implementation will be slower than an optimised assembler implementation. + * But beware of assembler implementations: a good Pentium implementation + * uses completely different code than a good Pentium II implementation. + * You basically have to re-write the assembly code for every generation of + * processor. Unless you are severely pressed for speed, stick with C. + * + * The initialisation routine of this implementation contains a self-test. + * If initialisation succeeds without calling the fatal routine, then + * the implementation works. I don't think you can break the implementation + * in such a way that it still passes the tests, unless you are malicious. + * In other words: if the initialisation routine returns, + * you have successfully ported the implementation. + * (Or not implemented the fatal routine properly, but that is your problem.) + * + * I'm indebted to many people who helped me in one way or another to write + * this code. During the design of Twofish and the AES process I had very + * extensive discussions of all implementation issues with various people. + * Doug Whiting in particular provided a wealth of information. The Twofish + * team spent untold hours discussion various cipher features, and their + * implementation. Brian Gladman implemented all AES candidates in C, + * and we had some fruitful discussions on how to implement Twofish in C. + * Jan Nieuwenhuizen tested this code on Linux using GCC. + * + * Now for the license: + * The author hereby grants a perpetual license to everybody to + * use this code for any purpose as long as the copyright message is included + * in the source code of this or any derived work. + * + * Yes, this means that you, your company, your club, and anyone else + * can use this code anywhere you want. You can change it and distribute it + * under the GPL, include it in your commercial product without releasing + * the source code, put it on the web, etc. + * The only thing you cannot do is remove my copyright message, + * or distribute any source code based on this implementation that does not + * include my copyright message. + * + * I appreciate a mention in the documentation or credits, + * but I understand if that is difficult to do. + * I also appreciate it if you tell me where and why you used my code. + * + * Please send any questions or comments to niels@ferguson.net + * + * Have Fun! + * + * Niels + */ + +/* + * DISCLAIMER: As I'm giving away my work for free, I'm of course not going + * to accept any liability of any form. This code, or the Twofish cipher, + * might very well be flawed; you have been warned. + * This software is provided as-is, without any kind of warrenty or + * guarantee. And that is really all you can expect when you download + * code for free from the Internet. + * + * I think it is really sad that disclaimers like this seem to be necessary. + * If people only had a little bit more common sense, and didn't come + * whining like little children every time something happens.... + */ + +/* + * Version history: + * Version 0.0, 2002-08-30 + * First written. + * Version 0.1, 2002-09-03 + * Added disclaimer. Improved self-tests. + * Version 0.2, 2002-09-09 + * Removed last non-portabilities. Default now works completely within + * the C standard. UInt32 can be larger than 32 bits without problems. + * Version 0.3, 2002-09-28 + * Bugfix: use instead of to adhere to ANSI/ISO. + * Rename BIG_ENDIAN macro to CPU_IS_BIG_ENDIAN. The gcc library + * header already defines BIG_ENDIAN, even though it is not + * supposed to. + */ + + +/* + * Minimum set of include files. + * You should not need any application-specific include files for this code. + * In fact, adding you own header files could break one of the many macros or + * functions in this file. Be very careful. + * Standard include files will probably be ok. + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +/* #include * for memset(), memcpy(), and memcmp() */ +#include "twofish.h" + + +/* + * PLATFORM FIXES + * ============== + * + * Fix the type definitions in twofish.h first! + * + * The following definitions have to be fixed for each particular platform + * you work on. If you have a multi-platform program, you no doubt have + * portable definitions that you can substitute here without changing the + * rest of the code. + */ + + +/* + * Function called if something is fatally wrong with the implementation. + * This fatal function is called when a coding error is detected in the + * Twofish implementation, or when somebody passes an obviously erroneous + * parameter to this implementation. There is not much you can do when + * the code contains bugs, so we just stop. + * + * The argument is a string. Ideally the fatal function prints this string + * as an error message. Whatever else this function does, it should never + * return. A typical implementation would stop the program completely after + * printing the error message. + * + * This default implementation is not very useful, + * but does not assume anything about your environment. + * It will at least let you know something is wrong.... + * I didn't want to include any libraries to print and error or so, + * as this makes the code much harder to integrate in a project. + * + * Note that the Twofish_fatal function may not return to the caller. + * Unfortunately this is not something the self-test can test for, + * so you have to make sure of this yourself. + * + * If you want to call an external function, be careful about including + * your own header files here. This code uses a lot of macros, and your + * header file could easily break it. Maybe the best solution is to use + * a separate extern statement for your fatal function. + */ +/* #define Twofish_fatal(pmsgx) { fprintf(stderr, pmsgx); exit(1); } */ +#define Twofish_fatal(pmsgx, code) { return(code); } + + +/* + * The rest of the settings are not important for the functionality + * of this Twofish implementation. That is, their default settings + * work on all platforms. You can change them to improve the + * speed of the implementation on your platform. Erroneous settings + * will result in erroneous implementations, but the self-test should + * catch those. + */ + + +/* + * Macros to rotate a Twofish_UInt32 value left or right by the + * specified number of bits. This should be a 32-bit rotation, + * and not rotation of, say, 64-bit values. + * + * Every encryption or decryption operation uses 32 of these rotations, + * so it is a good idea to make these macros efficient. + * + * This fully portable definition has one piece of tricky stuff. + * The UInt32 might be larger than 32 bits, so we have to mask + * any higher bits off. The simplest way to do this is to 'and' the + * value first with 0xffffffff and then shift it right. An optimising + * compiler that has a 32-bit type can optimise this 'and' away. + * + * Unfortunately there is no portable way of writing the constant + * 0xffffffff. You don't know which suffix to use (U, or UL?) + * The UINT32_MASK definition uses a bit of trickery. Shift-left + * is only defined if the shift amount is strictly less than the size + * of the UInt32, so we can't use (1<<32). The answer it to take the value + * 2, cast it to a UInt32, shift it left 31 positions, and subtract one. + * Another example of how to make something very simple extremely difficult. + * I hate C. + * + * The rotation macros are straightforward. + * They are only applied to UInt32 values, which are _unsigned_ + * so the >> operator must do a logical shift that brings in zeroes. + * On most platforms you will only need to optimise the ROL32 macro; the + * ROR32 macro is not inefficient on an optimising compiler as all rotation + * amounts in this code are known at compile time. + * + * On many platforms there is a faster solution. + * For example, MS compilers have the __rotl and __rotr functions + * that generate x86 rotation instructions. + */ +#define UINT32_MASK ( (((Twofish_UInt32)2)<<31) - 1 ) + +#ifndef _MSC_VER +#define ROL32(x,n) ( (x)<<(n) | ((x) & UINT32_MASK) >> (32-(n)) ) +#define ROR32(x,n) ( (x)>>(n) | ((x) & UINT32_MASK) << (32-(n)) ) +#else +#define ROL32(x,n) (_lrotl((x), (n))) +#define ROR32(x,n) (_lrotr((x), (n))) +#endif + +/* + * Select data type for q-table entries. + * + * Larger entry types cost more memory (1.5 kB), and might be faster + * or slower depending on the CPU and compiler details. + * + * This choice only affects the static data size and the key setup speed. + * Functionality, expanded key size, or encryption speed are not affected. + * Define to 1 to get large q-table entries. + */ +#define LARGE_Q_TABLE 0 /* default = 0 */ + + +/* + * Method to select a single byte from a UInt32. + * WARNING: non-portable code if set; might not work on all platforms. + * + * Inside the inner loop of Twofish it is necessary to access the 4 + * individual bytes of a UInt32. This can be done using either shifts + * and masks, or memory accesses. + * + * Set to 0 to use shift and mask operations for the byte selection. + * This is more ALU intensive. It is also fully portable. + * + * Set to 1 to use memory accesses. The UInt32 is stored in memory and + * the individual bytes are read from memory one at a time. + * This solution is more memory-intensive, and not fully portable. + * It might be faster on your platform, or not. If you use this option, + * make sure you set the CPU_IS_BIG_ENDIAN flag appropriately. + * + * This macro does not affect the conversion of the inputs and outputs + * of the cipher. See the CONVERT_USING_CASTS macro for that. + */ +#define SELECT_BYTE_FROM_UINT32_IN_MEMORY 0 /* default = 0 */ + + +/* + * Method used to read the input and write the output. + * WARNING: non-portable code if set; might not work on all platforms. + * + * Twofish operates on 32-bit words. The input to the cipher is + * a byte array, as is the output. The portable method of doing the + * conversion is a bunch of rotate and mask operations, but on many + * platforms it can be done faster using a cast. + * This only works if your CPU allows UInt32 accesses to arbitrary Byte + * addresses. + * + * Set to 0 to use the shift and mask operations. This is fully + * portable. . + * + * Set to 1 to use a cast. The Byte * is cast to a UInt32 *, and a + * UInt32 is read. If necessary (as indicated by the CPU_IS_BIG_ENDIAN + * macro) the byte order in the UInt32 is swapped. The reverse is done + * to write the output of the encryption/decryption. Make sure you set + * the CPU_IS_BIG_ENDIAN flag appropriately. + * This option does not work unless a UInt32 is exactly 32 bits. + * + * This macro only changes the reading/writing of the plaintext/ciphertext. + * See the SELECT_BYTE_FROM_UINT32_IN_MEMORY to affect the way in which + * a UInt32 is split into 4 bytes for the S-box selection. + */ +#define CONVERT_USING_CASTS 0 /* default = 0 */ + + +/* + * Endianness switch. + * Only relevant if SELECT_BYTE_FROM_UINT32_IN_MEMORY or + * CONVERT_USING_CASTS is set. + * + * Set to 1 on a big-endian machine, and to 0 on a little-endian machine. + * Twofish uses the little-endian convention (least significant byte first) + * and big-endian machines (using most significant byte first) + * have to do a few conversions. + * + * CAUTION: This code has never been tested on a big-endian machine, + * because I don't have access to one. Feedback appreciated. + */ +#define CPU_IS_BIG_ENDIAN 0 + + +/* + * Macro to reverse the order of the bytes in a UInt32. + * Used to convert to little-endian on big-endian machines. + * This macro is always tested, but only used in the encryption and + * decryption if CONVERT_USING_CASTS, and CPU_IS_BIG_ENDIAN + * are both set. In other words: this macro is only speed-critical if + * both these flags have been set. + * + * This default definition of SWAP works, but on many platforms there is a + * more efficient implementation. + */ +#define BSWAP(x) ((ROL32((x),8)&0x00ff00ff) | (ROR32((x),8) & 0xff00ff00)) + + +/* + * END OF PLATFORM FIXES + * ===================== + * + * You should not have to touch the rest of this file. + */ + + +/* + * Convert the external type names to some that are easier to use inside + * this file. I didn't want to use the names Byte and UInt32 in the + * header file, because many programs already define them and using two + * conventions at once can be very difficult. + * Don't change these definitions! Change the originals + * in twofish.h instead. + */ +/* A Byte must be an unsigned integer, 8 bits long. */ +/* typedef Twofish_Byte Byte; */ +/* A UInt32 must be an unsigned integer at least 32 bits long. */ +/* typedef Twofish_UInt32 UInt32; */ + + +/* + * Define a macro ENDIAN_CONVERT. + * + * We define a macro ENDIAN_CONVERT that performs a BSWAP on big-endian + * machines, and is the identity function on little-endian machines. + * The code then uses this macro without considering the endianness. + */ + +#if CPU_IS_BIG_ENDIAN +#define ENDIAN_CONVERT(x) BSWAP(x) +#else +#define ENDIAN_CONVERT(x) (x) +#endif + + +/* + * Compute byte offset within a UInt32 stored in memory. + * + * This is only used when SELECT_BYTE_FROM_UINT32_IN_MEMORY is set. + * + * The input is the byte number 0..3, 0 for least significant. + * Note the use of sizeof() to support UInt32 types that are larger + * than 4 bytes. + */ +#if CPU_IS_BIG_ENDIAN +#define BYTE_OFFSET( n ) (sizeof(Twofish_UInt32) - 1 - (n) ) +#else +#define BYTE_OFFSET( n ) (n) +#endif + + +/* + * Macro to get Byte no. b from UInt32 value X. + * We use two different definition, depending on the settings. + */ +#if SELECT_BYTE_FROM_UINT32_IN_MEMORY + /* Pick the byte from the memory in which X is stored. */ +#define SELECT_BYTE( X, b ) (((Twofish_Byte *)(&(X)))[BYTE_OFFSET(b)]) +#else + /* Portable solution: Pick the byte directly from the X value. */ +#define SELECT_BYTE( X, b ) (((X) >> (8*(b))) & 0xff) +#endif + + +/* Some shorthands because we use byte selection in large formulae. */ +#define b0(X) SELECT_BYTE((X),0) +#define b1(X) SELECT_BYTE((X),1) +#define b2(X) SELECT_BYTE((X),2) +#define b3(X) SELECT_BYTE((X),3) + + +/* + * We need macros to load and store UInt32 from/to byte arrays + * using the least-significant-byte-first convention. + * + * GET32( p ) gets a UInt32 in lsb-first form from four bytes pointed to + * by p. + * PUT32( v, p ) writes the UInt32 value v at address p in lsb-first form. + */ +#if CONVERT_USING_CASTS + + /* Get UInt32 from four bytes pointed to by p. */ +#define GET32( p ) ENDIAN_CONVERT( *((Twofish_UInt32 *)(p)) ) + /* Put UInt32 into four bytes pointed to by p */ +#define PUT32( v, p ) *((Twofish_UInt32 *)(p)) = ENDIAN_CONVERT(v) + +#else + + /* Get UInt32 from four bytes pointed to by p. */ +#define GET32( p ) \ + ( \ + (Twofish_UInt32)((p)[0]) \ + | (Twofish_UInt32)((p)[1])<< 8 \ + | (Twofish_UInt32)((p)[2])<<16 \ + | (Twofish_UInt32)((p)[3])<<24 \ + ) + /* Put UInt32 into four bytes pointed to by p */ +#define PUT32( v, p ) \ + (p)[0] = (Twofish_Byte)(((v) ) & 0xff); \ + (p)[1] = (Twofish_Byte)(((v) >> 8) & 0xff); \ + (p)[2] = (Twofish_Byte)(((v) >> 16) & 0xff); \ + (p)[3] = (Twofish_Byte)(((v) >> 24) & 0xff) + +#endif + + +/* + * Test the platform-specific macros. + * This function tests the macros defined so far to make sure the + * definitions are appropriate for this platform. + * If you make any mistake in the platform configuration, this should detect + * that and inform you what went wrong. + * Somewhere, someday, this is going to save somebody a lot of time, + * because misbehaving macros are hard to debug. + */ +static int test_platform() + { + /* Buffer with test values. */ + Twofish_Byte buf[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0}; + Twofish_UInt32 C; + Twofish_UInt32 x,y; + int i; + + /* + * Some sanity checks on the types that can't be done in compile time. + * A smart compiler will just optimise these tests away. + * The pre-processor doesn't understand different types, so we cannot + * do these checks in compile-time. + * + * I hate C. + * + * The first check in each case is to make sure the size is correct. + * The second check is to ensure that it is an unsigned type. + */ + if( ((Twofish_UInt32)((Twofish_UInt32)1 << 31) == 0) || ((Twofish_UInt32)-1 < 0 )) + { + Twofish_fatal( "Twofish code: Twofish_UInt32 type not suitable", ERR_UINT32 ); + } + if( (sizeof( Twofish_Byte ) != 1) || (((Twofish_Byte)-1) < 0) ) + { + Twofish_fatal( "Twofish code: Twofish_Byte type not suitable", ERR_BYTE ); + } + + /* + * Sanity-check the endianness conversions. + * This is just an aid to find problems. If you do the endianness + * conversion macros wrong you will fail the full cipher test, + * but that does not help you find the error. + * Always make it easy to find the bugs! + * + * Detail: There is no fully portable way of writing UInt32 constants, + * as you don't know whether to use the U or UL suffix. Using only U you + * might only be allowed 16-bit constants. Using UL you might get 64-bit + * constants which cannot be stored in a UInt32 without warnings, and + * which generally behave subtly different from a true UInt32. + * As long as we're just comparing with the constant, + * we can always use the UL suffix and at worst lose some efficiency. + * I use a separate '32-bit constant' macro in most of my other code. + * + * I hate C. + * + * Start with testing GET32. We test it on all positions modulo 4 + * to make sure we can handly any position of inputs. (Some CPUs + * do not allow non-aligned accesses which we would do if you used + * the CONVERT_USING_CASTS option. + */ + if( (GET32( buf ) != 0x78563412UL) || (GET32(buf+1) != 0x9a785634UL) + || (GET32( buf+2 ) != 0xbc9a7856UL) || (GET32(buf+3) != 0xdebc9a78UL) ) + { + Twofish_fatal( "Twofish code: GET32 not implemented properly", ERR_GET32 ); + } + + /* + * We can now use GET32 to test PUT32. + * We don't test the shifted versions. If GET32 can do that then + * so should PUT32. + */ + C = GET32( buf ); + PUT32( 3*C, buf ); + if( GET32( buf ) != 0x69029c36UL ) + { + Twofish_fatal( "Twofish code: PUT32 not implemented properly", ERR_PUT32 ); + } + + + /* Test ROL and ROR */ + for( i=1; i<32; i++ ) + { + /* Just a simple test. */ + x = ROR32( C, i ); + y = ROL32( C, i ); + x ^= (C>>i) ^ (C<<(32-i)); + /*y ^= (C<>(32-i)); */ + y ^= (C<<i) ^ (C>>(32-i)); + x |= y; + /* + * Now all we check is that x is zero in the least significant + * 32 bits. Using the UL suffix is safe here, as it doesn't matter + * if we get a larger type. + */ + if( (x & 0xffffffffUL) != 0 ) + { + Twofish_fatal( "Twofish ROL or ROR not properly defined.", ERR_ROLR ); + } + } + + /* Test the BSWAP macro */ + if( BSWAP(C) != 0x12345678UL ) + { + /* + * The BSWAP macro should always work, even if you are not using it. + * A smart optimising compiler will just remove this entire test. + */ + Twofish_fatal( "BSWAP not properly defined.", ERR_BSWAP ); + } + + /* And we can test the b macros which use SELECT_BYTE. */ + if( (b0(C)!=0x12) || (b1(C) != 0x34) || (b2(C) != 0x56) || (b3(C) != 0x78) ) + { + /* + * There are many reasons why this could fail. + * Most likely is that CPU_IS_BIG_ENDIAN has the wrong value. + */ + Twofish_fatal( "Twofish code: SELECT_BYTE not implemented properly", ERR_SELECTB ); + } + return SUCCESS; + } + + +/* + * Finally, we can start on the Twofish-related code. + * You really need the Twofish specifications to understand this code. The + * best source is the Twofish book: + * "The Twofish Encryption Algorithm", by Bruce Schneier, John Kelsey, + * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson. + * you can also use the AES submission document of Twofish, which is + * available from my list of publications on my personal web site at + * http://niels.ferguson.net/. + * + * The first thing we do is write the testing routines. This is what the + * implementation has to satisfy in the end. We only test the external + * behaviour of the implementation of course. + */ + + +/* + * Perform a single self test on a (plaintext,ciphertext,key) triple. + * Arguments: + * key array of key bytes + * key_len length of key in bytes + * p plaintext + * c ciphertext + */ +static int test_vector( Twofish_Byte key[], int key_len, Twofish_Byte p[16], Twofish_Byte c[16] ) + { + Twofish_Byte tmp[16]; /* scratch pad. */ + Twofish_key xkey; /* The expanded key */ + int i; + + + /* Prepare the key */ + if ((i = Twofish_prepare_key( key, key_len, &xkey)) < 0) + return i; + + /* + * We run the test twice to ensure that the xkey structure + * is not damaged by the first encryption. + * Those are hideous bugs to find if you get them in an application. + */ + for( i=0; i<2; i++ ) + { + /* Encrypt and test */ + Twofish_encrypt( &xkey, p, tmp ); + if( memcmp( c, tmp, 16 ) != 0 ) + { + Twofish_fatal( "Twofish encryption failure", ERR_TEST_ENC ); + } + + /* Decrypt and test */ + Twofish_decrypt( &xkey, c, tmp ); + if( memcmp( p, tmp, 16 ) != 0 ) + { + Twofish_fatal( "Twofish decryption failure", ERR_TEST_DEC ); + } + } + + /* The test keys are not secret, so we don't need to wipe xkey. */ + return SUCCESS; + } + + +/* + * Check implementation using three (key,plaintext,ciphertext) + * test vectors, one for each major key length. + * + * This is an absolutely minimal self-test. + * This routine does not test odd-sized keys. + */ +static int test_vectors() + { + /* + * We run three tests, one for each major key length. + * These test vectors come from the Twofish specification. + * One encryption and one decryption using randomish data and key + * will detect almost any error, especially since we generate the + * tables ourselves, so we don't have the problem of a single + * damaged table entry in the source. + */ + + /* 128-bit test is the I=3 case of section B.2 of the Twofish book. */ + static Twofish_Byte k128[] = { + 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, + 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A, + }; + static Twofish_Byte p128[] = { + 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, + 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 + }; + static Twofish_Byte c128[] = { + 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, + 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 + }; + + /* 192-bit test is the I=4 case of section B.2 of the Twofish book. */ + static Twofish_Byte k192[] = { + 0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, + 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88, + 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44 + }; + static Twofish_Byte p192[] = { + 0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, + 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2 + }; + static Twofish_Byte c192[] = { + 0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, + 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65 + }; + + /* 256-bit test is the I=4 case of section B.2 of the Twofish book. */ + static Twofish_Byte k256[] = { + 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, + 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, + 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, + 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F + }; + static Twofish_Byte p256[] = { + 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, + 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 + }; + static Twofish_Byte c256[] = { + 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, + 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA + }; + + int ret; + + /* Run the actual tests. */ + if ((ret = test_vector( k128, 16, p128, c128 )) < 0) + return ret; + if ((ret = test_vector( k192, 24, p192, c192 )) < 0) + return ret; + if ((ret = test_vector( k256, 32, p256, c256 )) < 0) + return ret; + return SUCCESS; + } + + +/* + * Perform extensive test for a single key size. + * + * Test a single key size against the test vectors from section + * B.2 in the Twofish book. This is a sequence of 49 encryptions + * and decryptions. Each plaintext is equal to the ciphertext of + * the previous encryption. The key is made up from the ciphertext + * two and three encryptions ago. Both plaintext and key start + * at the zero value. + * We should have designed a cleaner recurrence relation for + * these tests, but it is too late for that now. At least we learned + * how to do it better next time. + * For details see appendix B of the book. + * + * Arguments: + * key_len Number of bytes of key + * final_value Final plaintext value after 49 iterations + */ +static int test_sequence( int key_len, Twofish_Byte final_value[] ) + { + Twofish_Byte buf[ (50+3)*16 ]; /* Buffer to hold our computation values. */ + Twofish_Byte tmp[16]; /* Temp for testing the decryption. */ + Twofish_key xkey; /* The expanded key */ + int i, ret; + Twofish_Byte * p; + + /* Wipe the buffer */ + memset( buf, 0, sizeof( buf ) ); + + /* + * Because the recurrence relation is done in an inconvenient manner + * we end up looping backwards over the buffer. + */ + + /* Pointer in buffer points to current plaintext. */ + p = &buf[50*16]; + for( i=1; i<50; i++ ) + { + /* + * Prepare a key. + * This automatically checks that key_len is valid. + */ + if ((ret = Twofish_prepare_key( p+16, key_len, &xkey)) < 0) + return ret; + + /* Compute the next 16 bytes in the buffer */ + Twofish_encrypt( &xkey, p, p-16 ); + + /* Check that the decryption is correct. */ + Twofish_decrypt( &xkey, p-16, tmp ); + if( memcmp( tmp, p, 16 ) != 0 ) + { + Twofish_fatal( "Twofish decryption failure in sequence", ERR_SEQ_DEC ); + } + /* Move on to next 16 bytes in the buffer. */ + p -= 16; + } + + /* And check the final value. */ + if( memcmp( p, final_value, 16 ) != 0 ) + { + Twofish_fatal( "Twofish encryption failure in sequence", ERR_SEQ_ENC ); + } + + /* None of the data was secret, so there is no need to wipe anything. */ + return SUCCESS; + } + + +/* + * Run all three sequence tests from the Twofish test vectors. + * + * This checks the most extensive test vectors currently available + * for Twofish. The data is from the Twofish book, appendix B.2. + */ +static int test_sequences() + { + static Twofish_Byte r128[] = { + 0x5D, 0x9D, 0x4E, 0xEF, 0xFA, 0x91, 0x51, 0x57, + 0x55, 0x24, 0xF1, 0x15, 0x81, 0x5A, 0x12, 0xE0 + }; + static Twofish_Byte r192[] = { + 0xE7, 0x54, 0x49, 0x21, 0x2B, 0xEE, 0xF9, 0xF4, + 0xA3, 0x90, 0xBD, 0x86, 0x0A, 0x64, 0x09, 0x41 + }; + static Twofish_Byte r256[] = { + 0x37, 0xFE, 0x26, 0xFF, 0x1C, 0xF6, 0x61, 0x75, + 0xF5, 0xDD, 0xF4, 0xC3, 0x3B, 0x97, 0xA2, 0x05 + }; + + /* Run the three sequence test vectors */ + int ret; + if ((ret = test_sequence( 16, r128)) < 0) + return ret; + if ((ret = test_sequence( 24, r192)) < 0) + return ret; + if ((ret = test_sequence( 32, r256)) < 0) + return ret; + return SUCCESS; + } + + +/* + * Test the odd-sized keys. + * + * Every odd-sized key is equivalent to a one of 128, 192, or 256 bits. + * The equivalent key is found by padding at the end with zero bytes + * until a regular key size is reached. + * + * We just test that the key expansion routine behaves properly. + * If the expanded keys are identical, then the encryptions and decryptions + * will behave the same. + */ +static int test_odd_sized_keys() + { + Twofish_Byte buf[32]; + Twofish_key xkey; + Twofish_key xkey_two; + int i, ret; + + /* + * We first create an all-zero key to use as PRNG key. + * Normally we would not have to fill the buffer with zeroes, as we could + * just pass a zero key length to the Twofish_prepare_key function. + * However, this relies on using odd-sized keys, and those are just the + * ones we are testing here. We can't use an untested function to test + * itself. + */ + memset( buf, 0, sizeof( buf ) ); + if ((ret = Twofish_prepare_key( buf, 16, &xkey)) < 0) + return ret; + + /* Fill buffer with pseudo-random data derived from two encryptions */ + Twofish_encrypt( &xkey, buf, buf ); + Twofish_encrypt( &xkey, buf, buf+16 ); + + /* Create all possible shorter keys that are prefixes of the buffer. */ + for( i=31; i>=0; i-- ) + { + /* Set a byte to zero. This is the new padding byte */ + buf[i] = 0; + + /* Expand the key with only i bytes of length */ + if ((ret = Twofish_prepare_key( buf, i, &xkey)) < 0) + return ret; + + /* Expand the corresponding padded key of regular length */ + if ((ret = Twofish_prepare_key( buf, i<=16 ? 16 : (i<= 24 ? 24 : 32), &xkey_two )) < 0) + return ret; + + /* Compare the two */ + if( memcmp( &xkey, &xkey_two, sizeof( xkey ) ) != 0 ) + { + Twofish_fatal( "Odd sized keys do not expand properly", ERR_ODD_KEY ); + } + } + + /* None of the key values are secret, so we don't need to wipe them. */ + return SUCCESS; + } + + +/* + * Test the Twofish implementation. + * + * This routine runs all the self tests, in order of importance. + * It is called by the Twofish_initialise routine. + * + * In almost all applications the cost of running the self tests during + * initialisation is insignificant, especially + * compared to the time it takes to load the application from disk. + * If you are very pressed for initialisation performance, + * you could remove some of the tests. Make sure you did run them + * once in the software and hardware configuration you are using. + */ +static int self_test() + { + int ret; + /* The three test vectors form an absolute minimal test set. */ + if ((ret = test_vectors()) < 0) + return ret; + + /* + * If at all possible you should run these tests too. They take + * more time, but provide a more thorough coverage. + */ + if ((ret = test_sequences()) < 0) + return ret; + + /* Test the odd-sized keys. */ + if ((ret = test_odd_sized_keys()) < 0) + return ret; + return SUCCESS; + } + + +/* + * And now, the actual Twofish implementation. + * + * This implementation generates all the tables during initialisation. + * I don't like large tables in the code, especially since they are easily + * damaged in the source without anyone noticing it. You need code to + * generate them anyway, and this way all the code is close together. + * Generating them in the application leads to a smaller executable + * (the code is smaller than the tables it generates) and a + * larger static memory footprint. + * + * Twofish can be implemented in many ways. I have chosen to + * use large tables with a relatively long key setup time. + * If you encrypt more than a few blocks of data it pays to pre-compute + * as much as possible. This implementation is relatively inefficient for + * applications that need to re-key every block or so. + */ + +/* + * We start with the t-tables, directly from the Twofish definition. + * These are nibble-tables, but merging them and putting them two nibbles + * in one byte is more work than it is worth. + */ +static Twofish_Byte t_table[2][4][16] = { + { + {0x8,0x1,0x7,0xD,0x6,0xF,0x3,0x2,0x0,0xB,0x5,0x9,0xE,0xC,0xA,0x4}, + {0xE,0xC,0xB,0x8,0x1,0x2,0x3,0x5,0xF,0x4,0xA,0x6,0x7,0x0,0x9,0xD}, + {0xB,0xA,0x5,0xE,0x6,0xD,0x9,0x0,0xC,0x8,0xF,0x3,0x2,0x4,0x7,0x1}, + {0xD,0x7,0xF,0x4,0x1,0x2,0x6,0xE,0x9,0xB,0x3,0x0,0x8,0x5,0xC,0xA} + }, + { + {0x2,0x8,0xB,0xD,0xF,0x7,0x6,0xE,0x3,0x1,0x9,0x4,0x0,0xA,0xC,0x5}, + {0x1,0xE,0x2,0xB,0x4,0xC,0x3,0x7,0x6,0xD,0xA,0x5,0xF,0x9,0x0,0x8}, + {0x4,0xC,0x7,0x5,0x1,0x6,0x9,0xA,0x0,0xE,0xD,0x8,0x2,0xB,0x3,0xF}, + {0xB,0x9,0x5,0x1,0xC,0x3,0xD,0xE,0x6,0x4,0x7,0xF,0x2,0x0,0x8,0xA} + } +}; + + +/* A 1-bit rotation of 4-bit values. Input must be in range 0..15 */ +#define ROR4BY1( x ) (((x)>>1) | (((x)<<3) & 0x8) ) + +/* + * The q-boxes are only used during the key schedule computations. + * These are 8->8 bit lookup tables. Some CPUs prefer to have 8->32 bit + * lookup tables as it is faster to load a 32-bit value than to load an + * 8-bit value and zero the rest of the register. + * The LARGE_Q_TABLE switch allows you to choose 32-bit entries in + * the q-tables. Here we just define the Qtype which is used to store + * the entries of the q-tables. + */ +#if LARGE_Q_TABLE +typedef Twofish_UInt32 Qtype; +#else +typedef Twofish_Byte Qtype; +#endif + +/* + * The actual q-box tables. + * There are two q-boxes, each having 256 entries. + */ +static Qtype q_table[2][256]; + + +/* + * Now the function that converts a single t-table into a q-table. + * + * Arguments: + * t[4][16] : four 4->4bit lookup tables that define the q-box + * q[256] : output parameter: the resulting q-box as a lookup table. + */ +static void make_q_table( Twofish_Byte t[4][16], Qtype q[256] ) + { + int ae,be,ao,bo; /* Some temporaries. */ + int i; + /* Loop over all input values and compute the q-box result. */ + for( i=0; i<256; i++ ) { + /* + * This is straight from the Twofish specifications. + * + * The ae variable is used for the a_i values from the specs + * with even i, and ao for the odd i's. Similarly for the b's. + */ + ae = i>>4; be = i&0xf; + ao = ae ^ be; bo = ae ^ ROR4BY1(be) ^ ((ae<<3)&8); + ae = t[0][ao]; be = t[1][bo]; + ao = ae ^ be; bo = ae ^ ROR4BY1(be) ^ ((ae<<3)&8); + ae = t[2][ao]; be = t[3][bo]; + + /* Store the result in the q-box table, the cast avoids a warning. */ + q[i] = (Qtype) ((be<<4) | ae); + } + } + + +/* + * Initialise both q-box tables. + */ +static void initialise_q_boxes() { + /* Initialise each of the q-boxes using the t-tables */ + make_q_table( t_table[0], q_table[0] ); + make_q_table( t_table[1], q_table[1] ); + } + + +/* + * Next up is the MDS matrix multiplication. + * The MDS matrix multiplication operates in the field + * GF(2)[x]/p(x) with p(x)=x^8+x^6+x^5+x^3+1. + * If you don't understand this, read a book on finite fields. You cannot + * follow the finite-field computations without some background. + * + * In this field, multiplication by x is easy: shift left one bit + * and if bit 8 is set then xor the result with 0x169. + * + * The MDS coefficients use a multiplication by 1/x, + * or rather a division by x. This is easy too: first make the + * value 'even' (i.e. bit 0 is zero) by xorring with 0x169 if necessary, + * and then shift right one position. + * Even easier: shift right and xor with 0xb4 if the lsbit was set. + * + * The MDS coefficients are 1, EF, and 5B, and we use the fact that + * EF = 1 + 1/x + 1/x^2 + * 5B = 1 + 1/x^2 + * in this field. This makes multiplication by EF and 5B relatively easy. + * + * This property is no accident, the MDS matrix was designed to allow + * this implementation technique to be used. + * + * We have four MDS tables, each mapping 8 bits to 32 bits. + * Each table performs one column of the matrix multiplication. + * As the MDS is always preceded by q-boxes, each of these tables + * also implements the q-box just previous to that column. + */ + +/* The actual MDS tables. */ +static Twofish_UInt32 MDS_table[4][256]; + +/* A small table to get easy conditional access to the 0xb4 constant. */ +static Twofish_UInt32 mds_poly_divx_const[] = {0,0xb4}; + +/* Function to initialise the MDS tables. */ +static void initialise_mds_tables() + { + int i; + Twofish_UInt32 q,qef,q5b; /* Temporary variables. */ + + /* Loop over all 8-bit input values */ + for( i=0; i<256; i++ ) + { + /* + * To save some work during the key expansion we include the last + * of the q-box layers from the h() function in these MDS tables. + */ + + /* We first do the inputs that are mapped through the q0 table. */ + q = q_table[0][i]; + /* + * Here we divide by x, note the table to get 0xb4 only if the + * lsbit is set. + * This sets qef = (1/x)*q in the finite field + */ + qef = (q >> 1) ^ mds_poly_divx_const[ q & 1 ]; + /* + * Divide by x again, and add q to get (1+1/x^2)*q. + * Note that (1+1/x^2) = 5B in the field, and addition in the field + * is exclusive or on the bits. + */ + q5b = (qef >> 1) ^ mds_poly_divx_const[ qef & 1 ] ^ q; + /* + * Add q5b to qef to set qef = (1+1/x+1/x^2)*q. + * Again, (1+1/x+1/x^2) = EF in the field. + */ + qef ^= q5b; + + /* + * Now that we have q5b = 5B * q and qef = EF * q + * we can fill two of the entries in the MDS matrix table. + * See the Twofish specifications for the order of the constants. + */ + MDS_table[1][i] = (q <<24) | (q5b<<16) | (qef<<8) | qef; + MDS_table[3][i] = (q5b<<24) | (qef<<16) | (q <<8) | q5b; + + /* Now we do it all again for the two columns that have a q1 box. */ + q = q_table[1][i]; + qef = (q >> 1) ^ mds_poly_divx_const[ q & 1 ]; + q5b = (qef >> 1) ^ mds_poly_divx_const[ qef & 1 ] ^ q; + qef ^= q5b; + + /* The other two columns use the coefficient in a different order. */ + MDS_table[0][i] = (qef<<24) | (qef<<16) | (q5b<<8) | q ; + MDS_table[2][i] = (qef<<24) | (q <<16) | (qef<<8) | q5b; + } + } + + +/* + * The h() function is the heart of the Twofish cipher. + * It is a complicated sequence of q-box lookups, key material xors, + * and finally the MDS matrix. + * We use lots of macros to make this reasonably fast. + */ + +/* First a shorthand for the two q-tables */ +#define q0 q_table[0] +#define q1 q_table[1] + +/* + * Each macro computes one column of the h for either 2, 3, or 4 stages. + * As there are 4 columns, we have 12 macros in all. + * + * The key bytes are stored in the Byte array L at offset + * 0,1,2,3, 8,9,10,11, [16,17,18,19, [24,25,26,27]] as this is the + * order we get the bytes from the user. If you look at the Twofish + * specs, you'll see that h() is applied to the even key words or the + * odd key words. The bytes of the even words appear in this spacing, + * and those of the odd key words too. + * + * These macros are the only place where the q-boxes and the MDS table + * are used. + */ +#define H02( y, L ) MDS_table[0][q0[q0[y]^L[ 8]]^L[0]] +#define H12( y, L ) MDS_table[1][q0[q1[y]^L[ 9]]^L[1]] +#define H22( y, L ) MDS_table[2][q1[q0[y]^L[10]]^L[2]] +#define H32( y, L ) MDS_table[3][q1[q1[y]^L[11]]^L[3]] +#define H03( y, L ) H02( q1[y]^L[16], L ) +#define H13( y, L ) H12( q1[y]^L[17], L ) +#define H23( y, L ) H22( q0[y]^L[18], L ) +#define H33( y, L ) H32( q0[y]^L[19], L ) +#define H04( y, L ) H03( q1[y]^L[24], L ) +#define H14( y, L ) H13( q0[y]^L[25], L ) +#define H24( y, L ) H23( q0[y]^L[26], L ) +#define H34( y, L ) H33( q1[y]^L[27], L ) + +/* + * Now we can define the h() function given an array of key bytes. + * This function is only used in the key schedule, and not to pre-compute + * the keyed S-boxes. + * + * In the key schedule, the input is always of the form k*(1+2^8+2^16+2^24) + * so we only provide k as an argument. + * + * Arguments: + * k input to the h() function. + * L pointer to array of key bytes at + * offsets 0,1,2,3, ... 8,9,10,11, [16,17,18,19, [24,25,26,27]] + * kCycles # key cycles, 2, 3, or 4. + */ +static Twofish_UInt32 h( int k, Twofish_Byte L[], int kCycles ) + { + switch( kCycles ) { + /* We code all 3 cases separately for speed reasons. */ + case 2: + return H02(k,L) ^ H12(k,L) ^ H22(k,L) ^ H32(k,L); + case 3: + return H03(k,L) ^ H13(k,L) ^ H23(k,L) ^ H33(k,L); + case 4: + return H04(k,L) ^ H14(k,L) ^ H24(k,L) ^ H34(k,L); + default: + /* This is always a coding error, which is fatal. */ + Twofish_fatal( "Twofish h(): Illegal argument", ERR_ILL_ARG ); + return ERR_ILL_ARG; + } + } + + +/* + * Pre-compute the keyed S-boxes. + * Fill the pre-computed S-box array in the expanded key structure. + * Each pre-computed S-box maps 8 bits to 32 bits. + * + * The S argument contains half the number of bytes of the full key, but is + * derived from the full key. (See Twofish specifications for details.) + * S has the weird byte input order used by the Hxx macros. + * + * This function takes most of the time of a key expansion. + * + * Arguments: + * S pointer to array of 8*kCycles Bytes containing the S vector. + * kCycles number of key words, must be in the set {2,3,4} + * xkey pointer to Twofish_key structure that will contain the S-boxes. + */ +static int fill_keyed_sboxes( Twofish_Byte S[], int kCycles, Twofish_key * xkey ) + { + int i; + switch( kCycles ) { + /* We code all 3 cases separately for speed reasons. */ + case 2: + for( i=0; i<256; i++ ) + { + xkey->s[0][i]= H02( i, S ); + xkey->s[1][i]= H12( i, S ); + xkey->s[2][i]= H22( i, S ); + xkey->s[3][i]= H32( i, S ); + } + break; + case 3: + for( i=0; i<256; i++ ) + { + xkey->s[0][i]= H03( i, S ); + xkey->s[1][i]= H13( i, S ); + xkey->s[2][i]= H23( i, S ); + xkey->s[3][i]= H33( i, S ); + } + break; + case 4: + for( i=0; i<256; i++ ) + { + xkey->s[0][i]= H04( i, S ); + xkey->s[1][i]= H14( i, S ); + xkey->s[2][i]= H24( i, S ); + xkey->s[3][i]= H34( i, S ); + } + break; + default: + /* This is always a coding error, which is fatal. */ + Twofish_fatal( "Twofish fill_keyed_sboxes(): Illegal argument", ERR_ILL_ARG ); + } + return SUCCESS; + } + + +/* A flag to keep track of whether we have been initialised or not. */ +static int Twofish_initialised = 0; + +/* + * Initialise the Twofish implementation. + * This function must be called before any other function in the + * Twofish implementation is called. + * This routine also does some sanity checks, to make sure that + * all the macros behave, and it tests the whole cipher. + */ +int Twofish_initialise() + { + int ret; + /* First test the various platform-specific definitions. */ + if ((ret = test_platform()) < 0) + return ret; + + /* We can now generate our tables, in the right order of course. */ + initialise_q_boxes(); + initialise_mds_tables(); + + /* We're finished with the initialisation itself. */ + Twofish_initialised = 1; + + /* + * And run some tests on the whole cipher. + * Yes, you need to do this every time you start your program. + * It is called assurance; you have to be certain that your program + * still works properly. + */ + return self_test(); + } + + +/* + * The Twofish key schedule uses an Reed-Solomon code matrix multiply. + * Just like the MDS matrix, the RS-matrix is designed to be easy + * to implement. Details are below in the code. + * + * These constants make it easy to compute in the finite field used + * for the RS code. + * + * We use Bytes for the RS computation, but these are automatically + * widened to unsigned integers in the expressions. Having unsigned + * ints in these tables therefore provides the fastest access. + */ +static unsigned int rs_poly_const[] = {0, 0x14d}; +static unsigned int rs_poly_div_const[] = {0, 0xa6 }; + + +/* + * Prepare a key for use in encryption and decryption. + * Like most block ciphers, Twofish allows the key schedule + * to be pre-computed given only the key. + * Twofish has a fairly 'heavy' key schedule that takes a lot of time + * to compute. The main work is pre-computing the S-boxes used in the + * encryption and decryption. We feel that this makes the cipher much + * harder to attack. The attacker doesn't even know what the S-boxes + * contain without including the entire key schedule in the analysis. + * + * Unlike most Twofish implementations, this one allows any key size from + * 0 to 32 bytes. Odd key sizes are defined for Twofish (see the + * specifications); the key is simply padded with zeroes to the next real + * key size of 16, 24, or 32 bytes. + * Each odd-sized key is thus equivalent to a single normal-sized key. + * + * Arguments: + * key array of key bytes + * key_len number of bytes in the key, must be in the range 0,...,32. + * xkey Pointer to an Twofish_key structure that will be filled + * with the internal form of the cipher key. + */ +int Twofish_prepare_key( Twofish_Byte key[], int key_len, Twofish_key * xkey ) + { + /* We use a single array to store all key material in, + * to simplify the wiping of the key material at the end. + * The first 32 bytes contain the actual (padded) cipher key. + * The next 32 bytes contain the S-vector in its weird format, + * and we have 4 bytes of overrun necessary for the RS-reduction. + */ + Twofish_Byte K[32+32+4]; + + int kCycles; /* # key cycles, 2,3, or 4. */ + + int i; + Twofish_UInt32 A, B; /* Used to compute the round keys. */ + + Twofish_Byte * kptr; /* Three pointers for the RS computation. */ + Twofish_Byte * sptr; + Twofish_Byte * t; + + Twofish_Byte b,bx,bxx; /* Some more temporaries for the RS computation. */ + + /* Check that the Twofish implementation was initialised. */ + if( Twofish_initialised == 0 ) + { + /* + * You didn't call Twofish_initialise before calling this routine. + * This is a programming error, and therefore we call the fatal + * routine. + * + * I could of course call the initialisation routine here, + * but there are a few reasons why I don't. First of all, the + * self-tests have to be done at startup. It is no good to inform + * the user that the cipher implementation fails when he wants to + * write his data to disk in encrypted form. You have to warn him + * before he spends time typing his data. Second, the initialisation + * and self test are much slower than a single key expansion. + * Calling the initialisation here makes the performance of the + * cipher unpredictable. This can lead to really weird problems + * if you use the cipher for a real-time task. Suddenly it fails + * once in a while the first time you try to use it. Things like + * that are almost impossible to debug. + */ + /* Twofish_fatal( "Twofish implementation was not initialised.", ERR_INIT ); */ + + /* + * There is always a danger that the Twofish_fatal routine returns, + * in spite of the specifications that it should not. + * (A good programming rule: don't trust the rest of the code.) + * This would be disasterous. If the q-tables and MDS-tables have + * not been initialised, they are probably still filled with zeroes. + * Suppose the MDS-tables are all zero. The key expansion would then + * generate all-zero round keys, and all-zero s-boxes. The danger + * is that nobody would notice as the encry + * mangles the input, and the decryption still 'decrypts' it, + * but now in a completely key-independent manner. + * To stop such security disasters, we use blunt force. + * If your program hangs here: fix the fatal routine! + */ + for(;;); /* Infinite loop, which beats being insecure. */ + } + + /* Check for valid key length. */ + if( key_len < 0 || key_len > 32 ) + { + /* + * This can only happen if a programmer didn't read the limitations + * on the key size. + */ + Twofish_fatal( "Twofish_prepare_key: illegal key length", ERR_KEY_LEN ); + /* + * A return statement just in case the fatal macro returns. + * The rest of the code assumes that key_len is in range, and would + * buffer-overflow if it wasn't. + * + * Why do we still use a programming language that has problems like + * buffer overflows, when these problems were solved in 1960 with + * the development of Algol? Have we not leared anything? + */ + return ERR_KEY_LEN; + } + + /* Pad the key with zeroes to the next suitable key length. */ + memcpy( K, key, key_len ); + memset( K+key_len, 0, sizeof(K)-key_len ); + + /* + * Compute kCycles: the number of key cycles used in the cipher. + * 2 for 128-bit keys, 3 for 192-bit keys, and 4 for 256-bit keys. + */ + kCycles = (key_len + 7) >> 3; + /* Handle the special case of very short keys: minimum 2 cycles. */ + if( kCycles < 2 ) + { + kCycles = 2; + } + + /* + * From now on we just pretend to have 8*kCycles bytes of + * key material in K. This handles all the key size cases. + */ + + /* + * We first compute the 40 expanded key words, + * formulas straight from the Twofish specifications. + */ + for( i=0; i<40; i+=2 ) + { + /* + * Due to the byte spacing expected by the h() function + * we can pick the bytes directly from the key K. + * As we use bytes, we never have the little/big endian + * problem. + * + * Note that we apply the rotation function only to simple + * variables, as the rotation macro might evaluate its argument + * more than once. + */ + A = h( i , K , kCycles ); + B = h( i+1, K+4, kCycles ); + B = ROL32( B, 8 ); + + /* Compute and store the round keys. */ + A += B; + B += A; + xkey->K[i] = A; + xkey->K[i+1] = ROL32( B, 9 ); + } + + /* Wipe variables that contained key material. */ + A=B=0; + + /* + * And now the dreaded RS multiplication that few seem to understand. + * The RS matrix is not random, and is specially designed to compute the + * RS matrix multiplication in a simple way. + * + * We work in the field GF(2)[x]/x^8+x^6+x^3+x^2+1. Note that this is a + * different field than used for the MDS matrix. + * (At least, it is a different representation because all GF(2^8) + * representations are equivalent in some form.) + * + * We take 8 consecutive bytes of the key and interpret them as + * a polynomial k_0 + k_1 y + k_2 y^2 + ... + k_7 y^7 where + * the k_i bytes are the key bytes and are elements of the finite field. + * We multiply this polynomial by y^4 and reduce it modulo + * y^4 + (x + 1/x)y^3 + (x)y^2 + (x + 1/x)y + 1. + * using straightforward polynomial modulo reduction. + * The coefficients of the result are the result of the RS + * matrix multiplication. When we wrote the Twofish specification, + * the original RS definition used the polynomials, + * but that requires much more mathematical knowledge. + * We were already using matrix multiplication in a finite field for + * the MDS matrix, so I re-wrote the RS operation as a matrix + * multiplication to reduce the difficulty of understanding it. + * Some implementors have not picked up on this simpler method of + * computing the RS operation, even though it is mentioned in the + * specifications. + * + * It is possible to perform these computations faster by using 32-bit + * word operations, but that is not portable and this is not a speed- + * critical area. + * + * We explained the 1/x computation when we did the MDS matrix. + * + * The S vector is stored in K[32..64]. + * The S vector has to be reversed, so we loop cross-wise. + * + * Note the weird byte spacing of the S-vector, to match the even + * or odd key words arrays. See the discussion at the Hxx macros for + * details. + */ + kptr = K + 8*kCycles; /* Start at end of key */ + sptr = K + 32; /* Start at start of S */ + + /* Loop over all key material */ + while( kptr > K ) + { + kptr -= 8; + /* + * Initialise the polynimial in sptr[0..12] + * The first four coefficients are 0 as we have to multiply by y^4. + * The next 8 coefficients are from the key material. + */ + memset( sptr, 0, 4 ); + memcpy( sptr+4, kptr, 8 ); + + /* + * The 12 bytes starting at sptr are now the coefficients of + * the polynomial we need to reduce. + */ + + /* Loop over the polynomial coefficients from high to low */ + t = sptr+11; + /* Keep looping until polynomial is degree 3; */ + while( t > sptr+3 ) + { + /* Pick up the highest coefficient of the poly. */ + b = *t; + + /* + * Compute x and (x+1/x) times this coefficient. + * See the MDS matrix implementation for a discussion of + * multiplication by x and 1/x. We just use different + * constants here as we are in a + * different finite field representation. + * + * These two statements set + * bx = (x) * b + * bxx= (x + 1/x) * b + */ + bx = (Twofish_Byte)((b<<1) ^ rs_poly_const[ b>>7 ]); + bxx= (Twofish_Byte)((b>>1) ^ rs_poly_div_const[ b&1 ] ^ bx); + + /* + * Subtract suitable multiple of + * y^4 + (x + 1/x)y^3 + (x)y^2 + (x + 1/x)y + 1 + * from the polynomial, except that we don't bother + * updating t[0] as it will become zero anyway. + */ + t[-1] ^= bxx; + t[-2] ^= bx; + t[-3] ^= bxx; + t[-4] ^= b; + + /* Go to the next coefficient. */ + t--; + } + + /* Go to next S-vector word, obeying the weird spacing rules. */ + sptr += 8; + } + + /* Wipe variables that contained key material. */ + b = bx = bxx = 0; + + /* And finally, we can compute the key-dependent S-boxes. */ + fill_keyed_sboxes( &K[32], kCycles, xkey ); + + /* Wipe array that contained key material. */ + memset( K, 0, sizeof( K ) ); + return SUCCESS; + } + + +/* + * We can now start on the actual encryption and decryption code. + * As these are often speed-critical we will use a lot of macros. + */ + +/* + * The g() function is the heart of the round function. + * We have two versions of the g() function, one without an input + * rotation and one with. + * The pre-computed S-boxes make this pretty simple. + */ +#define g0(X,xkey) \ + (xkey->s[0][b0(X)]^xkey->s[1][b1(X)]^xkey->s[2][b2(X)]^xkey->s[3][b3(X)]) + +#define g1(X,xkey) \ + (xkey->s[0][b3(X)]^xkey->s[1][b0(X)]^xkey->s[2][b1(X)]^xkey->s[3][b2(X)]) + +/* + * A single round of Twofish. The A,B,C,D are the four state variables, + * T0 and T1 are temporaries, xkey is the expanded key, and r the + * round number. + * + * Note that this macro does not implement the swap at the end of the round. + */ +#define ENCRYPT_RND( A,B,C,D, T0, T1, xkey, r ) \ + T0 = g0(A,xkey); T1 = g1(B,xkey);\ + C ^= T0+T1+xkey->K[8+2*(r)]; C = ROR32(C,1);\ + D = ROL32(D,1); D ^= T0+2*T1+xkey->K[8+2*(r)+1] + +/* + * Encrypt a single cycle, consisting of two rounds. + * This avoids the swapping of the two halves. + * Parameter r is now the cycle number. + */ +#define ENCRYPT_CYCLE( A, B, C, D, T0, T1, xkey, r ) \ + ENCRYPT_RND( A,B,C,D,T0,T1,xkey,2*(r) );\ + ENCRYPT_RND( C,D,A,B,T0,T1,xkey,2*(r)+1 ) + +/* Full 16-round encryption */ +#define ENCRYPT( A,B,C,D,T0,T1,xkey ) \ + ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 0 );\ + ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 1 );\ + ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 2 );\ + ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 3 );\ + ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 4 );\ + ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 5 );\ + ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 6 );\ + ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 7 ) + +/* + * A single round of Twofish for decryption. It differs from + * ENCRYTP_RND only because of the 1-bit rotations. + */ +#define DECRYPT_RND( A,B,C,D, T0, T1, xkey, r ) \ + T0 = g0(A,xkey); T1 = g1(B,xkey);\ + C = ROL32(C,1); C ^= T0+T1+xkey->K[8+2*(r)];\ + D ^= T0+2*T1+xkey->K[8+2*(r)+1]; D = ROR32(D,1) + +/* + * Decrypt a single cycle, consisting of two rounds. + * This avoids the swapping of the two halves. + * Parameter r is now the cycle number. + */ +#define DECRYPT_CYCLE( A, B, C, D, T0, T1, xkey, r ) \ + DECRYPT_RND( A,B,C,D,T0,T1,xkey,2*(r)+1 );\ + DECRYPT_RND( C,D,A,B,T0,T1,xkey,2*(r) ) + +/* Full 16-round decryption. */ +#define DECRYPT( A,B,C,D,T0,T1, xkey ) \ + DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 7 );\ + DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 6 );\ + DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 5 );\ + DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 4 );\ + DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 3 );\ + DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 2 );\ + DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 1 );\ + DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 0 ) + +/* + * A macro to read the state from the plaintext and do the initial key xors. + * The koff argument allows us to use the same macro + * for the decryption which uses different key words at the start. + */ +#define GET_INPUT( src, A,B,C,D, xkey, koff ) \ + A = GET32(src )^xkey->K[ koff]; B = GET32(src+ 4)^xkey->K[1+koff]; \ + C = GET32(src+ 8)^xkey->K[2+koff]; D = GET32(src+12)^xkey->K[3+koff] + +/* + * Similar macro to put the ciphertext in the output buffer. + * We xor the keys into the state variables before we use the PUT32 + * macro as the macro might use its argument multiple times. + */ +#define PUT_OUTPUT( A,B,C,D, dst, xkey, koff ) \ + A ^= xkey->K[ koff]; B ^= xkey->K[1+koff]; \ + C ^= xkey->K[2+koff]; D ^= xkey->K[3+koff]; \ + PUT32( A, dst ); PUT32( B, dst+ 4 ); \ + PUT32( C, dst+8 ); PUT32( D, dst+12 ) + + +/* + * Twofish block encryption + * + * Arguments: + * xkey expanded key array + * p 16 bytes of plaintext + * c 16 bytes in which to store the ciphertext + */ +void Twofish_encrypt( Twofish_key * xkey, Twofish_Byte p[16], Twofish_Byte c[16]) + { + Twofish_UInt32 A,B,C,D,T0,T1; /* Working variables */ + + /* Get the four plaintext words xorred with the key */ + GET_INPUT( p, A,B,C,D, xkey, 0 ); + + /* Do 8 cycles (= 16 rounds) */ + ENCRYPT( A,B,C,D,T0,T1,xkey ); + + /* Store them with the final swap and the output whitening. */ + PUT_OUTPUT( C,D,A,B, c, xkey, 4 ); + } + + +/* + * Twofish block decryption. + * + * Arguments: + * xkey expanded key array + * p 16 bytes of plaintext + * c 16 bytes in which to store the ciphertext + */ +void Twofish_decrypt( Twofish_key * xkey, Twofish_Byte c[16], Twofish_Byte p[16]) + { + Twofish_UInt32 A,B,C,D,T0,T1; /* Working variables */ + + /* Get the four plaintext words xorred with the key */ + GET_INPUT( c, A,B,C,D, xkey, 4 ); + + /* Do 8 cycles (= 16 rounds) */ + DECRYPT( A,B,C,D,T0,T1,xkey ); + + /* Store them with the final swap and the output whitening. */ + PUT_OUTPUT( C,D,A,B, p, xkey, 0 ); + } + +/* + * Using the macros it is easy to make special routines for + * CBC mode, CTR mode etc. The only thing you might want to + * add is a XOR_PUT_OUTPUT which xors the outputs into the + * destinationa instead of overwriting the data. This requires + * a XOR_PUT32 macro as well, but that should all be trivial. + * + * I thought about including routines for the separate cipher + * modes here, but it is unclear which modes should be included, + * and each encryption or decryption routine takes up a lot of code space. + * Also, I don't have any test vectors for any cipher modes + * with Twofish. + */ + + diff --git a/jni/libzrtp/sources/cryptcommon/twofish.h b/jni/libzrtp/sources/src/libzrtpcpp/crypto/twofish.h similarity index 97% rename from jni/libzrtp/sources/cryptcommon/twofish.h rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/twofish.h index 21d7e9634..0c8b0d71f 100755 --- a/jni/libzrtp/sources/cryptcommon/twofish.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/twofish.h @@ -1,265 +1,265 @@ -/* - * Fast, portable, and easy-to-use Twofish implementation, - * Version 0.3. - * Copyright (c) 2002 by Niels Ferguson. - * - * See the twofish.c file for the details of the how and why of this code. - * - * The author hereby grants a perpetual license to everybody to - * use this code for any purpose as long as the copyright message is included - * in the source code of this or any derived work. - */ - - -/* - * PLATFORM FIXES - * ============== - * - * The following definitions have to be fixed for each particular platform - * you work on. If you have a multi-platform program, you no doubt have - * portable definitions that you can substitute here without changing - * the rest of the code. - * - * The defaults provided here should work on most PC compilers. - */ - -#ifndef TWOFISH_H -#define TWOFISH_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * @file twofish.h - * @brief Function that provide basic Twofish crypto support - * - * @ingroup GNU_ZRTP - * @{ - */ - -/** - * A Twofish_Byte must be an unsigned 8-bit integer. - * - * It must also be the elementary data size of your C platform, - * i.e. sizeof( Twofish_Byte ) == 1. - */ -typedef unsigned char Twofish_Byte; - -/** - * A Twofish_UInt32 must be an unsigned integer of at least 32 bits. - * - * This type is used only internally in the implementation, so ideally it - * would not appear in the header file, but it is used inside the - * Twofish_key structure which means it has to be included here. - */ -typedef unsigned int Twofish_UInt32; - - -/* - * END OF PLATFORM FIXES - * ===================== - * - * You should not have to touch the rest of this file, but the code - * in twofish.c has a few things you need to fix too. - */ - -/** - * Return codes - */ -#define SUCCESS 1 -#define ERR_UINT32 -2 -#define ERR_BYTE -3 -#define ERR_GET32 -4 -#define ERR_PUT32 -5 -#define ERR_ROLR -6 -#define ERR_BSWAP -7 -#define ERR_SELECTB -8 -#define ERR_TEST_ENC -9 -#define ERR_TEST_DEC -10 -#define ERR_SEQ_ENC -11 -#define ERR_SEQ_DEC -12 -#define ERR_ODD_KEY -13 -#define ERR_INIT -14 -#define ERR_KEY_LEN -15 -#define ERR_ILL_ARG -16 - - -/** - * Structure that contains a prepared Twofish key. - * - * A cipher key is used in two stages. In the first stage it is converted - * form the original form to an internal representation. - * This internal form is then used to encrypt and decrypt data. - * This structure contains the internal form. It is rather large: 4256 bytes - * on a platform with 32-bit unsigned values. - * - * Treat this as an opague structure, and don't try to manipulate the - * elements in it. I wish I could hide the inside of the structure, - * but C doesn't allow that. - */ -typedef - struct - { - Twofish_UInt32 s[4][256]; /* pre-computed S-boxes */ - Twofish_UInt32 K[40]; /* Round key words */ - } - Twofish_key; - - -/** - * Initialise and test the Twofish implementation. - * - * This function MUST be called before any other function in the - * Twofish implementation is called. - * It only needs to be called once. - * - * Apart from initialising the implementation it performs a self test. - * If the Twofish_fatal function is not called, the code passed the test. - * (See the twofish.c file for details on the Twofish_fatal function.) - * - * @returns a negative number if an error happend, +1 otherwise - */ -extern int Twofish_initialise(); - - -/** - * Convert a cipher key to the internal form used for - * encryption and decryption. - * - * The cipher key is an array of bytes; the Twofish_Byte type is - * defined above to a type suitable on your platform. - * - * Any key must be converted to an internal form in the Twofisk_key structure - * before it can be used. - * The encryption and decryption functions only work with the internal form. - * The conversion to internal form need only be done once for each key value. - * - * Be sure to wipe all key storage, including the Twofish_key structure, - * once you are done with the key data. - * A simple memset( TwofishKey, 0, sizeof( TwofishKey ) ) will do just fine. - * - * Unlike most implementations, this one allows any key size from 0 bytes - * to 32 bytes. According to the Twofish specifications, - * irregular key sizes are handled by padding the key with zeroes at the end - * until the key size is 16, 24, or 32 bytes, whichever - * comes first. Note that each key of irregular size is equivalent to exactly - * one key of 16, 24, or 32 bytes. - * - * WARNING: Short keys have low entropy, and result in low security. - * Anything less than 8 bytes is utterly insecure. For good security - * use at least 16 bytes. I prefer to use 32-byte keys to prevent - * any collision attacks on the key. - * - * The key length argument key_len must be in the proper range. - * If key_len is not in the range 0,...,32 this routine attempts to generate - * a fatal error (depending on the code environment), - * and at best (or worst) returns without having done anything. - * - * @param key Array of key bytes - * @param key_len Number of key bytes, must be in the range 0,1,...,32. - * @param xkey Pointer to an Twofish_key structure that will be filled - * with the internal form of the cipher key. - * @returns a negative number if an error happend, +1 otherwise - */ -extern int Twofish_prepare_key( - Twofish_Byte key[], - int key_len, - Twofish_key * xkey - ); - - -/** - * Encrypt a single block of data. - * - * This function encrypts a single block of 16 bytes of data. - * If you want to encrypt a larger or variable-length message, - * you will have to use a cipher mode, such as CBC or CTR. - * These are outside the scope of this implementation. - * - * The xkey structure is not modified by this routine, and can be - * used for further encryption and decryption operations. - * - * @param xkey pointer to Twofish_key, internal form of the key - * produces by Twofish_prepare_key() - * @param p Plaintext to be encrypted - * @param c Place to store the ciphertext - */ -extern void Twofish_encrypt( - Twofish_key * xkey, - Twofish_Byte p[16], - Twofish_Byte c[16] - ); - - -/** - * Decrypt a single block of data. - * - * This function decrypts a single block of 16 bytes of data. - * If you want to decrypt a larger or variable-length message, - * you will have to use a cipher mode, such as CBC or CTR. - * These are outside the scope of this implementation. - * - * The xkey structure is not modified by this routine, and can be - * used for further encryption and decryption operations. - * - * @param xkey pointer to Twofish_key, internal form of the key - * produces by Twofish_prepare_key() - * @param c Ciphertext to be decrypted - * @param p Place to store the plaintext - */ -extern void Twofish_decrypt( - Twofish_key * xkey, - Twofish_Byte c[16], - Twofish_Byte p[16] - ); - - -/** - * Encrypt data in CFB mode. - * - * This function encrypts data in CFB mode. - * - * The key structure is not modified by this routine, and can be - * used for further encryption and decryption operations. - * - * @param keyCtx pointer to Twofish_key, internal form of the key - * produced by Twofish_prepare_key() - * @param in Plaintext to be encrypted - * @param out Place to store the ciphertext - * @param len number of bytes to encrypt. - * @param ivec initialization vector for this CFB mode encryption. - * @param num pointer to integer that holds number of available crypto bytes. - */ -void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in, - Twofish_Byte* out, size_t len, - Twofish_Byte* ivec, int *num); - -/** - * Decrypt data in CFB mode. - * - * This function decrypts data in CFB. - * - * The key structure is not modified by this routine, and can be - * used for further encryption and decryption operations. - * - * @param keyCtx pointer to Twofish_key, internal form of the key - * produced by Twofish_prepare_key() - * @param in Ciphertext to be decrypted - * @param out Place to store the plaintext - * @param len number of bytes to decrypt. - * @param ivec initialization vector for this CFB mode encryption. - * @param num pointer to integer that holds number of available crypto bytes. - */ -void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in, - Twofish_Byte* out, size_t len, - Twofish_Byte* ivec, int *num); -/** - * @} - */ -#ifdef __cplusplus -} -#endif - -#endif +/* + * Fast, portable, and easy-to-use Twofish implementation, + * Version 0.3. + * Copyright (c) 2002 by Niels Ferguson. + * + * See the twofish.c file for the details of the how and why of this code. + * + * The author hereby grants a perpetual license to everybody to + * use this code for any purpose as long as the copyright message is included + * in the source code of this or any derived work. + */ + + +/* + * PLATFORM FIXES + * ============== + * + * The following definitions have to be fixed for each particular platform + * you work on. If you have a multi-platform program, you no doubt have + * portable definitions that you can substitute here without changing + * the rest of the code. + * + * The defaults provided here should work on most PC compilers. + */ + +#ifndef TWOFISH_H +#define TWOFISH_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @file twofish.h + * @brief Function that provide basic Twofish crypto support + * + * @ingroup GNU_ZRTP + * @{ + */ + +/** + * A Twofish_Byte must be an unsigned 8-bit integer. + * + * It must also be the elementary data size of your C platform, + * i.e. sizeof( Twofish_Byte ) == 1. + */ +typedef unsigned char Twofish_Byte; + +/** + * A Twofish_UInt32 must be an unsigned integer of at least 32 bits. + * + * This type is used only internally in the implementation, so ideally it + * would not appear in the header file, but it is used inside the + * Twofish_key structure which means it has to be included here. + */ +typedef unsigned int Twofish_UInt32; + + +/* + * END OF PLATFORM FIXES + * ===================== + * + * You should not have to touch the rest of this file, but the code + * in twofish.c has a few things you need to fix too. + */ + +/** + * Return codes + */ +#define SUCCESS 1 +#define ERR_UINT32 -2 +#define ERR_BYTE -3 +#define ERR_GET32 -4 +#define ERR_PUT32 -5 +#define ERR_ROLR -6 +#define ERR_BSWAP -7 +#define ERR_SELECTB -8 +#define ERR_TEST_ENC -9 +#define ERR_TEST_DEC -10 +#define ERR_SEQ_ENC -11 +#define ERR_SEQ_DEC -12 +#define ERR_ODD_KEY -13 +#define ERR_INIT -14 +#define ERR_KEY_LEN -15 +#define ERR_ILL_ARG -16 + + +/** + * Structure that contains a prepared Twofish key. + * + * A cipher key is used in two stages. In the first stage it is converted + * form the original form to an internal representation. + * This internal form is then used to encrypt and decrypt data. + * This structure contains the internal form. It is rather large: 4256 bytes + * on a platform with 32-bit unsigned values. + * + * Treat this as an opague structure, and don't try to manipulate the + * elements in it. I wish I could hide the inside of the structure, + * but C doesn't allow that. + */ +typedef + struct + { + Twofish_UInt32 s[4][256]; /* pre-computed S-boxes */ + Twofish_UInt32 K[40]; /* Round key words */ + } + Twofish_key; + + +/** + * Initialise and test the Twofish implementation. + * + * This function MUST be called before any other function in the + * Twofish implementation is called. + * It only needs to be called once. + * + * Apart from initialising the implementation it performs a self test. + * If the Twofish_fatal function is not called, the code passed the test. + * (See the twofish.c file for details on the Twofish_fatal function.) + * + * @returns a negative number if an error happend, +1 otherwise + */ +extern int Twofish_initialise(); + + +/** + * Convert a cipher key to the internal form used for + * encryption and decryption. + * + * The cipher key is an array of bytes; the Twofish_Byte type is + * defined above to a type suitable on your platform. + * + * Any key must be converted to an internal form in the Twofisk_key structure + * before it can be used. + * The encryption and decryption functions only work with the internal form. + * The conversion to internal form need only be done once for each key value. + * + * Be sure to wipe all key storage, including the Twofish_key structure, + * once you are done with the key data. + * A simple memset( TwofishKey, 0, sizeof( TwofishKey ) ) will do just fine. + * + * Unlike most implementations, this one allows any key size from 0 bytes + * to 32 bytes. According to the Twofish specifications, + * irregular key sizes are handled by padding the key with zeroes at the end + * until the key size is 16, 24, or 32 bytes, whichever + * comes first. Note that each key of irregular size is equivalent to exactly + * one key of 16, 24, or 32 bytes. + * + * WARNING: Short keys have low entropy, and result in low security. + * Anything less than 8 bytes is utterly insecure. For good security + * use at least 16 bytes. I prefer to use 32-byte keys to prevent + * any collision attacks on the key. + * + * The key length argument key_len must be in the proper range. + * If key_len is not in the range 0,...,32 this routine attempts to generate + * a fatal error (depending on the code environment), + * and at best (or worst) returns without having done anything. + * + * @param key Array of key bytes + * @param key_len Number of key bytes, must be in the range 0,1,...,32. + * @param xkey Pointer to an Twofish_key structure that will be filled + * with the internal form of the cipher key. + * @returns a negative number if an error happend, +1 otherwise + */ +extern int Twofish_prepare_key( + Twofish_Byte key[], + int key_len, + Twofish_key * xkey + ); + + +/** + * Encrypt a single block of data. + * + * This function encrypts a single block of 16 bytes of data. + * If you want to encrypt a larger or variable-length message, + * you will have to use a cipher mode, such as CBC or CTR. + * These are outside the scope of this implementation. + * + * The xkey structure is not modified by this routine, and can be + * used for further encryption and decryption operations. + * + * @param xkey pointer to Twofish_key, internal form of the key + * produces by Twofish_prepare_key() + * @param p Plaintext to be encrypted + * @param c Place to store the ciphertext + */ +extern void Twofish_encrypt( + Twofish_key * xkey, + Twofish_Byte p[16], + Twofish_Byte c[16] + ); + + +/** + * Decrypt a single block of data. + * + * This function decrypts a single block of 16 bytes of data. + * If you want to decrypt a larger or variable-length message, + * you will have to use a cipher mode, such as CBC or CTR. + * These are outside the scope of this implementation. + * + * The xkey structure is not modified by this routine, and can be + * used for further encryption and decryption operations. + * + * @param xkey pointer to Twofish_key, internal form of the key + * produces by Twofish_prepare_key() + * @param c Ciphertext to be decrypted + * @param p Place to store the plaintext + */ +extern void Twofish_decrypt( + Twofish_key * xkey, + Twofish_Byte c[16], + Twofish_Byte p[16] + ); + + +/** + * Encrypt data in CFB mode. + * + * This function encrypts data in CFB mode. + * + * The key structure is not modified by this routine, and can be + * used for further encryption and decryption operations. + * + * @param keyCtx pointer to Twofish_key, internal form of the key + * produced by Twofish_prepare_key() + * @param in Plaintext to be encrypted + * @param out Place to store the ciphertext + * @param len number of bytes to encrypt. + * @param ivec initialization vector for this CFB mode encryption. + * @param num pointer to integer that holds number of available crypto bytes. + */ +void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in, + Twofish_Byte* out, size_t len, + Twofish_Byte* ivec, int *num); + +/** + * Decrypt data in CFB mode. + * + * This function decrypts data in CFB. + * + * The key structure is not modified by this routine, and can be + * used for further encryption and decryption operations. + * + * @param keyCtx pointer to Twofish_key, internal form of the key + * produced by Twofish_prepare_key() + * @param in Ciphertext to be decrypted + * @param out Place to store the plaintext + * @param len number of bytes to decrypt. + * @param ivec initialization vector for this CFB mode encryption. + * @param num pointer to integer that holds number of available crypto bytes. + */ +void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in, + Twofish_Byte* out, size_t len, + Twofish_Byte* ivec, int *num); +/** + * @} + */ +#ifdef __cplusplus +} +#endif + +#endif diff --git a/jni/libzrtp/sources/cryptcommon/twofish_cfb.c b/jni/libzrtp/sources/src/libzrtpcpp/crypto/twofish_cfb.c similarity index 66% rename from jni/libzrtp/sources/cryptcommon/twofish_cfb.c rename to jni/libzrtp/sources/src/libzrtpcpp/crypto/twofish_cfb.c index 241b95608..75407387d 100755 --- a/jni/libzrtp/sources/cryptcommon/twofish_cfb.c +++ b/jni/libzrtp/sources/src/libzrtpcpp/crypto/twofish_cfb.c @@ -1,94 +1,82 @@ -#include <stdint.h> -#include <stdlib.h> - -#include "twofish.h" - -void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in, - Twofish_Byte* out, size_t len, - Twofish_Byte* ivec, int32_t *num) -{ - uint32_t n; - - n = *num; - - do { - while (n && len) { - *(out++) = ivec[n] ^= *(in++); - --len; - n = (n+1) % 16; - } - while (len>=16) { - Twofish_encrypt(keyCtx, ivec, ivec); - for (n=0; n<16; n+=sizeof(size_t)) { - -/* - * Some GCC version(s) of Android's NDK produce code that leads to a crash (SIGBUS). The - * offending line if the line that produces the output by xor'ing the ivec. Somehow the - * compiler/optimizer seems to incorrectly setup the pointers. Adding a call to an - * external function that uses the pointer disabled or modifies this optimzing - * behaviour. This debug functions as such does nothing, it just disables some - * optimization. Don't use a local (static) function - the compiler sees that it does - * nothing and optimizes again :-) . - */ -#ifdef ANDROID - Two_debugDummy(in, out, ivec); -#endif - *(size_t*)(out+n) = *(size_t*)(ivec+n) ^= *(size_t*)(in+n);; - } - len -= 16; - out += 16; - in += 16; - } - n = 0; - if (len) { - Twofish_encrypt(keyCtx, ivec, ivec); - while (len--) { - out[n] = ivec[n] ^= in[n]; - ++n; - } - } - *num = n; - return; - } while (0); -} - - -void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in, - Twofish_Byte* out, size_t len, - Twofish_Byte* ivec, int32_t *num) -{ - uint32_t n; - - n = *num; - - do { - while (n && len) { - unsigned char c; - *(out++) = ivec[n] ^ (c = *(in++)); ivec[n] = c; - --len; - n = (n+1) % 16; - } - while (len>=16) { - Twofish_encrypt(keyCtx, ivec, ivec); - for (n=0; n<16; n+=sizeof(size_t)) { - size_t t = *(size_t*)(in+n); - *(size_t*)(out+n) = *(size_t*)(ivec+n) ^ t; - *(size_t*)(ivec+n) = t; - } - len -= 16; - out += 16; - in += 16; - } - n = 0; - if (len) { - Twofish_encrypt(keyCtx, ivec, ivec); - while (len--) { - unsigned char c; - out[n] = ivec[n] ^ (c = in[n]); ivec[n] = c; - ++n; - } - } - *num = n; - return; - } while (0); -} +#include <stdint.h> +#include <stdlib.h> + +#include "twofish.h" + +void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in, + Twofish_Byte* out, size_t len, + Twofish_Byte* ivec, int32_t *num) +{ + uint32_t n; + + n = *num; + + do { + while (n && len) { + *(out++) = ivec[n] ^= *(in++); + --len; + n = (n+1) % 16; + } + while (len>=16) { + Twofish_encrypt(keyCtx, ivec, ivec); + for (n=0; n<16; n+=sizeof(size_t)) { + *(size_t*)(out+n) = + *(size_t*)(ivec+n) ^= *(size_t*)(in+n); + } + len -= 16; + out += 16; + in += 16; + } + n = 0; + if (len) { + Twofish_encrypt(keyCtx, ivec, ivec); + while (len--) { + out[n] = ivec[n] ^= in[n]; + ++n; + } + } + *num = n; + return; + } while (0); +} + + +void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in, + Twofish_Byte* out, size_t len, + Twofish_Byte* ivec, int32_t *num) +{ + uint32_t n; + + n = *num; + + do { + while (n && len) { + unsigned char c; + *(out++) = ivec[n] ^ (c = *(in++)); ivec[n] = c; + --len; + n = (n+1) % 16; + } + while (len>=16) { + Twofish_encrypt(keyCtx, ivec, ivec); + for (n=0; n<16; n+=sizeof(size_t)) { + size_t t = *(size_t*)(in+n); + *(size_t*)(out+n) = *(size_t*)(ivec+n) ^ t; + *(size_t*)(ivec+n) = t; + } + len -= 16; + out += 16; + in += 16; + } + n = 0; + if (len) { + Twofish_encrypt(keyCtx, ivec, ivec); + while (len--) { + unsigned char c; + out[n] = ivec[n] ^ (c = in[n]); ivec[n] = c; + ++n; + } + } + *num = n; + return; + } while (0); +} diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpPacket.h b/jni/libzrtp/sources/src/libzrtpcpp/zrtpPacket.h similarity index 98% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpPacket.h rename to jni/libzrtp/sources/src/libzrtpcpp/zrtpPacket.h index f01fb52b5..18ba7a12a 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpPacket.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/zrtpPacket.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpccrtp.h b/jni/libzrtp/sources/src/libzrtpcpp/zrtpccrtp.h similarity index 98% rename from jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpccrtp.h rename to jni/libzrtp/sources/src/libzrtpcpp/zrtpccrtp.h index 3eae18325..d94ca5a2f 100644 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpccrtp.h +++ b/jni/libzrtp/sources/src/libzrtpcpp/zrtpccrtp.h @@ -19,7 +19,7 @@ #define _ZRTPCCRTP_H_ #include <ccrtp/rtp.h> -#include <ZrtpQueue.h> +#include <libzrtpcpp/ZrtpQueue.h> NAMESPACE_COMMONCPP diff --git a/jni/libzrtp/sources/srtp/CryptoContext.cpp b/jni/libzrtp/sources/srtp/CryptoContext.cpp index 89eb699d7..d486f86c7 100644 --- a/jni/libzrtp/sources/srtp/CryptoContext.cpp +++ b/jni/libzrtp/sources/srtp/CryptoContext.cpp @@ -1,6 +1,4 @@ /* - Copyright (C) 2006 - 2012 Werner Dittmann - This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -16,20 +14,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - * @author Werner Dittmann <Werner.Dittmann@t-online.de> +/* Copyright (C) 2004-2012 + * + * Authors: Israel Abad <i_abad@terra.es> + * Erik Eliasson <eliasson@it.kth.se> + * Johan Bilien <jobi@via.ecp.fr> + * Joachim Orrblad <joachim@orrblad.com> + * Werner Dittmann <Werner.Dittmann@t-online.de> */ #include <string.h> +#include <arpa/inet.h> #include <stdio.h> -#include <stdint.h> - -#include <common/osSpecifics.h> #include <CryptoContext.h> -#include <crypto/SrtpSymCrypto.h> #include <crypto/hmac.h> -#include <cryptcommon/macSkein.h> +#include <crypto/macSkein.h> CryptoContext::CryptoContext( uint32_t ssrc, int32_t roc, @@ -45,10 +45,11 @@ CryptoContext::CryptoContext( uint32_t ssrc, int32_t skeyl, int32_t tagLength): - ssrcCtx(ssrc),using_mki(false),mkiLength(0),mki(NULL), roc(roc),guessed_roc(0), - s_l(0),key_deriv_rate(key_deriv_rate), replay_window(0), master_key_srtp_use_nb(0), - master_key_srtcp_use_nb(0), labelBase(0), seqNumSet(false), macCtx(NULL), cipher(NULL), - f8Cipher(NULL) + ssrcCtx(ssrc),using_mki(false),mkiLength(0),mki(NULL), + roc(roc),guessed_roc(0),s_l(0),key_deriv_rate(key_deriv_rate), + replay_window(0), + master_key_srtp_use_nb(0), master_key_srtcp_use_nb(0), seqNumSet(false), + macCtx(NULL), cipher(NULL), f8Cipher(NULL) { this->ealg = ealg; this->aalg = aalg; @@ -188,7 +189,7 @@ void CryptoContext::srtpEncrypt(uint8_t* pkt, uint8_t* payload, uint32_t paylen, iv[i] = (0xFF & (ssrc >> ((7-i)*8))) ^ k_s[i]; } for (i = 8; i < 14; i++ ) { - iv[i] = (0xFF & (unsigned char)(index >> ((13-i)*8) ) ) ^ k_s[i]; + iv[i] = (0xFF & (unsigned char)( index >> ((13-i)*8) ) ) ^ k_s[i]; } iv[14] = iv[15] = 0; @@ -212,7 +213,7 @@ void CryptoContext::srtpEncrypt(uint8_t* pkt, uint8_t* payload, uint32_t paylen, iv[0] = 0; // set ROC in network order into IV - ui32p[3] = zrtpHtonl(roc); + ui32p[3] = htonl(roc); cipher->f8_encrypt(payload, paylen, iv, f8Cipher); } @@ -230,7 +231,7 @@ void CryptoContext::srtpAuthenticate(uint8_t* pkt, uint32_t pktlen, uint32_t roc unsigned char temp[20]; const unsigned char* chunks[3]; unsigned int chunkLength[3]; - uint32_t beRoc = zrtpHtonl(roc); + uint32_t beRoc = htonl(roc); chunks[0] = pkt; chunkLength[0] = pktlen; @@ -288,8 +289,10 @@ static void computeIv(unsigned char* iv, uint64_t label, uint64_t index, } for (i = 7; i < 14 ; i++ ) { - iv[i] = (unsigned char)(0xFF & (key_id >> (8*(13-i)))) ^ master_salt[i]; + iv[i] = (unsigned char)(0xFF & (key_id >> (8*(13-i)))) ^ + master_salt[i]; } + iv[14] = iv[15] = 0; } @@ -298,17 +301,17 @@ void CryptoContext::deriveSrtpKeys(uint64_t index) { uint8_t iv[16]; - // prepare cipher to compute derived keys. + // prepare AES cipher to compute derived keys. cipher->setNewKey(master_key, master_key_length); memset(master_key, 0, master_key_length); // compute the session encryption key - uint64_t label = labelBase + 0; + uint64_t label = 0; computeIv(iv, label, index, key_deriv_rate, master_salt); cipher->get_ctr_cipher_stream(k_e, n_e, iv); // compute the session authentication key - label = labelBase + 0x01; + label = 0x01; computeIv(iv, label, index, key_deriv_rate, master_salt); cipher->get_ctr_cipher_stream(k_a, n_a, iv); @@ -325,12 +328,12 @@ void CryptoContext::deriveSrtpKeys(uint64_t index) memset(k_a, 0, n_a); // compute the session salt - label = labelBase + 0x02; + label = 0x02; computeIv(iv, label, index, key_deriv_rate, master_salt); cipher->get_ctr_cipher_stream(k_s, n_s, iv); memset(master_salt, 0, master_salt_length); - // as last step prepare cipher with derived key. + // as last step prepare AES cipher with derived key. cipher->setNewKey(k_e, n_e); if (f8Cipher != NULL) cipher->f8_deriveForIV(f8Cipher, k_e, n_e, k_s, n_s); @@ -388,18 +391,22 @@ bool CryptoContext::checkReplay( uint16_t new_seq_nb ) int64_t delta = guessed_index - local_index; if (delta > 0) { - return true; /* Packet not yet received*/ + /* Packet not yet received*/ + return true; } else { - if ( -delta >= REPLAY_WINDOW_SIZE ) { - return false; /* Packet too old */ + if ( -delta > REPLAY_WINDOW_SIZE ) { + /* Packet too old */ + return false; } else { if ((replay_window >> (-delta)) & 0x1) { - return false; /* Packet already received ! */ + /* Packet already received ! */ + return false; } else { - return true; /* Packet not yet received */ + /* Packet not yet received */ + return true; } } } @@ -447,3 +454,12 @@ CryptoContext* CryptoContext::newCryptoContextForSSRC(uint32_t ssrc, int roc, in return pcc; } + +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ + diff --git a/jni/libzrtp/sources/srtp/CryptoContext.h b/jni/libzrtp/sources/srtp/CryptoContext.h index 25c3a08fc..3075bf5ca 100644 --- a/jni/libzrtp/sources/srtp/CryptoContext.h +++ b/jni/libzrtp/sources/srtp/CryptoContext.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2006 - 2012 Werner Dittmann + Copyright (C) 2004-2006 the Minisip Team This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,6 +16,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + #ifndef CRYPTOCONTEXT_H #define CRYPTOCONTEXT_H @@ -38,21 +40,21 @@ const int SrtpEncryptionAESF8 = 2; const int SrtpEncryptionTWOCM = 3; const int SrtpEncryptionTWOF8 = 4; -// Check if included via CryptoContextCtrl.cpp - avoid double definitions #ifndef CRYPTOCONTEXTCTRL_H #include <stdint.h> +#include <crypto/SrtpSymCrypto.h> class SrtpSymCrypto; /** - * @brief Implementation for a SRTP cryptographic context. + * The implementation for a SRTP cryptographic context. * * This class holds data and provides functions that implement a - * cryptographic context for SRTP. Refer to RFC 3711, chapter 3.2 for some + * cryptographic context for SRTP, Refer to RFC 3711, chapter 3.2 for some * more detailed information about the SRTP cryptographic context. * - * Each SRTP cryptographic context uses a RTP source identified by + * Each SRTP cryptographic context maintains a RTP source identified by * its SSRC. Thus you can independently protect each source inside a RTP * session. * @@ -60,93 +62,35 @@ class SrtpSymCrypto; * cryptographic context, such as master key, key length, authentication * length and so on. The key management mechanisms are not part of * SRTP. Refer to MIKEY (RFC 3880) or to Phil Zimmermann's ZRTP protocol - * (RFC6189). After key management negotiated the data the application can - * setup the SRTP cryptographic context and enable SRTP processing. - * - * This SRTP context implementation supports RTP only. - * - * A short eample how to setup a SRTP CryptoContext: - @verbatim - - // First some key and salt data - this data is just for demo purposes - uint8 masterKey[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; - - uint8 masterSalt[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d }; - - ... - - CryptoContext* cryptoCtxSend = - new CryptoContext(0xfeedbacc, - 0, // roc, - 0L, // keyderivation rate << 48, - SrtpEncryptionAESCM, // encryption algo - SrtpAuthenticationSha1Hmac, // authtication algo - masterKey, // Master Key data - 128 / 8, // Master Key length in bytes - masterSalt, // Master Salt data - 112 / 8, // Master Salt length in bytes - 128 / 8, // encryption keylength in bytes - 160 / 8, // authentication key length in bytes (SHA1) - 112 / 8, // session salt length in bytes - 80 / 8); // authentication tag length in bytes - - cryptoCtxSend->deriveSrtpKeys(0); - - .... - - // To protect a RTP packet - // buffer: pointer to the RTP packet, length of the RTP data, newLength is a - // pointer to a size_t that gets the updated length. - bool rc = SrtpHandler::protect(cryptoCtxSend, buffer, length, newLength); - - // To unprotect a SRTP packet: - // buffer: pointer to the RTP packet, length of the SRTP data, newLength is a - // pointer to a size_t that gets the updated length. - int32_t rc = SrtpHandler::unprotect(cryptoCtxRecv, buffer, length, newLength); - - @endverbatim - * - * @note You need two CryptoContext instances - one for the sending channel the - * other one for the receiving channel. - * - * Before an appliction can use a CryptoContext it must call the key derivation - * function deriveSrtpKeys() first. Only then this SRTP cryptographic context is ready - * to protect or unprotect a RTP SSRC stream. + * (draft-zimmermann-avt-zrtp-01). After key management negotiated the + * data the application can setup the SRTP cryptographic context and + * enable SRTP processing. * - * Together with the newCryptoContextForSSRC() function an application can prepare a - * CryptoContext and save it as template. Once it needs a new CryptoContext, say - * for a new SSRC, it calls newCryptoContextForSSRC() on the saved context to get an - * initialized copy and then call deriveSrtpKeys() to compute and process the keys. + * Currently this implementation supports RTP only, not RTCP. * - * @note A saved, pre-initialized template contains the non-processed keys. Only - * the method deriveSrtpKeys() processes the keys and cleares them. Thus don't store - * CryptoContext templates if the application cannot protect the templates against - * reading from other possibly rogue applications. - * - * @sa SrtpHandler - * + * @author Israel Abad <i_abad@terra.es> + * @author Erik Eliasson <eliasson@it.kth.se> + * @author Johan Bilien <jobi@via.ecp.fr> + * @author Joachim Orrblad <joachim@orrblad.com> * @author Werner Dittmann <Werner.Dittmann@t-online.de> */ + class CryptoContext { public: /** - * @brief Constructor for an active SRTP cryptographic context. - * - * This constructor creates an pre-initialized SRTP cryptographic context were - * algorithms are allocated, keys are stored and so on. An application can - * call newCryptoContextForSSRC() to get a full copy of this pre-initialized - * CryptoContext. + * Constructor for an active SRTP cryptographic context. * + * This constructor creates an active SRTP cryptographic context were + * algorithms are enabled, keys are computed and so on. This SRTP + * cryptographic context can protect a RTP SSRC stream. * * @param ssrc - * The RTP SSRC that this SRTP cryptographic context belongs to. + * The RTP SSRC that this SRTP cryptographic context protects. * * @param roc * The initial Roll-Over-Counter according to RFC 3711. These are the - * upper 32 bit of the overall 48 bit SRTP packet index. Usually set to zero. - * Refer to chapter 3.2.1 of the RFC. + * upper 32 bit of the overall 48 bit SRTP packet index. Refer to + * chapter 3.2.1 of the RFC. * * @param keyDerivRate * The key derivation rate defines when to recompute the SRTP session @@ -154,14 +98,15 @@ public: * * @param ealg * The encryption algorithm to use. Possible values are <code> - * SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8, - * SrtpEncryptionTWOCM, SrtpEncryptionTWOF8</code>. See chapter 4.1.1 - * for AESCM (Counter mode) and 4.1.2 for AES F8 mode. + * SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8 + * </code>. See chapter 4.1.1 for AESCM (Counter mode) and 4.1.2 + * for AES F8 mode. * * @param aalg * The authentication algorithm to use. Possible values are <code> - * SrtpEncryptionNull, SrtpAuthenticationSha1Hmac, SrtpAuthenticationSkeinHmac - * </code>. + * SrtpEncryptionNull, SrtpAuthenticationSha1Hmac</code>. The only + * active algorithm here is SHA1 HMAC, a SHA1 based hashed message + * authentication code as defined in RFC 2104. * * @param masterKey * Pointer to the master key for this SRTP cryptographic context. @@ -175,26 +120,27 @@ public: * bytes (128 or 256 bit master key) * * @param masterSalt - * SRTP uses the master salt to generate the initialization vector + * SRTP uses the master salt to computer the initialization vector * that in turn is input to compute the session key, session * authentication key and the session salt. * * @param masterSaltLength - * The length in bytes of the master salt data in bytes. According to - * RFC3711 the standard value for the master salt length should - * be 14 bytes (112 bit). + * The length in bytes of the master salt data in bytes. SRTP uses + * AES as encryption algorithm. AES encrypts 16 byte blocks + * (independent of the key length). According to RFC3711 the standard + * value for the master salt length should be 112 bit (14 bytes). * * @param ekeyl * The length in bytes of the session encryption key that SRTP shall - * generate and use. Usually the same length as for the master key - * length, however you may use a different length as well. + * compute and use. Usually the same length as for the master key + * length. But you may use a different length as well. Be carefull + * that the key management mechanisms supports different key lengths. * * @param akeyl * The length in bytes of the session authentication key. SRTP * computes this key and uses it as input to the authentication * algorithm. - * This is usually 160 bits (20 bytes) for @c SrtpAuthenticationSha1Hmac - * and 256 bits (32 bytes) for @c SrtpAuthenticationSkeinHmac. + * The standard value is 160 bits (20 bytes). * * @param skeyl * The length in bytes of the session salt. SRTP computes this salt @@ -203,11 +149,9 @@ public: * * @param tagLength * The length is bytes of the authentication tag that SRTP appends - * to the RTP packet. The @c CryptoContext supports @c SrtpAuthenticationSha1Hmac - * with 4 and 10 byte (32 and 80 bits) and @c SrtpAuthenticationSkeinHmac - * with 4 and 8 bytes (32 and 64 bits) tag length. Refer to chapter 4.2. in RFC 3711. + * to the RTP packet. Refer to chapter 4.2. in the RFC 3711. */ - CryptoContext(uint32_t ssrc, int32_t roc, + CryptoContext( uint32_t ssrc, int32_t roc, int64_t keyDerivRate, const int32_t ealg, const int32_t aalg, @@ -218,17 +162,16 @@ public: int32_t ekeyl, int32_t akeyl, int32_t skeyl, - int32_t tagLength); - + int32_t tagLength ); /** - * @brief Destructor. + * Destructor. * * Cleans the SRTP cryptographic context. */ ~CryptoContext(); /** - * @brief Set the Roll-Over-Counter. + * Set the Roll-Over-Counter. * * Ths method sets the upper 32 bit of the 48 bit SRTP packet index * (the roll-over-part) @@ -236,20 +179,28 @@ public: * @param r * The roll-over-counter */ - inline void setRoc(uint32_t r) { roc = r; } + inline void + setRoc(uint32_t r) + { + roc = r; + } /** - * @brief Get the Roll-Over-Counter. + * Get the Roll-Over-Counter. * * Ths method get the upper 32 bit of the 48 bit SRTP packet index * (the roll-over-part) * * @return The roll-over-counter */ - inline uint32_t getRoc() const { return roc; } + inline uint32_t + getRoc() const + { + return roc; + } /** - * @brief Perform SRTP encryption. + * Perform SRTP encryption. * * This method encrypts <em>and</em> decrypts SRTP payload data. Plain * data gets encrypted, encrypted data get decrypted. @@ -270,10 +221,10 @@ public: * @param ssrc * The RTP SSRC data in <em>host</em> order. */ - void srtpEncrypt(uint8_t* pkt, uint8_t* payload, uint32_t paylen, uint64_t index, uint32_t ssrc); + void srtpEncrypt(uint8_t* pkt, uint8_t* payload, uint32_t paylen, uint64_t index, uint32_t ssrc ); /** - * @brief Compute the authentication tag. + * Compute the authentication tag. * * Compute the authentication tag according the the paramters in the * SRTP Cryptograhic context. @@ -291,26 +242,23 @@ public: * Points to a buffer that hold the computed tag. This buffer must * be able to hold <code>tagLength</code> bytes. */ - void srtpAuthenticate(uint8_t* pkt, uint32_t pktlen, uint32_t roc, uint8_t* tag); + void srtpAuthenticate(uint8_t* pkt, uint32_t pktlen, uint32_t roc, uint8_t* tag ); /** - * @brief Perform key derivation according to SRTP specification + * Perform key derivation according to SRTP specification * * This method computes the session key, session authentication key and the * session salt key. This method must be called at least once after the * SRTP Cryptograhic context was set up. * - * This method clears the key data once it was processed by the encryptions' - * set key functions. - * * @param index * The 48 bit SRTP packet index. See the <code>guessIndex</code> - * method. Usually 0. + * method. */ void deriveSrtpKeys(uint64_t index); /** - * @brief Compute (guess) the new SRTP index based on the sequence number of + * Compute (guess) the new SRTP index based on the sequence number of * a received RTP packet. * * The method uses the algorithm show in RFC3711, Appendix A, to compute @@ -324,7 +272,7 @@ public: uint64_t guessIndex(uint16_t newSeqNumber); /** - * @brief Check for packet replay. + * Check for packet replay. * * The method check if a received packet is either to old or was already * received. @@ -341,7 +289,7 @@ public: bool checkReplay(uint16_t newSeqNumber); /** - * @brief Update the SRTP packet index. + * Update the SRTP packet index. * * Call this method after all checks were successful. See chapter * 3.3.1 in the RFC when to update the ROC and ROC processing. @@ -349,67 +297,64 @@ public: * @param newSeqNumber * The sequence number of the received RTP packet in host order. */ - void update(uint16_t newSeqNumber); + void update( uint16_t newSeqNumber ); /** - * @brief Get the length of the SRTP authentication tag in bytes. + * Get the length of the SRTP authentication tag in bytes. * * @return the length of the authentication tag. */ - int32_t getTagLength() const { return tagLength; } + inline int32_t + getTagLength() const + { + return tagLength; + } + /** - * @brief Get the length of the MKI in bytes. + * Get the length of the MKI in bytes. * * @return the length of the MKI. */ - int32_t getMkiLength() const { return mkiLength; } + inline int32_t + getMkiLength() const + { + return mkiLength; + } /** - * @brief Get the SSRC of this SRTP Cryptograhic context. + * Get the SSRC of this SRTP Cryptograhic context. * * @return the SSRC. */ - uint32_t getSsrc() const { return ssrcCtx; } + inline uint32_t + getSsrc() const + { + return ssrcCtx; + } /** - * @brief Set the start (base) number to compute the PRF labels. - * - * Refer to RFC3711, chapters 4.3.1 and 4.3.2 about values for labels. - * CryptoContext computes the labes as follows: - * - * - labelBase + 0 -> encryption label - * - labelBase + 1 -> authentication label - * - labelBase + 2 -> salting key label - * - * The CryptoContext constructor initializes CryptoContext::labelBase - * with 0 to comply with RFC 3711 label values. - * - * Applications may set the #labelBase to other values to use the CryptoContext - * for other purposes. - */ - void setLabelbase(uint8_t base) { labelBase = base; } - - /** - * @brief Derive a new Crypto Context for use with a new SSRC + * Derive a new Crypto Context for use with a new SSRC * * This method returns a new Crypto Context initialized with the data * of this crypto context. Replacing the SSRC, Roll-over-Counter, and - * the key derivation rate the application can use this Crypto Context + * the key derivation rate the application cab use this Crypto Context * to encrypt / decrypt a new stream (Synchronization source) inside * one RTP session. * - * Before the application can use this crypto context it must call deriveSrtpKeys(). + * Before the application can use this crypto context it must call + * the <code>deriveSrtpKeys</code> method. * * @param ssrc * The SSRC for this context * @param roc - * The Roll-Over-Counter for this context, usually 0 + * The Roll-Over-Counter for this context * @param keyDerivRate - * The key derivation rate for this context, usally 0 + * The key derivation rate for this context * @return * a new CryptoContext with all relevant data set. */ + CryptoContext* newCryptoContextForSSRC(uint32_t ssrc, int roc, int64_t keyDerivRate); private: @@ -448,7 +393,6 @@ private: int32_t akeyl; int32_t skeyl; int32_t tagLength; - uint8_t labelBase; bool seqNumSet; void* macCtx; @@ -464,3 +408,11 @@ private: */ #endif +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ + diff --git a/jni/libzrtp/sources/srtp/CryptoContextCtrl.cpp b/jni/libzrtp/sources/srtp/CryptoContextCtrl.cpp index 952a82304..caf5746d2 100644 --- a/jni/libzrtp/sources/srtp/CryptoContextCtrl.cpp +++ b/jni/libzrtp/sources/srtp/CryptoContextCtrl.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2011 - 2012 Werner Dittmann + Copyright (C) 2004-2006 the Minisip Team This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,22 +16,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - * @author Werner Dittmann <Werner.Dittmann@t-online.de> +/* Copyright (C) 2004-2012 + * + * Authors: Israel Abad <i_abad@terra.es> + * Erik Eliasson <eliasson@it.kth.se> + * Johan Bilien <jobi@via.ecp.fr> + * Joachim Orrblad <joachim@orrblad.com> + * Werner Dittmann <Werner.Dittmann@t-online.de> */ #include <string.h> +#include <arpa/inet.h> #include <stdio.h> -#include <stdint.h> - -#include <common/osSpecifics.h> #include <CryptoContextCtrl.h> #include <CryptoContext.h> -#include <crypto/SrtpSymCrypto.h> #include <crypto/hmac.h> -#include <cryptcommon/macSkein.h> +#include <crypto/macSkein.h> CryptoContextCtrl::CryptoContextCtrl(uint32_t ssrc, @@ -45,9 +47,8 @@ CryptoContextCtrl::CryptoContextCtrl(uint32_t ssrc, int32_t akeyl, int32_t skeyl, int32_t tagLength): -ssrcCtx(ssrc),using_mki(false),mkiLength(0),mki(NULL), replay_window(0), srtcpIndex(0), -labelBase(3), macCtx(NULL), cipher(NULL), f8Cipher(NULL) // SRTCP labels start at 3 - +ssrcCtx(ssrc),using_mki(false),mkiLength(0),mki(NULL), +replay_window(0), macCtx(NULL), cipher(NULL), f8Cipher(NULL) { this->ealg = ealg; this->aalg = aalg; @@ -163,7 +164,7 @@ CryptoContextCtrl::~CryptoContextCtrl(){ aalg = SrtpAuthenticationNull; } -void CryptoContextCtrl::srtcpEncrypt( uint8_t* rtp, int32_t len, uint32_t index, uint32_t ssrc ) +void CryptoContextCtrl::srtcpEncrypt( uint8_t* rtp, int32_t len, uint64_t index, uint32_t ssrc ) { if (ealg == SrtpEncryptionNull) { return; @@ -243,7 +244,7 @@ void CryptoContextCtrl::srtcpAuthenticate(uint8_t* rtp, int32_t len, uint32_t in unsigned char temp[20]; const unsigned char* chunks[3]; unsigned int chunkLength[3]; - uint32_t beIndex = zrtpHtonl(index); + uint32_t beIndex = htonl(index); chunks[0] = rtp; chunkLength[0] = len; @@ -295,17 +296,17 @@ void CryptoContextCtrl::deriveSrtcpKeys() { uint8_t iv[16]; - // prepare cipher to compute derived keys. + // prepare AES cipher to compute derived keys. cipher->setNewKey(master_key, master_key_length); memset(master_key, 0, master_key_length); // compute the session encryption key - uint8_t label = labelBase; + uint8_t label = 3; computeIv(iv, label, master_salt); cipher->get_ctr_cipher_stream(k_e, n_e, iv); // compute the session authentication key - label = labelBase + 1; + label = 4; computeIv(iv, label, master_salt); cipher->get_ctr_cipher_stream(k_a, n_a, iv); @@ -322,12 +323,12 @@ void CryptoContextCtrl::deriveSrtcpKeys() memset(k_a, 0, n_a); // compute the session salt - label = labelBase + 2; + label = 5; computeIv(iv, label, master_salt); cipher->get_ctr_cipher_stream(k_s, n_s, iv); memset(master_salt, 0, master_salt_length); - // as last step prepare cipher with derived key. + // as last step prepare AES cipher with derived key. cipher->setNewKey(k_e, n_e); if (f8Cipher != NULL) cipher->f8_deriveForIV(f8Cipher, k_e, n_e, k_s, n_s); @@ -341,21 +342,24 @@ bool CryptoContextCtrl::checkReplay( uint32_t index ) return true; } - int64_t delta = index - s_l; + int64_t delta = s_l - index; if (delta > 0) { /* Packet not yet received*/ return true; } else { - if( -delta >= REPLAY_WINDOW_SIZE ) { - return false; /* Packet too old */ + if( -delta > REPLAY_WINDOW_SIZE ) { + /* Packet too old */ + return false; } else { if((replay_window >> (-delta)) & 0x1) { - return false; /* Packet already received ! */ + /* Packet already received ! */ + return false; } else { - return true; /* Packet not yet received */ + /* Packet not yet received */ + return true; } } } @@ -373,8 +377,7 @@ void CryptoContextCtrl::update(uint32_t index) else { replay_window |= ( 1 << delta ); } - if (index > s_l) - s_l = index; + s_l = index; } CryptoContextCtrl* CryptoContextCtrl::newCryptoContextForSSRC(uint32_t ssrc) @@ -394,3 +397,12 @@ CryptoContextCtrl* CryptoContextCtrl::newCryptoContextForSSRC(uint32_t ssrc) return pcc; } + +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ + diff --git a/jni/libzrtp/sources/srtp/CryptoContextCtrl.h b/jni/libzrtp/sources/srtp/CryptoContextCtrl.h index 3adcd8d24..456e58fec 100644 --- a/jni/libzrtp/sources/srtp/CryptoContextCtrl.h +++ b/jni/libzrtp/sources/srtp/CryptoContextCtrl.h @@ -1,6 +1,7 @@ /* - Copyright (C) 2011 - 2012 Werner Dittmann - + Copyright (C) 2004-2006 the Minisip Team + Copyright (C) 2011 Werner Dittmann for the SRTCP support + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -16,110 +17,117 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + #ifndef CRYPTOCONTEXTCTRL_H #define CRYPTOCONTEXTCTRL_H /** - * @file CryptoContextCtrl.h - * @brief The C++ SRTCP implementation + * @file CryptoContext.h + * @brief The C++ SRTP implementation * @ingroup Z_SRTP * @{ */ +#include <crypto/SrtpSymCrypto.h> + class SrtpSymCrypto; -/** - * The implementation for a SRTCP cryptographic context. - * - * This class holds data and provides functions that implement a - * cryptographic context for SRTCP, Refer to RFC 3711, chapter 3.2 for some - * more detailed information about the SRTCP cryptographic context. - * - * Each SRTCP cryptographic context maintains a RTCP source identified by - * its SSRC. Thus you can independently protect each source inside a RTP - * session. - * - * Key management mechanisms negotiate the parameters for the SRTCP - * cryptographic context, such as master key, key length, authentication - * length and so on. The key management mechanisms are not part of - * SRTCP. Refer to MIKEY (RFC 3880) or to Phil Zimmermann's ZRTP protocol - * (RFC6189). After key management negotiated the data the application - * can setup the SRTCP cryptographic context and enable SRTCP processing. - * - * @sa CryptoContext - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - */ + /** + * The implementation for a SRTCP cryptographic context. + * + * This class holds data and provides functions that implement a + * cryptographic context for SRTP, Refer to RFC 3711, chapter 3.2 for some + * more detailed information about the SRTP cryptographic context. + * + * Each SRTP cryptographic context maintains a RTP source identified by + * its SSRC. Thus you can independently protect each source inside a RTP + * session. + * + * Key management mechanisms negotiate the parameters for the SRTP + * cryptographic context, such as master key, key length, authentication + * length and so on. The key management mechanisms are not part of + * SRTP. Refer to MIKEY (RFC 3880) or to Phil Zimmermann's ZRTP protocol + * (draft-zimmermann-avt-zrtp-01). After key management negotiated the + * data the application can setup the SRTCP cryptographic context and + * enable SRTCP processing. + * + * + * @author Israel Abad <i_abad@terra.es> + * @author Erik Eliasson <eliasson@it.kth.se> + * @author Johan Bilien <jobi@via.ecp.fr> + * @author Joachim Orrblad <joachim@orrblad.com> + * @author Werner Dittmann <Werner.Dittmann@t-online.de> + */ + class CryptoContextCtrl { public: /** - * @brief Constructor for an active SRTCP cryptographic context. + * Constructor for an active SRTP cryptographic context. * - * This constructor creates an active SRTCP cryptographic context were - * algorithms are enabled, keys are computed and so on. This SRTCP - * cryptographic context can protect a RTCP SSRC stream. - * - * See the notes in CryptoContext documentation regarding the handling - * of key data. + * This constructor creates an active SRTP cryptographic context were + * algorithms are enabled, keys are computed and so on. This SRTP + * cryptographic context can protect a RTP SSRC stream. * * @param ssrc - * The RTP SSRC that this SRTCP cryptographic context protects. + * The RTP SSRC that this SRTP cryptographic context protects. * * @param ealg * The encryption algorithm to use. Possible values are <code> - * SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8, + * SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8 * </code>. See chapter 4.1.1 for AESCM (Counter mode) and 4.1.2 * for AES F8 mode. * * @param aalg * The authentication algorithm to use. Possible values are <code> - * SrtpEncryptionNull, SrtpAuthenticationSha1Hmac, SrtpAuthenticationSkeinHmac - * </code>. + * SrtpEncryptionNull, SrtpAuthenticationSha1Hmac</code>. The only + * active algorithm here is SHA1 HMAC, a SHA1 based hashed message + * authentication code as defined in RFC 2104. * * @param masterKey - * Pointer to the master key for this SRTCP cryptographic context. + * Pointer to the master key for this SRTP cryptographic context. * Must point to <code>masterKeyLength</code> bytes. Refer to chapter * 3.2.1 of the RFC about the role of the master key. * * @param masterKeyLength * The length in bytes of the master key in bytes. The length must - * match the selected encryption algorithm. Because SRTCP uses AES + * match the selected encryption algorithm. Because SRTP uses AES * based encryption only, then master key length may be 16 or 32 * bytes (128 or 256 bit master key) * * @param masterSalt - * SRTCP uses the master salt to computer the initialization vector + * SRTP uses the master salt to computer the initialization vector * that in turn is input to compute the session key, session * authentication key and the session salt. * * @param masterSaltLength - * The length in bytes of the master salt data in bytes. SRTCP uses + * The length in bytes of the master salt data in bytes. SRTP uses * AES as encryption algorithm. AES encrypts 16 byte blocks * (independent of the key length). According to RFC3711 the standard * value for the master salt length should be 112 bit (14 bytes). * * @param ekeyl - * The length in bytes of the session encryption key that SRTCP shall + * The length in bytes of the session encryption key that SRTP shall * compute and use. Usually the same length as for the master key * length. But you may use a different length as well. Be carefull * that the key management mechanisms supports different key lengths. * * @param akeyl - * The length in bytes of the session authentication key. SRTCP + * The length in bytes of the session authentication key. SRTP * computes this key and uses it as input to the authentication * algorithm. * The standard value is 160 bits (20 bytes). * * @param skeyl - * The length in bytes of the session salt. SRTCP computes this salt + * The length in bytes of the session salt. SRTP computes this salt * key and uses it as input during encryption. The length usually * is the same as the master salt length. * * @param tagLength - * The length is bytes of the authentication tag that SRTCP appends + * The length is bytes of the authentication tag that SRTP appends * to the RTP packet. Refer to chapter 4.2. in the RFC 3711. */ - CryptoContextCtrl(uint32_t ssrc, + CryptoContextCtrl( uint32_t ssrc, const int32_t ealg, const int32_t aalg, uint8_t* masterKey, @@ -129,71 +137,65 @@ class CryptoContextCtrl { int32_t ekeyl, int32_t akeyl, int32_t skeyl, - int32_t tagLength); - + int32_t tagLength ); /** - * @brief Destructor. + * Destructor. * - * Cleans the SRTCP cryptographic context. + * Cleans the SRTP cryptographic context. */ ~CryptoContextCtrl(); /** - * @brief Perform SRTCP encryption. + * Perform SRTP encryption. * - * This method encrypts <em>and</em> decrypts SRTCP payload data. Plain + * This method encrypts <em>and</em> decrypts SRTP payload data. Plain * data gets encrypted, encrypted data get decrypted. * * @param rtp * The RTP packet that contains the data to encrypt. * - * @param len - * Length of the RTCP packet - * * @param index - * The 31 bit SRTCP packet index. + * The 48 bit SRTP packet index. See the <code>guessIndex</code> + * method. * * @param ssrc - * The RTCP SSRC data in <em>host</em> order. + * The RTP SSRC data in <em>host</em> order. */ - void srtcpEncrypt(uint8_t* rtp, int32_t len, uint32_t index, uint32_t ssrc); + void srtcpEncrypt( uint8_t* rtp, int32_t len, uint64_t index, uint32_t ssrc ); /** - * @brief Compute the authentication tag. + * Compute the authentication tag. * * Compute the authentication tag according the the paramters in the - * SRTCP Cryptograhic context. + * SRTP Cryptograhic context. * * @param rtp - * The RTCP packet that contains the data to authenticate. + * The RTP packet that contains the data to authenticate. * - * @param len - * Length of the RTCP packet - * - * @param index - * The 31 bit SRTCP index. + * @param roc + * The 32 bit SRTP roll-over-counter. * * @param tag * Points to a buffer that hold the computed tag. This buffer must * be able to hold <code>tagLength</code> bytes. */ - void srtcpAuthenticate(uint8_t* rtp, int32_t len, uint32_t index, uint8_t* tag); + void srtcpAuthenticate(uint8_t* rtp, int32_t len, uint32_t roc, uint8_t* tag ); /** - * @brief Perform key derivation according to SRTCP specification + * Perform key derivation according to SRTP specification * * This method computes the session key, session authentication key and the * session salt key. This method must be called at least once after the - * SRTCP cryptograhic context was set up. - * - * This method clears the key data once it was processed by the encryptions' - * set key functions. + * SRTP Cryptograhic context was set up. * + * @param index + * The 48 bit SRTP packet index. See the <code>guessIndex</code> + * method. */ void deriveSrtcpKeys(); /** - * @brief Check for packet replay. + * Check for packet replay. * * The method check if a received packet is either to old or was already * received. @@ -210,7 +212,7 @@ class CryptoContextCtrl { bool checkReplay(uint32_t newSeqNumber); /** - * @brief Update the SRTCP packet index. + * Update the SRTP packet index. * * Call this method after all checks were successful. See chapter * 3.3.1 in the RFC when to update the ROC and ROC processing. @@ -218,77 +220,56 @@ class CryptoContextCtrl { * @param newSeqNumber * The sequence number of the received RTCP packet in host order. */ - void update(uint32_t newSeqNumber); + void update( uint32_t newSeqNumber ); /** - * @brief Get the length of the SRTCP authentication tag in bytes. + * Get the length of the SRTP authentication tag in bytes. * * @return the length of the authentication tag. */ - inline int32_t getTagLength() const { return tagLength; } + inline int32_t + getTagLength() const + {return tagLength;} + /** - * @brief Get the length of the MKI in bytes. + * Get the length of the MKI in bytes. * * @return the length of the MKI. */ - inline int32_t getMkiLength() const { return mkiLength; } + inline int32_t + getMkiLength() const + {return mkiLength;} /** - * @brief Get the SSRC of this SRTCP Cryptograhic context. + * Get the SSRC of this SRTP Cryptograhic context. * * @return the SSRC. */ - inline uint32_t getSsrc() const { return ssrcCtx; } - - /** - * @brief Get the SRTCP index field of this SRTCP Cryptograhic context. - * - * @return the SRTCP. - */ - uint32_t getSrtcpIndex() const { return srtcpIndex; } - - /** - * @brief Set the SRTCP index field of this SRTCP Cryptograhic context. - * - * @param index the new SRTCP index value. - * - */ - void setSrtcpIndex(uint32_t index) { srtcpIndex = index; } - - /** - * @brief Set the start (base) number to compute the PRF labels. - * - * Refer to RFC3711, chapters 4.3.1 and 4.3.2 about values for labels. - * CryptoContextCtrl computes the labes as follows: - * - * - labelBase + 0 -> encryption label - * - labelBase + 1 -> authentication label - * - labelBase + 2 -> salting key label - * - * The CryptoContextCtrl constructor initializes CryptoContextCtrl#labelBase - * with 3 to comply with RFC 3711 label values. - * - * Applications may set #labelBase to other values to use CryptoContextCtrl - * for other purposes. - */ - void setLabelbase(uint8_t base) { labelBase = base; } + inline uint32_t + getSsrc() const + {return ssrcCtx;} /** - * @brief Derive a new Crypto Context for use with a new SSRC + * Derive a new Crypto Context for use with a new SSRC * - * This method returns a new CryptoContextCtrl initialized with the data - * of this crypto context. The application can use this CryptoContextCtrl - * instance to encrypt / decrypt a new stream (Synchronization source) inside - * one RTCP session. + * This method returns a new Crypto Context initialized with the data + * of this crypto context. Replacing the SSRC, Roll-over-Counter, and + * the key derivation rate the application cab use this Crypto Context + * to encrypt / decrypt a new stream (Synchronization source) inside + * one RTP session. * - * Before the application can use this crypto context it must call deriveSrtcpKeys(). + * Before the application can use this crypto context it must call + * the <code>deriveSrtpKeys</code> method. * * @param ssrc * The SSRC for this context - * + * @param roc + * The Roll-Over-Counter for this context + * @param keyDerivRate + * The key derivation rate for this context * @return - * a new CryptoContextCtrl with all relevant data set. + * a new CryptoContext with all relevant data set. */ CryptoContextCtrl* newCryptoContextForSSRC(uint32_t ssrc); @@ -323,8 +304,6 @@ class CryptoContextCtrl { int32_t akeyl; int32_t skeyl; int32_t tagLength; - uint32_t srtcpIndex; - uint8_t labelBase; void* macCtx; @@ -338,3 +317,11 @@ class CryptoContextCtrl { #endif +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ + diff --git a/jni/libzrtp/sources/srtp/SrtpHandler.cpp b/jni/libzrtp/sources/srtp/SrtpHandler.cpp deleted file mode 100644 index 621e25a9e..000000000 --- a/jni/libzrtp/sources/srtp/SrtpHandler.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - Copyright (C) 2012 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> - -#include <common/osSpecifics.h> - -#include <SrtpHandler.h> -#include <CryptoContext.h> -#include <CryptoContextCtrl.h> - -#define RTP_HEADER_LENGTH 12 - -bool SrtpHandler::decodeRtp(uint8_t* buffer, int32_t length, uint32_t *ssrc, uint16_t *seq, uint8_t** payload, int32_t *payloadlen) -{ - int offset; - uint16_t *pus; - uint32_t *pui; - - /* Assume RTP header at the start of buffer. */ - - if ((*buffer & 0xC0) != 0x80) { // check version bits - return false; - } - if (length < RTP_HEADER_LENGTH) - return false; - - /* Get some handy pointers */ - pus = (uint16_t*)buffer; - pui = (uint32_t*)buffer; - - uint16_t tmp16 = pus[1]; // get seq number - *seq = zrtpNtohs(tmp16); // and return in host oder - - uint32_t tmp32 = pui[2]; // get SSRC - *ssrc = zrtpNtohl(tmp32); // and return in host order - - /* Payload is located right after header plus CSRC */ - int32_t numCC = buffer[0] & 0x0f; // lower 4 bits in first byte is num of contrib SSRC - offset = RTP_HEADER_LENGTH + (numCC * sizeof(uint32_t)); - - // Sanity check - if (offset > length) - return false; - - /* Adjust payload offset if RTP extension is used. */ - if ((*buffer & 0x10) == 0x10) { // packet contains RTP extension - pus = (uint16_t*)(buffer + offset); // pus points to extension as 16bit pointer - tmp16 = pus[1]; // the second 16 bit word is the length - tmp16 = zrtpNtohs(tmp16); // to host order - offset += (tmp16 + 1) * sizeof(uint32_t); - } - /* Sanity check */ - if (offset > length) - return false; - - /* Set payload and payload length. */ - *payload = buffer + offset; - *payloadlen = length - offset; - - return true; -} - -bool SrtpHandler::protect(CryptoContext* pcc, uint8_t* buffer, size_t length, size_t* newLength) -{ - uint8_t* payload = NULL; - int32_t payloadlen = 0; - uint16_t seqnum; - uint32_t ssrc; - - - if (pcc == NULL) { - return false; - } - if (!decodeRtp(buffer, length, &ssrc, &seqnum, &payload, &payloadlen)) - return false; - - /* Encrypt the packet */ - uint64_t index = ((uint64_t)pcc->getRoc() << 16) | (uint64_t)seqnum; - - pcc->srtpEncrypt(buffer, payload, payloadlen, index, ssrc); - - // NO MKI support yet - here we assume MKI is zero. To build in MKI - // take MKI length into account when storing the authentication tag. - - /* Compute MAC and store at end of RTP packet data */ - if (pcc->getTagLength() > 0) { - pcc->srtpAuthenticate(buffer, length, pcc->getRoc(), buffer+length); - } - *newLength = length + pcc->getTagLength(); - - /* Update the ROC if necessary */ - if (seqnum == 0xFFFF ) { - pcc->setRoc(pcc->getRoc() + 1); - } - return true; -} - -int32_t SrtpHandler::unprotect(CryptoContext* pcc, uint8_t* buffer, size_t length, size_t* newLength) -{ - uint8_t* payload = NULL; - int32_t payloadlen = 0; - uint16_t seqnum; - uint32_t ssrc; - - if (pcc == NULL) { - return 0; - } - - if (!decodeRtp(buffer, length, &ssrc, &seqnum, &payload, &payloadlen)) - return 0; - /* - * This is the setting of the packet data when we come to this point: - * - * length: complete length of received data - * buffer: points to data as received from network - * payloadlen: length of data excluding hdrSize and padding - * - * Because this is an SRTP packet we need to adjust some values here. - * The SRTP MKI and authentication data is always at the end of a - * packet. Thus compute the position of this data. - */ - uint32_t srtpDataIndex = length - (pcc->getTagLength() + pcc->getMkiLength()); - - // Compute new length - length -= pcc->getTagLength() + pcc->getMkiLength(); - *newLength = length; - - // recompute payloadlen by subtracting SRTP data - payloadlen -= pcc->getTagLength() + pcc->getMkiLength(); - - // MKI is unused, so just skip it - // const uint8* mki = buffer + srtpDataIndex; - uint8_t* tag = buffer + srtpDataIndex + pcc->getMkiLength(); - - /* Replay control */ - if (!pcc->checkReplay(seqnum)) { - return -2; - } - /* Guess the index */ - uint64_t guessedIndex = pcc->guessIndex(seqnum); - - if (pcc->getTagLength() > 0) { - uint32_t guessedRoc = guessedIndex >> 16; - uint8_t mac[20]; - - pcc->srtpAuthenticate(buffer, (uint32_t)length, guessedRoc, mac); - if (memcmp(tag, mac, pcc->getTagLength()) != 0) { - return -1; - } - } - /* Decrypt the content */ - pcc->srtpEncrypt(buffer, payload, payloadlen, guessedIndex, ssrc); - - /* Update the Crypto-context */ - pcc->update(seqnum); - - return 1; -} - - -bool SrtpHandler::protectCtrl(CryptoContextCtrl* pcc, uint8_t* buffer, size_t length, size_t* newLength) -{ - - if (pcc == NULL) { - return false; - } - /* Encrypt the packet */ - uint32_t ssrc = *(reinterpret_cast<uint32_t*>(buffer + 4)); // always SSRC of sender - ssrc = zrtpNtohl(ssrc); - - uint32_t encIndex = pcc->getSrtcpIndex(); - pcc->srtcpEncrypt(buffer + 8, length - 8, encIndex, ssrc); - - encIndex |= 0x80000000; // set the E flag - - // Fill SRTCP index as last word - uint32_t* ip = reinterpret_cast<uint32_t*>(buffer+length); - *ip = zrtpHtonl(encIndex); - - // NO MKI support yet - here we assume MKI is zero. To build in MKI - // take MKI length into account when storing the authentication tag. - - // Compute MAC and store in packet after the SRTCP index field - pcc->srtcpAuthenticate(buffer, length, encIndex, buffer + length + sizeof(uint32_t)); - - encIndex++; - encIndex &= ~0x80000000; // clear the E-flag and modulo 2^31 - pcc->setSrtcpIndex(encIndex); - *newLength = length + pcc->getTagLength() + sizeof(uint32_t); - - return true; -} - -int32_t SrtpHandler::unprotectCtrl(CryptoContextCtrl* pcc, uint8_t* buffer, size_t length, size_t* newLength) -{ - - if (pcc == NULL) { - return 0; - } - - // Compute the total length of the payload - int32_t payloadLen = length - (pcc->getTagLength() + pcc->getMkiLength() + 4); - *newLength = payloadLen; - - // point to the SRTCP index field just after the real payload - const uint32_t* index = reinterpret_cast<uint32_t*>(buffer + payloadLen); - - uint32_t encIndex = zrtpNtohl(*index); - uint32_t remoteIndex = encIndex & ~0x80000000; // get index without Encryption flag - - if (!pcc->checkReplay(remoteIndex)) { - return -2; - } - - uint8_t mac[20]; - - // Now get a pointer to the authentication tag field - const uint8_t* tag = buffer + (length - pcc->getTagLength()); - - // Authenticate includes the index, but not MKI and not (obviously) the tag itself - pcc->srtcpAuthenticate(buffer, payloadLen, encIndex, mac); - if (memcmp(tag, mac, pcc->getTagLength()) != 0) { - return -1; - } - - uint32_t ssrc = *(reinterpret_cast<uint32_t*>(buffer + 4)); // always SSRC of sender - ssrc = zrtpNtohl(ssrc); - - // Decrypt the content, exclude the very first SRTCP header (fixed, 8 bytes) - if (encIndex & 0x80000000) - pcc->srtcpEncrypt(buffer + 8, payloadLen - 8, remoteIndex, ssrc); - - // Update the Crypto-context - pcc->update(remoteIndex); - - return 1; -} - diff --git a/jni/libzrtp/sources/srtp/SrtpHandler.h b/jni/libzrtp/sources/srtp/SrtpHandler.h deleted file mode 100644 index 1cc420ba4..000000000 --- a/jni/libzrtp/sources/srtp/SrtpHandler.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - Copyright (C) 2012 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include <stdint.h> - -class CryptoContext; -class CryptoContextCtrl; - -/** - * @brief SRTP and SRTCP protect and unprotect functions. - * - * The static methods take SRTP or SRTCP crypto contexts, a pointer uint8_t buffer - * that must contain an RTP/SRTP packet and perform the actions necessary to protect - * the RTP/RTCP packet or to unprotect the SRTP/SRTCP packet. - * - * The methods assume that the buffer contains all protocol relevant fields (SSRC, - * sequence number etc.) in network order. - * - * When encrypting the buffer must be big enough to store additional data, usually - * 4 - 14 bytes, depending on how the application configured the authentication parameters. - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - */ -class SrtpHandler -{ -public: - /** - * @brief Protect an RTP packet. - * - * @param pcc the SRTP CryptoContext instance - * - * @param buffer the RTP packet to protect - * - * @param length the length of the RTP packet data in bytes - * - * @param newLength the length of the resulting SRTP packet data in bytes - * - * @return @c true if protection was successful, @c false otherwise - */ - static bool protect(CryptoContext* pcc, uint8_t* buffer, size_t length, size_t* newLength); - - /** - * @brief Unprotect a SRTP packet. - * - * @param pcc the SRTP CryptoContext instance - * - * @param buffer the SRTP packet to unprotect - * - * @param length the length of the SRTP packet data in bytes - * - * @param newLength the length of the resulting RTP packet data in bytes - * - * @return an integer value - * - 1 - success - * - -1 - SRTP authentication failed - * - -2 - SRTP replay check failed - */ - static int32_t unprotect(CryptoContext* pcc, uint8_t* buffer, size_t length, size_t* newLength); - - /** - * @brief Protect an RTCP packet. - * - * @param pcc the SRTCP CryptoContextCtrl instance - * - * @param buffer the RTCP packet to protect - * - * @param length the length of the RTCP packet data in bytes - * - * @param newLength the length of the resulting SRTCP packet data in bytes - * - * @return @c true if protection was successful, @c false otherwise - */ - static bool protectCtrl(CryptoContextCtrl* pcc, uint8_t* buffer, size_t length, size_t* newLength); - - /** - * @brief Unprotect a SRTCP packet. - * - * @param pcc the SRTCP CryptoContextCtrl instance - * - * @param buffer the SRTCP packet to unprotect - * - * @param length the length of the SRTCP packet data in bytes - * - * @param newLength the length of the resulting RTCP packet data in bytes - * - * @return an integer value - * - 0 - illegal packet (too short, not a valid RTP header byte), dismiss it - * - 1 - success - * - -1 - SRTCP authentication failed - * - -2 - SRTCP replay check failed - */ - static int32_t unprotectCtrl(CryptoContextCtrl* pcc, uint8_t* buffer, size_t length, size_t* newLength); - -private: - static bool decodeRtp(uint8_t* buffer, int32_t length, uint32_t *ssrc, uint16_t *seq, uint8_t** payload, int32_t *payloadlen); - -}; \ No newline at end of file diff --git a/jni/libzrtp/sources/srtp/crypto/SrtpSymCrypto.cpp b/jni/libzrtp/sources/srtp/crypto/SrtpSymCrypto.cpp deleted file mode 100644 index f92514dda..000000000 --- a/jni/libzrtp/sources/srtp/crypto/SrtpSymCrypto.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* - Copyright (C) 2012 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/** - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#define MAKE_F8_TEST - -#include <stdlib.h> -#include <crypto/SrtpSymCrypto.h> -#include <cryptcommon/twofish.h> -#include <cryptcommon/aesopt.h> -#include <string.h> -#include <stdio.h> -#include <common/osSpecifics.h> - -SrtpSymCrypto::SrtpSymCrypto(int algo):key(NULL), algorithm(algo) { -} - -SrtpSymCrypto::SrtpSymCrypto( uint8_t* k, int32_t keyLength, int algo): - key(NULL), algorithm(algo) { - - setNewKey(k, keyLength); -} - -SrtpSymCrypto::~SrtpSymCrypto() { - if (key != NULL) { - if (algorithm == SrtpEncryptionAESCM || algorithm == SrtpEncryptionAESF8) { - AESencrypt *saAes = reinterpret_cast<AESencrypt*>(key); - memset(saAes->cx, 0, sizeof(aes_encrypt_ctx)); - delete saAes; - } - else if (algorithm == SrtpEncryptionTWOCM || algorithm == SrtpEncryptionTWOF8) { - memset(key, 0, sizeof(Twofish_key)); - delete[] (uint8_t*)key; - } - key = NULL; - } -} - -static int twoFishInit = 0; - -bool SrtpSymCrypto::setNewKey(const uint8_t* k, int32_t keyLength) { - // release an existing key before setting a new one - if (key != NULL) { - if (algorithm == SrtpEncryptionAESCM || algorithm == SrtpEncryptionAESF8) { - AESencrypt *saAes = reinterpret_cast<AESencrypt*>(key); - memset(saAes->cx, 0, sizeof(aes_encrypt_ctx)); - delete saAes; - } - else if (algorithm == SrtpEncryptionTWOCM || algorithm == SrtpEncryptionTWOF8) { - memset(key, 0, sizeof(Twofish_key)); - delete[] (uint8_t*)key; - } - key = NULL; - } - - if (!(keyLength == 16 || keyLength == 32)) { - return false; - } - if (algorithm == SrtpEncryptionAESCM || algorithm == SrtpEncryptionAESF8) { - AESencrypt *saAes = new AESencrypt(); - if (keyLength == 16) - saAes->key128(k); - else - saAes->key256(k); - key = saAes; - } - else if (algorithm == SrtpEncryptionTWOCM || algorithm == SrtpEncryptionTWOF8) { - if (!twoFishInit) { - Twofish_initialise(); - twoFishInit = 1; - } - key = new uint8_t[sizeof(Twofish_key)]; - memset(key, 0, sizeof(Twofish_key)); - Twofish_prepare_key((Twofish_Byte*)k, keyLength, (Twofish_key*)key); - } - else - return false; - - return true; -} - -void SrtpSymCrypto::encrypt(const uint8_t* input, uint8_t* output) { - if (algorithm == SrtpEncryptionAESCM || algorithm == SrtpEncryptionAESF8) { - AESencrypt *saAes = reinterpret_cast<AESencrypt*>(key); - saAes->encrypt(input, output); - } - else if (algorithm == SrtpEncryptionTWOCM || algorithm == SrtpEncryptionTWOF8) { - Twofish_encrypt((Twofish_key*)key, (Twofish_Byte*)input, - (Twofish_Byte*)output); - } -} - -void SrtpSymCrypto::get_ctr_cipher_stream(uint8_t* output, uint32_t length, uint8_t* iv) { - uint16_t ctr = 0; - unsigned char temp[SRTP_BLOCK_SIZE]; - - for(ctr = 0; ctr < length/SRTP_BLOCK_SIZE; ctr++) { - //compute the cipher stream - iv[14] = (uint8_t)((ctr & 0xFF00) >> 8); - iv[15] = (uint8_t)((ctr & 0x00FF)); - - encrypt(iv, &output[ctr*SRTP_BLOCK_SIZE]); - } - if ((length % SRTP_BLOCK_SIZE) > 0) { - // Treat the last bytes: - iv[14] = (uint8_t)((ctr & 0xFF00) >> 8); - iv[15] = (uint8_t)((ctr & 0x00FF)); - - encrypt(iv, temp); - memcpy(&output[ctr*SRTP_BLOCK_SIZE], temp, length % SRTP_BLOCK_SIZE ); - } -} - -void SrtpSymCrypto::ctr_encrypt(const uint8_t* input, uint32_t input_length, uint8_t* output, uint8_t* iv) { - - if (key == NULL) - return; - - uint16_t ctr = 0; - unsigned char temp[SRTP_BLOCK_SIZE]; - - int l = input_length/SRTP_BLOCK_SIZE; - for (ctr = 0; ctr < l; ctr++ ) { - iv[14] = (uint8_t)((ctr & 0xFF00) >> 8); - iv[15] = (uint8_t)((ctr & 0x00FF)); - - encrypt(iv, temp); - for (int i = 0; i < SRTP_BLOCK_SIZE; i++ ) { - *output++ = temp[i] ^ *input++; - } - - } - l = input_length % SRTP_BLOCK_SIZE; - if (l > 0) { - // Treat the last bytes: - iv[14] = (uint8_t)((ctr & 0xFF00) >> 8); - iv[15] = (uint8_t)((ctr & 0x00FF)); - - encrypt(iv, temp); - for (int i = 0; i < l; i++ ) { - *output++ = temp[i] ^ *input++; - } - } -} - -void SrtpSymCrypto::ctr_encrypt( uint8_t* data, uint32_t data_length, uint8_t* iv ) { - - if (key == NULL) - return; - - uint16_t ctr = 0; - unsigned char temp[SRTP_BLOCK_SIZE]; - - int l = data_length/SRTP_BLOCK_SIZE; - for (ctr = 0; ctr < l; ctr++ ) { - iv[14] = (uint8_t)((ctr & 0xFF00) >> 8); - iv[15] = (uint8_t)((ctr & 0x00FF)); - - encrypt(iv, temp); - for (int i = 0; i < SRTP_BLOCK_SIZE; i++ ) { - *data++ ^= temp[i]; - } - - } - l = data_length % SRTP_BLOCK_SIZE; - if (l > 0) { - // Treat the last bytes: - iv[14] = (uint8_t)((ctr & 0xFF00) >> 8); - iv[15] = (uint8_t)((ctr & 0x00FF)); - - encrypt(iv, temp); - for (int i = 0; i < l; i++ ) { - *data++ ^= temp[i]; - } - } -} - -void SrtpSymCrypto::f8_encrypt(const uint8_t* data, uint32_t data_length, - uint8_t* iv, SrtpSymCrypto* f8Cipher ) { - - f8_encrypt(data, data_length, const_cast<uint8_t*>(data), iv, f8Cipher); -} - -#define MAX_KEYLEN 32 - -void SrtpSymCrypto::f8_deriveForIV(SrtpSymCrypto* f8Cipher, uint8_t* key, int32_t keyLen, - uint8_t* salt, int32_t saltLen) { - - unsigned char *cp_in, *cp_in1, *cp_out; - - unsigned char maskedKey[MAX_KEYLEN]; - unsigned char saltMask[MAX_KEYLEN]; - - if (keyLen > MAX_KEYLEN) - return; - - if (saltLen > keyLen) - return; - /* - * First copy the salt into the mask field, then fill with 0x55 to - * get a full key. - */ - memcpy(saltMask, salt, saltLen); - memset(saltMask+saltLen, 0x55, keyLen-saltLen); - - /* - * XOR the original key with the above created mask to - * get the special key. - */ - cp_out = maskedKey; - cp_in = key; - cp_in1 = saltMask; - for (int i = 0; i < keyLen; i++) { - *cp_out++ = *cp_in++ ^ *cp_in1++; - } - /* - * Prepare the a new AES cipher with the special key to compute IV' - */ - f8Cipher->setNewKey(maskedKey, keyLen); -} - -void SrtpSymCrypto::f8_encrypt(const uint8_t* in, uint32_t in_length, uint8_t* out, - uint8_t* iv, SrtpSymCrypto* f8Cipher ) { - - - int offset = 0; - - unsigned char ivAccent[SRTP_BLOCK_SIZE]; - unsigned char S[SRTP_BLOCK_SIZE]; - - F8_CIPHER_CTX f8ctx; - - if (key == NULL) - return; - /* - * Get memory for the derived IV (IV') - */ - f8ctx.ivAccent = ivAccent; - /* - * Use the derived IV encryption setup to encrypt the original IV to produce IV'. - */ - f8Cipher->encrypt(iv, f8ctx.ivAccent); - - f8ctx.J = 0; // initialize the counter - f8ctx.S = S; // get the key stream buffer - - memset(f8ctx.S, 0, SRTP_BLOCK_SIZE); // initial value for key stream - - while (in_length >= SRTP_BLOCK_SIZE) { - processBlock(&f8ctx, in+offset, SRTP_BLOCK_SIZE, out+offset); - in_length -= SRTP_BLOCK_SIZE; - offset += SRTP_BLOCK_SIZE; - } - if (in_length > 0) { - processBlock(&f8ctx, in+offset, in_length, out+offset); - } -} - -int SrtpSymCrypto::processBlock(F8_CIPHER_CTX *f8ctx, const uint8_t* in, int32_t length, uint8_t* out) { - - int i; - const uint8_t *cp_in; - uint8_t* cp_in1, *cp_out; - uint32_t *ui32p; - - /* - * XOR the previous key stream with IV' - * ( S(-1) xor IV' ) - */ - cp_in = f8ctx->ivAccent; - cp_out = f8ctx->S; - for (i = 0; i < SRTP_BLOCK_SIZE; i++) { - *cp_out++ ^= *cp_in++; - } - /* - * Now XOR (S(n-1) xor IV') with the current counter, then increment the counter - */ - ui32p = (uint32_t *)f8ctx->S; - ui32p[3] ^= zrtpHtonl(f8ctx->J); - f8ctx->J++; - /* - * Now compute the new key stream using AES encrypt - */ - encrypt(f8ctx->S, f8ctx->S); - /* - * as the last step XOR the plain text with the key stream to produce - * the ciphertext. - */ - cp_out = out; - cp_in = in; - cp_in1 = f8ctx->S; - for (i = 0; i < length; i++) { - *cp_out++ = *cp_in++ ^ *cp_in1++; - } - return length; -} - diff --git a/jni/libzrtp/sources/srtp/crypto/SrtpSymCrypto.h b/jni/libzrtp/sources/srtp/crypto/SrtpSymCrypto.h index 09bdcabe4..1b596c8ba 100644 --- a/jni/libzrtp/sources/srtp/crypto/SrtpSymCrypto.h +++ b/jni/libzrtp/sources/srtp/crypto/SrtpSymCrypto.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2008-2012 Werner Dittmann + Copyright (C) 2005, 2004, 2010, 2012 Erik Eliasson, Johan Bilien, Werner Dittmann This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -36,7 +36,7 @@ /** * @file SrtpSymCrypto.h - * @brief Class which implements SRTP cryptographic functions + * @brief Class which implements SRTP AES cryptographic functions * * @ingroup GNU_ZRTP * @{ @@ -56,7 +56,7 @@ typedef struct _f8_ctx { } F8_CIPHER_CTX; /** - * @brief Implments the SRTP encryption modes as defined in RFC3711 + * Implments the SRTP encryption modes as defined in RFC3711 * * The SRTP specification defines two encryption modes, AES-CTR * (AES Counter mode) and AES-F8 mode. The AES-CTR is required, @@ -70,43 +70,31 @@ typedef struct _f8_ctx { * The implementation uses the openSSL library as its cryptographic * backend. * + * @author Erik Eliasson <eliasson@it.kth.se> + * @author Johan Bilien <jobi@via.ecp.fr> * @author Werner Dittmann <Werner.Dittmann@t-online.de> */ class SrtpSymCrypto { public: - /** - * @brief Constructor that does not initialize key data - * - * @param algo - * The Encryption algorithm to use.Possible values are <code> - * SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8 - * SrtpEncryptionTWOCM, SrtpEncryptionTWOF8</code>. See chapter 4.1.1 - * for CM (Counter mode) and 4.1.2 for F8 mode. - */ SrtpSymCrypto(int algo = SrtpEncryptionAESCM); /** - * @brief Constructor that initializes key data + * Constructor that initializes key data * * @param key * Pointer to key bytes. * @param key_length * Number of key bytes. - * @param algo - * The Encryption algorithm to use.Possible values are <code> - * SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8 - * SrtpEncryptionTWOCM, SrtpEncryptionTWOF8</code>. See chapter 4.1.1 - * for CM (Counter mode) and 4.1.2 for F8 mode. */ SrtpSymCrypto(uint8_t* key, int32_t key_length, int algo = SrtpEncryptionAESCM); ~SrtpSymCrypto(); /** - * @brief Encrypts the input to the output. + * Encrypts the inpout to the output. * * Encrypts one input block to one output block. Each block - * is 16 bytes according to the encryption algorithms used. + * is 16 bytes according to the AES encryption algorithm used. * * @param input * Pointer to input block, must be 16 bytes @@ -117,7 +105,7 @@ public: void encrypt( const uint8_t* input, uint8_t* output ); /** - * @brief Set new key + * Set new key * * @param key * Pointer to key data, must have at least a size of keyLength @@ -131,7 +119,7 @@ public: bool setNewKey(const uint8_t* key, int32_t keyLength); /** - * @brief Computes the cipher stream for AES CM mode. + * Computes the cipher stream for AES CM mode. * * @param output * Pointer to a buffer that receives the cipher stream. Must be @@ -148,9 +136,9 @@ public: void get_ctr_cipher_stream(uint8_t* output, uint32_t length, uint8_t* iv); /** - * @brief Counter-mode encryption. + * Counter-mode encryption. * - * This method performs the CM encryption. + * This method performs the AES CM encryption. * * @param input * Pointer to input buffer, must be <code>inputLen</code> bytes. @@ -168,9 +156,9 @@ public: void ctr_encrypt(const uint8_t* input, uint32_t inputLen, uint8_t* output, uint8_t* iv ); /** - * @brief Counter-mode encryption, in place. + * Counter-mode encryption, in place. * - * This method performs the CM encryption. + * This method performs the AES CM encryption. * * @param data * Pointer to input and output block, must be <code>dataLen</code> @@ -186,12 +174,12 @@ public: void ctr_encrypt(uint8_t* data, uint32_t data_length, uint8_t* iv ); /** - * @brief Derive a cipher context to compute the IV'. + * Derive a AES context to compute the IV'. * * See chapter 4.1.2.1 in RFC 3711. * * @param f8Cipher - * Pointer to the cipher context that will be used to encrypt IV to IV' + * Pointer to the AES context that will be used to encrypt IV to IV' * * @param key * The master key @@ -208,9 +196,10 @@ public: void f8_deriveForIV(SrtpSymCrypto* f8Cipher, uint8_t* key, int32_t keyLen, uint8_t* salt, int32_t saltLen); /** - * @brief F8 mode encryption, in place. + * AES F8 mode encryption, in place. * - * This method performs the F8 encryption, see chapter 4.1.2 in RFC 3711. + * This method performs the AES F8 encryption, see chapter 4.1.2 + * in RFC 3711. * * @param data * Pointer to input and output block, must be <code>dataLen</code> @@ -229,9 +218,10 @@ public: void f8_encrypt(const uint8_t* data, uint32_t dataLen, uint8_t* iv, SrtpSymCrypto* f8Cipher); /** - * @brief F8 mode encryption. + * AES F8 mode encryption. * - * This method performs the F8 encryption, see chapter 4.1.2 in RFC 3711. + * This method performs the AES F8 encryption, see chapter 4.1.2 + * in RFC 3711. * * @param data * Pointer to input and output block, must be <code>dataLen</code> @@ -262,13 +252,13 @@ private: int testF8(); #pragma GCC visibility pop -/* Only SrtpSymCrypto functions defines the MAKE_F8_TEST */ +/* Only SrtpSymCrypto functions define the MAKE_F8_TEST */ #ifdef MAKE_F8_TEST #include <cstring> #include <iostream> #include <cstdio> -#include <common/osSpecifics.h> +#include <arpa/inet.h> using namespace std; @@ -348,7 +338,7 @@ int testF8() derivedIv[0] = 0; // set ROC in network order into IV - ui32p[3] = zrtpHtonl(ROC); + ui32p[3] = htonl(ROC); int32_t pad = 0; @@ -393,3 +383,11 @@ int testF8() #endif +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ + diff --git a/jni/libzrtp/sources/cryptcommon/brg_endian.h b/jni/libzrtp/sources/srtp/crypto/brg_endian.h similarity index 65% rename from jni/libzrtp/sources/cryptcommon/brg_endian.h rename to jni/libzrtp/sources/srtp/crypto/brg_endian.h index 82e48f0bc..c03c7c5d1 100644 --- a/jni/libzrtp/sources/cryptcommon/brg_endian.h +++ b/jni/libzrtp/sources/srtp/crypto/brg_endian.h @@ -1,39 +1,49 @@ /* ---------------------------------------------------------------------------- -Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + --------------------------------------------------------------------------- + Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. All rights reserved. -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: + LICENSE TERMS - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 20/10/2006 */ -#ifndef _BRG_ENDIAN_H -#define _BRG_ENDIAN_H +#ifndef BRG_ENDIAN_H +#define BRG_ENDIAN_H #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ /* Include files where endian defines and byteswap functions may reside */ -#if defined( __sun ) -# include <sys/isa_defs.h> -#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) +#if defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) # include <sys/endian.h> #elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) # include <machine/endian.h> #elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) -# if !defined( __MINGW32__ ) && !defined( _AIX ) +# if !defined( __MINGW32__ ) && !defined(AVR) # include <endian.h> # if !defined( __BEOS__ ) # include <byteswap.h> @@ -101,7 +111,7 @@ Issue Date: 20/12/2007 defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ defined( vax ) || defined( vms ) || defined( VMS ) || \ - defined( __VMS ) || defined( _M_X64 ) + defined( __VMS ) || defined( _M_X64 ) || defined( AVR ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ @@ -110,7 +120,7 @@ Issue Date: 20/12/2007 defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ - defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) + defined( THINK_C ) || defined( __VMCMS__ ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif 0 /* **** EDIT HERE IF NECESSARY **** */ @@ -120,7 +130,19 @@ Issue Date: 20/12/2007 #else # error Please edit lines 126 or 128 in brg_endian.h to set the platform byte order #endif +#endif +/* special handler for IA64, which may be either endianness (?) */ +/* here we assume little-endian, but this may need to be changed */ +#if defined(__ia64) || defined(__ia64__) || defined(_M_IA64) +# define PLATFORM_MUST_ALIGN (1) +#ifndef PLATFORM_BYTE_ORDER +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif #endif +#ifndef PLATFORM_MUST_ALIGN +# define PLATFORM_MUST_ALIGN (0) #endif + +#endif /* ifndef BRG_ENDIAN_H */ diff --git a/jni/libzrtp/sources/cryptcommon/brg_types.h b/jni/libzrtp/sources/srtp/crypto/brg_types.h similarity index 55% rename from jni/libzrtp/sources/cryptcommon/brg_types.h rename to jni/libzrtp/sources/srtp/crypto/brg_types.h index 40d4af5bd..6db737d71 100644 --- a/jni/libzrtp/sources/cryptcommon/brg_types.h +++ b/jni/libzrtp/sources/srtp/crypto/brg_types.h @@ -1,21 +1,33 @@ /* ---------------------------------------------------------------------------- -Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved. + --------------------------------------------------------------------------- + Copyright (c) 1998-2006, Brian Gladman, Worcester, UK. All rights reserved. -The redistribution and use of this software (with or without changes) -is allowed without the payment of fees or royalties provided that: + LICENSE TERMS - source code distributions include the above copyright notice, this - list of conditions and the following disclaimer; + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: - binary distributions include the above copyright notice, this list - of conditions and the following disclaimer in their documentation. + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; -This software is provided 'as is' with no explicit or implied warranties -in respect of its operation, including, but not limited to, correctness -and fitness for purpose. ---------------------------------------------------------------------------- -Issue Date: 20/12/2007 + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 The unsigned integer types defined here are of the form uint_<nn>t where <nn> is the length of the type; for example, the unsigned 32-bit type is @@ -27,8 +39,8 @@ Issue Date: 20/12/2007 can be used to convert the types used here to the C99 standard types. */ -#ifndef _BRG_TYPES_H -#define _BRG_TYPES_H +#ifndef BRG_TYPES_H +#define BRG_TYPES_H #if defined(__cplusplus) extern "C" { @@ -36,19 +48,6 @@ extern "C" { #include <limits.h> -#if defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) -# include <stddef.h> -# define ptrint_t intptr_t -#elif defined( __ECOS__ ) -# define intptr_t unsigned int -# define ptrint_t intptr_t -#elif defined( __GNUC__ ) && ( __GNUC__ >= 3 ) -# include <stdint.h> -# define ptrint_t intptr_t -#else -# define ptrint_t int -#endif - #ifndef BRG_UI8 # define BRG_UI8 # if UCHAR_MAX == 255u @@ -91,14 +90,10 @@ extern "C" { # define BRG_UI64 # define li_64(h) 0x##h##ui64 typedef unsigned __int64 uint_64t; -# elif defined( __sun ) && defined( ULONG_MAX ) && ULONG_MAX == 0xfffffffful +# elif defined( __sun ) && defined(ULONG_MAX) && ULONG_MAX == 0xfffffffful # define BRG_UI64 # define li_64(h) 0x##h##ull typedef unsigned long long uint_64t; -# elif defined( __MVS__ ) -# define BRG_UI64 -# define li_64(h) 0x##h##ull - typedef unsigned int long long uint_64t; # elif defined( UINT_MAX ) && UINT_MAX > 4294967295u # if UINT_MAX == 18446744073709551615u # define BRG_UI64 @@ -123,13 +118,15 @@ extern "C" { # define li_64(h) 0x##h##ull typedef unsigned long long uint_64t; # endif +# elif defined(__GNUC__) /* DLW: avoid mingw problem with -ansi */ +# define BRG_UI64 +# define li_64(h) 0x##h##ull + typedef unsigned long long uint_64t; # endif #endif -#if !defined( BRG_UI64 ) -# if defined( NEED_UINT_64T ) -# error Please define uint_64t as an unsigned 64 bit type in brg_types.h -# endif +#if defined( NEED_UINT_64T ) && !defined( BRG_UI64 ) +# error Please define uint_64t as an unsigned 64 bit type in brg_types.h #endif #ifndef RETURN_VALUES @@ -163,54 +160,26 @@ extern "C" { # endif #endif -/* These defines are used to detect and set the memory alignment of pointers. - Note that offsets are in bytes. - - ALIGN_OFFSET(x,n) return the positive or zero offset of - the memory addressed by the pointer 'x' - from an address that is aligned on an - 'n' byte boundary ('n' is a power of 2) - - ALIGN_FLOOR(x,n) return a pointer that points to memory - that is aligned on an 'n' byte boundary - and is not higher than the memory address - pointed to by 'x' ('n' is a power of 2) - - ALIGN_CEIL(x,n) return a pointer that points to memory - that is aligned on an 'n' byte boundary - and is not lower than the memory address - pointed to by 'x' ('n' is a power of 2) -*/ - -#define ALIGN_OFFSET(x,n) (((ptrint_t)(x)) & ((n) - 1)) -#define ALIGN_FLOOR(x,n) ((uint_8t*)(x) - ( ((ptrint_t)(x)) & ((n) - 1))) -#define ALIGN_CEIL(x,n) ((uint_8t*)(x) + (-((ptrint_t)(x)) & ((n) - 1))) - /* These defines are used to declare buffers in a way that allows faster operations on longer variables to be used. In all these - defines 'size' must be a power of 2 and >= 8. NOTE that the - buffer size is in bytes but the type length is in bits + defines 'size' must be a power of 2 and >= 8 - UNIT_TYPEDEF(x,size) declares a variable 'x' of length + dec_unit_type(size,x) declares a variable 'x' of length 'size' bits - BUFR_TYPEDEF(x,size,bsize) declares a buffer 'x' of length 'bsize' + dec_bufr_type(size,bsize,x) declares a buffer 'x' of length 'bsize' bytes defined as an array of variables each of 'size' bits (bsize must be a multiple of size / 8) - UNIT_CAST(x,size) casts a variable to a type of - length 'size' bits - - UPTR_CAST(x,size) casts a pointer to a pointer to a + ptr_cast(x,size) casts a pointer to a pointer to a varaiable of length 'size' bits */ -#define UI_TYPE(size) uint_##size##t -#define UNIT_TYPEDEF(x,size) typedef UI_TYPE(size) x -#define BUFR_TYPEDEF(x,size,bsize) typedef UI_TYPE(size) x[bsize / (size >> 3)] -#define UNIT_CAST(x,size) ((UI_TYPE(size) )(x)) -#define UPTR_CAST(x,size) ((UI_TYPE(size)*)(x)) +#define ui_type(size) uint_##size##t +#define dec_unit_type(size,x) typedef ui_type(size) x +#define dec_bufr_type(size,bsize,x) typedef ui_type(size) x[bsize / (size >> 3)] +#define ptr_cast(x,size) ((ui_type(size)*)(x)) #if defined(__cplusplus) } diff --git a/jni/libzrtp/sources/srtp/crypto/gcrypt/InitializeGcrypt.cpp b/jni/libzrtp/sources/srtp/crypto/gcrypt/InitializeGcrypt.cpp index 1c743d2f9..78fad51c6 100644 --- a/jni/libzrtp/sources/srtp/crypto/gcrypt/InitializeGcrypt.cpp +++ b/jni/libzrtp/sources/srtp/crypto/gcrypt/InitializeGcrypt.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2006-2013 Werner Dittmann + Copyright (C) 2006-2007 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -17,7 +17,7 @@ #include <stdio.h> -#include <string.h> +#include <malloc.h> #include <pthread.h> #include <errno.h> #include <gcrypt.h> diff --git a/jni/libzrtp/sources/srtp/crypto/hmac.cpp b/jni/libzrtp/sources/srtp/crypto/hmac.cpp deleted file mode 100644 index 38028a372..000000000 --- a/jni/libzrtp/sources/srtp/crypto/hmac.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright (C) 2012 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/* - * Authors: Werner Dittmann - */ - -#include <stdint.h> -#include <string.h> -#include <stdio.h> -#include "crypto/sha1.h" -#include "crypto/hmac.h" - -typedef struct _hmacSha1Context { - sha1_ctx ctx; - sha1_ctx innerCtx; - sha1_ctx outerCtx; -} hmacSha1Context; - -static int32_t hmacSha1Init(hmacSha1Context *ctx, const uint8_t *key, uint32_t kLength) -{ - int32_t i; - uint8_t localPad[SHA1_BLOCK_SIZE] = {0}; - uint8_t localKey[SHA1_BLOCK_SIZE] = {0}; - - if (key == NULL) - return 0; - - memset(ctx, 0, sizeof(hmacSha1Context)); - - /* check key length and reduce it if necessary */ - if (kLength > SHA1_BLOCK_SIZE) { - sha1_begin(&ctx->ctx); - sha1_hash(key, kLength, &ctx->ctx); - sha1_end(localKey, &ctx->ctx); - } - else { - memcpy(localKey, key, kLength); - } - /* prepare inner hash and hold the context */ - for (i = 0; i < SHA1_BLOCK_SIZE; i++) - localPad[i] = localKey[i] ^ 0x36; - - sha1_begin(&ctx->innerCtx); - sha1_hash(localPad, SHA1_BLOCK_SIZE, &ctx->innerCtx); - - /* prepare outer hash and hold the context */ - for (i = 0; i < SHA1_BLOCK_SIZE; i++) - localPad[i] = localKey[i] ^ 0x5c; - - sha1_begin(&ctx->outerCtx); - sha1_hash(localPad, SHA1_BLOCK_SIZE, &ctx->outerCtx); - - /* copy prepared inner hash to work hash - ready to process data */ - memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha1_ctx)); - - memset(localKey, 0, sizeof(localKey)); - - return 1; -} - -static void hmacSha1Reset(hmacSha1Context *ctx) -{ - /* copy prepared inner hash to work hash context */ - memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha1_ctx)); -} - -static void hmacSha1Update(hmacSha1Context *ctx, const uint8_t *data, uint32_t dLength) -{ - /* hash new data to work hash context */ - sha1_hash(data, dLength, &ctx->ctx); -} - -static void hmacSha1Final(hmacSha1Context *ctx, uint8_t *mac) -{ - uint8_t tmpDigest[SHA1_DIGEST_SIZE]; - - /* finalize work hash context */ - sha1_end(tmpDigest, &ctx->ctx); - - /* copy prepared outer hash to work hash */ - memcpy(&ctx->ctx, &ctx->outerCtx, sizeof(sha1_ctx)); - - /* hash inner digest to work (outer) hash context */ - sha1_hash(tmpDigest, SHA1_DIGEST_SIZE, &ctx->ctx); - - /* finalize work hash context to get the hmac*/ - sha1_end(mac, &ctx->ctx); -} - - -void hmac_sha1(uint8_t *key, int32_t keyLength, const uint8_t* data, uint32_t dataLength, uint8_t* mac, int32_t* macLength) -{ - hmacSha1Context ctx; - - hmacSha1Init(&ctx, key, keyLength); - hmacSha1Update(&ctx, data, dataLength); - hmacSha1Final(&ctx, mac); - *macLength = SHA1_BLOCK_SIZE; -} - -void hmac_sha1( uint8_t* key, int32_t keyLength, const uint8_t* dataChunks[], uint32_t dataChunckLength[], - uint8_t* mac, int32_t* macLength ) -{ - hmacSha1Context ctx; - - hmacSha1Init(&ctx, key, keyLength); - - while (*dataChunks) { - hmacSha1Update(&ctx, *dataChunks, *dataChunckLength); - dataChunks ++; - dataChunckLength ++; - } - hmacSha1Final(&ctx, mac); - *macLength = SHA1_BLOCK_SIZE; -} - -void* createSha1HmacContext(uint8_t* key, int32_t keyLength) -{ - hmacSha1Context *ctx = reinterpret_cast<hmacSha1Context*>(malloc(sizeof(hmacSha1Context))); - - hmacSha1Init(ctx, key, keyLength); - return ctx; -} - -void hmacSha1Ctx(void* ctx, const uint8_t* data, uint32_t dataLength, - uint8_t* mac, int32_t* macLength) -{ - hmacSha1Context *pctx = (hmacSha1Context*)ctx; - - hmacSha1Reset(pctx); - hmacSha1Update(pctx, data, dataLength); - hmacSha1Final(pctx, mac); - *macLength = SHA1_BLOCK_SIZE; -} - -void hmacSha1Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], - uint8_t* mac, int32_t* macLength ) -{ - hmacSha1Context *pctx = (hmacSha1Context*)ctx; - - hmacSha1Reset(pctx); - while (*data) { - hmacSha1Update(pctx, *data, *dataLength); - data++; - dataLength++; - } - hmacSha1Final(pctx, mac); - *macLength = SHA1_BLOCK_SIZE; -} - -void freeSha1HmacContext(void* ctx) -{ - if (ctx) { - memset(ctx, 0, sizeof(hmacSha1Context)); - free(ctx); - } -} \ No newline at end of file diff --git a/jni/libzrtp/sources/srtp/crypto/hmac.h b/jni/libzrtp/sources/srtp/crypto/hmac.h index 6d99f92d8..4abfa8f0a 100644 --- a/jni/libzrtp/sources/srtp/crypto/hmac.h +++ b/jni/libzrtp/sources/srtp/crypto/hmac.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2010 Werner Dittmann + Copyright (C) 2005, 2004, 2010 Erik Eliasson, Johan Bilien, Werner Dittmann This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -32,6 +32,8 @@ /** * Functions to compute SHA1 HAMAC. * + * @author Erik Eliasson <eliasson@it.kth.se> + * @author Johan Bilien <jobi@via.ecp.fr> * @author Werner Dittmann */ diff --git a/jni/libzrtp/sources/cryptcommon/macSkein.cpp b/jni/libzrtp/sources/srtp/crypto/macSkein.cpp similarity index 93% rename from jni/libzrtp/sources/cryptcommon/macSkein.cpp rename to jni/libzrtp/sources/srtp/crypto/macSkein.cpp index 9da946f31..ba4c260a8 100644 --- a/jni/libzrtp/sources/cryptcommon/macSkein.cpp +++ b/jni/libzrtp/sources/srtp/crypto/macSkein.cpp @@ -1,8 +1,8 @@ /* - Copyright (C) 2010-2013 Werner Dittmann + Copyright (C) 2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -15,7 +15,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <cryptcommon/macSkein.h> +#include <crypto/macSkein.h> #include <stdlib.h> void macSkein(uint8_t* key, int32_t key_length, diff --git a/jni/libzrtp/sources/cryptcommon/macSkein.h b/jni/libzrtp/sources/srtp/crypto/macSkein.h similarity index 96% rename from jni/libzrtp/sources/cryptcommon/macSkein.h rename to jni/libzrtp/sources/srtp/crypto/macSkein.h index ce5d380ec..71c2ad96c 100644 --- a/jni/libzrtp/sources/cryptcommon/macSkein.h +++ b/jni/libzrtp/sources/srtp/crypto/macSkein.h @@ -1,8 +1,8 @@ /* - Copyright (C) 2010-2013 Werner Dittmann + Copyright (C) 2010 Werner Dittmann This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -19,7 +19,7 @@ #ifndef MAC_SKEIN_H #define MAC_SKEIN_H -#include <cryptcommon/skeinApi.h> +#include <crypto/skeinApi.h> /** * @file macSkein.h * @brief Function that provide Skein MAC support diff --git a/jni/libzrtp/sources/srtp/crypto/openssl/SrtpSymCrypto.cpp b/jni/libzrtp/sources/srtp/crypto/openssl/SrtpSymCrypto.cpp index 00d44768d..3d6747d4b 100644 --- a/jni/libzrtp/sources/srtp/crypto/openssl/SrtpSymCrypto.cpp +++ b/jni/libzrtp/sources/srtp/crypto/openssl/SrtpSymCrypto.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Werner Dittmann + Copyright (C) 2005, 2004, 2012 Erik Eliasson, Johan Bilien, Werner Dittmann This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -30,6 +30,8 @@ */ /** + * @author Erik Eliasson <eliasson@it.kth.se> + * @author Johan Bilien <jobi@via.ecp.fr> * @author Werner Dittmann <Werner.Dittmann@t-online.de> */ @@ -38,10 +40,10 @@ #include <stdlib.h> #include <openssl/aes.h> // the include of openSSL #include <crypto/SrtpSymCrypto.h> -#include <cryptcommon/twofish.h> +#include <crypto/twofish.h> #include <string.h> #include <stdio.h> -#include <common/osSpecifics.h> +#include <arpa/inet.h> SrtpSymCrypto::SrtpSymCrypto(int algo):key(NULL), algorithm(algo) { } @@ -294,7 +296,7 @@ int SrtpSymCrypto::processBlock(F8_CIPHER_CTX *f8ctx, const uint8_t* in, int32_t * Now XOR (S(n-1) xor IV') with the current counter, then increment the counter */ ui32p = (uint32_t *)f8ctx->S; - ui32p[3] ^= zrtpHtonl(f8ctx->J); + ui32p[3] ^= htonl(f8ctx->J); f8ctx->J++; /* * Now compute the new key stream using AES encrypt @@ -313,3 +315,12 @@ int SrtpSymCrypto::processBlock(F8_CIPHER_CTX *f8ctx, const uint8_t* in, int32_t return length; } + +/** EMACS ** + * Local variables: + * mode: c++ + * c-default-style: ellemtel + * c-basic-offset: 4 + * End: + */ + diff --git a/jni/libzrtp/sources/srtp/crypto/openssl/hmac.cpp b/jni/libzrtp/sources/srtp/crypto/openssl/hmac.cpp index cfe73c30f..88d33a1cf 100644 --- a/jni/libzrtp/sources/srtp/crypto/openssl/hmac.cpp +++ b/jni/libzrtp/sources/srtp/crypto/openssl/hmac.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2010 Werner Dittmann + Copyright (C) 2005, 2004, 2010, Erik Eliasson, Johan Bilien, Werner Dittmann This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -30,7 +30,9 @@ */ /* - * Authors: Werner Dittmann + * Authors: Erik Eliasson <eliasson@it.kth.se> + * Johan Bilien <jobi@via.ecp.fr> + * Werner Dittmann */ #include <stdint.h> @@ -65,7 +67,7 @@ void hmac_sha1( uint8_t* key, int32_t key_length, void* createSha1HmacContext(uint8_t* key, int32_t key_length) { HMAC_CTX* ctx = (HMAC_CTX*)malloc(sizeof(HMAC_CTX)); - + HMAC_CTX_init(ctx); HMAC_Init_ex(ctx, key, key_length, EVP_sha1(), NULL); return ctx; diff --git a/jni/libzrtp/sources/srtp/crypto/sha1.c b/jni/libzrtp/sources/srtp/crypto/sha1.c deleted file mode 100644 index 31cee60e2..000000000 --- a/jni/libzrtp/sources/srtp/crypto/sha1.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - ALTERNATIVELY, provided that this notice is retained in full, this product - may be distributed under the terms of the GNU General Public License (GPL), - in which case the provisions of the GPL apply INSTEAD OF those given above. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 01/08/2005 - - This is a byte oriented version of SHA1 that operates on arrays of bytes - stored in memory. -*/ - -#include <string.h> /* for memcpy() etc. */ - -#include "sha1.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#if defined( _MSC_VER ) && ( _MSC_VER > 800 ) -#pragma intrinsic(memcpy) -#endif - -#if 0 && defined(_MSC_VER) -#define rotl32 _lrotl -#define rotr32 _lrotr -#else -#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) -#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) -#endif - -#if !defined(bswap_32) -#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) -#endif - -#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) -#define SWAP_BYTES -#else -#undef SWAP_BYTES -#endif - -#if defined(SWAP_BYTES) -#define bsw_32(p,n) \ - { int _i = (n); while(_i--) ((uint_32t*)p)[_i] = bswap_32(((uint_32t*)p)[_i]); } -#else -#define bsw_32(p,n) -#endif - -#define SHA1_MASK (SHA1_BLOCK_SIZE - 1) - -#if 0 - -#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) -#define parity(x,y,z) ((x) ^ (y) ^ (z)) -#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -#else /* Discovered by Rich Schroeppel and Colin Plumb */ - -#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define parity(x,y,z) ((x) ^ (y) ^ (z)) -#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) - -#endif - -/* Compile 64 bytes of hash data into SHA1 context. Note */ -/* that this routine assumes that the byte order in the */ -/* ctx->wbuf[] at this point is in such an order that low */ -/* address bytes in the ORIGINAL byte stream will go in */ -/* this buffer to the high end of 32-bit words on BOTH big */ -/* and little endian systems */ - -#ifdef ARRAY -#define q(v,n) v[n] -#else -#define q(v,n) v##n -#endif - -#define one_cycle(v,a,b,c,d,e,f,k,h) \ - q(v,e) += rotr32(q(v,a),27) + \ - f(q(v,b),q(v,c),q(v,d)) + k + h; \ - q(v,b) = rotr32(q(v,b), 2) - -#define five_cycle(v,f,k,i) \ - one_cycle(v, 0,1,2,3,4, f,k,hf(i )); \ - one_cycle(v, 4,0,1,2,3, f,k,hf(i+1)); \ - one_cycle(v, 3,4,0,1,2, f,k,hf(i+2)); \ - one_cycle(v, 2,3,4,0,1, f,k,hf(i+3)); \ - one_cycle(v, 1,2,3,4,0, f,k,hf(i+4)) - -VOID_RETURN sha1_compile(sha1_ctx ctx[1]) -{ uint_32t *w = ctx->wbuf; - -#ifdef ARRAY - uint_32t v[5]; - memcpy(v, ctx->hash, 5 * sizeof(uint_32t)); -#else - uint_32t v0, v1, v2, v3, v4; - v0 = ctx->hash[0]; v1 = ctx->hash[1]; - v2 = ctx->hash[2]; v3 = ctx->hash[3]; - v4 = ctx->hash[4]; -#endif - -#define hf(i) w[i] - - five_cycle(v, ch, 0x5a827999, 0); - five_cycle(v, ch, 0x5a827999, 5); - five_cycle(v, ch, 0x5a827999, 10); - one_cycle(v,0,1,2,3,4, ch, 0x5a827999, hf(15)); \ - -#undef hf -#define hf(i) (w[(i) & 15] = rotl32( \ - w[((i) + 13) & 15] ^ w[((i) + 8) & 15] \ - ^ w[((i) + 2) & 15] ^ w[(i) & 15], 1)) - - one_cycle(v,4,0,1,2,3, ch, 0x5a827999, hf(16)); - one_cycle(v,3,4,0,1,2, ch, 0x5a827999, hf(17)); - one_cycle(v,2,3,4,0,1, ch, 0x5a827999, hf(18)); - one_cycle(v,1,2,3,4,0, ch, 0x5a827999, hf(19)); - - five_cycle(v, parity, 0x6ed9eba1, 20); - five_cycle(v, parity, 0x6ed9eba1, 25); - five_cycle(v, parity, 0x6ed9eba1, 30); - five_cycle(v, parity, 0x6ed9eba1, 35); - - five_cycle(v, maj, 0x8f1bbcdc, 40); - five_cycle(v, maj, 0x8f1bbcdc, 45); - five_cycle(v, maj, 0x8f1bbcdc, 50); - five_cycle(v, maj, 0x8f1bbcdc, 55); - - five_cycle(v, parity, 0xca62c1d6, 60); - five_cycle(v, parity, 0xca62c1d6, 65); - five_cycle(v, parity, 0xca62c1d6, 70); - five_cycle(v, parity, 0xca62c1d6, 75); - -#ifdef ARRAY - ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; - ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; - ctx->hash[4] += v[4]; -#else - ctx->hash[0] += v0; ctx->hash[1] += v1; - ctx->hash[2] += v2; ctx->hash[3] += v3; - ctx->hash[4] += v4; -#endif -} - -VOID_RETURN sha1_begin(sha1_ctx ctx[1]) -{ - ctx->count[0] = ctx->count[1] = 0; - ctx->hash[0] = 0x67452301; - ctx->hash[1] = 0xefcdab89; - ctx->hash[2] = 0x98badcfe; - ctx->hash[3] = 0x10325476; - ctx->hash[4] = 0xc3d2e1f0; -} - -/* SHA1 hash data in an array of bytes into hash buffer and */ -/* call the hash_compile function as required. */ - -VOID_RETURN sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]) -{ - uint_32t pos = (uint_32t)(ctx->count[0] & SHA1_MASK), - space = SHA1_BLOCK_SIZE - pos; - const unsigned char *sp = data; - - if((ctx->count[0] += len) < len) - ++(ctx->count[1]); - - while(len >= space) /* tranfer whole blocks if possible */ - { - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); - sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0; - bsw_32(ctx->wbuf, SHA1_BLOCK_SIZE >> 2); - sha1_compile(ctx); - } - - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); -} - -/* SHA1 final padding and digest calculation */ - -VOID_RETURN sha1_end(unsigned char hval[], sha1_ctx ctx[1]) -{ uint_32t i = (uint_32t)(ctx->count[0] & SHA1_MASK); - - /* put bytes in the buffer in an order in which references to */ - /* 32-bit words will put bytes with lower addresses into the */ - /* top of 32 bit words on BOTH big and little endian machines */ - bsw_32(ctx->wbuf, (i + 3) >> 2); - - /* we now need to mask valid bytes and add the padding which is */ - /* a single 1 bit and as many zero bits as necessary. Note that */ - /* we can always add the first padding byte here because the */ - /* buffer always has at least one empty slot */ - ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3); - ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3); - - /* we need 9 or more empty positions, one for the padding byte */ - /* (above) and eight for the length count. If there is not */ - /* enough space, pad and empty the buffer */ - if(i > SHA1_BLOCK_SIZE - 9) - { - if(i < 60) ctx->wbuf[15] = 0; - sha1_compile(ctx); - i = 0; - } - else /* compute a word index for the empty buffer positions */ - i = (i >> 2) + 1; - - while(i < 14) /* and zero pad all but last two positions */ - ctx->wbuf[i++] = 0; - - /* the following 32-bit length fields are assembled in the */ - /* wrong byte order on little endian machines but this is */ - /* corrected later since they are only ever used as 32-bit */ - /* word values. */ - ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); - ctx->wbuf[15] = ctx->count[0] << 3; - sha1_compile(ctx); - - /* extract the hash value as bytes in case the hash buffer is */ - /* misaligned for 32-bit words */ - for(i = 0; i < SHA1_DIGEST_SIZE; ++i) - hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); -} - -VOID_RETURN bg_sha1(unsigned char hval[], const unsigned char data[], unsigned long len) -{ sha1_ctx cx[1]; - - sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx); -} - -#if defined(__cplusplus) -} -#endif diff --git a/jni/libzrtp/sources/srtp/crypto/sha1.h b/jni/libzrtp/sources/srtp/crypto/sha1.h deleted file mode 100644 index 79fb6809a..000000000 --- a/jni/libzrtp/sources/srtp/crypto/sha1.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - ALTERNATIVELY, provided that this notice is retained in full, this product - may be distributed under the terms of the GNU General Public License (GPL), - in which case the provisions of the GPL apply INSTEAD OF those given above. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 01/08/2005 -*/ - -#ifndef _SHA1_H -#define _SHA1_H - -#include <stdlib.h> -#include <cryptcommon/brg_types.h> - -#define SHA1_BLOCK_SIZE 64 -#define SHA1_DIGEST_SIZE 20 - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* type to hold the SHA256 context */ - -typedef struct -{ uint_32t count[2]; - uint_32t hash[5]; - uint_32t wbuf[16]; -} sha1_ctx; - -/* Note that these prototypes are the same for both bit and */ -/* byte oriented implementations. However the length fields */ -/* are in bytes or bits as appropriate for the version used */ -/* and bit sequences are input as arrays of bytes in which */ -/* bit sequences run from the most to the least significant */ -/* end of each byte */ - -VOID_RETURN sha1_compile(sha1_ctx ctx[1]); - -VOID_RETURN sha1_begin(sha1_ctx ctx[1]); -VOID_RETURN sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]); -VOID_RETURN sha1_end(unsigned char hval[], sha1_ctx ctx[1]); -VOID_RETURN sha1(unsigned char hval[], const unsigned char data[], unsigned long len); - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/jni/libzrtp/sources/cryptcommon/skein.c b/jni/libzrtp/sources/srtp/crypto/skein.c similarity index 97% rename from jni/libzrtp/sources/cryptcommon/skein.c rename to jni/libzrtp/sources/srtp/crypto/skein.c index 9c6451db1..5935a2a76 100644 --- a/jni/libzrtp/sources/cryptcommon/skein.c +++ b/jni/libzrtp/sources/srtp/crypto/skein.c @@ -11,8 +11,8 @@ #define SKEIN_PORT_CODE /* instantiate any code in skein_port.h */ #include <string.h> /* get the memcpy/memset functions */ -#include <cryptcommon/skein.h> /* get the Skein API definitions */ -#include <cryptcommon/skein_iv.h> /* get precomputed IVs */ +#include <crypto/skein.h> /* get the Skein API definitions */ +#include <crypto/skein_iv.h> /* get precomputed IVs */ /*****************************************************************/ /* External function to process blkCnt (nonzero) full block(s) of data. */ diff --git a/jni/libzrtp/sources/cryptcommon/skein.h b/jni/libzrtp/sources/srtp/crypto/skein.h similarity index 97% rename from jni/libzrtp/sources/cryptcommon/skein.h rename to jni/libzrtp/sources/srtp/crypto/skein.h index 135aeb32b..345a11278 100644 --- a/jni/libzrtp/sources/cryptcommon/skein.h +++ b/jni/libzrtp/sources/srtp/crypto/skein.h @@ -33,7 +33,7 @@ extern "C" #endif #include <stddef.h> /* get size_t definition */ -#include <cryptcommon/skein_port.h> /* get platform-specific definitions */ +#include <crypto/skein_port.h> /* get platform-specific definitions */ enum { diff --git a/jni/libzrtp/sources/cryptcommon/skeinApi.c b/jni/libzrtp/sources/srtp/crypto/skeinApi.c similarity index 99% rename from jni/libzrtp/sources/cryptcommon/skeinApi.c rename to jni/libzrtp/sources/srtp/crypto/skeinApi.c index f403b537e..84f012026 100644 --- a/jni/libzrtp/sources/cryptcommon/skeinApi.c +++ b/jni/libzrtp/sources/srtp/crypto/skeinApi.c @@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE. */ #define SKEIN_ERR_CHECK 1 -#include <cryptcommon/skeinApi.h> +#include <crypto/skeinApi.h> #include <string.h> #include <stdio.h> diff --git a/jni/libzrtp/sources/cryptcommon/skeinApi.h b/jni/libzrtp/sources/srtp/crypto/skeinApi.h similarity index 94% rename from jni/libzrtp/sources/cryptcommon/skeinApi.h rename to jni/libzrtp/sources/srtp/crypto/skeinApi.h index 4d25ba5ca..2f2507365 100644 --- a/jni/libzrtp/sources/cryptcommon/skeinApi.h +++ b/jni/libzrtp/sources/srtp/crypto/skeinApi.h @@ -32,12 +32,12 @@ OTHER DEALINGS IN THE SOFTWARE. * @brief A Skein API and its functions. * @{ * - * This API and the functions that implement this API simplify usage + * This API and the functions that implement this API simplify the usage * of Skein. The design and the way to use the functions follow the openSSL * design but at the same time take care of some Skein specific behaviour * and possibilities. * - * The functions enable applications to create normal Skein hashes and + * The functions enable applications to create a normal Skein hashes and * message authentication codes (MAC). * * Using these functions is simple and straight forward: @@ -52,9 +52,9 @@ OTHER DEALINGS IN THE SOFTWARE. * // prepare context, here for a Skein with a state size of 512 bits. * skeinCtxPrepare(&ctx, Skein512); * - * // Initialize the context to set the requested hash length in bits: - * // request an output hash size of 31 bits (Skein supports variable - * // output sizes, even very strange sizes) + * // Initialize the context to set the requested hash length in bits + * // here request a output hash size of 31 bits (Skein supports variable + * // output sizes even very strange sizes) * skeinInit(&ctx, 31); * * // Now update Skein with any number of message bits. A function that @@ -71,14 +71,14 @@ OTHER DEALINGS IN THE SOFTWARE. * An application may use @c skeinReset to reset a Skein context and use * it for creation of another hash with the same Skein state size and output * bit length. In this case the API implementation restores some internal - * state data and saves a full Skein initialization round. + * internal state data and saves a full Skein initialization round. * * To create a MAC the application just uses @c skeinMacInit instead of - * @c skeinInit. All other function calls remain the same. + * @c skeinInit. All other functions calls remain the same. * */ -#include <cryptcommon/skein.h> +#include <crypto/skein.h> #ifdef _MSC_VER typedef signed __int8 int8_t; diff --git a/jni/libzrtp/sources/cryptcommon/skein_block.c b/jni/libzrtp/sources/srtp/crypto/skein_block.c similarity index 97% rename from jni/libzrtp/sources/cryptcommon/skein_block.c rename to jni/libzrtp/sources/srtp/crypto/skein_block.c index d1c5eced1..fbf37e7da 100644 --- a/jni/libzrtp/sources/cryptcommon/skein_block.c +++ b/jni/libzrtp/sources/srtp/crypto/skein_block.c @@ -15,7 +15,7 @@ ************************************************************************/ #include <string.h> -#include <cryptcommon/skein.h> +#include <crypto/skein.h> #ifndef SKEIN_USE_ASM #define SKEIN_USE_ASM (0) /* default is all C code (no ASM) */ diff --git a/jni/libzrtp/sources/cryptcommon/skein_iv.h b/jni/libzrtp/sources/srtp/crypto/skein_iv.h similarity index 95% rename from jni/libzrtp/sources/cryptcommon/skein_iv.h rename to jni/libzrtp/sources/srtp/crypto/skein_iv.h index 22f591e79..0c62facbc 100644 --- a/jni/libzrtp/sources/cryptcommon/skein_iv.h +++ b/jni/libzrtp/sources/srtp/crypto/skein_iv.h @@ -1,7 +1,7 @@ #ifndef _SKEIN_IV_H_ #define _SKEIN_IV_H_ -#include <cryptcommon/skein.h> /* get Skein macros and types */ +#include <crypto/skein.h> /* get Skein macros and types */ /* ***************** Pre-computed Skein IVs ******************* diff --git a/jni/libzrtp/sources/cryptcommon/skein_port.h b/jni/libzrtp/sources/srtp/crypto/skein_port.h similarity index 93% rename from jni/libzrtp/sources/cryptcommon/skein_port.h rename to jni/libzrtp/sources/srtp/crypto/skein_port.h index 10cc08c3c..256e9d5a2 100644 --- a/jni/libzrtp/sources/cryptcommon/skein_port.h +++ b/jni/libzrtp/sources/srtp/crypto/skein_port.h @@ -15,7 +15,7 @@ ** ********************************************************************/ -#include <cryptcommon/brg_types.h> /* get integer type definitions */ +#include <crypto/brg_types.h> /* get integer type definitions */ /*r3gis3r : android already has that defined in types */ #ifndef ANDROID @@ -49,7 +49,7 @@ typedef uint_64t u64b_t; /* 64-bit unsigned integer */ */ #ifndef SKEIN_NEED_SWAP /* compile-time "override" for endianness? */ -#include <cryptcommon/brg_endian.h> /* get endianness selection */ +#include <crypto/brg_endian.h> /* get endianness selection */ #if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN /* here for big-endian CPUs */ #define SKEIN_NEED_SWAP (1) diff --git a/jni/libzrtp/sources/zrtp/ZIDCacheDb.cpp b/jni/libzrtp/sources/zrtp/ZIDCacheDb.cpp deleted file mode 100644 index abe0a814b..000000000 --- a/jni/libzrtp/sources/zrtp/ZIDCacheDb.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Authors: Werner Dittmann <Werner.Dittmann@t-online.de> - */ -// #define UNIT_TEST - -#include <string> -#include <time.h> -#include <stdlib.h> - -#include <libzrtpcpp/ZIDCacheDb.h> - - -static ZIDCacheDb* instance; - -/** - * A poor man's factory. - * - * The build process must not allow to implementation classes linked - * into the same library. - */ - -ZIDCache* getZidCacheInstance() { - - if (instance == NULL) { - instance = new ZIDCacheDb(); - } - return instance; -} - - -ZIDCacheDb::~ZIDCacheDb() { - close(); -} - -int ZIDCacheDb::open(char* name) { - - // check for an already active ZID file - if (zidFile != NULL) { - return 0; - } - if (cacheOps.openCache(name, &zidFile, errorBuffer) == 0) - cacheOps.readLocalZid(zidFile, associatedZid, NULL, errorBuffer); - else { - cacheOps.closeCache(zidFile); - zidFile = NULL; - } - - return ((zidFile == NULL) ? -1 : 1); -} - -void ZIDCacheDb::close() { - - if (zidFile != NULL) { - cacheOps.closeCache(zidFile); - zidFile = NULL; - } -} - -ZIDRecord *ZIDCacheDb::getRecord(unsigned char *zid) { - ZIDRecordDb *zidRecord = new ZIDRecordDb(); - - cacheOps.readRemoteZidRecord(zidFile, zid, associatedZid, zidRecord->getRecordData(), errorBuffer); - - zidRecord->setZid(zid); - - // We need to create a new ZID record. - if (!zidRecord->isValid()) { - zidRecord->setValid(); - zidRecord->getRecordData()->secureSince = (int64_t)time(NULL); - cacheOps.insertRemoteZidRecord(zidFile, zid, associatedZid, zidRecord->getRecordData(), errorBuffer); - } - return zidRecord; -} - -unsigned int ZIDCacheDb::saveRecord(ZIDRecord *zidRec) { - ZIDRecordDb *zidRecord = reinterpret_cast<ZIDRecordDb *>(zidRec); - - cacheOps.updateRemoteZidRecord(zidFile, zidRecord->getIdentifier(), associatedZid, zidRecord->getRecordData(), errorBuffer); - return 1; -} - -int32_t ZIDCacheDb::getPeerName(const uint8_t *peerZid, std::string *name) { - zidNameRecord_t nameRec; - char buffer[201] = {'\0'}; - - nameRec.name = buffer; - nameRec.nameLength = 200; - cacheOps.readZidNameRecord(zidFile, peerZid, associatedZid, NULL, &nameRec, errorBuffer); - if ((nameRec.flags & Valid) != Valid) { - return 0; - } - name->assign(buffer); - return name->length(); -} - -void ZIDCacheDb::putPeerName(const uint8_t *peerZid, const std::string name) { - zidNameRecord_t nameRec; - char buffer[201] = {'\0'}; - - nameRec.name = buffer; - nameRec.nameLength = 200; - cacheOps.readZidNameRecord(zidFile, peerZid, associatedZid, NULL, &nameRec, errorBuffer); - - nameRec.name = (char*)name.c_str(); - nameRec.nameLength = name.length(); - nameRec.nameLength = nameRec.nameLength > 200 ? 200 : nameRec.nameLength; - if ((nameRec.flags & Valid) != Valid) { - nameRec.flags = Valid; - cacheOps.insertZidNameRecord(zidFile, peerZid, associatedZid, NULL, &nameRec, errorBuffer); - } - else - cacheOps.updateZidNameRecord(zidFile, peerZid, associatedZid, NULL, &nameRec, errorBuffer); - - return; -} - -void ZIDCacheDb::cleanup() { - cacheOps.cleanCache(zidFile, errorBuffer); - cacheOps.readLocalZid(zidFile, associatedZid, NULL, errorBuffer); -} diff --git a/jni/libzrtp/sources/zrtp/ZIDCacheFile.cpp b/jni/libzrtp/sources/zrtp/ZIDCacheFile.cpp deleted file mode 100644 index 5975fc2c5..000000000 --- a/jni/libzrtp/sources/zrtp/ZIDCacheFile.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Authors: Werner Dittmann <Werner.Dittmann@t-online.de> - */ -// #define UNIT_TEST - -#include <string> -#include <stdlib.h> -#include <unistd.h> - -#include <crypto/zrtpDH.h> - -#include <libzrtpcpp/ZIDCacheFile.h> - - -static ZIDCacheFile* instance; -static int errors = 0; // maybe we will use as member of ZIDCache later... - - -/** - * A poor man's factory. - * - * The build process must not allow two cache file implementation classes linked - * into the same library. - */ - -ZIDCache* getZidCacheInstance() { - - if (instance == NULL) { - instance = new ZIDCacheFile(); - } - return instance; -} - - -void ZIDCacheFile::createZIDFile(char* name) { - zidFile = fopen(name, "wb+"); - // New file, generate an associated random ZID and save - // it as first record - if (zidFile != NULL) { - randomZRTP(associatedZid, IDENTIFIER_LEN); - - ZIDRecordFile rec; - rec.setZid(associatedZid); - rec.setOwnZIDRecord(); - fseek(zidFile, 0L, SEEK_SET); - if (fwrite(rec.getRecordData(), rec.getRecordLength(), 1, zidFile) < 1) - ++errors; - fflush(zidFile); - } -} - -/** - * Migrate old ZID file format to new one. - * - * If ZID file is old format: - * - close it, rename it, then re-open - * - create ZID file for new format - * - copy over contents and flags. - */ -void ZIDCacheFile::checkDoMigration(char* name) { - FILE* fdOld; - unsigned char inb[2]; - zidrecord1_t recOld; - - fseek(zidFile, 0L, SEEK_SET); - if (fread(inb, 2, 1, zidFile) < 1) { - ++errors; - inb[0] = 0; - } - - if (inb[0] > 0) { // if it's new format just return - return; - } - fclose(zidFile); // close old ZID file - zidFile = NULL; - - // create save file name, rename and re-open - // if rename fails, just unlink old ZID file and create a brand new file - // just a little inconvenience for the user, need to verify new SAS - std::string fn = std::string(name) + std::string(".save"); - if (rename(name, fn.c_str()) < 0) { - unlink(name); - createZIDFile(name); - return; - } - fdOld = fopen(fn.c_str(), "rb"); // reopen old format in read only mode - - // Get first record from old file - is the own ZID - fseek(fdOld, 0L, SEEK_SET); - if (fread(&recOld, sizeof(zidrecord1_t), 1, fdOld) != 1) { - fclose(fdOld); - return; - } - if (recOld.ownZid != 1) { - fclose(fdOld); - return; - } - zidFile = fopen(name, "wb+"); // create new format file in binary r/w mode - if (zidFile == NULL) { - return; - } - // create ZIDRecord in new format, copy over own ZID and write the record - ZIDRecordFile rec; - rec.setZid(recOld.identifier); - rec.setOwnZIDRecord(); - if (fwrite(rec.getRecordData(), rec.getRecordLength(), 1, zidFile) < 1) - ++errors; - - // now copy over all valid records from old ZID file format. - // Sequentially read old records, sequentially write new records - int numRead; - do { - numRead = fread(&recOld, sizeof(zidrecord1_t), 1, fdOld); - if (numRead == 0) { // all old records processed - break; - } - // skip own ZID record and invalid records - if (recOld.ownZid == 1 || recOld.recValid == 0) { - continue; - } - ZIDRecordFile rec2; - rec2.setZid(recOld.identifier); - rec2.setValid(); - if (recOld.rs1Valid & SASVerified) { - rec2.setSasVerified(); - } - rec2.setNewRs1(recOld.rs2Data); // TODO: check squenec - rec2.setNewRs1(recOld.rs1Data); - if (fwrite(rec2.getRecordData(), rec2.getRecordLength(), 1, zidFile) < 1) - ++errors; - - } while (numRead == 1); - fflush(zidFile); -} - -ZIDCacheFile::~ZIDCacheFile() { - close(); -} - -int ZIDCacheFile::open(char* name) { - - // check for an already active ZID file - if (zidFile != NULL) { - return 0; - } - if ((zidFile = fopen(name, "rb+")) == NULL) { - createZIDFile(name); - } else { - checkDoMigration(name); - if (zidFile != NULL) { - ZIDRecordFile rec; - fseek(zidFile, 0L, SEEK_SET); - if (fread(rec.getRecordData(), rec.getRecordLength(), 1, zidFile) != 1) { - fclose(zidFile); - zidFile = NULL; - return -1; - } - if (!rec.isOwnZIDRecord()) { - fclose(zidFile); - zidFile = NULL; - return -1; - } - memcpy(associatedZid, rec.getIdentifier(), IDENTIFIER_LEN); - } - } - return ((zidFile == NULL) ? -1 : 1); -} - -void ZIDCacheFile::close() { - - if (zidFile != NULL) { - fclose(zidFile); - zidFile = NULL; - } -} - -ZIDRecord *ZIDCacheFile::getRecord(unsigned char *zid) { - unsigned long pos; - int numRead; - // ZIDRecordFile rec; - ZIDRecordFile *zidRecord = new ZIDRecordFile(); - - // set read pointer behind first record ( - fseek(zidFile, zidRecord->getRecordLength(), SEEK_SET); - - do { - pos = ftell(zidFile); - numRead = fread(zidRecord->getRecordData(), zidRecord->getRecordLength(), 1, zidFile); - if (numRead == 0) { - break; - } - - // skip own ZID record and invalid records - if (zidRecord->isOwnZIDRecord() || !zidRecord->isValid()) { - continue; - } - - } while (numRead == 1 && - memcmp(zidRecord->getIdentifier(), zid, IDENTIFIER_LEN) != 0); - - // If we reached end of file, then no record with the ZID - // found. We need to create a new ZID record. - if (numRead == 0) { - // create new record - // ZIDRecordFile rec1; - zidRecord->setZid(zid); - zidRecord->setValid(); - if (fwrite(zidRecord->getRecordData(), zidRecord->getRecordLength(), 1, zidFile) < 1) - ++errors; - } - // remember position of record in file for save operation - zidRecord->setPosition(pos); - return zidRecord; -} - -unsigned int ZIDCacheFile::saveRecord(ZIDRecord *zidRec) { - ZIDRecordFile *zidRecord = reinterpret_cast<ZIDRecordFile *>(zidRec); - - fseek(zidFile, zidRecord->getPosition(), SEEK_SET); - if (fwrite(zidRecord->getRecordData(), zidRecord->getRecordLength(), 1, zidFile) < 1) - ++errors; - fflush(zidFile); - return 1; -} - -int32_t ZIDCacheFile::getPeerName(const uint8_t *peerZid, std::string *name) { - return 0; -} - -void ZIDCacheFile::putPeerName(const uint8_t *peerZid, const std::string name) { - return; -} diff --git a/jni/libzrtp/sources/zrtp/ZIDRecordDb.cpp b/jni/libzrtp/sources/zrtp/ZIDRecordDb.cpp deleted file mode 100644 index b097cbfa4..000000000 --- a/jni/libzrtp/sources/zrtp/ZIDRecordDb.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Authors: Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#include <time.h> - -#include <libzrtpcpp/ZIDRecordDb.h> - -void ZIDRecordDb::setNewRs1(const unsigned char* data, int32_t expire) { - - // shift RS1 data into RS2 position - memcpy(record.rs2, record.rs1, RS_LENGTH); - record.rs2Ttl = record.rs1Ttl; - - // set new RS1 data - memcpy(record.rs1, data, RS_LENGTH); - - time_t validThru; - if (expire == -1) { - validThru = -1; - } - else if (expire <= 0) { - validThru = 0; - } - else { - validThru = time(NULL) + expire; - } - record.rs1Ttl = validThru; - resetRs2Valid(); - setRs1Valid(); -} - - -bool ZIDRecordDb::isRs1NotExpired() { - time_t current = time(NULL); - time_t validThru; - - validThru = record.rs1Ttl; - - if (validThru == -1) - return true; - if (validThru == 0) - return false; - return (current <= validThru) ? true : false; -} - -bool ZIDRecordDb::isRs2NotExpired() { - time_t current = time(NULL); - time_t validThru; - - validThru = record.rs2Ttl; - - if (validThru == -1) - return true; - if (validThru == 0) - return false; - return (current <= validThru) ? true : false; -} - -void ZIDRecordDb::setMiTMData(const unsigned char* data) { - memcpy(record.mitmKey, data, RS_LENGTH); - setMITMKeyAvailable(); -} diff --git a/jni/libzrtp/sources/zrtp/ZrtpSdesStream.cpp b/jni/libzrtp/sources/zrtp/ZrtpSdesStream.cpp deleted file mode 100644 index a6756af75..000000000 --- a/jni/libzrtp/sources/zrtp/ZrtpSdesStream.cpp +++ /dev/null @@ -1,729 +0,0 @@ -/* - Copyright (C) 2012-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -#include <string> -#include <sstream> - -#include <libzrtpcpp/ZrtpSdesStream.h> -#include <libzrtpcpp/ZrtpTextData.h> -#include <libzrtpcpp/ZrtpConfigure.h> -#include <libzrtpcpp/zrtpB64Decode.h> -#include <libzrtpcpp/zrtpB64Encode.h> -#include <srtp/SrtpHandler.h> -#include <srtp/CryptoContext.h> -#include <srtp/CryptoContextCtrl.h> -#include <cryptcommon/ZrtpRandom.h> -#include <crypto/hmac384.h> - - -#if defined(_WIN32) || defined(_WIN64) -# define snprintf _snprintf -#endif - -// SRTP authentication tag length is 80 bits = 10 bytes -#define ZRTP_TUNNEL_AUTH_LEN 10 -#define ZRTP_TUNNEL_LABEL 10 -/* - * The ABNF grammar for the crypto attribute is defined below (from RFC 4568): - * - * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params *(1*WSP session-param) - * - * tag = 1*9DIGIT - */ - -/* - * Buffer size for names and other strings inside the crypto string. The parse - * format below restricts parsing to 99 char to provide space for the @c nul byte. - */ -#define MAX_INNER_LEN 100 - -/* - * This format scans a received SDES crypto attribute string according to the - * grammer shown above but without a "a=crypto:" prefix. - * - * The format string parses: - * - %d - the tag as decimal value - * - %s - the crypto suite name, limited to 99 chars (see MAX_INNER_LEN) - * - %s - the key parameters, limited to 99 chars - * - %n - the number of parsed characters to far. The pointer to the session - * parameters is: cryptoString + numParsedChars. - */ -static const char parseCrypto[] = "%d %99s %99s %n"; - -static const int64_t maxTagValue = 999999999; - -static const int minElementsCrypto = 3; - -/* - * The ABNF grammar for the key-param (from RFC 4568): - * - * key-param = key-method ":" key-info - * - * The SRTP specific definitions: - * - * key-method = srtp-key-method - * key-info = srtp-key-info - * - * srtp-key-method = "inline" - * srtp-key-info = key-salt ["|" lifetime] ["|" mki] - * - */ - -/* - * This format parses the key parameter string which is never longer than - * 99 chars (see parse string above): - * - the fixed string "inline:" - * - %[A-Za-z0-9+/=] - base 64 characters of master key||master salt - * - the fixed separator character '|' - * - %[0-9^] - the lifetime infomration as string that contains digits and ^ - * - the fixed separator character '|' - * - %[0-9]:%d - parses and strore MKI value and MKI length, separated by ':' - * - * If the key parameter string does not contain the operional fields lifetime - * and MKI information the respective parameters are not filled. - */ -static const char parseKeyParam[] = " inline:%[A-Za-z0-9+/=]|%[0-9^]|%[0-9]:%d"; - -static const int minElementsKeyParam = 1; - -typedef struct _cryptoMix { - const char* name; - int32_t hashLength; - ZrtpSdesStream::sdesHmacTypeMix hashType; -} cryptoMix; - -static const size_t MIX_HMAC_STRING_MIN_LEN = sizeof("HMAC-SHA-384"); - -static cryptoMix knownMixAlgos[] = { - {"HMAC-SHA-384", 384, ZrtpSdesStream::MIX_HMAC_SHA}, - {NULL, 0, ZrtpSdesStream::MIX_NONE} -}; - -typedef struct _suite { - ZrtpSdesStream::sdesSuites suite; - const char *name; - int32_t keyLength; // key length in bits - int32_t saltLength; // salt lenght in bits - int32_t authKeyLength; // authentication key length in bits - const char *tagLength; // tag type hs80 or hs32 - const char *cipher; // aes1 or aes3 - uint32_t b64length; // length of b64 encoded key/saltstring - uint64_t defaultSrtpLifetime; // key lifetimes in number of packets - uint64_t defaultSrtcpLifetime; -} suiteParam; - -/* NOTE: the b64len of a 128 bit suite is 40, a 256bit suite uses 64 characters */ -static suiteParam knownSuites[] = { - {ZrtpSdesStream::AES_CM_128_HMAC_SHA1_32, "AES_CM_128_HMAC_SHA1_32", 128, 112, 160, - hs32, "AES-128", 40, (uint64_t)1<<48, (uint64_t)1<<31 - }, - {ZrtpSdesStream::AES_CM_128_HMAC_SHA1_80, "AES_CM_128_HMAC_SHA1_80", 128, 112, 160, - hs80, "AES-128", 40, (uint64_t)1<<48, (uint64_t)1<<31 - }, - {(ZrtpSdesStream::sdesSuites)0, NULL, 0, 0, 0, 0, 0, 0, 0, 0} -}; - -ZrtpSdesStream::ZrtpSdesStream(const sdesSuites s) : - state(STREAM_INITALIZED), suite(s), recvSrtp(NULL), recvSrtcp(NULL), sendSrtp(NULL), - sendSrtcp(NULL), srtcpIndex(0), recvZrtpTunnel(0), sendZrtpTunnel(0), cryptoMixHashLength(0), - cryptoMixHashType(MIX_NONE) { -} - -ZrtpSdesStream::~ZrtpSdesStream() { - close(); -} - -void ZrtpSdesStream::close() { - delete sendSrtp; - sendSrtp = NULL; - - delete recvSrtp; - recvSrtp = NULL; - - delete sendSrtcp; - sendSrtp = NULL; - - delete recvSrtcp; - recvSrtp = NULL; - - delete recvZrtpTunnel; - recvZrtpTunnel = NULL; - - delete sendZrtpTunnel; - sendZrtpTunnel = NULL; -} - -bool ZrtpSdesStream::createSdes(char *cryptoString, size_t *maxLen, bool sipInvite) { - - if (sipInvite) { - if (state != STREAM_INITALIZED) - return false; - tag = 1; - } - else { - if (state != IN_PROFILE_READY) - return false; - } - - bool s = createSdesProfile(cryptoString, maxLen); - if (!s) - return s; - - if (sipInvite) { - state = OUT_PROFILE_READY; - } - else { - createSrtpContexts(sipInvite); - state = SDES_SRTP_ACTIVE; - } - return s; -} - -bool ZrtpSdesStream::parseSdes(const char *cryptoString, size_t length, bool sipInvite) { - - if (sipInvite) { - if (state != OUT_PROFILE_READY) - return false; - } - else { - if (state != STREAM_INITALIZED) - return false; - } - sdesSuites tmpSuite; - int32_t tmpTag; - - bool s = parseCreateSdesProfile(cryptoString, length, &tmpSuite, &tmpTag); - if (!s) - return s; - - if (sipInvite) { - // Check if answerer used same tag and suite as the offerer - if (tmpTag != tag || suite != tmpSuite) - return false; - createSrtpContexts(sipInvite); - state = SDES_SRTP_ACTIVE; - } - else { - // Answerer stores tag and suite and uses it in createSdesProfile - suite = tmpSuite; - tag = tmpTag; - state = IN_PROFILE_READY; - } - return s; -} - -bool ZrtpSdesStream::outgoingRtp(uint8_t *packet, size_t length, size_t *newLength) { - - if (state != SDES_SRTP_ACTIVE || sendSrtp == NULL) { - *newLength = length; - return true; - } - bool rc = SrtpHandler::protect(sendSrtp, packet, length, newLength); - if (rc) - ;//protect++; - return rc; -} - -int ZrtpSdesStream::incomingRtp(uint8_t *packet, size_t length, size_t *newLength) { - if (state != SDES_SRTP_ACTIVE || recvSrtp == NULL) { // SRTP inactive, just return with newLength set - *newLength = length; - return 1; - } - int32_t rc = SrtpHandler::unprotect(recvSrtp, packet, length, newLength); - if (rc == 1) { -// unprotect++ - } - else { -// unprotectFailed++; - } - return rc; -} - - -bool ZrtpSdesStream::outgoingZrtpTunnel(uint8_t *packet, size_t length, size_t *newLength) { - - if (state != SDES_SRTP_ACTIVE || sendZrtpTunnel == NULL) { - *newLength = length; - return true; - } - bool rc = SrtpHandler::protect(sendZrtpTunnel, packet, length, newLength); - if (rc) - ;//protect++; - return rc; -} - -int ZrtpSdesStream::incomingZrtpTunnel(uint8_t *packet, size_t length, size_t *newLength) { - if (state != SDES_SRTP_ACTIVE || recvZrtpTunnel == NULL) { // SRTP inactive, just return with newLength set - *newLength = length; - return 1; - } - int32_t rc = SrtpHandler::unprotect(recvZrtpTunnel, packet, length, newLength); - if (rc == 1) { -// unprotect++ - } - else { -// unprotectFailed++; - } - return rc; -} - - - -bool ZrtpSdesStream::outgoingRtcp(uint8_t *packet, size_t length, size_t *newLength) { -#if 0 -SrtpHandler::protectCtrl(CryptoContextCtrl* pcc, uint8_t* buffer, size_t length, size_t* newLength, uint32_t *srtcpIndex) -#endif - return false; -} - -int ZrtpSdesStream::incomingSrtcp(uint8_t *packet, size_t length, size_t *newLength) { -#if 0 -int32_t SrtpHandler::unprotectCtrl(CryptoContextCtrl* pcc, uint8_t* buffer, size_t length, size_t* newLength) -#endif - return 0; -} - -const char* ZrtpSdesStream::getCipher() { - return knownSuites[suite].cipher; -} - -const char* ZrtpSdesStream::getAuthAlgo() { - if (strcmp(knownSuites[suite].tagLength, hs80) == 0) - return "HMAC-SHA1 80 bit"; - else - return "HMAC-SHA1 32 bit"; -} - -int ZrtpSdesStream::getCryptoMixAttribute(char *algoNames, size_t length) { - - if (length < MIX_HMAC_STRING_MIN_LEN) - return 0; - - // In case we support more than one MIX profile select the correct one if the - // application called setCryptoMixAttribute(...) and we already selected the one to use. - if (cryptoMixHashType != MIX_NONE) { - for (cryptoMix* cp = knownMixAlgos; cp->name != NULL; cp++) { - if (cp->hashLength == cryptoMixHashLength && cp->hashType == cryptoMixHashType) { - strcpy(algoNames, cp->name); - return strlen(cp->name); - } - } - } - // TODO: enhance here to support multiple algorithms (concatenate strings into the buffer until buffer full) - else { - strcpy(algoNames, knownMixAlgos[0].name); - return strlen(algoNames); - } - return 0; -} - -bool ZrtpSdesStream::setCryptoMixAttribute(const char *algoNames) { - - int len = strlen(algoNames); - if (len <= 0) - return false; - - std::string algoIn(algoNames); - algoIn += ' '; - - // split input name string and lookup if we support one of the offered algorithms - // We take the first match. - std::string delimiters = " "; - size_t current; - size_t next = -1; - - do { - current = next + 1; - next = algoIn.find_first_of(delimiters, current); - if (next == std::string::npos) - break; - - std::string tmps = algoIn.substr(current, next - current ); - const char* nm = tmps.c_str(); - - for (cryptoMix* cp = knownMixAlgos; cp->name != NULL; cp++) { - if (strncmp(cp->name, nm, strlen(cp->name)) == 0) { - cryptoMixHashLength = cp->hashLength; - cryptoMixHashType = cp->hashType; - return true; - } - } - } while (true); - - return false; -} - -#ifdef WEAKRANDOM -/* - * A standard random number generator that uses the portable random() system function. - * - * This should be enhanced to use a better random generator - */ -static int _random(unsigned char *output, size_t len) -{ - size_t i; - - for(i = 0; i < len; ++i ) - output[i] = random(); - - return( 0 ); -} -#else -#include <cryptcommon/ZrtpRandom.h> -static int _random(unsigned char *output, size_t len) -{ - return ZrtpRandom::getRandomData(output, len); -} -#endif - -static int b64Encode(const uint8_t *binData, int32_t binLength, char *b64Data, int32_t b64Length) -{ - base64_encodestate _state; - int codelength; - - base64_init_encodestate(&_state, 0); - codelength = base64_encode_block(binData, binLength, b64Data, &_state); - codelength += base64_encode_blockend(b64Data+codelength, &_state); - - return codelength; -} - -static int b64Decode(const char *b64Data, int32_t b64length, uint8_t *binData, int32_t binLength) -{ - base64_decodestate _state; - int codelength; - - base64_init_decodestate(&_state); - codelength = base64_decode_block(b64Data, b64length, binData, &_state); - return codelength; -} - -void* createSha384HmacContext(uint8_t* key, int32_t keyLength); -void freeSha384HmacContext(void* ctx); -void hmacSha384Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], uint8_t* mac, int32_t* macLength ); - -static int expand(uint8_t* prk, uint32_t prkLen, uint8_t* info, int32_t infoLen, int32_t L, uint32_t hashLen, uint8_t* outbuffer) -{ - int32_t n; - uint8_t *T; - void* hmacCtx; - - const uint8_t* data[4]; // 3 data pointers for HMAC data plus terminating NULL - uint32_t dataLen[4]; - int32_t dataIdx = 0; - - uint8_t counter; - int32_t macLength; - - if (prkLen < hashLen) - return -1; - - n = (L + (hashLen-1)) / hashLen; - - // T points to buffer that holds concatenated T(1) || T(2) || ... T(N)) - T = reinterpret_cast<uint8_t*>(malloc(n * hashLen)); - - if (hashLen == 384/8) - hmacCtx = createSha384HmacContext(prk, prkLen); - else - return -1; - - // Prepare first HMAC. T(0) has zero length, thus we ignore it in first run. - // After first run use its output (T(1)) as first data in next HMAC run. - for (int i = 1; i <= n; i++) { - if (infoLen > 0 && info != NULL) { - data[dataIdx] = info; - dataLen[dataIdx++] = infoLen; - } - counter = i & 0xff; - data[dataIdx] = &counter; - dataLen[dataIdx++] = 1; - - data[dataIdx] = NULL; - dataLen[dataIdx++] = 0; - - if (hashLen == 384/8) - hmacSha384Ctx(hmacCtx, data, dataLen, T + ((i-1) * hashLen), &macLength); - - // Use output of previous hash run as first input of next hash run - dataIdx = 0; - data[dataIdx] = T + ((i-1) * hashLen); - dataLen[dataIdx++] = hashLen; - } - freeSha384HmacContext(hmacCtx); - memcpy(outbuffer, T, L); - free(T); - return 0; -} - -void ZrtpSdesStream::computeMixedKeys(bool sipInvite) { - uint8_t salt[MAX_SALT_LEN*2]; - uint8_t ikm[MAX_KEY_LEN*2]; - - // Concatenate the existing salt and key data. Depending on our role we have to change - // the order of the data. - if (sipInvite) { // We are offerer, use local created data as mso and mko, so they go first - memcpy(salt, &localKeySalt[localKeyLenBytes], localSaltLenBytes); - memcpy(&salt[localSaltLenBytes], &remoteKeySalt[remoteKeyLenBytes], remoteSaltLenBytes); - - memcpy(ikm, localKeySalt, localKeyLenBytes); - memcpy(&ikm[localKeyLenBytes], remoteKeySalt, remoteKeyLenBytes); - } - else { - memcpy(salt, &remoteKeySalt[remoteKeyLenBytes], remoteSaltLenBytes); - memcpy(&salt[remoteSaltLenBytes], &localKeySalt[localKeyLenBytes], localSaltLenBytes); - - memcpy(ikm, remoteKeySalt, remoteKeyLenBytes); - memcpy(&ikm[remoteKeyLenBytes], localKeySalt, localKeyLenBytes); - } - uint32_t saltLen = localSaltLenBytes + remoteSaltLenBytes; - uint32_t keyLen = localKeyLenBytes + remoteKeyLenBytes; - uint32_t L = saltLen + keyLen; - - uint8_t prk[MAX_DIGEST_LENGTH]; - uint32_t prkLen; - - switch(cryptoMixHashType) { - case MIX_HMAC_SHA: - if (cryptoMixHashLength == 384) - hmac_sha384(salt, saltLen, ikm, keyLen, prk, &prkLen); - else - return; - break; - - case MIX_MAC_SKEIN: - return; - - default: - return; - } - - uint8_t T[(MAX_SALT_LEN + MAX_KEY_LEN)*2] = {0}; - expand(prk, prkLen, NULL, 0, L, cryptoMixHashLength/8, T); - - // We have a new set of SRTP key data now, replace the old with the new. - int32_t offset = 0; - if (sipInvite) { // We are offerer, replace local created data with mso and mko, remote with msa, mka - memcpy(&localKeySalt[localKeyLenBytes], T, localSaltLenBytes); - offset += localSaltLenBytes; - memcpy(&remoteKeySalt[remoteKeyLenBytes], &T[offset], remoteSaltLenBytes); - offset += remoteSaltLenBytes; - - memcpy(localKeySalt, &T[offset], localKeyLenBytes); - offset += localKeyLenBytes; - memcpy(remoteKeySalt, &T[offset], remoteKeyLenBytes); - } - else { // We are answerer, replace remote data with mso and mko, local data with msa, mka - memcpy(&remoteKeySalt[remoteKeyLenBytes], T, remoteSaltLenBytes); - offset += remoteSaltLenBytes; - memcpy(&localKeySalt[localKeyLenBytes], &T[offset], localSaltLenBytes); - offset += localSaltLenBytes; - - memcpy(remoteKeySalt, &T[offset], remoteKeyLenBytes); - offset += remoteKeyLenBytes; - memcpy(localKeySalt, &T[offset], localKeyLenBytes); - } -} - -void ZrtpSdesStream::createSrtpContexts(bool sipInvite) { - - if (cryptoMixHashType != MIX_NONE) { - computeMixedKeys(sipInvite); - } - - sendSrtp = new CryptoContext(0, // SSRC (used for lookup) - 0, // Roll-Over-Counter (ROC) - 0L, // keyderivation << 48, - localCipher, // encryption algo - localAuthn, // authtentication algo - localKeySalt, // Master Key - localKeyLenBytes, // Master Key length - &localKeySalt[localKeyLenBytes], // Master Salt - localSaltLenBytes, // Master Salt length - localKeyLenBytes, // encryption keylen - localAuthKeyLen, // authentication key len (HMAC key lenght) - localSaltLenBytes, // session salt len - localTagLength); // authentication tag len - sendSrtp->deriveSrtpKeys(0L); - - sendZrtpTunnel = new CryptoContext(0, // SSRC (used for lookup) - 0, // Roll-Over-Counter (ROC) - 0L, // keyderivation << 48, - localCipher, // encryption algo - localAuthn, // authtentication algo - localKeySalt, // Master Key - localKeyLenBytes, // Master Key length - &localKeySalt[localKeyLenBytes], // Master Salt - localSaltLenBytes, // Master Salt length - localKeyLenBytes, // encryption keylen - localAuthKeyLen, // authentication key len (HMAC key lenght) - localSaltLenBytes, // session salt len - ZRTP_TUNNEL_AUTH_LEN); // authentication tag len - - sendZrtpTunnel->setLabelbase(ZRTP_TUNNEL_LABEL); - sendZrtpTunnel->deriveSrtpKeys(0L); - memset(localKeySalt, 0, sizeof(localKeySalt)); - - recvSrtp = new CryptoContext(0, // SSRC (used for lookup) - 0, // Roll-Over-Counter (ROC) - 0L, // keyderivation << 48, - remoteCipher, // encryption algo - remoteAuthn, // authtentication algo - remoteKeySalt, // Master Key - remoteKeyLenBytes, // Master Key length - &remoteKeySalt[remoteKeyLenBytes], // Master Salt - remoteSaltLenBytes, // Master Salt length - remoteKeyLenBytes, // encryption keylen - remoteAuthKeyLen, // authentication key len (HMAC key lenght) - remoteSaltLenBytes, // session salt len - remoteTagLength); // authentication tag len - recvSrtp->deriveSrtpKeys(0L); - - recvZrtpTunnel = new CryptoContext(0, // SSRC (used for lookup) - 0, // Roll-Over-Counter (ROC) - 0L, // keyderivation << 48, - remoteCipher, // encryption algo - remoteAuthn, // authtentication algo - remoteKeySalt, // Master Key - remoteKeyLenBytes, // Master Key length - &remoteKeySalt[remoteKeyLenBytes], // Master Salt - remoteSaltLenBytes, // Master Salt length - remoteKeyLenBytes, // encryption keylen - remoteAuthKeyLen, // authentication key len (HMAC key lenght) - remoteSaltLenBytes, // session salt len - ZRTP_TUNNEL_AUTH_LEN); // authentication tag len - - recvZrtpTunnel->setLabelbase(ZRTP_TUNNEL_LABEL); - recvZrtpTunnel->deriveSrtpKeys(0L); - memset(remoteKeySalt, 0, sizeof(remoteKeySalt)); -} - -bool ZrtpSdesStream::createSdesProfile(char *cryptoString, size_t *maxLen) { - - char b64keySalt[(MAX_KEY_LEN + MAX_SALT_LEN) * 2] = {'\0'}; - uint32_t sidx; - int32_t b64Len; - - for (sidx = 0; knownSuites[sidx].name != NULL; sidx++) { // Lookup crypto suite parameters - if (knownSuites[sidx].suite == suite) - break; - } - if (sidx >= sizeof(knownSuites)/sizeof(struct _suite)) { - return false; - } - suiteParam *pSuite = &knownSuites[sidx]; - _random(localKeySalt, sizeof(localKeySalt)); - - AlgorithmEnum& auth = zrtpAuthLengths.getByName(pSuite->tagLength); - localAuthn = SrtpAuthenticationSha1Hmac; - localAuthKeyLen = pSuite->authKeyLength / 8; - localTagLength = auth.getKeylen() / 8; - - // If SDES will support other encryption algos - get it here based on - // the algorithm name in suite - localCipher = SrtpEncryptionAESCM; - - localKeyLenBytes = pSuite->keyLength / 8; - localSaltLenBytes = pSuite->saltLength / 8; - - if (tag == -1) - tag = 1; - - // Get B64 code for master key and master salt and then construct the SDES crypto string - b64Len = b64Encode(localKeySalt, localKeyLenBytes + localSaltLenBytes, b64keySalt, sizeof(b64keySalt)); - b64keySalt[b64Len] = '\0'; - memset(cryptoString, 0, *maxLen); - *maxLen = snprintf(cryptoString, *maxLen-1, "%d %s inline:%s", tag, pSuite->name, b64keySalt); - - return true; -} - -bool ZrtpSdesStream::parseCreateSdesProfile(const char *cryptoStr, size_t length, sdesSuites *parsedSuite, int32_t *outTag) { - int elements, i; - int charsScanned; - int mkiLength = 0; - uint32_t sidx; - - char cryptoString[MAX_CRYPT_STRING_LEN+1] = {'\0'}; - - /* Parsed strings */ - char suiteName[MAX_INNER_LEN] = {'\0'}; - char keyParams[MAX_INNER_LEN] = {'\0'}; - char keySaltB64[MAX_INNER_LEN] = {'\0'}; - char lifetime[MAX_INNER_LEN] = {'\0'}; - char mkiVal[MAX_INNER_LEN] = {'\0'}; - - if (length == 0) - length = strlen(cryptoStr); - - if (length > MAX_CRYPT_STRING_LEN) { - return false; - } - memcpy(cryptoString, cryptoStr, length); // make own copy, null terminated - - *outTag = -1; - elements = sscanf(cryptoString, parseCrypto, outTag, suiteName, keyParams, &charsScanned); - - if (elements < minElementsCrypto) { // Do we have enough elements in the string - return false; - } - - for (sidx = 0; knownSuites[sidx].name != NULL; sidx++) { // Lookup crypto suite - if (!strcmp(knownSuites[sidx].name, suiteName)) - break; - } - if (sidx >= sizeof(knownSuites)/sizeof(struct _suite)) { - return false; - } - suiteParam *pSuite = &knownSuites[sidx]; - *parsedSuite = pSuite->suite; - - /* Now scan the key parameters */ - elements = sscanf(keyParams, parseKeyParam, keySaltB64, lifetime, mkiVal, &mkiLength); - - if (elements != minElementsKeyParam) { // Currently we only accept key||salt B64 string, no other parameters - return false; - } - - remoteKeyLenBytes = pSuite->keyLength / 8; - remoteSaltLenBytes = pSuite->saltLength / 8; - - if (strlen(keySaltB64) != pSuite->b64length) { // Check if key||salt B64 string hast the correct length - return false; - } - i = b64Decode(keySaltB64, pSuite->b64length, remoteKeySalt, remoteKeyLenBytes + remoteSaltLenBytes); - - if (i != (remoteKeyLenBytes + remoteSaltLenBytes)) { // Did the B64 decode delivered enough data for key||salt - return false; - } - - AlgorithmEnum& auth = zrtpAuthLengths.getByName(pSuite->tagLength); - remoteAuthn = SrtpAuthenticationSha1Hmac; - remoteAuthKeyLen = pSuite->authKeyLength / 8; - remoteTagLength = auth.getKeylen() / 8; - - // If SDES will support other encryption algos - get it here based on - // the algorithm name in suite - remoteCipher = SrtpEncryptionAESCM; - - return true; -} \ No newline at end of file diff --git a/jni/libzrtp/sources/zrtp/ZrtpTextData.cpp b/jni/libzrtp/sources/zrtp/ZrtpTextData.cpp deleted file mode 100644 index ecf5b6d2d..000000000 --- a/jni/libzrtp/sources/zrtp/ZrtpTextData.cpp +++ /dev/null @@ -1,621 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Authors: Werner Dittmann <Werner.Dittmann@t-online.de> - */ -#include <stdint.h> -#include <libzrtpcpp/ZrtpConfigure.h> -// 1 -// 1234567890123456 -char clientId[] = "GNU ZRTP 4.1.1 "; // 16 chars max. -char zrtpVersion_11[] = "1.10"; // must be 4 chars -char zrtpVersion_12[] = "1.20"; // must be 4 chars -/** - * - */ -char HelloMsg[] = "Hello "; -char HelloAckMsg[] = "HelloACK"; -char CommitMsg[] = "Commit "; -char DHPart1Msg[] = "DHPart1 "; -char DHPart2Msg[] = "DHPart2 "; -char Confirm1Msg[] = "Confirm1"; -char Confirm2Msg[] = "Confirm2"; -char Conf2AckMsg[] = "Conf2ACK"; -char ErrorMsg[] = "Error "; -char ErrorAckMsg[] = "ErrorACK"; -char GoClearMsg[] = "GoClear "; -char ClearAckMsg[] = "ClearACK"; -char PingMsg[] = "Ping "; -char PingAckMsg[] = "PingACK "; -char SasRelayMsg[] = "SASrelay"; -char RelayAckMsg[] = "RelayACK"; - -char responder[] = "Responder"; -char initiator[] = "Initiator"; -char iniMasterKey[] = "Initiator SRTP master key"; -char iniMasterSalt[] = "Initiator SRTP master salt"; -char respMasterKey[] = "Responder SRTP master key"; -char respMasterSalt[] = "Responder SRTP master salt"; - -char iniHmacKey[] = "Initiator HMAC key"; -char respHmacKey[] = "Responder HMAC key"; -char retainedSec[] = "retained secret"; - -char iniZrtpKey[] = "Initiator ZRTP key"; -char respZrtpKey[] = "Responder ZRTP key"; - -char sasString[] = "SAS"; - -char KDFString[] = "ZRTP-HMAC-KDF"; - -char zrtpSessionKey[] = "ZRTP Session Key"; - -char zrtpMsk[] = "ZRTP MSK"; -char zrtpTrustedMitm[] = "Trusted MiTM key"; - -char s256[] = "S256"; -char s384[] = "S384"; -char skn2[] = "SKN2"; -char skn3[] = "SKN3"; -const char* mandatoryHash = s256; - -char aes3[] = "AES3"; -char aes2[] = "AES2"; -char aes1[] = "AES1"; -char two3[] = "2FS3"; -char two2[] = "2FS2"; -char two1[] = "2FS1"; -const char* mandatoryCipher = aes1; - -char dh2k[] = "DH2k"; -char ec25[] = "EC25"; -char dh3k[] = "DH3k"; -char ec38[] = "EC38"; -char e255[] = "E255"; -char e414[] = "E414"; -char mult[] = "Mult"; -const char* mandatoryPubKey = dh3k; - -char b32[] = "B32 "; -char b256[] = "B256"; -const char* mandatorySasType = b32; - -char hs32[] = "HS32"; -char hs80[] = "HS80"; -char sk32[] = "SK32"; -char sk64[] = "SK64"; -const char* mandatoryAuthLen_1 = hs32; -const char* mandatoryAuthLen_2 = hs80; - -const char* sas256WordsOdd[] = { - "adroitness", - "adviser", - "aftermath", - "aggregate", - "alkali", - "almighty", - "amulet", - "amusement", - "antenna", - "applicant", - "Apollo", - "armistice", - "article", - "asteroid", - "Atlantic", - "atmosphere", - "autopsy", - "Babylon", - "backwater", - "barbecue", - "belowground", - "bifocals", - "bodyguard", - "bookseller", - "borderline", - "bottomless", - "Bradbury", - "bravado", - "Brazilian", - "breakaway", - "Burlington", - "businessman", - "butterfat", - "Camelot", - "candidate", - "cannonball", - "Capricorn", - "caravan", - "caretaker", - "celebrate", - "cellulose", - "certify", - "chambermaid", - "Cherokee", - "Chicago", - "clergyman", - "coherence", - "combustion", - "commando", - "company", - "component", - "concurrent", - "confidence", - "conformist", - "congregate", - "consensus", - "consulting", - "corporate", - "corrosion", - "councilman", - "crossover", - "crucifix", - "cumbersome", - "customer", - "Dakota", - "decadence", - "December", - "decimal", - "designing", - "detector", - "detergent", - "determine", - "dictator", - "dinosaur", - "direction", - "disable", - "disbelief", - "disruptive", - "distortion", - "document", - "embezzle", - "enchanting", - "enrollment", - "enterprise", - "equation", - "equipment", - "escapade", - "Eskimo", - "everyday", - "examine", - "existence", - "exodus", - "fascinate", - "filament", - "finicky", - "forever", - "fortitude", - "frequency", - "gadgetry", - "Galveston", - "getaway", - "glossary", - "gossamer", - "graduate", - "gravity", - "guitarist", - "hamburger", - "Hamilton", - "handiwork", - "hazardous", - "headwaters", - "hemisphere", - "hesitate", - "hideaway", - "holiness", - "hurricane", - "hydraulic", - "impartial", - "impetus", - "inception", - "indigo", - "inertia", - "infancy", - "inferno", - "informant", - "insincere", - "insurgent", - "integrate", - "intention", - "inventive", - "Istanbul", - "Jamaica", - "Jupiter", - "leprosy", - "letterhead", - "liberty", - "maritime", - "matchmaker", - "maverick", - "Medusa", - "megaton", - "microscope", - "microwave", - "midsummer", - "millionaire", - "miracle", - "misnomer", - "molasses", - "molecule", - "Montana", - "monument", - "mosquito", - "narrative", - "nebula", - "newsletter", - "Norwegian", - "October", - "Ohio", - "onlooker", - "opulent", - "Orlando", - "outfielder", - "Pacific", - "pandemic", - "Pandora", - "paperweight", - "paragon", - "paragraph", - "paramount", - "passenger", - "pedigree", - "Pegasus", - "penetrate", - "perceptive", - "performance", - "pharmacy", - "phonetic", - "photograph", - "pioneer", - "pocketful", - "politeness", - "positive", - "potato", - "processor", - "provincial", - "proximate", - "puberty", - "publisher", - "pyramid", - "quantity", - "racketeer", - "rebellion", - "recipe", - "recover", - "repellent", - "replica", - "reproduce", - "resistor", - "responsive", - "retraction", - "retrieval", - "retrospect", - "revenue", - "revival", - "revolver", - "sandalwood", - "sardonic", - "Saturday", - "savagery", - "scavenger", - "sensation", - "sociable", - "souvenir", - "specialist", - "speculate", - "stethoscope", - "stupendous", - "supportive", - "surrender", - "suspicious", - "sympathy", - "tambourine", - "telephone", - "therapist", - "tobacco", - "tolerance", - "tomorrow", - "torpedo", - "tradition", - "travesty", - "trombonist", - "truncated", - "typewriter", - "ultimate", - "undaunted", - "underfoot", - "unicorn", - "unify", - "universe", - "unravel", - "upcoming", - "vacancy", - "vagabond", - "vertigo", - "Virginia", - "visitor", - "vocalist", - "voyager", - "warranty", - "Waterloo", - "whimsical", - "Wichita", - "Wilmington", - "Wyoming", - "yesteryear", - "Yucatan" - }; - -const char* sas256WordsEven[] = { - "aardvark", - "absurd", - "accrue", - "acme", - "adrift", - "adult", - "afflict", - "ahead", - "aimless", - "Algol", - "allow", - "alone", - "ammo", - "ancient", - "apple", - "artist", - "assume", - "Athens", - "atlas", - "Aztec", - "baboon", - "backfield", - "backward", - "banjo", - "beaming", - "bedlamp", - "beehive", - "beeswax", - "befriend", - "Belfast", - "berserk", - "billiard", - "bison", - "blackjack", - "blockade", - "blowtorch", - "bluebird", - "bombast", - "bookshelf", - "brackish", - "breadline", - "breakup", - "brickyard", - "briefcase", - "Burbank", - "button", - "buzzard", - "cement", - "chairlift", - "chatter", - "checkup", - "chisel", - "choking", - "chopper", - "Christmas", - "clamshell", - "classic", - "classroom", - "cleanup", - "clockwork", - "cobra", - "commence", - "concert", - "cowbell", - "crackdown", - "cranky", - "crowfoot", - "crucial", - "crumpled", - "crusade", - "cubic", - "dashboard", - "deadbolt", - "deckhand", - "dogsled", - "dragnet", - "drainage", - "dreadful", - "drifter", - "dropper", - "drumbeat", - "drunken", - "Dupont", - "dwelling", - "eating", - "edict", - "egghead", - "eightball", - "endorse", - "endow", - "enlist", - "erase", - "escape", - "exceed", - "eyeglass", - "eyetooth", - "facial", - "fallout", - "flagpole", - "flatfoot", - "flytrap", - "fracture", - "framework", - "freedom", - "frighten", - "gazelle", - "Geiger", - "glitter", - "glucose", - "goggles", - "goldfish", - "gremlin", - "guidance", - "hamlet", - "highchair", - "hockey", - "indoors", - "indulge", - "inverse", - "involve", - "island", - "jawbone", - "keyboard", - "kickoff", - "kiwi", - "klaxon", - "locale", - "lockup", - "merit", - "minnow", - "miser", - "Mohawk", - "mural", - "music", - "necklace", - "Neptune", - "newborn", - "nightbird", - "Oakland", - "obtuse", - "offload", - "optic", - "orca", - "payday", - "peachy", - "pheasant", - "physique", - "playhouse", - "Pluto", - "preclude", - "prefer", - "preshrunk", - "printer", - "prowler", - "pupil", - "puppy", - "python", - "quadrant", - "quiver", - "quota", - "ragtime", - "ratchet", - "rebirth", - "reform", - "regain", - "reindeer", - "rematch", - "repay", - "retouch", - "revenge", - "reward", - "rhythm", - "ribcage", - "ringbolt", - "robust", - "rocker", - "ruffled", - "sailboat", - "sawdust", - "scallion", - "scenic", - "scorecard", - "Scotland", - "seabird", - "select", - "sentence", - "shadow", - "shamrock", - "showgirl", - "skullcap", - "skydive", - "slingshot", - "slowdown", - "snapline", - "snapshot", - "snowcap", - "snowslide", - "solo", - "southward", - "soybean", - "spaniel", - "spearhead", - "spellbind", - "spheroid", - "spigot", - "spindle", - "spyglass", - "stagehand", - "stagnate", - "stairway", - "standard", - "stapler", - "steamship", - "sterling", - "stockman", - "stopwatch", - "stormy", - "sugar", - "surmount", - "suspense", - "sweatband", - "swelter", - "tactics", - "talon", - "tapeworm", - "tempest", - "tiger", - "tissue", - "tonic", - "topmost", - "tracker", - "transit", - "trauma", - "treadmill", - "Trojan", - "trouble", - "tumor", - "tunnel", - "tycoon", - "uncut", - "unearth", - "unwind", - "uproot", - "upset", - "upshot", - "vapor", - "village", - "virus", - "Vulcan", - "waffle", - "wallet", - "watchword", - "wayside", - "willow", - "woodlark", - "Zulu" - }; diff --git a/jni/libzrtp/sources/zrtp/crypto/aesCFB.cpp b/jni/libzrtp/sources/zrtp/crypto/aesCFB.cpp deleted file mode 100644 index f3042f8be..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/aesCFB.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2012-2013 by Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/** - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#include <string.h> - -#include <zrtp/crypto/aesCFB.h> -#include <cryptcommon/aescpp.h> - -void aesCfbEncrypt(uint8_t *key, int32_t keyLength, uint8_t* IV, uint8_t *data, int32_t dataLength) -{ - AESencrypt *saAes = new AESencrypt(); - - if (keyLength == 16) - saAes->key128(key); - else if (keyLength == 32) - saAes->key256(key); - else - return; - - // Note: maybe copy IV to an internal array if we encounter strange things. - // the cfb encrypt modify the IV on return. Same for output data (inplace encryption) - saAes->cfb_encrypt(data, data, dataLength, IV); - delete saAes; -} - - -void aesCfbDecrypt(uint8_t *key, int32_t keyLength, uint8_t* IV, uint8_t *data, int32_t dataLength) -{ - AESencrypt *saAes = new AESencrypt(); - if (keyLength == 16) - saAes->key128(key); - else if (keyLength == 32) - saAes->key256(key); - else - return; - - // Note: maybe copy IV to an internal array if we encounter strange things. - // the cfb encrypt modify the IV on return. Same for output data (inplace encryption) - saAes->cfb_decrypt(data, data, dataLength, IV); - delete saAes; -} diff --git a/jni/libzrtp/sources/zrtp/crypto/hmac256.cpp b/jni/libzrtp/sources/zrtp/crypto/hmac256.cpp deleted file mode 100644 index 1e3ceb7d6..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/hmac256.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright (C) 2012-2013 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/* - * Authors: Werner Dittmann - */ - -#include <stdint.h> -#include <string.h> -#include <stdio.h> -#include "zrtp/crypto/sha2.h" -#include "zrtp/crypto/hmac256.h" - -typedef struct _hmacSha256Context { - sha256_ctx ctx; - sha256_ctx innerCtx; - sha256_ctx outerCtx; -} hmacSha256Context; - -static int32_t hmacSha256Init(hmacSha256Context *ctx, const uint8_t *key, uint32_t kLength) -{ - int32_t i; - uint8_t localPad[SHA256_BLOCK_SIZE] = {0}; - uint8_t localKey[SHA256_BLOCK_SIZE] = {0}; - - if (key == NULL) - return 0; - - memset(ctx, 0, sizeof(hmacSha256Context)); - - /* check key length and reduce it if necessary */ - if (kLength > SHA256_BLOCK_SIZE) { - sha256_begin(&ctx->ctx); - sha256_hash(key, kLength, &ctx->ctx); - sha256_end(localKey, &ctx->ctx); - } - else { - memcpy(localKey, key, kLength); - } - /* prepare inner hash and hold the context */ - for (i = 0; i < SHA256_BLOCK_SIZE; i++) - localPad[i] = localKey[i] ^ 0x36; - - sha256_begin(&ctx->innerCtx); - sha256_hash(localPad, SHA256_BLOCK_SIZE, &ctx->innerCtx); - - /* prepare outer hash and hold the context */ - for (i = 0; i < SHA256_BLOCK_SIZE; i++) - localPad[i] = localKey[i] ^ 0x5c; - - sha256_begin(&ctx->outerCtx); - sha256_hash(localPad, SHA256_BLOCK_SIZE, &ctx->outerCtx); - - /* copy prepared inner hash to work hash - ready to process data */ - memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha256_ctx)); - - memset(localKey, 0, sizeof(localKey)); - - return 1; -} - -static void hmacSha256Reset(hmacSha256Context *ctx) -{ - /* copy prepared inner hash to work hash context */ - memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha256_ctx)); -} - -static void hmacSha256Update(hmacSha256Context *ctx, const uint8_t *data, uint32_t dLength) -{ - /* hash new data to work hash context */ - sha256_hash(data, dLength, &ctx->ctx); -} - -static void hmacSha256Final(hmacSha256Context *ctx, uint8_t *mac) -{ - uint8_t tmpDigest[SHA256_DIGEST_SIZE]; - - /* finalize work hash context */ - sha256_end(tmpDigest, &ctx->ctx); - - /* copy prepared outer hash to work hash */ - memcpy(&ctx->ctx, &ctx->outerCtx, sizeof(sha256_ctx)); - - /* hash inner digest to work (outer) hash context */ - sha256_hash(tmpDigest, SHA256_DIGEST_SIZE, &ctx->ctx); - - /* finalize work hash context to get the hmac*/ - sha256_end(mac, &ctx->ctx); -} - - -void hmac_sha256(uint8_t *key, uint32_t keyLength, uint8_t* data, int32_t dataLength, uint8_t* mac, uint32_t* macLength) -{ - hmacSha256Context ctx; - - hmacSha256Init(&ctx, key, keyLength); - hmacSha256Update(&ctx, data, dataLength); - hmacSha256Final(&ctx, mac); - *macLength = SHA256_DIGEST_SIZE; -} - -void hmac_sha256(uint8_t* key, uint32_t keyLength, uint8_t* dataChunks[], uint32_t dataChunckLength[], - uint8_t* mac, uint32_t* macLength ) -{ - hmacSha256Context ctx; - - hmacSha256Init(&ctx, key, keyLength); - - while (*dataChunks) { - hmacSha256Update(&ctx, *dataChunks, *dataChunckLength); - dataChunks ++; - dataChunckLength ++; - } - hmacSha256Final(&ctx, mac); - *macLength = SHA256_DIGEST_SIZE; -} - -void* createSha256HmacContext(uint8_t* key, int32_t keyLength) -{ - hmacSha256Context *ctx = reinterpret_cast<hmacSha256Context*>(malloc(sizeof(hmacSha256Context))); - - hmacSha256Init(ctx, key, keyLength); - return ctx; -} - -void hmacSha256Ctx(void* ctx, const uint8_t* data, uint32_t dataLength, - uint8_t* mac, int32_t* macLength) -{ - hmacSha256Context *pctx = (hmacSha256Context*)ctx; - - hmacSha256Reset(pctx); - hmacSha256Update(pctx, data, dataLength); - hmacSha256Final(pctx, mac); - *macLength = SHA256_DIGEST_SIZE; -} - -void hmacSha256Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], - uint8_t* mac, int32_t* macLength ) -{ - hmacSha256Context *pctx = (hmacSha256Context*)ctx; - - hmacSha256Reset(pctx); - while (*data) { - hmacSha256Update(pctx, *data, *dataLength); - data++; - dataLength++; - } - hmacSha256Final(pctx, mac); - *macLength = SHA256_DIGEST_SIZE; -} - -void freeSha256HmacContext(void* ctx) -{ - if (ctx) { - memset(ctx, 0, sizeof(hmacSha256Context)); - free(ctx); - } -} \ No newline at end of file diff --git a/jni/libzrtp/sources/zrtp/crypto/hmac384.cpp b/jni/libzrtp/sources/zrtp/crypto/hmac384.cpp deleted file mode 100644 index c7a7abdad..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/hmac384.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright (C) 2012 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/* - * Authors: Werner Dittmann - */ - -#include <stdint.h> -#include <string.h> -#include <stdio.h> -#include "zrtp/crypto/sha2.h" -#include "zrtp/crypto/hmac384.h" - -typedef struct _hmacSha384Context { - sha384_ctx ctx; - sha384_ctx innerCtx; - sha384_ctx outerCtx; -} hmacSha384Context; - -static int32_t hmacSha384Init(hmacSha384Context *ctx, const uint8_t *key, uint32_t kLength) -{ - int32_t i; - uint8_t localPad[SHA384_BLOCK_SIZE] = {0}; - uint8_t localKey[SHA384_BLOCK_SIZE] = {0}; - - if (key == NULL) - return 0; - - memset(ctx, 0, sizeof(hmacSha384Context)); - - /* check key length and reduce it if necessary */ - if (kLength > SHA384_BLOCK_SIZE) { - sha384_begin(&ctx->ctx); - sha384_hash(key, kLength, &ctx->ctx); - sha384_end(localKey, &ctx->ctx); - } - else { - memcpy(localKey, key, kLength); - } - /* prepare inner hash and hold the context */ - for (i = 0; i < SHA384_BLOCK_SIZE; i++) - localPad[i] = localKey[i] ^ 0x36; - - sha384_begin(&ctx->innerCtx); - sha384_hash(localPad, SHA384_BLOCK_SIZE, &ctx->innerCtx); - - /* prepare outer hash and hold the context */ - for (i = 0; i < SHA384_BLOCK_SIZE; i++) - localPad[i] = localKey[i] ^ 0x5c; - - sha384_begin(&ctx->outerCtx); - sha384_hash(localPad, SHA384_BLOCK_SIZE, &ctx->outerCtx); - - /* copy prepared inner hash to work hash - ready to process data */ - memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha384_ctx)); - - memset(localKey, 0, sizeof(localKey)); - - return 1; -} - -static void hmacSha384Reset(hmacSha384Context *ctx) -{ - /* copy prepared inner hash to work hash context */ - memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha384_ctx)); -} - -static void hmacSha384Update(hmacSha384Context *ctx, const uint8_t *data, uint32_t dLength) -{ - /* hash new data to work hash context */ - sha384_hash(data, dLength, &ctx->ctx); -} - -static void hmacSha384Final(hmacSha384Context *ctx, uint8_t *mac) -{ - uint8_t tmpDigest[SHA384_DIGEST_SIZE]; - - /* finalize work hash context */ - sha384_end(tmpDigest, &ctx->ctx); - - /* copy prepared outer hash to work hash */ - memcpy(&ctx->ctx, &ctx->outerCtx, sizeof(sha384_ctx)); - - /* hash inner digest to work (outer) hash context */ - sha384_hash(tmpDigest, SHA384_DIGEST_SIZE, &ctx->ctx); - - /* finalize work hash context to get the hmac*/ - sha384_end(mac, &ctx->ctx); -} - - -void hmac_sha384(uint8_t *key, uint32_t keyLength, uint8_t* data, int32_t dataLength, uint8_t* mac, uint32_t* macLength) -{ - hmacSha384Context ctx; - - hmacSha384Init(&ctx, key, keyLength); - hmacSha384Update(&ctx, data, dataLength); - hmacSha384Final(&ctx, mac); - *macLength = SHA384_DIGEST_SIZE; -} - -void hmac_sha384( uint8_t* key, uint32_t keyLength, uint8_t* dataChunks[], uint32_t dataChunckLength[], - uint8_t* mac, uint32_t* macLength ) -{ - hmacSha384Context ctx; - - hmacSha384Init(&ctx, key, keyLength); - - while (*dataChunks) { - hmacSha384Update(&ctx, *dataChunks, *dataChunckLength); - dataChunks ++; - dataChunckLength ++; - } - hmacSha384Final(&ctx, mac); - *macLength = SHA384_DIGEST_SIZE; -} - -void* createSha384HmacContext(uint8_t* key, int32_t keyLength) -{ - hmacSha384Context *ctx = reinterpret_cast<hmacSha384Context*>(malloc(sizeof(hmacSha384Context))); - - hmacSha384Init(ctx, key, keyLength); - return ctx; -} - -void hmacSha384Ctx(void* ctx, const uint8_t* data, uint32_t dataLength, - uint8_t* mac, int32_t* macLength) -{ - hmacSha384Context *pctx = (hmacSha384Context*)ctx; - - hmacSha384Reset(pctx); - hmacSha384Update(pctx, data, dataLength); - hmacSha384Final(pctx, mac); - *macLength = SHA384_DIGEST_SIZE; -} - -void hmacSha384Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], - uint8_t* mac, int32_t* macLength ) -{ - hmacSha384Context *pctx = (hmacSha384Context*)ctx; - - hmacSha384Reset(pctx); - while (*data) { - hmacSha384Update(pctx, *data, *dataLength); - data++; - dataLength++; - } - hmacSha384Final(pctx, mac); - *macLength = SHA384_DIGEST_SIZE; -} - -void freeSha384HmacContext(void* ctx) -{ - if (ctx) { - memset(ctx, 0, sizeof(hmacSha384Context)); - free(ctx); - } -} \ No newline at end of file diff --git a/jni/libzrtp/sources/zrtp/crypto/sha2.c b/jni/libzrtp/sources/zrtp/crypto/sha2.c deleted file mode 100644 index 22761f3d1..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/sha2.c +++ /dev/null @@ -1,773 +0,0 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - ALTERNATIVELY, provided that this notice is retained in full, this product - may be distributed under the terms of the GNU General Public License (GPL), - in which case the provisions of the GPL apply INSTEAD OF those given above. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 01/08/2005 - - This is a byte oriented version of SHA2 that operates on arrays of bytes - stored in memory. This code implements sha256, sha384 and sha512 but the - latter two functions rely on efficient 64-bit integer operations that - may not be very efficient on 32-bit machines - - The sha256 functions use a type 'sha256_ctx' to hold details of the - current hash state and uses the following three calls: - - void sha256_begin(sha256_ctx ctx[1]) - void sha256_hash(const unsigned char data[], - unsigned long len, sha256_ctx ctx[1]) - void sha_end1(unsigned char hval[], sha256_ctx ctx[1]) - - The first subroutine initialises a hash computation by setting up the - context in the sha256_ctx context. The second subroutine hashes 8-bit - bytes from array data[] into the hash state withinh sha256_ctx context, - the number of bytes to be hashed being given by the the unsigned long - integer len. The third subroutine completes the hash calculation and - places the resulting digest value in the array of 8-bit bytes hval[]. - - The sha384 and sha512 functions are similar and use the interfaces: - - void sha384_begin(sha384_ctx ctx[1]); - void sha384_hash(const unsigned char data[], - unsigned long len, sha384_ctx ctx[1]); - void sha384_end(unsigned char hval[], sha384_ctx ctx[1]); - - void sha512_begin(sha512_ctx ctx[1]); - void sha512_hash(const unsigned char data[], - unsigned long len, sha512_ctx ctx[1]); - void sha512_end(unsigned char hval[], sha512_ctx ctx[1]); - - In addition there is a function sha2 that can be used to call all these - functions using a call with a hash length parameter as follows: - - int sha2_begin(unsigned long len, sha2_ctx ctx[1]); - void sha2_hash(const unsigned char data[], - unsigned long len, sha2_ctx ctx[1]); - void sha2_end(unsigned char hval[], sha2_ctx ctx[1]); - - My thanks to Erik Andersen <andersen@codepoet.org> for testing this code - on big-endian systems and for his assistance with corrections -*/ - -#if 0 -#define UNROLL_SHA2 /* for SHA2 loop unroll */ -#endif - -#include <string.h> /* for memcpy() etc. */ - -#include "sha2.h" - -#include <cryptcommon/brg_endian.h> - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#if defined( _MSC_VER ) && ( _MSC_VER > 800 ) -#pragma intrinsic(memcpy) -#endif - -#if 0 && defined(_MSC_VER) -#define rotl32 _lrotl -#define rotr32 _lrotr -#else -#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) -#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) -#endif - -#if !defined(bswap_32) -#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) -#endif - -#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) -#define SWAP_BYTES -#else -#undef SWAP_BYTES -#endif - -#if 0 - -#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) -#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -#else /* Thanks to Rich Schroeppel and Colin Plumb for the following */ - -#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) - -#endif - -/* round transforms for SHA256 and SHA512 compression functions */ - -#define vf(n,i) v[(n - i) & 7] - -#define hf(i) (p[i & 15] += \ - g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15])) - -#define v_cycle(i,j) \ - vf(7,i) += (j ? hf(i) : p[i]) + k_0[i+j] \ - + s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i)); \ - vf(3,i) += vf(7,i); \ - vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i)) - -#if defined(SHA_224) || defined(SHA_256) - -#define SHA256_MASK (SHA256_BLOCK_SIZE - 1) - -#if defined(SWAP_BYTES) -#define bsw_32(p,n) \ - { int _i = (n); while(_i--) ((uint_32t*)p)[_i] = bswap_32(((uint_32t*)p)[_i]); } -#else -#define bsw_32(p,n) -#endif - -#define s_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22)) -#define s_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25)) -#define g_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3)) -#define g_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10)) -#define k_0 k256 - -/* rotated SHA256 round definition. Rather than swapping variables as in */ -/* FIPS-180, different variables are 'rotated' on each round, returning */ -/* to their starting positions every eight rounds */ - -#define q(n) v##n - -#define one_cycle(a,b,c,d,e,f,g,h,k,w) \ - q(h) += s_1(q(e)) + ch(q(e), q(f), q(g)) + k + w; \ - q(d) += q(h); q(h) += s_0(q(a)) + maj(q(a), q(b), q(c)) - -/* SHA256 mixing data */ - -const uint_32t k256[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, -}; - -/* Compile 64 bytes of hash data into SHA256 digest value */ -/* NOTE: this routine assumes that the byte order in the */ -/* ctx->wbuf[] at this point is such that low address bytes */ -/* in the ORIGINAL byte stream will go into the high end of */ -/* words on BOTH big and little endian systems */ - -VOID_RETURN sha256_compile(sha256_ctx ctx[1]) -{ -#if !defined(UNROLL_SHA2) - - uint_32t j, *p = ctx->wbuf, v[8]; - - memcpy(v, ctx->hash, 8 * sizeof(uint_32t)); - - for(j = 0; j < 64; j += 16) - { - v_cycle( 0, j); v_cycle( 1, j); - v_cycle( 2, j); v_cycle( 3, j); - v_cycle( 4, j); v_cycle( 5, j); - v_cycle( 6, j); v_cycle( 7, j); - v_cycle( 8, j); v_cycle( 9, j); - v_cycle(10, j); v_cycle(11, j); - v_cycle(12, j); v_cycle(13, j); - v_cycle(14, j); v_cycle(15, j); - } - - ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; - ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; - ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; - ctx->hash[6] += v[6]; ctx->hash[7] += v[7]; - -#else - - uint_32t *p = ctx->wbuf,v0,v1,v2,v3,v4,v5,v6,v7; - - v0 = ctx->hash[0]; v1 = ctx->hash[1]; - v2 = ctx->hash[2]; v3 = ctx->hash[3]; - v4 = ctx->hash[4]; v5 = ctx->hash[5]; - v6 = ctx->hash[6]; v7 = ctx->hash[7]; - - one_cycle(0,1,2,3,4,5,6,7,k256[ 0],p[ 0]); - one_cycle(7,0,1,2,3,4,5,6,k256[ 1],p[ 1]); - one_cycle(6,7,0,1,2,3,4,5,k256[ 2],p[ 2]); - one_cycle(5,6,7,0,1,2,3,4,k256[ 3],p[ 3]); - one_cycle(4,5,6,7,0,1,2,3,k256[ 4],p[ 4]); - one_cycle(3,4,5,6,7,0,1,2,k256[ 5],p[ 5]); - one_cycle(2,3,4,5,6,7,0,1,k256[ 6],p[ 6]); - one_cycle(1,2,3,4,5,6,7,0,k256[ 7],p[ 7]); - one_cycle(0,1,2,3,4,5,6,7,k256[ 8],p[ 8]); - one_cycle(7,0,1,2,3,4,5,6,k256[ 9],p[ 9]); - one_cycle(6,7,0,1,2,3,4,5,k256[10],p[10]); - one_cycle(5,6,7,0,1,2,3,4,k256[11],p[11]); - one_cycle(4,5,6,7,0,1,2,3,k256[12],p[12]); - one_cycle(3,4,5,6,7,0,1,2,k256[13],p[13]); - one_cycle(2,3,4,5,6,7,0,1,k256[14],p[14]); - one_cycle(1,2,3,4,5,6,7,0,k256[15],p[15]); - - one_cycle(0,1,2,3,4,5,6,7,k256[16],hf( 0)); - one_cycle(7,0,1,2,3,4,5,6,k256[17],hf( 1)); - one_cycle(6,7,0,1,2,3,4,5,k256[18],hf( 2)); - one_cycle(5,6,7,0,1,2,3,4,k256[19],hf( 3)); - one_cycle(4,5,6,7,0,1,2,3,k256[20],hf( 4)); - one_cycle(3,4,5,6,7,0,1,2,k256[21],hf( 5)); - one_cycle(2,3,4,5,6,7,0,1,k256[22],hf( 6)); - one_cycle(1,2,3,4,5,6,7,0,k256[23],hf( 7)); - one_cycle(0,1,2,3,4,5,6,7,k256[24],hf( 8)); - one_cycle(7,0,1,2,3,4,5,6,k256[25],hf( 9)); - one_cycle(6,7,0,1,2,3,4,5,k256[26],hf(10)); - one_cycle(5,6,7,0,1,2,3,4,k256[27],hf(11)); - one_cycle(4,5,6,7,0,1,2,3,k256[28],hf(12)); - one_cycle(3,4,5,6,7,0,1,2,k256[29],hf(13)); - one_cycle(2,3,4,5,6,7,0,1,k256[30],hf(14)); - one_cycle(1,2,3,4,5,6,7,0,k256[31],hf(15)); - - one_cycle(0,1,2,3,4,5,6,7,k256[32],hf( 0)); - one_cycle(7,0,1,2,3,4,5,6,k256[33],hf( 1)); - one_cycle(6,7,0,1,2,3,4,5,k256[34],hf( 2)); - one_cycle(5,6,7,0,1,2,3,4,k256[35],hf( 3)); - one_cycle(4,5,6,7,0,1,2,3,k256[36],hf( 4)); - one_cycle(3,4,5,6,7,0,1,2,k256[37],hf( 5)); - one_cycle(2,3,4,5,6,7,0,1,k256[38],hf( 6)); - one_cycle(1,2,3,4,5,6,7,0,k256[39],hf( 7)); - one_cycle(0,1,2,3,4,5,6,7,k256[40],hf( 8)); - one_cycle(7,0,1,2,3,4,5,6,k256[41],hf( 9)); - one_cycle(6,7,0,1,2,3,4,5,k256[42],hf(10)); - one_cycle(5,6,7,0,1,2,3,4,k256[43],hf(11)); - one_cycle(4,5,6,7,0,1,2,3,k256[44],hf(12)); - one_cycle(3,4,5,6,7,0,1,2,k256[45],hf(13)); - one_cycle(2,3,4,5,6,7,0,1,k256[46],hf(14)); - one_cycle(1,2,3,4,5,6,7,0,k256[47],hf(15)); - - one_cycle(0,1,2,3,4,5,6,7,k256[48],hf( 0)); - one_cycle(7,0,1,2,3,4,5,6,k256[49],hf( 1)); - one_cycle(6,7,0,1,2,3,4,5,k256[50],hf( 2)); - one_cycle(5,6,7,0,1,2,3,4,k256[51],hf( 3)); - one_cycle(4,5,6,7,0,1,2,3,k256[52],hf( 4)); - one_cycle(3,4,5,6,7,0,1,2,k256[53],hf( 5)); - one_cycle(2,3,4,5,6,7,0,1,k256[54],hf( 6)); - one_cycle(1,2,3,4,5,6,7,0,k256[55],hf( 7)); - one_cycle(0,1,2,3,4,5,6,7,k256[56],hf( 8)); - one_cycle(7,0,1,2,3,4,5,6,k256[57],hf( 9)); - one_cycle(6,7,0,1,2,3,4,5,k256[58],hf(10)); - one_cycle(5,6,7,0,1,2,3,4,k256[59],hf(11)); - one_cycle(4,5,6,7,0,1,2,3,k256[60],hf(12)); - one_cycle(3,4,5,6,7,0,1,2,k256[61],hf(13)); - one_cycle(2,3,4,5,6,7,0,1,k256[62],hf(14)); - one_cycle(1,2,3,4,5,6,7,0,k256[63],hf(15)); - - ctx->hash[0] += v0; ctx->hash[1] += v1; - ctx->hash[2] += v2; ctx->hash[3] += v3; - ctx->hash[4] += v4; ctx->hash[5] += v5; - ctx->hash[6] += v6; ctx->hash[7] += v7; -#endif -} - -/* SHA256 hash data in an array of bytes into hash buffer */ -/* and call the hash_compile function as required. */ - -VOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]) -{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA256_MASK), - space = SHA256_BLOCK_SIZE - pos; - const unsigned char *sp = data; - - if((ctx->count[0] += len) < len) - ++(ctx->count[1]); - - while(len >= space) /* tranfer whole blocks while possible */ - { - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); - sp += space; len -= space; space = SHA256_BLOCK_SIZE; pos = 0; - bsw_32(ctx->wbuf, SHA256_BLOCK_SIZE >> 2) - sha256_compile(ctx); - } - - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); -} - -/* SHA256 Final padding and digest calculation */ - -static void sha_end1(unsigned char hval[], sha256_ctx ctx[1], const unsigned int hlen) -{ uint_32t i = (uint_32t)(ctx->count[0] & SHA256_MASK); - - /* put bytes in the buffer in an order in which references to */ - /* 32-bit words will put bytes with lower addresses into the */ - /* top of 32 bit words on BOTH big and little endian machines */ - bsw_32(ctx->wbuf, (i + 3) >> 2) - - /* we now need to mask valid bytes and add the padding which is */ - /* a single 1 bit and as many zero bits as necessary. Note that */ - /* we can always add the first padding byte here because the */ - /* buffer always has at least one empty slot */ - ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3); - ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3); - - /* we need 9 or more empty positions, one for the padding byte */ - /* (above) and eight for the length count. If there is not */ - /* enough space pad and empty the buffer */ - if(i > SHA256_BLOCK_SIZE - 9) - { - if(i < 60) ctx->wbuf[15] = 0; - sha256_compile(ctx); - i = 0; - } - else /* compute a word index for the empty buffer positions */ - i = (i >> 2) + 1; - - while(i < 14) /* and zero pad all but last two positions */ - ctx->wbuf[i++] = 0; - - /* the following 32-bit length fields are assembled in the */ - /* wrong byte order on little endian machines but this is */ - /* corrected later since they are only ever used as 32-bit */ - /* word values. */ - ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); - ctx->wbuf[15] = ctx->count[0] << 3; - sha256_compile(ctx); - - /* extract the hash value as bytes in case the hash buffer is */ - /* mislaigned for 32-bit words */ - for(i = 0; i < hlen; ++i) - hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); -} - -#endif - -#if defined(SHA_224) - -const uint_32t i224[8] = -{ - 0xc1059ed8ul, 0x367cd507ul, 0x3070dd17ul, 0xf70e5939ul, - 0xffc00b31ul, 0x68581511ul, 0x64f98fa7ul, 0xbefa4fa4ul -}; - -VOID_RETURN sha224_begin(sha224_ctx ctx[1]) -{ - ctx->count[0] = ctx->count[1] = 0; - memcpy(ctx->hash, i224, 8 * sizeof(uint_32t)); -} - -VOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1]) -{ - sha_end1(hval, ctx, SHA224_DIGEST_SIZE); -} - -VOID_RETURN sha224(unsigned char hval[], const unsigned char data[], unsigned long len) -{ sha224_ctx cx[1]; - - sha224_begin(cx); - sha224_hash(data, len, cx); - sha_end1(hval, cx, SHA224_DIGEST_SIZE); -} - -#endif - -#if defined(SHA_256) - -const uint_32t i256[8] = -{ - 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, - 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul -}; - -VOID_RETURN sha256_begin(sha256_ctx ctx[1]) -{ - ctx->count[0] = ctx->count[1] = 0; - memcpy(ctx->hash, i256, 8 * sizeof(uint_32t)); -} - -VOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1]) -{ - sha_end1(hval, ctx, SHA256_DIGEST_SIZE); -} - -VOID_RETURN sha256(unsigned char hval[], const unsigned char data[], unsigned long len) -{ sha256_ctx cx[1]; - - sha256_begin(cx); - sha256_hash(data, len, cx); - sha_end1(hval, cx, SHA256_DIGEST_SIZE); -} - -#endif - -#if defined(SHA_384) || defined(SHA_512) - -#define SHA512_MASK (SHA512_BLOCK_SIZE - 1) - -#define rotr64(x,n) (((x) >> n) | ((x) << (64 - n))) - -#if !defined(bswap_64) -#define bswap_64(x) (((uint_64t)(bswap_32((uint_32t)(x)))) << 32 | bswap_32((uint_32t)((x) >> 32))) -#endif - -#if defined(SWAP_BYTES) -#define bsw_64(p,n) \ - { int _i = (n); while(_i--) ((uint_64t*)p)[_i] = bswap_64(((uint_64t*)p)[_i]); } -#else -#define bsw_64(p,n) -#endif - -/* SHA512 mixing function definitions */ - -#ifdef s_0 -# undef s_0 -# undef s_1 -# undef g_0 -# undef g_1 -# undef k_0 -#endif - -#define s_0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39)) -#define s_1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41)) -#define g_0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7)) -#define g_1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6)) -#define k_0 k512 - -/* SHA384/SHA512 mixing data */ - -const uint_64t k512[80] = -{ - li_64(428a2f98d728ae22), li_64(7137449123ef65cd), - li_64(b5c0fbcfec4d3b2f), li_64(e9b5dba58189dbbc), - li_64(3956c25bf348b538), li_64(59f111f1b605d019), - li_64(923f82a4af194f9b), li_64(ab1c5ed5da6d8118), - li_64(d807aa98a3030242), li_64(12835b0145706fbe), - li_64(243185be4ee4b28c), li_64(550c7dc3d5ffb4e2), - li_64(72be5d74f27b896f), li_64(80deb1fe3b1696b1), - li_64(9bdc06a725c71235), li_64(c19bf174cf692694), - li_64(e49b69c19ef14ad2), li_64(efbe4786384f25e3), - li_64(0fc19dc68b8cd5b5), li_64(240ca1cc77ac9c65), - li_64(2de92c6f592b0275), li_64(4a7484aa6ea6e483), - li_64(5cb0a9dcbd41fbd4), li_64(76f988da831153b5), - li_64(983e5152ee66dfab), li_64(a831c66d2db43210), - li_64(b00327c898fb213f), li_64(bf597fc7beef0ee4), - li_64(c6e00bf33da88fc2), li_64(d5a79147930aa725), - li_64(06ca6351e003826f), li_64(142929670a0e6e70), - li_64(27b70a8546d22ffc), li_64(2e1b21385c26c926), - li_64(4d2c6dfc5ac42aed), li_64(53380d139d95b3df), - li_64(650a73548baf63de), li_64(766a0abb3c77b2a8), - li_64(81c2c92e47edaee6), li_64(92722c851482353b), - li_64(a2bfe8a14cf10364), li_64(a81a664bbc423001), - li_64(c24b8b70d0f89791), li_64(c76c51a30654be30), - li_64(d192e819d6ef5218), li_64(d69906245565a910), - li_64(f40e35855771202a), li_64(106aa07032bbd1b8), - li_64(19a4c116b8d2d0c8), li_64(1e376c085141ab53), - li_64(2748774cdf8eeb99), li_64(34b0bcb5e19b48a8), - li_64(391c0cb3c5c95a63), li_64(4ed8aa4ae3418acb), - li_64(5b9cca4f7763e373), li_64(682e6ff3d6b2b8a3), - li_64(748f82ee5defb2fc), li_64(78a5636f43172f60), - li_64(84c87814a1f0ab72), li_64(8cc702081a6439ec), - li_64(90befffa23631e28), li_64(a4506cebde82bde9), - li_64(bef9a3f7b2c67915), li_64(c67178f2e372532b), - li_64(ca273eceea26619c), li_64(d186b8c721c0c207), - li_64(eada7dd6cde0eb1e), li_64(f57d4f7fee6ed178), - li_64(06f067aa72176fba), li_64(0a637dc5a2c898a6), - li_64(113f9804bef90dae), li_64(1b710b35131c471b), - li_64(28db77f523047d84), li_64(32caab7b40c72493), - li_64(3c9ebe0a15c9bebc), li_64(431d67c49c100d4c), - li_64(4cc5d4becb3e42b6), li_64(597f299cfc657e2a), - li_64(5fcb6fab3ad6faec), li_64(6c44198c4a475817) -}; - -/* Compile 128 bytes of hash data into SHA384/512 digest */ -/* NOTE: this routine assumes that the byte order in the */ -/* ctx->wbuf[] at this point is such that low address bytes */ -/* in the ORIGINAL byte stream will go into the high end of */ -/* words on BOTH big and little endian systems */ - -VOID_RETURN sha512_compile(sha512_ctx ctx[1]) -{ uint_64t v[8], *p = ctx->wbuf; - uint_32t j; - - memcpy(v, ctx->hash, 8 * sizeof(uint_64t)); - - for(j = 0; j < 80; j += 16) - { - v_cycle( 0, j); v_cycle( 1, j); - v_cycle( 2, j); v_cycle( 3, j); - v_cycle( 4, j); v_cycle( 5, j); - v_cycle( 6, j); v_cycle( 7, j); - v_cycle( 8, j); v_cycle( 9, j); - v_cycle(10, j); v_cycle(11, j); - v_cycle(12, j); v_cycle(13, j); - v_cycle(14, j); v_cycle(15, j); - } - - ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; - ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; - ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; - ctx->hash[6] += v[6]; ctx->hash[7] += v[7]; -} - -/* Compile 128 bytes of hash data into SHA256 digest value */ -/* NOTE: this routine assumes that the byte order in the */ -/* ctx->wbuf[] at this point is in such an order that low */ -/* address bytes in the ORIGINAL byte stream placed in this */ -/* buffer will now go to the high end of words on BOTH big */ -/* and little endian systems */ - -VOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]) -{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA512_MASK), - space = SHA512_BLOCK_SIZE - pos; - const unsigned char *sp = data; - - if((ctx->count[0] += len) < len) - ++(ctx->count[1]); - - while(len >= space) /* tranfer whole blocks while possible */ - { - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); - sp += space; len -= space; space = SHA512_BLOCK_SIZE; pos = 0; - bsw_64(ctx->wbuf, SHA512_BLOCK_SIZE >> 3); - sha512_compile(ctx); - } - - memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); -} - -/* SHA384/512 Final padding and digest calculation */ - -static void sha_end2(unsigned char hval[], sha512_ctx ctx[1], const unsigned int hlen) -{ uint_32t i = (uint_32t)(ctx->count[0] & SHA512_MASK); - - /* put bytes in the buffer in an order in which references to */ - /* 32-bit words will put bytes with lower addresses into the */ - /* top of 32 bit words on BOTH big and little endian machines */ - bsw_64(ctx->wbuf, (i + 7) >> 3); - - /* we now need to mask valid bytes and add the padding which is */ - /* a single 1 bit and as many zero bits as necessary. Note that */ - /* we can always add the first padding byte here because the */ - /* buffer always has at least one empty slot */ - ctx->wbuf[i >> 3] &= li_64(ffffffffffffff00) << 8 * (~i & 7); - ctx->wbuf[i >> 3] |= li_64(0000000000000080) << 8 * (~i & 7); - - /* we need 17 or more empty byte positions, one for the padding */ - /* byte (above) and sixteen for the length count. If there is */ - /* not enough space pad and empty the buffer */ - if(i > SHA512_BLOCK_SIZE - 17) - { - if(i < 120) ctx->wbuf[15] = 0; - sha512_compile(ctx); - i = 0; - } - else - i = (i >> 3) + 1; - - while(i < 14) - ctx->wbuf[i++] = 0; - - /* the following 64-bit length fields are assembled in the */ - /* wrong byte order on little endian machines but this is */ - /* corrected later since they are only ever used as 64-bit */ - /* word values. */ - ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 61); - ctx->wbuf[15] = ctx->count[0] << 3; - sha512_compile(ctx); - - /* extract the hash value as bytes in case the hash buffer is */ - /* misaligned for 32-bit words */ - for(i = 0; i < hlen; ++i) - hval[i] = (unsigned char)(ctx->hash[i >> 3] >> (8 * (~i & 7))); -} - -#endif - -#if defined(SHA_384) - -/* SHA384 initialisation data */ - -const uint_64t i384[80] = -{ - li_64(cbbb9d5dc1059ed8), li_64(629a292a367cd507), - li_64(9159015a3070dd17), li_64(152fecd8f70e5939), - li_64(67332667ffc00b31), li_64(8eb44a8768581511), - li_64(db0c2e0d64f98fa7), li_64(47b5481dbefa4fa4) -}; - -VOID_RETURN sha384_begin(sha384_ctx ctx[1]) -{ - ctx->count[0] = ctx->count[1] = 0; - memcpy(ctx->hash, i384, 8 * sizeof(uint_64t)); -} - -VOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1]) -{ - sha_end2(hval, ctx, SHA384_DIGEST_SIZE); -} - -VOID_RETURN sha384(unsigned char hval[], const unsigned char data[], unsigned long len) -{ sha384_ctx cx[1]; - - sha384_begin(cx); - sha384_hash(data, len, cx); - sha_end2(hval, cx, SHA384_DIGEST_SIZE); -} - -#endif - -#if defined(SHA_512) - -/* SHA512 initialisation data */ - -const uint_64t i512[80] = -{ - li_64(6a09e667f3bcc908), li_64(bb67ae8584caa73b), - li_64(3c6ef372fe94f82b), li_64(a54ff53a5f1d36f1), - li_64(510e527fade682d1), li_64(9b05688c2b3e6c1f), - li_64(1f83d9abfb41bd6b), li_64(5be0cd19137e2179) -}; - -VOID_RETURN sha512_begin(sha512_ctx ctx[1]) -{ - ctx->count[0] = ctx->count[1] = 0; - memcpy(ctx->hash, i512, 8 * sizeof(uint_64t)); -} - -VOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1]) -{ - sha_end2(hval, ctx, SHA512_DIGEST_SIZE); -} - -VOID_RETURN sha512(unsigned char hval[], const unsigned char data[], unsigned long len) -{ sha512_ctx cx[1]; - - sha512_begin(cx); - sha512_hash(data, len, cx); - sha_end2(hval, cx, SHA512_DIGEST_SIZE); -} - -#endif - -#if defined(SHA_2) - -#define CTX_224(x) ((x)->uu->ctx256) -#define CTX_256(x) ((x)->uu->ctx256) -#define CTX_384(x) ((x)->uu->ctx512) -#define CTX_512(x) ((x)->uu->ctx512) - -/* SHA2 initialisation */ - -INT_RETURN sha2_begin(unsigned long len, sha2_ctx ctx[1]) -{ - switch(len) - { -#if defined(SHA_224) - case 224: - case 28: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0; - memcpy(CTX_256(ctx)->hash, i224, 32); - ctx->sha2_len = 28; return EXIT_SUCCESS; -#endif -#if defined(SHA_256) - case 256: - case 32: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0; - memcpy(CTX_256(ctx)->hash, i256, 32); - ctx->sha2_len = 32; return EXIT_SUCCESS; -#endif -#if defined(SHA_384) - case 384: - case 48: CTX_384(ctx)->count[0] = CTX_384(ctx)->count[1] = 0; - memcpy(CTX_384(ctx)->hash, i384, 64); - ctx->sha2_len = 48; return EXIT_SUCCESS; -#endif -#if defined(SHA_512) - case 512: - case 64: CTX_512(ctx)->count[0] = CTX_512(ctx)->count[1] = 0; - memcpy(CTX_512(ctx)->hash, i512, 64); - ctx->sha2_len = 64; return EXIT_SUCCESS; -#endif - default: return EXIT_FAILURE; - } -} - -VOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]) -{ - switch(ctx->sha2_len) - { -#if defined(SHA_224) - case 28: sha224_hash(data, len, CTX_224(ctx)); return; -#endif -#if defined(SHA_256) - case 32: sha256_hash(data, len, CTX_256(ctx)); return; -#endif -#if defined(SHA_384) - case 48: sha384_hash(data, len, CTX_384(ctx)); return; -#endif -#if defined(SHA_512) - case 64: sha512_hash(data, len, CTX_512(ctx)); return; -#endif - } -} - -VOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1]) -{ - switch(ctx->sha2_len) - { -#if defined(SHA_224) - case 28: sha_end1(hval, CTX_224(ctx), SHA224_DIGEST_SIZE); return; -#endif -#if defined(SHA_256) - case 32: sha_end1(hval, CTX_256(ctx), SHA256_DIGEST_SIZE); return; -#endif -#if defined(SHA_384) - case 48: sha_end2(hval, CTX_384(ctx), SHA384_DIGEST_SIZE); return; -#endif -#if defined(SHA_512) - case 64: sha_end2(hval, CTX_512(ctx), SHA512_DIGEST_SIZE); return; -#endif - } -} - -INT_RETURN sha2_all(unsigned char hval[], unsigned long size, - const unsigned char data[], unsigned long len) -{ sha2_ctx cx[1]; - - if(sha2_begin(size, cx) == EXIT_SUCCESS) - { - sha2_hash(data, len, cx); sha2_end(hval, cx); return EXIT_SUCCESS; - } - else - return EXIT_FAILURE; -} - -#endif - -#if defined(__cplusplus) -} -#endif diff --git a/jni/libzrtp/sources/zrtp/crypto/sha2.h b/jni/libzrtp/sources/zrtp/crypto/sha2.h deleted file mode 100644 index 1ad3889e2..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/sha2.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - --------------------------------------------------------------------------- - Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - ALTERNATIVELY, provided that this notice is retained in full, this product - may be distributed under the terms of the GNU General Public License (GPL), - in which case the provisions of the GPL apply INSTEAD OF those given above. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and/or fitness for purpose. - --------------------------------------------------------------------------- - Issue Date: 01/08/2005 -*/ - -#ifndef _SHA2_H -#define _SHA2_H - -#include <stdlib.h> - -#define SHA_64BIT - -/* define the hash functions that you need */ -#define SHA_2 /* for dynamic hash length */ -#define SHA_224 -#define SHA_256 -#ifdef SHA_64BIT -# define SHA_384 -# define SHA_512 -# define NEED_UINT_64T -#endif - -#include <cryptcommon/brg_types.h> - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* Note that the following function prototypes are the same */ -/* for both the bit and byte oriented implementations. But */ -/* the length fields are in bytes or bits as is appropriate */ -/* for the version used. Bit sequences are arrays of bytes */ -/* in which bit sequence indexes increase from the most to */ -/* the least significant end of each byte */ - -#define SHA224_DIGEST_SIZE 28 -#define SHA224_BLOCK_SIZE 64 -#define SHA256_DIGEST_SIZE 32 -#define SHA256_BLOCK_SIZE 64 - -/* type to hold the SHA256 (and SHA224) context */ - -typedef struct -{ uint_32t count[2]; - uint_32t hash[8]; - uint_32t wbuf[16]; -} sha256_ctx; - -typedef sha256_ctx sha224_ctx; - -VOID_RETURN sha256_compile(sha256_ctx ctx[1]); - -VOID_RETURN sha224_begin(sha224_ctx ctx[1]); -#define sha224_hash sha256_hash -VOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1]); -VOID_RETURN sha224(unsigned char hval[], const unsigned char data[], unsigned long len); - -VOID_RETURN sha256_begin(sha256_ctx ctx[1]); -VOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]); -VOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1]); -VOID_RETURN sha256(unsigned char hval[], const unsigned char data[], unsigned long len); - -#ifndef SHA_64BIT - -typedef struct -{ union - { sha256_ctx ctx256[1]; - } uu[1]; - uint_32t sha2_len; -} sha2_ctx; - -#define SHA2_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE - -#else - -#define SHA384_DIGEST_SIZE 48 -#define SHA384_BLOCK_SIZE 128 -#define SHA512_DIGEST_SIZE 64 -#define SHA512_BLOCK_SIZE 128 -#define SHA2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE - -/* type to hold the SHA384 (and SHA512) context */ - -typedef struct -{ uint_64t count[2]; - uint_64t hash[8]; - uint_64t wbuf[16]; -} sha512_ctx; - -typedef sha512_ctx sha384_ctx; - -typedef struct -{ union - { sha256_ctx ctx256[1]; - sha512_ctx ctx512[1]; - } uu[1]; - uint_32t sha2_len; -} sha2_ctx; - -VOID_RETURN sha512_compile(sha512_ctx ctx[1]); - -VOID_RETURN sha384_begin(sha384_ctx ctx[1]); -#define sha384_hash sha512_hash -VOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1]); -VOID_RETURN sha384(unsigned char hval[], const unsigned char data[], unsigned long len); - -VOID_RETURN sha512_begin(sha512_ctx ctx[1]); -VOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]); -VOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1]); -VOID_RETURN sha512(unsigned char hval[], const unsigned char data[], unsigned long len); - -INT_RETURN sha2_begin(unsigned long size, sha2_ctx ctx[1]); -VOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]); -VOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1]); -INT_RETURN sha2_all(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len); - -#endif - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/jni/libzrtp/sources/zrtp/crypto/sha256.cpp b/jni/libzrtp/sources/zrtp/crypto/sha256.cpp deleted file mode 100644 index 593b5e578..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/sha256.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (C) 2012 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/** - * @author: Werner Dittmann - */ - -#include <zrtp/crypto/sha2.h> -#include <zrtp/crypto/sha256.h> - -void sha256(unsigned char *data, unsigned int dataLength, unsigned char *digest ) -{ - sha256_ctx ctx; - - sha256_begin(&ctx); - sha256_hash(data, dataLength, &ctx); - sha256_end(digest, &ctx); -} - -void sha256(unsigned char *dataChunks[], unsigned int dataChunckLength[], unsigned char *digest) -{ - sha256_ctx ctx; - - sha256_begin(&ctx); - while(*dataChunks) { - sha256_hash(*dataChunks, *dataChunckLength, &ctx); - dataChunks++; - dataChunckLength++; - } - sha256_end(digest, &ctx); -} - -void* createSha256Context() -{ - sha256_ctx *ctx = reinterpret_cast<sha256_ctx*>(malloc(sizeof(sha256_ctx))); - sha256_begin(ctx); - return (void*)ctx; -} - -void closeSha256Context(void* ctx, unsigned char* digest) -{ - sha256_ctx* hd = reinterpret_cast<sha256_ctx*>(ctx); - - if (digest != NULL) { - sha256_end(digest, hd); - } - free(hd); -} - -void sha256Ctx(void* ctx, unsigned char* data, unsigned int dataLength) -{ - sha256_ctx* hd = reinterpret_cast<sha256_ctx*>(ctx); - - sha256_hash(data, dataLength, hd); -} - -void sha256Ctx(void* ctx, unsigned char* dataChunks[], unsigned int dataChunkLength[]) -{ - sha256_ctx* hd = reinterpret_cast<sha256_ctx*>(ctx); - - while (*dataChunks) { - sha256_hash(*dataChunks, *dataChunkLength, hd); - dataChunks++; - dataChunkLength++; - } -} diff --git a/jni/libzrtp/sources/zrtp/crypto/sha384.cpp b/jni/libzrtp/sources/zrtp/crypto/sha384.cpp deleted file mode 100644 index d6b908530..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/sha384.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (C) 2012 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/** - * @author: Werner Dittmann - */ - -#include <zrtp/crypto/sha2.h> -#include <zrtp/crypto/sha384.h> - -void sha384(unsigned char *data, unsigned int dataLength, unsigned char *digest ) -{ - sha384_ctx ctx; - - sha384_begin(&ctx); - sha384_hash(data, dataLength, &ctx); - sha384_end(digest, &ctx); -} - -void sha384(unsigned char *dataChunks[], unsigned int dataChunckLength[], unsigned char *digest) -{ - sha384_ctx ctx; - - sha384_begin(&ctx); - while(*dataChunks) { - sha384_hash(*dataChunks, *dataChunckLength, &ctx); - dataChunks++; - dataChunckLength++; - } - sha384_end(digest, &ctx); -} - -void* createSha384Context() -{ - sha384_ctx *ctx = reinterpret_cast<sha384_ctx*>(malloc(sizeof(sha384_ctx))); - sha384_begin(ctx); - return (void*)ctx; -} - -void closeSha384Context(void* ctx, unsigned char* digest) -{ - sha384_ctx* hd = reinterpret_cast<sha384_ctx*>(ctx); - - if (digest != NULL) { - sha384_end(digest, hd); - } - free(hd); -} - -void sha384Ctx(void* ctx, unsigned char* data, unsigned int dataLength) -{ - sha384_ctx* hd = reinterpret_cast<sha384_ctx*>(ctx); - - sha384_hash(data, dataLength, hd); -} - -void sha384Ctx(void* ctx, unsigned char* dataChunks[], unsigned int dataChunkLength[]) -{ - sha384_ctx* hd = reinterpret_cast<sha384_ctx*>(ctx); - - while (*dataChunks) { - sha384_hash(*dataChunks, *dataChunkLength, hd); - dataChunks++; - dataChunkLength++; - } -} diff --git a/jni/libzrtp/sources/zrtp/crypto/skein256.cpp b/jni/libzrtp/sources/zrtp/crypto/skein256.cpp deleted file mode 100644 index 94cff6381..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/skein256.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - Copyright (C) 2013 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/** - * @author: Werner Dittmann - */ - -#include <cryptcommon/skeinApi.h> -#include <zrtp/crypto/skein256.h> - -#include <stdlib.h> - -void skein256(unsigned char *data, unsigned int dataLength, unsigned char *digest ) -{ - SkeinCtx_t ctx; - - skeinCtxPrepare(&ctx, SKEIN_SIZE); - skeinInit(&ctx, SKEIN256_DIGEST_LENGTH*8); - skeinUpdate(&ctx, data, dataLength); - - skeinFinal(&ctx, digest); -} - -void skein256(unsigned char *dataChunks[], unsigned int dataChunckLength[], unsigned char *digest) -{ - SkeinCtx_t ctx; - - skeinCtxPrepare(&ctx, SKEIN_SIZE); - skeinInit(&ctx, SKEIN256_DIGEST_LENGTH*8); - while(*dataChunks) { - skeinUpdate(&ctx, *dataChunks, *dataChunckLength); - dataChunks++; - dataChunckLength++; - } - skeinFinal(&ctx, digest); -} - -void* createSkein256Context() -{ - SkeinCtx_t *ctx = reinterpret_cast<SkeinCtx_t *>(malloc(sizeof(SkeinCtx_t ))); - skeinCtxPrepare(ctx, SKEIN_SIZE); - skeinInit(ctx, SKEIN256_DIGEST_LENGTH*8); - return (void*)ctx; -} - -void closeSkein256Context(void* ctx, unsigned char* digest) -{ - SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx); - - if (digest != NULL) { - skeinFinal(hd, digest); - } - free(hd); -} - -void skein256Ctx(void* ctx, unsigned char* data, unsigned int dataLength) -{ - SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx); - - skeinUpdate(hd, data, dataLength); -} - -void skein256Ctx(void* ctx, unsigned char* dataChunks[], unsigned int dataChunkLength[]) -{ - SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx); - - while (*dataChunks) { - skeinUpdate(hd, *dataChunks, *dataChunkLength); - dataChunks++; - dataChunkLength++; - } -} diff --git a/jni/libzrtp/sources/zrtp/crypto/skein256.h b/jni/libzrtp/sources/zrtp/crypto/skein256.h deleted file mode 100644 index 6d4e72268..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/skein256.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - Copyright (C) 2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/** - * Functions to compute Skein256 digest. - * - * @author: Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#ifndef _SKEIN256_H -#define _SKEIN256_H - -/** - * @file skein256.h - * @brief Functions that provide Skein256 support - * - * @ingroup GNU_ZRTP - * @{ - */ - -#include <stdint.h> - -#ifndef SKEIN256_DIGEST_LENGTH -#define SKEIN256_DIGEST_LENGTH 32 -#endif -#define SKEIN_SIZE Skein512 - - -/** - * Compute Skein256 digest. - * - * This functions takes one data chunk and computes its Skein256 digest. This - * function creates and deletes an own Skein256 context to perform the Skein256 - * operations. - * - * @param data - * Points to the data chunk. - * @param data_length - * Length of the data in bytes - * @param digest - * Points to a buffer that receives the computed digest. This - * buffer must have a size of at least 32 bytes (Skein256_DIGEST_LENGTH). - */ -void skein256(unsigned char *data, - unsigned int data_length, - unsigned char *digest); - -/** - * Compute Skein256 digest over several data cunks. - * - * This functions takes several data chunks and computes the Skein256 digest. - * This function creates and deletes an own Skein256 context to perform the - * Skein256 operations. - * - * @param data - * Points to an array of pointers that point to the data chunks. A NULL - * pointer in an array element terminates the data chunks. - * @param data_length - * Points to an array of integers that hold the length of each data chunk. - * @param digest - * Points to a buffer that receives the computed digest. This - * buffer must have a size of at least 32 bytes (Skein256_DIGEST_LENGTH). - */ -void skein256(unsigned char *data[], - unsigned int data_length[], - unsigned char *digest); -/** - * Create and initialize a Skein256 context. - * - * An application uses this context to hash several data into one Skein256 - * digest. See also skein256Ctx(...) and closeSha256Context(...). - * - * @return Returns a pointer to the initialized Skein256 context - */ -void* createSkein256Context(); - -/** - * Compute a digest and close the SHa256 digest. - * - * An application uses this function to compute the Skein256 digest and to - * close the Skein256 context. - * - * @param ctx - * Points to the Skein256 context. - * @param digest - * If this pointer is not NULL then it must point to a byte array that - * is big enough to hold the Skein256 digest (256 bit = 32 Bytes). If this - * pointer is NULL then the functions does not compute the digest but - * closes the context only. The context cannot be used anymore. - */ -void closeSkein256Context(void* ctx, - unsigned char* digest); - -/** - * Update the Skein256 context with data. - * - * This functions updates the Skein256 context with some data. - * See also CloseSha256Context(...) how to get the digest. - * - * @param ctx - * Points to the Skein256 context. - * @param data - * Points to the data to update the context. - * @param dataLength - * The length of the data in bytes. - */ -void skein256Ctx(void* ctx, unsigned char* data, - unsigned int dataLength); - -/** - * Update the Skein256 context with several data chunks. - * - * This functions updates the Skein256 context with some data. - * See also CloseSha256Context(...) how to get the digest. - * - * @param ctx - * Points to the Skein256 context. - * @param dataChunks - * Points to an array of pointers that point to the data chunks. A NULL - * pointer in an array element terminates the data chunks. - * @param dataChunkLength - * Points to an array of integers that hold the length of each data chunk. - * - */ -void skein256Ctx(void* ctx, unsigned char* dataChunks[], - unsigned int dataChunkLength[]); - -/** - * @} - */ -#endif - diff --git a/jni/libzrtp/sources/zrtp/crypto/skein384.cpp b/jni/libzrtp/sources/zrtp/crypto/skein384.cpp deleted file mode 100644 index 1dbe60896..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/skein384.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright (C) 2013 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/** - * @author: Werner Dittmann - */ - -#include <cryptcommon/skeinApi.h> -#include <zrtp/crypto/skein384.h> - -#include <stdlib.h> - -#define SKEIN_SIZE Skein512 -#define SKEIN384_DIGEST_LENGTH 48 - -void skein384(unsigned char *data, unsigned int dataLength, unsigned char *digest ) -{ - SkeinCtx_t ctx; - - skeinCtxPrepare(&ctx, SKEIN_SIZE); - skeinInit(&ctx, SKEIN384_DIGEST_LENGTH*8); - skeinUpdate(&ctx, data, dataLength); - - skeinFinal(&ctx, digest); -} - -void skein384(unsigned char *dataChunks[], unsigned int dataChunckLength[], unsigned char *digest) -{ - SkeinCtx_t ctx; - - skeinCtxPrepare(&ctx, SKEIN_SIZE); - skeinInit(&ctx, SKEIN384_DIGEST_LENGTH*8); - while(*dataChunks) { - skeinUpdate(&ctx, *dataChunks, *dataChunckLength); - dataChunks++; - dataChunckLength++; - } - skeinFinal(&ctx, digest); -} - -void* createSkein384Context() -{ - SkeinCtx_t *ctx = reinterpret_cast<SkeinCtx_t *>(malloc(sizeof(SkeinCtx_t ))); - skeinCtxPrepare(ctx, SKEIN_SIZE); - skeinInit(ctx, SKEIN384_DIGEST_LENGTH*8); - return (void*)ctx; -} - -void closeSkein384Context(void* ctx, unsigned char* digest) -{ - SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx); - - if (digest != NULL) { - skeinFinal(hd, digest); - } - free(hd); -} - -void skein384Ctx(void* ctx, unsigned char* data, unsigned int dataLength) -{ - SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx); - - skeinUpdate(hd, data, dataLength); -} - -void skein384Ctx(void* ctx, unsigned char* dataChunks[], unsigned int dataChunkLength[]) -{ - SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx); - - while (*dataChunks) { - skeinUpdate(hd, *dataChunks, *dataChunkLength); - dataChunks++; - dataChunkLength++; - } -} diff --git a/jni/libzrtp/sources/zrtp/crypto/skein384.h b/jni/libzrtp/sources/zrtp/crypto/skein384.h deleted file mode 100644 index 61fd64eae..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/skein384.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - Copyright (C) 2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/** - * Functions to compute Skein384 digest. - * - * @author: Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#ifndef _SKEIN384_H -#define _SKEIN384_H - -/** - * @file skein384.h - * @brief Functions that provide Skein384 support - * - * @ingroup GNU_ZRTP - * @{ - */ - -#include <stdint.h> - -#ifndef SKEIN384_DIGEST_LENGTH -#define SKEIN384_DIGEST_LENGTH 48 -#endif -#define SKEIN_SIZE Skein512 - - -/** - * Compute Skein384 digest. - * - * This functions takes one data chunk and computes its Skein384 digest. This - * function creates and deletes an own Skein384 context to perform the Skein384 - * operations. - * - * @param data - * Points to the data chunk. - * @param data_length - * Length of the data in bytes - * @param digest - * Points to a buffer that receives the computed digest. This - * buffer must have a size of at least 48 bytes (Skein384_DIGEST_LENGTH). - */ -void skein384(unsigned char *data, - unsigned int data_length, - unsigned char *digest); - -/** - * Compute Skein384 digest over several data cunks. - * - * This functions takes several data chunks and computes the Skein384 digest. - * This function creates and deletes an own Skein384 context to perform the - * Skein384 operations. - * - * @param data - * Points to an array of pointers that point to the data chunks. A NULL - * pointer in an array element terminates the data chunks. - * @param data_length - * Points to an array of integers that hold the length of each data chunk. - * @param digest - * Points to a buffer that receives the computed digest. This - * buffer must have a size of at least 48 bytes (Skein384_DIGEST_LENGTH). - */ -void skein384(unsigned char *data[], - unsigned int data_length[], - unsigned char *digest); -/** - * Create and initialize a Skein384 context. - * - * An application uses this context to hash several data into one Skein384 - * digest. See also skein384Ctx(...) and closeSha384Context(...). - * - * @return Returns a pointer to the initialized Skein384 context - */ -void* createSkein384Context(); - -/** - * Compute a digest and close the SHa384 digest. - * - * An application uses this function to compute the Skein384 digest and to - * close the Skein384 context. - * - * @param ctx - * Points to the Skein384 context. - * @param digest - * If this pointer is not NULL then it must point to a byte array that - * is big enough to hold the Skein384 digest (384 bit = 48 Bytes). If this - * pointer is NULL then the functions does not compute the digest but - * closes the context only. The context cannot be used anymore. - */ -void closeSkein384Context(void* ctx, - unsigned char* digest); - -/** - * Update the Skein384 context with data. - * - * This functions updates the Skein384 context with some data. - * See also CloseSha384Context(...) how to get the digest. - * - * @param ctx - * Points to the Skein384 context. - * @param data - * Points to the data to update the context. - * @param dataLength - * The length of the data in bytes. - */ -void skein384Ctx(void* ctx, unsigned char* data, - unsigned int dataLength); - -/** - * Update the Skein384 context with several data chunks. - * - * This functions updates the Skein384 context with some data. - * See also CloseSha384Context(...) how to get the digest. - * - * @param ctx - * Points to the Skein384 context. - * @param dataChunks - * Points to an array of pointers that point to the data chunks. A NULL - * pointer in an array element terminates the data chunks. - * @param dataChunkLength - * Points to an array of integers that hold the length of each data chunk. - * - */ -void skein384Ctx(void* ctx, unsigned char* dataChunks[], - unsigned int dataChunkLength[]); - -/** - * @} - */ -#endif - diff --git a/jni/libzrtp/sources/zrtp/crypto/skeinMac256.cpp b/jni/libzrtp/sources/zrtp/crypto/skeinMac256.cpp deleted file mode 100644 index b4234e51b..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/skeinMac256.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2013 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/* - * Authors: Werner Dittmann - */ - -#include <cryptcommon/macSkein.h> -#include <zrtp/crypto/skeinMac256.h> - -void macSkein256(uint8_t *key, uint32_t keyLength, uint8_t* data, int32_t dataLength, uint8_t* mac, uint32_t* macLength) -{ - macSkein(key, keyLength, data, dataLength, mac, SKEIN256_DIGEST_LENGTH*8, SKEIN_SIZE); - *macLength = SKEIN256_DIGEST_LENGTH; -} - - -void macSkein256( uint8_t* key, uint32_t keyLength, uint8_t* dataChunks[], uint32_t dataChunkLength[], uint8_t* mac, uint32_t* macLength ) -{ - macSkein(key, keyLength, (const uint8_t**)dataChunks, dataChunkLength, mac, SKEIN256_DIGEST_LENGTH*8, SKEIN_SIZE); - *macLength = SKEIN256_DIGEST_LENGTH; -} - -void* createMacSkein256Context(uint8_t* key, int32_t keyLength) -{ - return createSkeinMacContext(key, keyLength, SKEIN256_DIGEST_LENGTH*8, SKEIN_SIZE); -} - -void macSkein256Ctx(void* ctx, const uint8_t* data, uint32_t dataLength, uint8_t* mac, int32_t* macLength) -{ - - macSkeinCtx(ctx, data, dataLength, mac); - *macLength = SKEIN256_DIGEST_LENGTH; -} - -void macSkein256Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], uint8_t* mac, int32_t* macLength ) -{ - macSkeinCtx(ctx, data, dataLength, mac); - *macLength = SKEIN256_DIGEST_LENGTH; -} - -void freeMacSkein256Context(void* ctx) -{ - freeSkeinMacContext(ctx); -} \ No newline at end of file diff --git a/jni/libzrtp/sources/zrtp/crypto/skeinMac256.h b/jni/libzrtp/sources/zrtp/crypto/skeinMac256.h deleted file mode 100644 index e87a1e165..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/skeinMac256.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2013 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -/** - * Methods to compute a Skein256 HMAC. - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#ifndef HMAC_SKEIN256_H -#define HMAC_SKEIN256_H - -/** - * @file skeinMac256.h - * @brief Function that provide Skein256 HMAC support - * - * @ingroup GNU_ZRTP - * @{ - */ - -#include <stdint.h> - -#ifndef SKEIN256_DIGEST_LENGTH -#define SKEIN256_DIGEST_LENGTH 32 -#endif - -#define SKEIN_SIZE Skein512 - -/** - * Compute Skein256 HMAC. - * - * This functions takes one data chunk and computes its Skein256 HMAC. - * - * @param key - * The MAC key. - * @param key_length - * Lneght of the MAC key in bytes - * @param data - * Points to the data chunk. - * @param data_length - * Length of the data in bytes - * @param mac - * Points to a buffer that receives the computed digest. This - * buffer must have a size of at least 32 bytes (SKEIN256_DIGEST_LENGTH). - * @param mac_length - * Point to an integer that receives the length of the computed HMAC. - */ -void macSkein256( uint8_t* key, uint32_t key_length, uint8_t* data, int32_t data_length, uint8_t* mac, uint32_t* mac_length ); - -/** - * Compute Skein256 HMAC over several data cunks. - * - * This functions takes several data chunk and computes the Skein256 HAMAC. - * - * @param key - * The MAC key. - * @param key_length - * Lneght of the MAC key in bytes - * @param data - * Points to an array of pointers that point to the data chunks. A NULL - * pointer in an array element terminates the data chunks. - * @param data_length - * Points to an array of integers that hold the length of each data chunk. - * @param mac - * Points to a buffer that receives the computed digest. This - * buffer must have a size of at least 32 bytes (SKEIN256_DIGEST_LENGTH). - * @param mac_length - * Point to an integer that receives the length of the computed HMAC. - */ - -void macSkein256( uint8_t* key, uint32_t key_length, uint8_t* data[], uint32_t data_length[], uint8_t* mac, uint32_t* mac_length ); -/** - * @} - */ -#endif diff --git a/jni/libzrtp/sources/zrtp/crypto/skeinMac384.cpp b/jni/libzrtp/sources/zrtp/crypto/skeinMac384.cpp deleted file mode 100644 index 57c7ad198..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/skeinMac384.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright (C) 2013 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/* - * Authors: Werner Dittmann - */ - -#define SKEIN_SIZE Skein512 -#define SKEIN384_DIGEST_LENGTH 48 - -#include <cryptcommon/macSkein.h> -#include <zrtp/crypto/skeinMac384.h> - -void macSkein384(uint8_t *key, uint32_t keyLength, uint8_t* data, int32_t dataLength, uint8_t* mac, uint32_t* macLength) -{ - macSkein(key, keyLength, data, dataLength, mac, SKEIN384_DIGEST_LENGTH*8, SKEIN_SIZE); - *macLength = SKEIN384_DIGEST_LENGTH; -} - - -void macSkein384( uint8_t* key, uint32_t keyLength, uint8_t* dataChunks[], uint32_t dataChunkLength[], uint8_t* mac, uint32_t* macLength ) -{ - macSkein(key, keyLength, (const uint8_t**)dataChunks, dataChunkLength, mac, SKEIN384_DIGEST_LENGTH*8, SKEIN_SIZE); - *macLength = SKEIN384_DIGEST_LENGTH; -} - -void* createMacSkein384Context(uint8_t* key, int32_t keyLength) -{ - return createSkeinMacContext(key, keyLength, SKEIN384_DIGEST_LENGTH*8, SKEIN_SIZE); -} - -void macSkein384Ctx(void* ctx, const uint8_t* data, uint32_t dataLength, uint8_t* mac, int32_t* macLength) -{ - - macSkeinCtx(ctx, data, dataLength, mac); - *macLength = SKEIN384_DIGEST_LENGTH; -} - -void macSkein384Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], uint8_t* mac, int32_t* macLength ) -{ - macSkeinCtx(ctx, data, dataLength, mac); - *macLength = SKEIN384_DIGEST_LENGTH; -} - -void freeMacSkein384Context(void* ctx) -{ - freeSkeinMacContext(ctx); -} \ No newline at end of file diff --git a/jni/libzrtp/sources/zrtp/crypto/skeinMac384.h b/jni/libzrtp/sources/zrtp/crypto/skeinMac384.h deleted file mode 100644 index 206589913..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/skeinMac384.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2013 Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -/** - * Methods to compute a Skein384 HMAC. - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#ifndef HMAC_SKEIN384_H -#define HMAC_SKEIN384_H - -/** - * @file skeinMac384.h - * @brief Function that provide Skein384 HMAC support - * - * @ingroup GNU_ZRTP - * @{ - */ - -#include <stdint.h> - -#ifndef SKEIN384_DIGEST_LENGTH -#define SKEIN384_DIGEST_LENGTH 48 -#endif - -#define SKEIN_SIZE Skein512 - -/** - * Compute Skein384 HMAC. - * - * This functions takes one data chunk and computes its Skein384 HMAC. - * - * @param key - * The MAC key. - * @param key_length - * Lneght of the MAC key in bytes - * @param data - * Points to the data chunk. - * @param data_length - * Length of the data in bytes - * @param mac - * Points to a buffer that receives the computed digest. This - * buffer must have a size of at least 48 bytes (SKEIN384_DIGEST_LENGTH). - * @param mac_length - * Point to an integer that receives the length of the computed HMAC. - */ -void macSkein384( uint8_t* key, uint32_t key_length, uint8_t* data, int32_t data_length, uint8_t* mac, uint32_t* mac_length ); - -/** - * Compute Skein384 HMAC over several data cunks. - * - * This functions takes several data chunk and computes the Skein384 HAMAC. - * - * @param key - * The MAC key. - * @param key_length - * Lneght of the MAC key in bytes - * @param data - * Points to an array of pointers that point to the data chunks. A NULL - * pointer in an array element terminates the data chunks. - * @param data_length - * Points to an array of integers that hold the length of each data chunk. - * @param mac - * Points to a buffer that receives the computed digest. This - * buffer must have a size of at least 48 bytes (SKEIN384_DIGEST_LENGTH). - * @param mac_length - * Point to an integer that receives the length of the computed HMAC. - */ - -void macSkein384( uint8_t* key, uint32_t key_length, uint8_t* data[], uint32_t data_length[], uint8_t* mac, uint32_t* mac_length ); -/** - * @} - */ -#endif diff --git a/jni/libzrtp/sources/zrtp/crypto/zrtpDH.cpp b/jni/libzrtp/sources/zrtp/crypto/zrtpDH.cpp deleted file mode 100644 index d718f2493..000000000 --- a/jni/libzrtp/sources/zrtp/crypto/zrtpDH.cpp +++ /dev/null @@ -1,532 +0,0 @@ -/* - Copyright (C) 2006, 2009 by Werner Dittmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ - -/** Copyright (C) 2006, 2009 - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <bn.h> -#include <bnprint.h> -#include <ec/ec.h> -#include <ec/ecdh.h> -#include <zrtp/crypto/zrtpDH.h> -#include <zrtp/libzrtpcpp/ZrtpTextData.h> -#include <cryptcommon/aes.h> -#include <cryptcommon/ZrtpRandom.h> - - -static BigNum bnP2048 = {0}; -static BigNum bnP3072 = {0}; - -static BigNum bnP2048MinusOne = {0}; -static BigNum bnP3072MinusOne = {0}; - -static BigNum two = {0}; - -static uint8_t dhinit = 0; - -typedef struct _dhCtx { - BigNum privKey; - BigNum pubKey; - EcCurve curve; - EcPoint pubPoint; -} dhCtx; - -void randomZRTP(uint8_t *buf, int32_t length) -{ - ZrtpRandom::getRandomData(buf, length); -} - -static const uint8_t P2048[] = -{ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, - 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, - 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, - 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, - 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, - 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, - 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, - 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, - 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, - 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, - 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF -}; - -static const uint8_t P3072[] = -{ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, - 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, - 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, - 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, - 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, - 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, - 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, - 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, - 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, - 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, - 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, - 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, - 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, - 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, - 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, - 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, - 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* ************** -static const uint8_t P4096[] = -{ -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, -0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, -0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, -0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, -0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, -0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, -0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, -0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, -0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, -0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, -0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, -0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, -0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, -0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, -0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, -0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, -0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, -0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, -0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, -0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, -0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, -0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, -0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, -0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, -0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, -0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, -0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, -0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, -0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, -0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, -0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, -0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, -0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, -0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, -0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, -0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, -0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, -0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, -0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, -0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, -0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, -0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, -0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; -*************** */ - -ZrtpDH::ZrtpDH(const char* type) { - - uint8_t random[64]; - - ctx = static_cast<void*>(new dhCtx); - dhCtx* tmpCtx = static_cast<dhCtx*>(ctx); - - // Well - the algo type is only 4 char thus cast to int32 and compare - if (*(int32_t*)type == *(int32_t*)dh2k) { - pkType = DH2K; - } - else if (*(int32_t*)type == *(int32_t*)dh3k) { - pkType = DH3K; - } - else if (*(int32_t*)type == *(int32_t*)ec25) { - pkType = EC25; - } - else if (*(int32_t*)type == *(int32_t*)ec38) { - pkType = EC38; - } - else if (*(int32_t*)type == *(int32_t*)e255) { - pkType = E255; - } - else if (*(int32_t*)type == *(int32_t*)e414) { - pkType = E414; - } - else { - return; - } - - randomZRTP(random, sizeof(random)); - - if (!dhinit) { - bnBegin(&two); - bnSetQ(&two, 2); - - bnBegin(&bnP2048); - bnInsertBigBytes(&bnP2048, P2048, 0, sizeof(P2048)); - bnBegin(&bnP3072); - bnInsertBigBytes(&bnP3072, P3072, 0, sizeof(P3072)); - - bnBegin(&bnP2048MinusOne); - bnCopy(&bnP2048MinusOne, &bnP2048); - bnSubQ(&bnP2048MinusOne, 1); - - bnBegin(&bnP3072MinusOne); - bnCopy(&bnP3072MinusOne, &bnP3072); - bnSubQ(&bnP3072MinusOne, 1); - - dhinit = 1; - } - - bnBegin(&tmpCtx->privKey); - INIT_EC_POINT(&tmpCtx->pubPoint); - - switch (pkType) { - case DH2K: - case DH3K: - bnInsertBigBytes(&tmpCtx->privKey, random, 0, 256/8); - break; - - case EC25: - ecGetCurveNistECp(NIST256P, &tmpCtx->curve); - ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey); - break; - - case EC38: - ecGetCurveNistECp(NIST384P, &tmpCtx->curve); - ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey); - break; - - case E255: - ecGetCurvesCurve(Curve25519, &tmpCtx->curve); - ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey); - break; - - case E414: - ecGetCurvesCurve(Curve3617, &tmpCtx->curve); - ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey); - break; - } -} - -ZrtpDH::~ZrtpDH() { - if (ctx == NULL) - return; - - dhCtx* tmpCtx = static_cast<dhCtx*>(ctx); - FREE_EC_POINT(&tmpCtx->pubPoint); - bnEnd(&tmpCtx->privKey); - - switch (pkType) { - case DH2K: - case DH3K: - bnEnd(&tmpCtx->pubKey); - break; - - case EC25: - case EC38: - ecFreeCurveNistECp(&tmpCtx->curve); - break; - - case E255: - case E414: - ecFreeCurvesCurve(&tmpCtx->curve); - break; - } -} - -int32_t ZrtpDH::computeSecretKey(uint8_t *pubKeyBytes, uint8_t *secret) { - - dhCtx* tmpCtx = static_cast<dhCtx*>(ctx); - - int32_t length = getDhSize(); - - BigNum sec; - if (pkType == DH2K || pkType == DH3K) { - BigNum pubKeyOther; - bnBegin(&pubKeyOther); - bnBegin(&sec); - - bnInsertBigBytes(&pubKeyOther, pubKeyBytes, 0, length); - - if (pkType == DH2K) { - bnExpMod(&sec, &pubKeyOther, &tmpCtx->privKey, &bnP2048); - } - else if (pkType == DH3K) { - bnExpMod(&sec, &pubKeyOther, &tmpCtx->privKey, &bnP3072); - } - else { - return 0; - } - bnEnd(&pubKeyOther); - bnExtractBigBytes(&sec, secret, 0, length); - bnEnd(&sec); - - return length; - } - - if (pkType == EC25 || pkType == EC38 || pkType == E414) { - int32_t len = getPubKeySize() / 2; - EcPoint pub; - - bnBegin(&sec); - INIT_EC_POINT(&pub); - bnSetQ(pub.z, 1); // initialze Z to one, these are affine coords - - bnInsertBigBytes(pub.x, pubKeyBytes, 0, len); - bnInsertBigBytes(pub.y, pubKeyBytes+len, 0, len); - - /* Generate agreement for responder: sec = pub * privKey */ - ecdhComputeAgreement(&tmpCtx->curve, &sec, &pub, &tmpCtx->privKey); - bnExtractBigBytes(&sec, secret, 0, length); - bnEnd(&sec); - FREE_EC_POINT(&pub); - - return length; - } - if (pkType == E255) { - int32_t len = getPubKeySize(); - EcPoint pub; - - bnBegin(&sec); - INIT_EC_POINT(&pub); - - bnInsertLittleBytes(pub.x, pubKeyBytes, 0, len); - - /* Generate agreement for responder: sec = pub * privKey */ - ecdhComputeAgreement(&tmpCtx->curve, &sec, &pub, &tmpCtx->privKey); - bnExtractLittleBytes(&sec, secret, 0, length); - bnEnd(&sec); - FREE_EC_POINT(&pub); - - return length; - } - return -1; -} - -int32_t ZrtpDH::generatePublicKey() -{ - dhCtx* tmpCtx = static_cast<dhCtx*>(ctx); - - bnBegin(&tmpCtx->pubKey); - switch (pkType) { - case DH2K: - bnExpMod(&tmpCtx->pubKey, &two, &tmpCtx->privKey, &bnP2048); - break; - - case DH3K: - bnExpMod(&tmpCtx->pubKey, &two, &tmpCtx->privKey, &bnP3072); - break; - - case EC25: - case EC38: - case E255: - case E414: - while (!ecdhGeneratePublic(&tmpCtx->curve, &tmpCtx->pubPoint, &tmpCtx->privKey)) - ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey); - } - return 0; -} - -int32_t ZrtpDH::getDhSize() const -{ - switch (pkType) { - case DH2K: - return 2048/8; - break; - case DH3K: - return 3072/8; - break; - - case EC25: - return 32; - break; - case EC38: - return 48; - break; - - case E255: - return 32; - break; - case E414: - return 52; - break; - } - return 0; -} - -int32_t ZrtpDH::getPubKeySize() const -{ - dhCtx* tmpCtx = static_cast<dhCtx*>(ctx); - if (pkType == DH2K || pkType == DH3K) - return bnBytes(&tmpCtx->pubKey); - - if (pkType == EC25 || pkType == EC38 || pkType == E414) - return bnBytes(tmpCtx->curve.p) * 2; // *2 -> x and y coordinate - - if (pkType == E255) - return bnBytes(tmpCtx->curve.p); - return 0; - -} - -int32_t ZrtpDH::getPubKeyBytes(uint8_t *buf) const -{ - dhCtx* tmpCtx = static_cast<dhCtx*>(ctx); - - if (pkType == DH2K || pkType == DH3K) { - // get len of pub_key, prepend with zeros to DH size - int size = getPubKeySize(); - int32_t prepend = getDhSize() - size; - if (prepend > 0) { - memset(buf, 0, prepend); - } - bnExtractBigBytes(&tmpCtx->pubKey, buf + prepend, 0, size); - return size; - } - - if (pkType == EC25 || pkType == EC38 || pkType == E414) { - int32_t len = getPubKeySize() / 2; - - bnExtractBigBytes(tmpCtx->pubPoint.x, buf, 0, len); - bnExtractBigBytes(tmpCtx->pubPoint.y, buf+len, 0, len); - return len * 2; - } - if (pkType == E255) { - int32_t len = getPubKeySize(); - bnExtractLittleBytes(tmpCtx->pubPoint.x, buf, 0, len); - return len; - } - return 0; -} - -int32_t ZrtpDH::checkPubKey(uint8_t *pubKeyBytes) const -{ - - /* ECC validation (partial), NIST SP800-56A, section 5.6.2.6 */ - if (pkType == EC25 || pkType == EC38 || pkType == E414) { - - dhCtx* tmpCtx = static_cast<dhCtx*>(ctx); - EcPoint pub; - - INIT_EC_POINT(&pub); - int32_t len = getPubKeySize() / 2; - - bnInsertBigBytes(pub.x, pubKeyBytes, 0, len); - bnInsertBigBytes(pub.y, pubKeyBytes+len, 0, len); - - return ecCheckPubKey(&tmpCtx->curve, &pub); - } - - if (pkType == E255) { - return 1; - } - - BigNum pubKeyOther; - bnBegin(&pubKeyOther); - bnInsertBigBytes(&pubKeyOther, pubKeyBytes, 0, getDhSize()); - - if (pkType == DH2K) { - if (bnCmp(&bnP2048MinusOne, &pubKeyOther) == 0) { - return 0; - } - } - else if (pkType == DH3K) { - if (bnCmp(&bnP3072MinusOne, &pubKeyOther) == 0) { - return 0; - - } - } - else { - return 0; - } - if (bnCmpQ(&pubKeyOther, 1) == 0) { - return 0; - } - - bnEnd(&pubKeyOther); - return 1; -} - -const char* ZrtpDH::getDHtype() -{ - switch (pkType) { - case DH2K: - return dh2k; - case DH3K: - return dh3k; - case EC25: - return ec25; - case EC38: - return ec38; - case E255: - return e255; - case E414: - return e414; - } - return NULL; -} - -/** EMACS ** - * Local variables: - * mode: c++ - * c-default-style: ellemtel - * c-basic-offset: 4 - * End: - */ diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCache.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCache.h deleted file mode 100644 index 2ba1de683..000000000 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCache.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string> - -#include "ZIDRecord.h" - -#ifndef _ZIDCACHE_H_ -#define _ZIDCACHE_H_ - -/** - * @file ZIDCache.h - * @brief ZID cache management - * - * A ZID file stores (caches) some data that helps ZRTP to achives its - * key continuity feature. See @c ZIDRecord for further info which data - * the ZID file contains. - * - * @ingroup GNU_ZRTP - * @{ - */ - -/** - * Interface for classes that implements a ZID (ZRTP Identifiers) file. - * - * The ZID file holds information about peers. - * - * @author: Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -class ZIDCache; - -__EXPORT ZIDCache* getZidCacheInstance(); - - -class __EXPORT ZIDCache { - -public: - - /** - * @brief Destructor. - * Define a virtual destructor to enable cleanup in derived classes. - */ - virtual ~ZIDCache() {}; - - /** - * @brief Open the named ZID file and return a ZID file class. - * - * This static function either opens an existing ZID file or - * creates a new ZID file with the given name. The ZIDCache is a - * singleton, thus only <em>one</em> ZID file can be open at one - * time. - * - * To open another ZID file you must close the active ZID file - * first. - * - * @param name - * The name of the ZID file to open or create - * @return - * 1 if file could be opened/created, 0 if the ZID instance - * already has an open file, -1 if open/creation of file failed. - */ - virtual int open(char *name) =0; - - /** - * @brief Check if ZIDCache has an active (open) file. - * - * @return - * True if ZIDCache has an active file, false otherwise - */ - virtual bool isOpen() =0; - - /** - * @brief Close the ZID file. - * - * Closes the ZID file, and prepares to open a new ZID file. - */ - virtual void close() =0; - - /** - * @brief Get a ZID record from ZID cache or create a new record. - * - * The method tries to read a ZRTP cache record for the ZID. - * If no matching record exists in the cache the method creates - * it and fills it with default values. - * - * @param zid is the ZRTP id of the peer - * @return pointer to the ZID record. The call must @c delete the - * record if it is not longer used. - */ - virtual ZIDRecord *getRecord(unsigned char *zid) =0; - - /** - * @brief Save a ZID record into the active ZID file. - * - * This method saves the content of a ZID record into the ZID file. Before - * you can save the ZID record you must have performed a getRecord() - * first. - * - * @param zidRecord - * The ZID record to save. - * @return - * 1 on success - */ - virtual unsigned int saveRecord(ZIDRecord *zidRecord) =0; - - /** - * @brief Get the ZID associated with this ZID file. - * - * @return - * Pointer to the ZID - */ - virtual const unsigned char* getZid() =0; - - /** - * @brief Get peer name from database - * - * This is an optional function. - * - * A client may use this function to retrieve a name that was assigned - * to the peer's ZID. - * - * @param peerZid the peer's ZID - * - * @param name string that will get the peer's name. The returned name will - * be truncated to 200 bytes - * - * @return length og the name read or 0 if no name was previously stored. - */ - virtual int32_t getPeerName(const uint8_t *peerZid, std::string *name) =0; - - /** - * @brief Write peer name to database - * - * This is an optional function. - * - * A client may use this function to write a name in the ZRTP cache database and - * asign it to the peer's ZID. - * - * @param peerZid the peer's ZID - * - * @param name the name string - * - */ - virtual void putPeerName(const uint8_t *peerZid, const std::string name) =0; - - /** - * @brief Clean the cache. - * - * The function drops and re-creates all tables in the database. This removes all stored - * data. The application must not call this while a ZRTP call is active. Also the application - * <b>must</b> get the local ZID again. - * - */ - virtual void cleanup() =0; -}; - -/** - * @} - */ -#endif diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheDb.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheDb.h deleted file mode 100644 index 7aa6dd05c..000000000 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheDb.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdio.h> - -#include <libzrtpcpp/ZIDCache.h> -#include <libzrtpcpp/ZIDRecordDb.h> -#include <libzrtpcpp/zrtpCacheDbBackend.h> - -#ifndef _ZIDCACHEDB_H_ -#define _ZIDCACHEDB_H_ - - -/** - * @file ZIDCacheDb.h - * @brief ZID cache management - * - * A ZID file stores (caches) some data that helps ZRTP to achives its - * key continuity feature. See @c ZIDRecordDb for further info which data - * the ZID file contains. - * - * @ingroup GNU_ZRTP - * @{ - */ - -/** - * This class implements a ZID (ZRTP Identifiers) file. - * - * The interface defintion @c ZIDCache.h contains the method documentation. - * The ZID cache file holds information about peers. - * - * @author: Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -class __EXPORT ZIDCacheDb: public ZIDCache { - -private: - - void *zidFile; - unsigned char associatedZid[IDENTIFIER_LEN]; - - dbCacheOps_t cacheOps; - - char errorBuffer[DB_CACHE_ERR_BUFF_SIZE]; - - void createZIDFile(char* name); - -public: - - ZIDCacheDb(): zidFile(NULL) { - getDbCacheOps(&cacheOps); - }; - - ~ZIDCacheDb(); - - int open(char *name); - - bool isOpen() { return (zidFile != NULL); }; - - void close(); - - ZIDRecord *getRecord(unsigned char *zid); - - unsigned int saveRecord(ZIDRecord *zidRecord); - - const unsigned char* getZid() { return associatedZid; }; - - int32_t getPeerName(const uint8_t *peerZid, std::string *name); - - void putPeerName(const uint8_t *peerZid, const std::string name); - - void cleanup(); - -}; - -/** - * @} - */ -#endif diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheFile.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheFile.h deleted file mode 100644 index 7b264e8d0..000000000 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheFile.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdio.h> - -#include <libzrtpcpp/ZIDCache.h> -#include <libzrtpcpp/ZIDRecordFile.h> - -#ifndef _ZIDCACHEFILE_H_ -#define _ZIDCACHEFILE_H_ - - -/** - * @file ZIDCacheFile.h - * @brief ZID cache management - * - * A ZID file stores (caches) some data that helps ZRTP to achives its - * key continuity feature. See @c ZIDRecord for further info which data - * the ZID file contains. - * - * @ingroup GNU_ZRTP - * @{ - */ - -/** - * This class implements a ZID (ZRTP Identifiers) file. - * - * The interface defintion @c ZIDCache.h contains the method documentation. - * The ZID cache file holds information about peers. - * - * @author: Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -class __EXPORT ZIDCacheFile: public ZIDCache { - -private: - - FILE* zidFile; - unsigned char associatedZid[IDENTIFIER_LEN]; - - void createZIDFile(char* name); - void checkDoMigration(char* name); - -public: - - ZIDCacheFile(): zidFile(NULL) {}; - - ~ZIDCacheFile(); - - int open(char *name); - - bool isOpen() { return (zidFile != NULL); }; - - void close(); - - ZIDRecord *getRecord(unsigned char *zid); - - unsigned int saveRecord(ZIDRecord *zidRecord); - - const unsigned char* getZid() { return associatedZid; }; - - int32_t getPeerName(const uint8_t *peerZid, std::string *name); - - void putPeerName(const uint8_t *peerZid, const std::string name); - - // Not implemented for file base cache - void cleanup() {}; -}; - -/** - * @} - */ -#endif diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecord.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecord.h deleted file mode 100644 index c46fc24d5..000000000 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecord.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _ZIDRECORD_H_ -#define _ZIDRECORD_H_ - -#include <stdint.h> -#include <common/osSpecifics.h> -/** - * @file ZIDRecord.h - * @brief ZID cache record management - * - * A ZID record stores (caches) ZID (ZRTP ID) specific data that helps ZRTP - * to achives its key continuity feature. Please refer to the ZRTP - * specification to get detailed information about the ZID. - * - * @ingroup GNU_ZRTP - * @{ - */ - -/** - * These length are fixed for ZRTP. See RFC 6189. - */ -#define IDENTIFIER_LEN 12 -#define RS_LENGTH 32 - -#if defined(__cplusplus) -/** - * Interface for classes that implement a ZID cache record. - * - * The ZID cache record holds data about a peer. According to ZRTP specification - * we use a ZID to identify a peer. ZRTP uses the RS (Retained Secret) data - * to construct shared secrets. - * - * @author: Werner Dittmann <Werner.Dittmann@t-online.de> - */ -class __EXPORT ZIDRecord { - -public: - /** - * @brief Destructor. - * Define a virtual destructor to enable cleanup in derived classes. - */ - virtual ~ZIDRecord() {}; - - /** - * Set the @c ZID in the record. - * - * Set the ZID in this record before calling read or save. - */ - virtual void setZid(const unsigned char *zid) =0; - - /** - * Set @c valid flag in RS1 - */ - virtual void setRs1Valid() =0; - - /** - * reset @c valid flag in RS1 - */ - virtual void resetRs1Valid() =0; - - /** - * Check @c valid flag in RS1 - */ - virtual bool isRs1Valid() =0; - - /** - * Set @c valid flag in RS2 - */ - virtual void setRs2Valid() =0; - - /** - * Reset @c valid flag in RS2 - */ - virtual void resetRs2Valid() =0; - - /** - * Check @c valid flag in RS2 - */ - virtual bool isRs2Valid() =0; - - /** - * Set MITM key available - */ - virtual void setMITMKeyAvailable() =0; - - /** - * Reset MITM key available - */ - virtual void resetMITMKeyAvailable() =0; - - /** - * Check MITM key available is set - */ - virtual bool isMITMKeyAvailable() =0; - - /** - * Mark this as own ZID record - */ - virtual void setOwnZIDRecord() =0; - - /** - * Reset own ZID record marker - */ - virtual void resetOwnZIDRecord() =0; - - /** - * Check own ZID record marker - */ - virtual bool isOwnZIDRecord() =0; - - /** - * Set SAS for this ZID as verified - */ - virtual void setSasVerified() =0; - - /** - * Reset SAS for this ZID as verified - */ - virtual void resetSasVerified() =0; - - /** - * Check if SAS for this ZID was verified - */ - virtual bool isSasVerified() =0; - - /** - * Return the ZID for this record - */ - virtual const uint8_t* getIdentifier() =0; - - /** - * Check if RS1 is still valid - * - * Returns true if RS1 is still valid, false otherwise. - * - * @return - * Returns true is RS1 is not expired (valid), false otherwise. - */ - virtual bool isRs1NotExpired() =0; - - /** - * Returns pointer to RS1 data. - */ - virtual const unsigned char* getRs1() =0; - - /** - * Check if RS2 is still valid - * - * Returns true if RS2 is still valid, false otherwise. - * - * @return - * Returns true is RS2 is not expired (valid), false otherwise. - */ - virtual bool isRs2NotExpired() =0; - - /** - * Returns pointer to RS1 data. - */ - virtual const unsigned char* getRs2() =0; - - /** - * Sets new RS1 data and associated expiration value. - * - * If the expiration value is >0 or -1 the method stores the new - * RS1. Before it stores the new RS1 it shifts the exiting RS1 - * into RS2 (together with its expiration time). Then it computes - * the expiration time of the and stores the result together with - * the new RS1. - * - * If the expiration value is -1 then this RS will never expire. - * - * If the expiration value is 0 then the expiration value of a - * stored RS1 is cleared and no new RS1 value is stored. Also RS2 - * is left unchanged. - * - * @param data - * Points to the new RS1 data. - * @param expire - * The expiration interval in seconds. Default is -1. - * - */ - virtual void setNewRs1(const unsigned char* data, int32_t expire =-1) =0; - - /** - * Set MiTM key data. - * - */ - virtual void setMiTMData(const unsigned char* data) =0; - - /** - * Get MiTM key data. - * - */ - virtual const unsigned char* getMiTMData() =0; -}; -#endif /* (__cplusplus) */ -#endif diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordDb.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordDb.h deleted file mode 100644 index 111b4ed15..000000000 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordDb.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _ZIDRECORDDB_H_ -#define _ZIDRECORDDB_H_ - - -/** - * @file ZIDRecordDb.h - * @brief ZID cache record management - * - * A ZID record stores (caches) ZID (ZRTP ID) specific data that helps ZRTP - * to achives its key continuity feature. Please refer to the ZRTP - * specification to get detailed information about the ZID. - * - * @ingroup GNU_ZRTP - * @{ - */ - -#include <string.h> -#include <stdint.h> -#include <libzrtpcpp/ZIDRecord.h> - -#define TIME_LENGTH 8 // 64 bit, can hold time on 64 bit systems - -/** - * Internal structure that holds the non-key data of a remote ZID record. - * - * The data storage backends use this structure to get or to fill in data - * to store in or that was read from the data store. - * - * Some notes regarding the timestamps: the structure uses 64 bit variables to - * store a timestamp. The relevant SQL SELECT / UPDATE / INSERT statements and - * the relevant must take care of this. - * - * The methods shall use the standard C time() call to get the current time in - * seconds since Unix epoch (see time() documentation). - */ -typedef struct { - uint8_t identifier[IDENTIFIER_LEN]; /* < the peer's ZID or own ZID */ - uint32_t flags; - uint8_t rs1[RS_LENGTH]; - int64_t rs1LastUse; - int64_t rs1Ttl; - uint8_t rs2[RS_LENGTH]; - int64_t rs2LastUse; - int64_t rs2Ttl; - uint8_t mitmKey[RS_LENGTH]; - int64_t mitmLastUse; - int64_t secureSince; - uint32_t preshCounter; -} remoteZidRecord_t; - -/* - * The flag field stores the following bitflags - */ -static const uint32_t Valid = 0x1; -static const uint32_t SASVerified = 0x2; -static const uint32_t RS1Valid = 0x4; -static const uint32_t RS2Valid = 0x8; -static const uint32_t MITMKeyAvailable = 0x10; -static const uint32_t inUse = 0x20; - -/** - * Internal structure that holds the non-key data of a ZID name record. - * - * The flags field currently just uses the @c Valid bit. - * - * See comment on @c remoteZidRecord_t above. - */ -typedef struct { - uint32_t flags; - char *name; - int32_t nameLength; -} zidNameRecord_t; - -#if defined(__cplusplus) -/** - * This class implements the ZID record. - * - * The ZID record holds data about a peer. According to ZRTP specification - * we use a ZID to identify a peer. ZRTP uses the RS (Retained Secret) data - * to construct shared secrets. - * <p> - * NOTE: ZIDRecordDb has ZIDCacheDb as friend. ZIDCacheDb knows about the private - * data of ZIDRecord - please keep both classes synchronized. - * - * @author: Werner Dittmann <Werner.Dittmann@t-online.de> - */ -class __EXPORT ZIDRecordDb: public ZIDRecord { - friend class ZIDCacheDb; - -private: - remoteZidRecord_t record; - - remoteZidRecord_t* getRecordData() {return &record; } - int getRecordLength() {return sizeof(remoteZidRecord_t); } - - bool isValid() { return ((record.flags & Valid) == Valid); } - void setValid() { record.flags |= Valid; } - -public: - /* - * @brief The default constructor, - */ - ZIDRecordDb() { - memset(&record, 0, sizeof(remoteZidRecord_t)); - } - - /** - * Set the @c ZID in the record. - * - * Set the ZID in this record before calling read or save. - */ - void setZid(const unsigned char *zid) { - memcpy(record.identifier, zid, IDENTIFIER_LEN); - } - - /** - * Set @c valid flag in RS1 - */ - void setRs1Valid() { record.flags |= RS1Valid; } - - /** - * reset @c valid flag in RS1 - */ - void resetRs1Valid() { record.flags &= ~RS1Valid; } - - /** - * Check @c valid flag in RS1 - */ - bool isRs1Valid() { return ((record.flags & RS1Valid) == RS1Valid); } - - /** - * Set @c valid flag in RS2 - */ - void setRs2Valid() { record.flags |= RS2Valid; } - - /** - * Reset @c valid flag in RS2 - */ - void resetRs2Valid() { record.flags &= ~RS2Valid; } - - /** - * Check @c valid flag in RS2 - */ - bool isRs2Valid() { return ((record.flags & RS2Valid) == RS2Valid); } - - /** - * Set MITM key available - */ - void setMITMKeyAvailable() { record.flags |= MITMKeyAvailable; } - - /** - * Reset MITM key available - */ - void resetMITMKeyAvailable() { record.flags &= ~MITMKeyAvailable; } - - /** - * Check MITM key available is set - */ - bool isMITMKeyAvailable() { return ((record.flags & MITMKeyAvailable) == MITMKeyAvailable); } - - /** - * Mark this as own ZID record - not used in this DB cache backend - */ - void setOwnZIDRecord() {} - /** - * Reset own ZID record marker - */ - void resetOwnZIDRecord(){} - - /** - * Check own ZID record marker - */ - bool isOwnZIDRecord() { return false; } // in this DB cahe implementation a record is always 'remote' - - /** - * Set SAS for this ZID as verified - */ - void setSasVerified() { record.flags |= SASVerified; } - /** - * Reset SAS for this ZID as verified - */ - void resetSasVerified() { record.flags &= ~SASVerified; } - - /** - * Check if SAS for this ZID was verified - */ - bool isSasVerified() { return ((record.flags & SASVerified) == SASVerified); } - - /** - * Return the ZID for this record - */ - const uint8_t* getIdentifier() {return record.identifier; } - - /** - * Check if RS1 is still valid - * - * Returns true if RS1 is still valid, false otherwise. - * - * @return - * Returns true is RS1 is not expired (valid), false otherwise. - */ - bool isRs1NotExpired(); - - /** - * Returns pointer to RS1 data. - */ - const unsigned char* getRs1() { return record.rs1; } - - /** - * Check if RS2 is still valid - * - * Returns true if RS2 is still valid, false otherwise. - * - * @return - * Returns true is RS2 is not expired (valid), false otherwise. - */ - bool isRs2NotExpired(); - - /** - * Returns pointer to RS1 data. - */ - const unsigned char* getRs2() { return record.rs2; } - - /** - * Sets new RS1 data and associated expiration value. - * - * If the expiration value is >0 or -1 the method stores the new - * RS1. Before it stores the new RS1 it shifts the exiting RS1 - * into RS2 (together with its expiration time). Then it computes - * the expiration time of the and stores the result together with - * the new RS1. - * - * If the expiration value is -1 then this RS will never expire. - * - * If the expiration value is 0 then the expiration value of a - * stored RS1 is cleared and no new RS1 value is stored. Also RS2 - * is left unchanged. - * - * @param data - * Points to the new RS1 data. - * @param expire - * The expiration interval in seconds. Default is -1. - * - */ - void setNewRs1(const unsigned char* data, int32_t expire =-1); - - /** - * Set MiTM key data. - * - */ - void setMiTMData(const unsigned char* data); - - /** - * Get MiTM key data. - * - */ - const unsigned char* getMiTMData() {return record.mitmKey; } -}; -#endif /* (__cplusplus) */ - -#endif - diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h deleted file mode 100644 index d7d2265d3..000000000 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h +++ /dev/null @@ -1,547 +0,0 @@ -/* - Copyright (C) 2012-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _ZRTPSDESSTREAM_H_ -#define _ZRTPSDESSTREAM_H_ -/** - * @file ZrtpSdesStream.h - * @brief The ZRTP main engine - * @defgroup GNU_ZRTP The GNU ZRTP C++ implementation - * @{ - * - * This class implements SDES and provides a simple to use API for applications. - * - * This SDES implementation currently supports only two SDES algorithms and it does - * not support optional parameters such as lifetime or MKI parameters. Also session - * parameters are not supported. Most applications that use SDES don't use these - * optional parameters. - * - * It is not necessary to explicitly start the SDES stream. The class initiates - * the SRTP after it created and parsed all necessary SDES crypto strings. - * - * Because SDES works together with the signaling protocol, for example SIP, it is - * important to adhere to a defined flow. The following pseudo code snippet depicts - * such a flow. Applications shall follow this flow. - * - *<pre> - * - * Inviter Answerer - * (Offerer) - * - * ZrtpSdesStream inv; ZrtpSdesStream answ; - * - * // create/get own SDES data - * inv.createSdes(...); - * inv.getCryptoMixAttribute(...) - * - * // prepare SIP/SDP offer, send - * // it to answerer - * // receive SIP/SDP, get - * // SDES data, parse/set it - * answ.setCryptoMixAttribute(...) - * answ.parseSdes(...) - * - * // create/get own SDES data - * answ.getCryptoMixAttribute(...) - * answ.createSdes(...) - * - * // prepare SIP/SDP answer, - * // send to offerer - * // receive SIP/SDP answer, get - * // SDES data, parse, set mix algo - * // if availabe - * inv.setCryptoMixAttribute(...) - * inv.parseSdes(...) - * - * ... ... - * - * inv.outgoingRtp(...) - * answ.incomingRtp(...) - * - * answ.outgoingRtp(...) - * inv.incomingRtp(...) - *</pre> - * - * To use SDES without the new crypto mix feature just do not use the crypto mix functions. - * An application may always send crypto mix attributes. If the answerer does not support this - * feature it does not send back a selected algorithm and the offerer cannot set an algorithm. - * Thus the crypto mix feature is not used. - * - * @author Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#include <common/osSpecifics.h> - -class CryptoContext; -class CryptoContextCtrl; - -/* - * These functions support 256 bit encryption algorithms. - */ -#define MAX_KEY_LEN 32 -#define MAX_SALT_LEN 14 -#define MAX_DIGEST_LENGTH 64 - -/** - * Maximum length of a raw crypto string. - */ -#define MAX_CRYPT_STRING_LEN 200 - -class __EXPORT ZrtpSdesStream { - -public: - - /** - * Supported SDES crypto suites. - */ - typedef enum { - AES_CM_128_HMAC_SHA1_32 = 0, - AES_CM_128_HMAC_SHA1_80 - } sdesSuites; - - /** - * SDES stream state - */ - typedef enum { - STREAM_INITALIZED = 1, - OUT_PROFILE_READY, - IN_PROFILE_READY, - SDES_SRTP_ACTIVE - } sdesZrtpStates; - - typedef enum { - MIX_NONE = 0, - MIX_HMAC_SHA, - MIX_MAC_SKEIN - } sdesHmacTypeMix; - - /** - * @brief Create and SDES/ZRTP stream. - * - * This method creates an SDES stream with capabilities to handle RTP, - * RTCP, SRTP, and SRTCP packets. - * - * @param suite defines which crypto suite to use for this stream. The values are - * @c AES_CM_128_HMAC_SHA1_80 or @c AES_CM_128_HMAC_SHA1_32. - */ - ZrtpSdesStream(const sdesSuites suite =AES_CM_128_HMAC_SHA1_32); - - ~ZrtpSdesStream(); - - /** - * @brief Close an SDES/ZRTP stream. - * - * Close the stream and return allocated memory to the pool. - */ - void close(); - - /** - * @brief Creates an SDES crypto string for the SDES/ZRTP stream. - * - * Creates the crypto string that the application can use in the SDP fields of - * SIP INVITE or SIP 200 OK. - * - * An INVITE-ing application shall call this function at the same point when - * it calls the functions to get the @c zrtp-hash string and shall insert the - * created crypto string into the SDP. - * - * An answering application shall call this function directly @b after it called - * @c sdesZrtpStreamParseSdes. This usually at the same point when it gets the - * @c zrtp-hash from the SDP parameters and forwards it to @c libzrtp. The - * answering application's SRTP environment is now ready. - * - * @param cryptoString output buffer that receives the crypto string in raw - * format, without the any signaling prefix, for example - * @c a=crypto:. The function terminates the crypto string - * with a @c nul byte - * - * @param maxLen length of the crypto string buffer. On return it contains the - * actual length of the crypto string. - * - * @param sipInvite the inviter (offerer) must set this to @c true, the answerer must - * set it to @c false. - * - * @return @c true if data could be created, @c false otherwise. - */ - bool createSdes(char *cryptoString, size_t *maxLen, bool sipInvite); - - /** - * @brief Parses an SDES crypto string for the SDES/ZRTP stream. - * - * Parses a SDES crypto string that the application received in a SIP INVITE - * or SIP 200 OK. - * - * An INVITE-ing (offerer) application shall call this function right after it received - * the 200 OK from the answering application and must call this function with the - * @c sipInvite parameter set to @c true. The offerer's SRTP is now ready for use. - * - * The answering application calls this function after it received the INVITE and - * extracted the crypto string from the SDP and must call this function with the - * @c sipInvite parameter set to @c false. - * - * @param cryptoString the received crypto sting in raw format, - * without any signaling prefix, for example @c a=crypto: - * - * @param length length of the crypto string to parse. If the length is - * @c zero then the function uses @c strlen to compute - * the length. - * - * @param sipInvite the inviter (offerer) must set this to @c true, the answerer must - * set it to @c false. - * - * @return @c true if data could be created, @c false otherwise. - */ - bool parseSdes(const char *cryptoString, size_t length, bool sipInvite); - - /** - * @brief Get Crypto Mix attribute string - * - * The offerer calls this method to get a string of @b all supported crypto mix algorithms - * and shall send this list to the answerer. - * - * The answerer calls this function only @b after it received the crypto mix string and @b after - * calling @c setCryptoMixAttribute(...). The method returns only one (the selected) - * crypto mix algorithm and the answerer must send this to the offerer, for example in 200 OK. - * - * @param algoNames buffer to store the nul terminated crypto mix algorithm names. - * The buffer must be long enough to hold at least the name of the mandatory - * algorithm HMAC-SHA-384. - * - * @param length length of buffer - * - * @return Length of algorithm names (excluding nul byte) or zero if crypto mix not supported or - * enabled. - */ - int getCryptoMixAttribute(char *algoNames, size_t length); - - /** - * @brief Set Crypto Mix attribute string - * - * The method checks if it the string contains an supported algorithm and selects one algorithm. - * - * The offerer calls this method @b after it received the selected algorithm in the answer. - * - * The answerer must call this method @b before it calls the @c getCryptoMixAttribute() method. - * - * @param algoNames buffer that contains the received crypto mix algorithm names. - * The buffer must be nul terminated. - * - * @return @c false if none of the offered algorithms is supported. - */ - bool setCryptoMixAttribute(const char *algoNames); - - /* - * ******** Outgoing RTP/RTCP packet handling - */ - /** - * @brief Process an outgoing RTP packet - * - * This function processes an outgoing RTP packet. Depending on the state - * the packet is either: - * - not encrypted if neither SDES nor ZRTP are active or supported by the - * other client. This is the standard case if the stream was just initialized. - * - encrypted with SDES provided key data. This is the case if the application - * called both @c sdesZrtpStreamCreateSdes and @c sdesZrtpStreamParseSdes - * functions to properly setup the SDES key data. - * - * @param packet the buffer that contains the RTP packet. After processing, the - * encrypted packet is stored in the same buffer. The buffer must - * big enough to hold the additional SRTP data, depending on the - * SRTP profile these are usually 4 - 20 bytes. - * - * @param length length of the RTP packet - * - * @param newLength to an integer that get the new length of the packet including SRTP data. - * - * @return - * - @c true if encryption is successful, app shall send packet to the recipient. - * - @c false if there was an error during encryption, don't send the packet. - */ - bool outgoingRtp(uint8_t *packet, size_t length, size_t *newLength); - - /** - * @brief Process an outgoing RTCP packet - * - * This function works in the same way as @c outgoingRtp. - * - * @param packet the buffer that contains the RTCP packet. After processing, the - * encrypted packet is stored in the same buffer. The buffer must - * big enough to hold the additional SRTP data, depending on the - * SRTP profile these are usually 8 - 20 bytes. - * - * @param length length of the RTP packet - * - * @param newLength to an integer that get the new length of the packet including SRTP data. - * - * @return - * - @c true if encryption is successful, app shall send packet to the recipient. - * - @c false if there was an error during encryption, don't send the packet. - */ - bool outgoingRtcp(uint8_t *packet, size_t length, size_t *newLength); - - /* - * ******** Incoming SRTP/SRTCP packet handling - */ - /** - * @brief Process an incoming RTP or SRTP packet - * - * This function processes an incoming RTP/SRTP packet. Depending on the state - * the packet is either: - * - not decrypted if SDES is not active or supported by the - * other client. This is the standard case if the stream was just initialized. - * - decrypted with SDES provided key data. This is the case if the application - * called both @c sdesZrtpStreamCreateSdes and @c sdesZrtpStreamParseSdes - * functions to properly setup the SDES key data. - * - * @param packet the buffer that contains the RTP/SRTP packet. After processing, - * the decrypted packet is stored in the same buffer. - * - * @param length length of the RTP packet - * - * @param newLength to an integer that get the new length of the packet excluding SRTCP data. - * - * @return - * - 1: success, - * - -1: SRTP authentication failed, - * - -2: SRTP replay check failed - */ - int incomingRtp(uint8_t *packet, size_t length, size_t *newLength); - - /** - * @brief Process an incoming RTCP or SRTCP packet - * - * This function works in the same way as @c incomingRtp. - * - * @param packet the buffer that contains the RTCP/SRTCP packet. After processing, - * the decrypted packet is stored in the same buffer. - * - * @param length length of the RTCP packet - * - * @param newLength to an integer that get the new length of the packet excluding SRTCP data. - * - * @return - * - 1: success, - * - -1: SRTCP authentication failed, - * - -2: SRTCP replay check failed - */ - int incomingSrtcp(uint8_t *packet, size_t length, size_t *newLength); - - /** - * @brief Process an outgoing ZRTP packet. - * - * Works like @c outgoingRtp, refer to that documentation. - * - * @param packet the buffer that contains the ZRTP packet. - * - * @param length length of the ZRTP packet - * - * @param newLength to an integer that get the new length of the packet including SRTP data. - * - * @return - * - @c true if encryption is successful, app shall send packet to the recipient. - * - @c false if there was an error during encryption, don't send the packet. - */ - bool outgoingZrtpTunnel(uint8_t *packet, size_t length, size_t *newLength); - - /** - * @brief Process an incoming ZRTP packet - * - * Works like @c incomingRtp, refer to that documentation. - * - * @param packet the buffer that contains the ZRTP/SRTP packet. After processing, - * the decrypted packet is stored in the same buffer. - * - * @param length length of the RTP packet - * - * @param newLength to an integer that get the new length of the packet excluding SRTCP data. - * - * @return - * - 1: success, - * - -1: SRTP authentication failed, - * - -2: SRTP replay check failed - */ - int incomingZrtpTunnel(uint8_t *packet, size_t length, size_t *newLength); - - /** - * @brief Return state of SDES stream. - * - * @return state of stream. - */ - sdesZrtpStates getState() {return state;} - - /** - * @brief Return SDES crypto mixer HMAC type. - * - * @return HMAC type - */ - sdesHmacTypeMix getHmacTypeMix() {return cryptoMixHashType;} - - /** - * @brief Return name of active cipher algorithm. - * - * @return point to name of cipher algorithm. - */ - const char* getCipher(); - - /** - * @brief Return name of active SRTP authentication algorithm. - * - * @return point to name of authentication algorithm. - */ - const char* getAuthAlgo(); - - - /* - * ******** Lower layer functions - */ -private: - /** - * @brief Create an SRTP crypto context and the according SDES crypto string. - * - * This lower layer method creates an SDES crypto string. It selects a valid - * crypto suite, generates the key and salt data, converts these into base 64 - * and returns the crypto string in raw format without any signaling prefixes. - * - * The output string has the following format: - * @verbatim - * 1 AES_CM_128_HMAC_SHA1_32 inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj - * @endverbatim - * - * Applications usually don't use this method directly. Applications shall - * use the SDES stream functions. - * - * Depending on the crypto suite the overall length of the crypto string - * is variable. For a normal AES_128_CM suite the minumum lenth is 73 - * characters, a AES_256_CM suite results in 97 characters (not counting - * any signaling prefixes). - * - * @param cryptoString points to a char output buffer that receives the - * crypto string in the raw format, without the any - * signaling prefix, for example @c a=crypto: in case - * of SDP signaling. The function terminates the - * crypto string with a @c nul byte - * - * @param maxLen points to an integer. On input this integer specifies the - * length of the output buffer. If @c maxLen is smaller than - * the resulting crypto string the function returns an error - * conde. On return the functions sets @c maxLen to the - * actual length of the resultig crypto string. - * - * @param tag the value of the @c tag field in the crypto string. The - * answerer must use this input to make sure that the tag value - * in the answer matches the value in the offer. See RFC 4568, - * section 5.1.2. - * If the tag value is @c -1 the function sets the tag to @c 1. - * - * @return @c true if data could be created, @c false - * otherwise. - */ - bool createSdesProfile(char *cryptoString, size_t *maxLen); - - /** - * @brief Parse and check an offered SDES crypto string and create SRTP crypto context. - * - * The method parses an offered SDES crypto string and checks if it is - * valid. Next it checks if the string contains a supported crypto suite - * and if the key and salt lengths match the selected crypto suite. - * - * Applications usually don't use this method directly. Applications shall - * use the SDES stream functions. - * - * @b NOTE: This function does not support the optional parameters lifetime, - * MKI, and session parameters. While it can parse liftime and MKI theiy are - * not evaluated and used. If these parameters are used in the input crypto - * string the function return @c false. - * - * @param cryptoString points to the crypto sting in raw format, - * without any signaling prefix, for example @c a=crypto: in case of - * SDP signaling. - * - * @param length length of the crypto string to parse. If the length is - * @c zero then the function uses @c strlen to compute the length. - * - * @param parsedSuite the function sets this to the @c sdesSuites enumerator of - * the parsed crypto suite. The answerer shall use this as input to - * @c createSdesProfile to make sure that it creates the same crypto suite. - * See RFC 4568, section 5.1.2 - * - * @param tag the function sets this to the @c tag value of the parsed crypto - * string. The answerer must use this as input to @c createSdesProfile - * to make sure that it creates the correct tag in the crypto string. - * See RFC 4568, section 5.1.2 - * - * @return @c true if checks were ok, @c false - * otherwise. - */ - bool parseCreateSdesProfile(const char *cryptoString, size_t length, sdesSuites *parsedSuite, int32_t *tag); - - /** - * @brief Create the SRTP contexts after all SDES creation and parsing is done. - * - * @param sipInvite if this is set to @c true (not zero) then the method - * computes the key data for the inviting SIP application (offerer) and - * for the answerer otherwise. - */ - void createSrtpContexts(bool sipInvite); - - /** - * @brief Compute the mixed keys if SDES mixing attribute is set. - * - * The method takes the parsed or created SDES key material and computes the mixed keys and salt. - * It replaces the existing key material with the new data. - * - * @param sipInvite if this is set to @c true (not zero) then the method - * computes the key data for the inviting SIP application (offerer) and - * for the answerer otherwise. - */ - void computeMixedKeys(bool sipInvite); - - - sdesZrtpStates state; - sdesSuites suite; - int32_t tag; - CryptoContext *recvSrtp; //!< The SRTP context for this stream - CryptoContextCtrl *recvSrtcp; //!< The SRTCP context for this stream - CryptoContext *sendSrtp; //!< The SRTP context for this stream - CryptoContextCtrl *sendSrtcp; //!< The SRTCP context for this stream - uint32_t srtcpIndex; //!< the local SRTCP index - - CryptoContext *recvZrtpTunnel; //!< The SRTP context for sender ZRTP tunnel - CryptoContext *sendZrtpTunnel; //!< The SRTP context for receiver ZRTP tunnel - - int32_t cryptoMixHashLength; - sdesHmacTypeMix cryptoMixHashType; - - // Variables for crypto that this client creates and sends to the other client, filled during SDES create - uint8_t localKeySalt[((MAX_KEY_LEN + MAX_SALT_LEN + 3)/4)*4]; //!< Some buffer for key and salt, multiple of 4 - int localKeyLenBytes; - int localSaltLenBytes; - int localCipher; - int localAuthn; - int localAuthKeyLen; - int localTagLength; - - // Variables for crypto that this client receives from the other client, filled during SDES parse - uint8_t remoteKeySalt[((MAX_KEY_LEN + MAX_SALT_LEN + 3)/4)*4]; //!< Some buffer for key and salt, multiple of 4 - int remoteKeyLenBytes; - int remoteSaltLenBytes; - int remoteCipher; - int remoteAuthn; - int remoteAuthKeyLen; - int remoteTagLength; -}; -#endif \ No newline at end of file diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpB64Decode.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpB64Decode.h deleted file mode 100644 index f53f1adb6..000000000 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpB64Decode.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -cdecode.h - c header for a base64 decoding algorithm - -This is part of the libb64 project, and has been placed in the public domain. -For details, see http://sourceforge.net/projects/libb64 -*/ - -#ifndef BASE64_CDECODE_H -#define BASE64_CDECODE_H - -#include <stdint.h> - -#if defined(__cplusplus) -extern "C" -{ -#endif - -typedef enum -{ - step_a, step_b, step_c, step_d -} base64_decodestep; - -typedef struct -{ - base64_decodestep step; - char plainchar; -} base64_decodestate; - -void base64_init_decodestate(base64_decodestate* state_in); - -int base64_decode_value(char value_in); - -int base64_decode_block(const char* code_in, const int length_in, uint8_t *plaintext_out, base64_decodestate* state_in); - -#if defined(__cplusplus) -} -#endif - -#endif /* BASE64_CDECODE_H */ diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpB64Encode.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpB64Encode.h deleted file mode 100644 index f05439237..000000000 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpB64Encode.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -cencode.h - c header for a base64 encoding algorithm - -This is part of the libb64 project, and has been placed in the public domain. -For details, see http://sourceforge.net/projects/libb64 -*/ - -#ifndef BASE64_CENCODE_H -#define BASE64_CENCODE_H - -#include <stdint.h> - -#if defined(__cplusplus) -extern "C" -{ -#endif - -typedef enum -{ - step_A, step_B, step_C -} base64_encodestep; - -typedef struct -{ - base64_encodestep step; - char result; - int stepcount; - int lineLength; -} base64_encodestate; - -void base64_init_encodestate(base64_encodestate* state_in, int lineLength); - -char base64_encode_value(const int8_t value_in); - -int base64_encode_block(const uint8_t *plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); - -int base64_encode_blockend(char *code_out, base64_encodestate* state_in); -#if defined(__cplusplus) -} -#endif - -#endif /* BASE64_CENCODE_H */ diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpCacheDbBackend.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpCacheDbBackend.h deleted file mode 100644 index 8f3346237..000000000 --- a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpCacheDbBackend.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - Copyright (C) 2006-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _ZRTP_CACHE_DB_BACKEND_H_ -#define _ZRTP_CACHE_DB_BACKEND_H_ - -#include <libzrtpcpp/ZIDRecordDb.h> - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#define DB_CACHE_ERR_BUFF_SIZE 1000 - -/** - * Set of accessible operations of database ZRTP cache implementaion. - * - * The only public method of the database ZRTP implementation is - * getDbCacheOps(...) that fills in this call structure. This mechanism - * decouples the database implementations from libzrtp and possible other - * clients. - * - * Some implementation notes: - * <ul> - * <li> All data storage methods return 0 (zero) if the call was successful. - * </li> - - * <li> The @c errString parameter points to a buffer of at least @c - * DB_CACHE_ERR_BUFF_SIZE character. In case of an error methods shall - * store detailed, human readable information in this buffer. Use @c - * snprintf or similar functions to format the data. If this parameter - * is @c NULL then methods must not return an error string. - *</li> - * <li> The methods cast the @c void to the type they need. Be aware that the - * open functions requires a pointer to a pointer. - * </li> - * </ul> - * - * - * - */ -typedef struct { - /** - * @brief Open the cache. - * - * @param name String that identifies the database or data storage. - * - * @param pdb Pointer to an internal structure that the database - * implementation requires. - * - * @param errString Pointer to a character buffer, see implementation - * notes above. - */ - int (*openCache)(const char* name, void **pdb, char *errString); - - /** - * Close the cache. - * - * @param db Pointer to an internal structure that the database - * implementation requires. - */ - int (*closeCache)(void *db); - - /** - * @brief Read a local ZID from the database. - * - * The cache database may implement methods to generate and store local - * ZRTP identifiers (ZID) and optionally link them with account - * information. The account information data is the key to the request - * local ZID. If the application does not provide account information data - * the method implmentation shall use a standard predfined string that - * does not collide with usual account information. - * - * The SQLite backend uses the string @c "_STANDARD_" in this case and - * sets a specific type field. - * - * The first call to this method with a specific account information - * generates a ZID, stores it in the database usind the account - * information as key, and returns the ZID to the application. Any - * subsequent call with the same account information return the same local - * ZID. - * - * @param db Pointer to an internal structure that the database - * implementation requires. - * - * @param localZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The method stores the local ZID in this - * buffer. - * - * @param accountInfo Pointer to an account information string or @c NULL - * if explicit account information is not required. - * - * @param errString Pointer to a character buffer, see implementation - * notes above. - */ - int (*readLocalZid)(void *db, uint8_t *localZid, const char *accountInfo, char *errString); - - /** - * @brief Read a remote ZID data structure. - * - * The method uses @c remoteZid and @c localZid as keys to read the remote - * ZID record. If a record does not exist in the database the method - * clears the @c flags field in the @c remoteZidRecord_t structure and - * returns without error. The application must check the flags if the - * method found a valid record. - * - * @param db Pointer to an internal structure that the database - * implementation requires. - * - * @param localZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the local ZID. - * - * @param remoteZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the remote ZID. - * - * @param remZid Pointer to the @c remoteZidRecord_t structure. The method - * fills this structure with data it read from the database. - * - * @param errString Pointer to a character buffer, see implementation - * notes above. - */ - int (*readRemoteZidRecord)(void *db, const uint8_t *remoteZid, const uint8_t *localZid, - remoteZidRecord_t *remZid, char* errString); - /** - * @brief Update an existing remote ZID data structure. - * - * The method uses @c remoteZid and @c localZid as keys to update an - * existing remote ZID record. - * - * @b NOTE: application must use this methods only if - * @c readRemoteZidRecord (see above) returned a @b valid record. If - * @c readRemoteZidRecord returned an invalid record then no such - * record exists in the database and the application must use the - * @c insertRemoteZidRecord (see below). - * - * @param db Pointer to an internal structure that the database - * implementation requires. - * - * @param localZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the local ZID. - * - * @param remoteZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the remote ZID. - * - * @param remZid Pointer to the @c remoteZidRecord_t structure. The method - * gets data from this structure and stores it in the - * database. - * - * @param errString Pointer to a character buffer, see implementation - * notes above. - */ - int (*updateRemoteZidRecord)(void *db, const uint8_t *remoteZid, const uint8_t *localZid, - const remoteZidRecord_t *remZid, char* errString); - /** - * @brief Insert a new remote ZID data structure. - * - * The method uses @c remoteZid and @c localZid as keys to insert a new - * remote ZID record. - * - * @b NOTE: application must use this methods only if @c - * readRemoteZidRecord (see above) returned an @b invalid - * record. Refer to note. - * - * @param db Pointer to an internal structure that the database - * implementation requires. - * - * @param localZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the local ZID. - * - * @param remoteZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the remote ZID. - * - * @param remZid Pointer to the @c remoteZidRecord_t structure. The method - * gets data from this structure and stores it in the - * database. - * - * @param errString Pointer to a character buffer, see implementation - * notes above. - */ - int (*insertRemoteZidRecord)(void *db, const uint8_t *remoteZid, const uint8_t *localZid, - const remoteZidRecord_t *remZid, char* errString); - - /** - * @brief Read a remote ZID name. - * - * The method uses @c remoteZid, @c localZid, and @c accountInfo as keys - * to read the remote ZID name. If a record does not exist in the database - * the method clears the @c flags field in the @c zidNameRecord_t structure and - * returns without error. The application must check the flags if the - * method found a valid record. - * - * @param db Pointer to an internal structure that the database - * implementation requires. - * - * @param localZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the local ZID. - * - * @param remoteZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the remote ZID. - * - * @param accountInfo Pointer to an account information string or @c NULL - * if explicit account information is not required. - * - * @param zidName Pointer to the @c zidNameRecord_t structure. The method - * returns the data in this structure. - * - * @param errString Pointer to a character buffer, see implementation - * notes above. - */ - int (*readZidNameRecord)(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid, - const char *accountInfo, zidNameRecord_t *zidName, char* errString); - - /** - * @brief Update an existing remote ZID data structure. - * - * The method uses @c remoteZid and @c localZid as keys to update an - * existing remote ZID record. - * - * @b NOTE: application must use this methods only if - * @c readZidName (see above) returned a @b valid record. If - * @c readZidName returned an invalid record then no such - * record exists in the database and the application must use the - * @c insertZidNameRecord (see below). - * - * @param db Pointer to an internal structure that the database - * implementation requires. - * - * @param localZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the local ZID. - * - * @param remoteZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the remote ZID. - * - * @param accountInfo Pointer to an account information string or @c NULL - * if explicit account information is not required. - * - * @param zidName Pointer to the @c zidNameRecord_t structure. The method - * gets data from this structure and stores it in the - * database. - * - * @param errString Pointer to a character buffer, see implementation - * notes above. - */ - int (*updateZidNameRecord)(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid, - const char *accountInfo, zidNameRecord_t *zidName, char* errString); - - /** - * @brief Insert a new ZID name record. - * - * The method uses @c remoteZid, @c localZid, and @c accountInfo as keys to - * insert a new ZID name record. - * - * @b NOTE: application must use this methods only if @c readZidName - * (see above) returned an @b invalid record. - * - * @param db Pointer to an internal structure that the database - * implementation requires. - * - * @param localZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the local ZID. - * - * @param remoteZid Pointer to a buffer of at least @c IDENTIFIER_LEN @c - * uint8_t bytes. The buffer must contain the remote ZID. - * - * @param accountInfo Pointer to an account information string or @c NULL - * if explicit account information is not required. - * - * @param zidName Pointer to the @c zidNameRecord_t structure. The method - * gets data from this structure and stores it in the - * database. - * - * @param errString Pointer to a character buffer, see implementation - * notes above. - */ - int (*insertZidNameRecord)(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid, - const char *accountInfo, zidNameRecord_t *zidName, char* errString); - - - /** - * @brief Clean the cache. - * - * The function drops and re-creates all tables in the database. This removes all stored - * data. The application must not call this while a ZRTP call is active. Also the application - * <b>must</b> get the local ZID again. - * - * @param db Pointer to an internal structure that the database - * implementation requires. - * - * @param errString Pointer to a character buffer, see implementation - * notes above. - */ - int (*cleanCache)(void *db, char* errString); -} dbCacheOps_t; - -void getDbCacheOps(dbCacheOps_t *ops); - - -#if defined(__cplusplus) -} -#endif - -#endif /* _ZRTP_CACHE_DB_BACKEND_H_*/ diff --git a/jni/libzrtp/sources/zrtp/zrtpB64Decode.c b/jni/libzrtp/sources/zrtp/zrtpB64Decode.c deleted file mode 100644 index d0fb69e0a..000000000 --- a/jni/libzrtp/sources/zrtp/zrtpB64Decode.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * cdecoder.c - c source to a base64 decoding algorithm implementation - * - * This is part of the libb64 project, and has been placed in the public domain. - * For details, see http://sourceforge.net/projects/libb64 - */ - -#include <libzrtpcpp/zrtpB64Decode.h> - -int base64_decode_value(char value_in) -{ - static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51}; - static const char decoding_size = sizeof(decoding); - value_in -= 43; - if (value_in < 0 || value_in > decoding_size) return -1; - return decoding[(int)value_in]; -} - -void base64_init_decodestate(base64_decodestate* state_in) -{ - state_in->step = step_a; - state_in->plainchar = 0; -} - -int base64_decode_block(const char* code_in, const int length_in, uint8_t *plaintext_out, base64_decodestate* state_in) -{ - const char* codechar = code_in; - uint8_t *plainchar = plaintext_out; - char fragment; - - *plainchar = state_in->plainchar; - - switch (state_in->step) - { - while (1) - { - case step_a: - do { - if (codechar == code_in+length_in) - { - state_in->step = step_a; - state_in->plainchar = *plainchar; - return plainchar - plaintext_out; - } - fragment = (char)base64_decode_value(*codechar++); - } while (fragment < 0); - *plainchar = (fragment & 0x03f) << 2; - case step_b: - do { - if (codechar == code_in+length_in) - { - state_in->step = step_b; - state_in->plainchar = *plainchar; - return plainchar - plaintext_out; - } - fragment = (char)base64_decode_value(*codechar++); - } while (fragment < 0); - *plainchar++ |= (fragment & 0x030) >> 4; - *plainchar = (fragment & 0x00f) << 4; - case step_c: - do { - if (codechar == code_in+length_in) - { - state_in->step = step_c; - state_in->plainchar = *plainchar; - return plainchar - plaintext_out; - } - fragment = (char)base64_decode_value(*codechar++); - } while (fragment < 0); - *plainchar++ |= (fragment & 0x03c) >> 2; - *plainchar = (fragment & 0x003) << 6; - case step_d: - do { - if (codechar == code_in+length_in) - { - state_in->step = step_d; - state_in->plainchar = *plainchar; - return plainchar - plaintext_out; - } - fragment = (char)base64_decode_value(*codechar++); - } while (fragment < 0); - *plainchar++ |= (fragment & 0x03f); - } - } - /* control should not reach here */ - return plainchar - plaintext_out; -} - diff --git a/jni/libzrtp/sources/zrtp/zrtpB64Encode.c b/jni/libzrtp/sources/zrtp/zrtpB64Encode.c deleted file mode 100644 index 241e3c577..000000000 --- a/jni/libzrtp/sources/zrtp/zrtpB64Encode.c +++ /dev/null @@ -1,116 +0,0 @@ -/* -cencoder.c - c source to a base64 encoding algorithm implementation - -This is part of the libb64 project, and has been placed in the public domain. -For details, see http://sourceforge.net/projects/libb64 -*/ - -#include <libzrtpcpp/zrtpB64Encode.h> - -const int CHARS_PER_LINE = 72; - -void base64_init_encodestate(base64_encodestate* state_in, int lineLength) -{ - state_in->step = step_A; - state_in->result = 0; - state_in->stepcount = 0; - if (lineLength < 0) - state_in->lineLength = CHARS_PER_LINE / 4; - else - state_in->lineLength = (lineLength+3) / 4; -} - -char base64_encode_value(const int8_t value_in) -{ - static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - if (value_in > 63) return '='; - return encoding[(int)value_in]; -} - -int base64_encode_block(const uint8_t *plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) -{ - const uint8_t *plainchar = plaintext_in; - const uint8_t *const plaintextend = plaintext_in + length_in; - char* codechar = code_out; - char result; - char fragment; - - result = state_in->result; - - switch (state_in->step) - { - while (1) - { - case step_A: - if (plainchar == plaintextend) - { - state_in->result = result; - state_in->step = step_A; - return codechar - code_out; - } - fragment = *plainchar++; - result = (fragment & 0x0fc) >> 2; - *codechar++ = base64_encode_value(result); - result = (fragment & 0x003) << 4; - case step_B: - if (plainchar == plaintextend) - { - state_in->result = result; - state_in->step = step_B; - return codechar - code_out; - } - fragment = *plainchar++; - result |= (fragment & 0x0f0) >> 4; - *codechar++ = base64_encode_value(result); - result = (fragment & 0x00f) << 2; - case step_C: - if (plainchar == plaintextend) - { - state_in->result = result; - state_in->step = step_C; - return codechar - code_out; - } - fragment = *plainchar++; - result |= (fragment & 0x0c0) >> 6; - *codechar++ = base64_encode_value(result); - result = (fragment & 0x03f) >> 0; - *codechar++ = base64_encode_value(result); - - if (state_in->lineLength > 0) { - state_in->stepcount++; - if (state_in->stepcount == state_in->lineLength) - { - *codechar++ = '\n'; - state_in->stepcount = 0; - } - } - } - } - /* control should not reach here */ - return codechar - code_out; -} - -int base64_encode_blockend(char* code_out, base64_encodestate* state_in) -{ - char* codechar = code_out; - - switch (state_in->step) - { - case step_B: - *codechar++ = base64_encode_value(state_in->result); - *codechar++ = '='; - *codechar++ = '='; - break; - case step_C: - *codechar++ = base64_encode_value(state_in->result); - *codechar++ = '='; - break; - case step_A: - break; - } - if (state_in->lineLength > 0) - *codechar++ = '\n'; - - return codechar - code_out; -} - diff --git a/jni/libzrtp/sources/zrtp/zrtpCacheSqliteBackend.c b/jni/libzrtp/sources/zrtp/zrtpCacheSqliteBackend.c deleted file mode 100644 index 7dc9cdf28..000000000 --- a/jni/libzrtp/sources/zrtp/zrtpCacheSqliteBackend.c +++ /dev/null @@ -1,789 +0,0 @@ -/* - Copyright (C) 2012-2013 Werner Dittmann - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Authors: Werner Dittmann <Werner.Dittmann@t-online.de> - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <time.h> -#include <sqlite3.h> - -#include <crypto/zrtpDH.h> - -#include <libzrtpcpp/zrtpB64Encode.h> -#include <libzrtpcpp/zrtpB64Decode.h> - -#include <libzrtpcpp/zrtpCacheDbBackend.h> - -/* Some ported SQLite3 libs do not support the _v2 variants */ -#define SQLITE_USE_V2 - -#ifdef SQLITE_USE_V2 -#define SQLITE_PREPARE sqlite3_prepare_v2 -#else -#define SQLITE_PREPARE sqlite3_prepare -#endif - -#if defined(_WIN32) || defined(_WIN64) -# define snprintf _snprintf -#endif - -#ifdef TRANSACTIONS -static const char *beginTransactionSql = "BEGIN TRANSACTION;"; -static const char *commitTransactionSql = "COMMIT;"; -#endif - -/* - * The database backend uses the following definitions if it implements the localZid storage. - */ - -/* The type field in zrtpIdOwn stores the following values */ -static const int32_t localZidStandard = 1; /* this local ZID is not tied to a specific account */ -static const int32_t localZidWithAccount = 2; - -/* Default data for account info if none specified */ -static const char *defaultAccountString = "_STANDARD_"; - - -/* ***************************************************************************** - * The SQLite master table. - * - * Used to check if we have valid ZRTP cache tables. - */ -static char *lookupTables = "SELECT name FROM sqlite_master WHERE type='table' AND name='zrtpIdOwn';"; - - -/* ***************************************************************************** - * SQL statements to process the zrtpIdOwn table. - */ -static const char *dropZrtpIdOwn = "DROP TABLE zrtpIdOwn;"; - -/* SQLite doesn't care about the VARCHAR length. */ -static char *createZrtpIdOwn = "CREATE TABLE zrtpIdOwn(localZid CHAR(18), type INTEGER, accountInfo VARCHAR(1000));"; - -static char *selectZrtpIdOwn = "SELECT localZid FROM zrtpIdOwn WHERE type = ?1 AND accountInfo = ?2;"; -static char *insertZrtpIdOwn = "INSERT INTO zrtpIdOwn (localZid, type, accountInfo) VALUES (?1, ?2, ?3);"; - - -/* ***************************************************************************** - * SQL statements to process the remoteId table. - */ -static const char *dropZrtpIdRemote = "DROP TABLE zrtpIdRemote;"; - -static const char *createZrtpIdRemote = - "CREATE TABLE zrtpIdRemote " - "(remoteZid CHAR(16), localZid CHAR(16), flags INTEGER," - "rs1 BLOB(32), rs1LastUsed TIMESTAMP, rs1TimeToLive TIMESTAMP," - "rs2 BLOB(32), rs2LastUsed TIMESTAMP, rs2TimeToLive TIMESTAMP," - "mitmKey BLOB(32), mitmLastUsed TIMESTAMP, secureSince TIMESTAMP, preshCounter INTEGER);"; - -static const char *selectZrtpIdRemoteAll = - "SELECT flags," - "rs1, strftime('%s', rs1LastUsed, 'unixepoch'), strftime('%s', rs1TimeToLive, 'unixepoch')," - "rs2, strftime('%s', rs2LastUsed, 'unixepoch'), strftime('%s', rs2TimeToLive, 'unixepoch')," - "mitmKey, strftime('%s', mitmLastUsed, 'unixepoch'), strftime('%s', secureSince, 'unixepoch')," - "preshCounter " - "FROM zrtpIdRemote WHERE remoteZid=?1 AND localZid=?2;"; - -static const char *insertZrtpIdRemote = - "INSERT INTO zrtpIdRemote " - "(remoteZid, localZid, flags," - "rs1, rs1LastUsed, rs1TimeToLive," - "rs2, rs2LastUsed, rs2TimeToLive," - "mitmKey, mitmLastUsed, secureSince, preshCounter)" - "VALUES" - "(?1, ?12, ?2," - "?3, strftime('%s', ?4, 'unixepoch'), strftime('%s', ?5, 'unixepoch')," - "?6, strftime('%s', ?7, 'unixepoch'), strftime('%s', ?8, 'unixepoch')," - "?9, strftime('%s', ?10, 'unixepoch'), strftime('%s', ?11, 'unixepoch'), ?13);"; - -static const char *updateZrtpIdRemote = - "UPDATE zrtpIdRemote SET " - "flags=?2," - "rs1=?3, rs1LastUsed=strftime('%s', ?4, 'unixepoch'), rs1TimeToLive=strftime('%s', ?5, 'unixepoch')," - "rs2=?6, rs2LastUsed=strftime('%s', ?7, 'unixepoch'), rs2TimeToLive=strftime('%s', ?8, 'unixepoch')," - "mitmKey=?9, mitmLastUsed=strftime('%s', ?10, 'unixepoch')," - "secureSince=strftime('%s', ?11, 'unixepoch'), preshCounter=?13 " - "WHERE remoteZid=?1 AND localZid=?12;"; - - -/* ***************************************************************************** - * SQL statements to process the name table. - * - * The name tables holds free format information and binds it to the combination - * of local, remote ZIDs and an optional account information. - */ -static const char *dropZrtpNames = "DROP TABLE zrtpNames;"; - -static const char *createZrtpNames = - "CREATE TABLE zrtpNames " - "(remoteZid CHAR(16), localZid CHAR(16), flags INTEGER, " - "lastUpdate TIMESTAMP, accountInfo VARCHAR(1000), name VARCHAR(1000));"; - -static const char *selectZrtpNames = - "SELECT flags, strftime('%s', lastUpdate, 'unixepoch'), name " - "FROM zrtpNames " - "WHERE remoteZid=?1 AND localZid=?2 AND accountInfo=?3;"; - -static const char *insertZrtpNames = - "INSERT INTO zrtpNames " - "(remoteZid, localZid, flags, lastUpdate, accountInfo, name)" - "VALUES" - "(?1, ?2, ?4, strftime('%s', ?5, 'unixepoch'), ?3, ?6);"; - -static const char *updateZrtpNames = - "UPDATE zrtpNames SET " - "flags=?4," - "lastUpdate=strftime('%s', ?5, 'unixepoch'), name=?6 " - "WHERE remoteZid=?1 AND localZid=?2 AND accountInfo=?3;"; - - -/* ***************************************************************************** - * A few helping macros. - * These macros require some names/patterns in the methods that use these - * macros: - * - * ERRMSG requires: - * - a variable with name "db" is the pointer to sqlite3 - * - a char* with name "errString" points to a buffer of at least SQL_CACHE_ERR_BUFF_SIZE chars - * - * SQLITE_CHK requires: - * - a cleanup label, the macro goes to that label in case of error - * - an integer (int) variable with name "rc" that stores return codes from sqlite - * - ERRMSG - */ -#define ERRMSG {if (errString) snprintf(errString, (size_t)DB_CACHE_ERR_BUFF_SIZE, \ - "SQLite3 error: %s, line: %d, error message: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));} -#define SQLITE_CHK(func) { \ - rc = (func); \ - if(rc != SQLITE_OK) { \ - ERRMSG; \ - goto cleanup; \ - } \ - } - -static int b64Encode(const uint8_t *binData, int32_t binLength, char *b64Data, int32_t b64Length) -{ - base64_encodestate _state; - int codelength; - - base64_init_encodestate(&_state, 0); - codelength = base64_encode_block(binData, binLength, b64Data, &_state); - codelength += base64_encode_blockend(b64Data+codelength, &_state); - - return codelength; -} - -static int b64Decode(const char *b64Data, int32_t b64length, uint8_t *binData, int32_t binLength) -{ - base64_decodestate _state; - int codelength; - - base64_init_decodestate(&_state); - codelength = base64_decode_block(b64Data, b64length, binData, &_state); - return codelength; -} - -#ifdef TRANSACTIONS -static int beginTransaction(sqlite3 *db, char* errString) -{ - sqlite3_stmt *stmt; - int rc; - - SQLITE_CHK(SQLITE_PREPARE(db, beginTransactionSql, strlen(beginTransactionSql)+1, &stmt, NULL)); - - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - return SQLITE_OK; - - cleanup: - sqlite3_finalize(stmt); - return rc; -} - -static int commitTransaction(sqlite3 *db, char* errString) -{ - sqlite3_stmt *stmt; - int rc; - - SQLITE_CHK(SQLITE_PREPARE(db, commitTransactionSql, strlen(commitTransactionSql)+1, &stmt, NULL)); - - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - return SQLITE_OK; - - cleanup: - sqlite3_finalize(stmt); - return rc; -} -#endif - -/** - * Initialize remote ZID and remote name tables. - * - * First drop the remote ZID and remote name tables and create them again. - * All information regarding remote peers is lost. - */ -static int initializeRemoteTables(sqlite3 *db, char* errString) -{ - sqlite3_stmt * stmt; - int rc; - - /* First drop them, just to be on the save side - * Ignore errors, there is nothing to drop on empty DB. If ZrtpIdOwn was - * deleted using DB admin command then we need to drop the remote id table - * and names also to have a clean state. - */ - rc = SQLITE_PREPARE(db, dropZrtpIdRemote, strlen(dropZrtpIdRemote)+1, &stmt, NULL); - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - - rc = SQLITE_PREPARE(db, dropZrtpNames, strlen(dropZrtpNames)+1, &stmt, NULL); - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - - SQLITE_CHK(SQLITE_PREPARE(db, createZrtpIdRemote, strlen(createZrtpIdRemote)+1, &stmt, NULL)); - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - SQLITE_CHK(SQLITE_PREPARE(db, createZrtpNames, strlen(createZrtpNames)+1, &stmt, NULL)); - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - return 0; - - cleanup: - sqlite3_finalize(stmt); - return rc; - -} -/** - * Create ZRTP cache tables in database. - * - * openCache calls this function if it cannot find the table zrtpId_own. This indicates - * that no ZRTP cache tables are available in the database. - */ -static int createTables(sqlite3 *db, char* errString) -{ - sqlite3_stmt * stmt; - int rc; - - /* no ZRTP cache tables were found - create them, first the OwnId table */ - SQLITE_CHK(SQLITE_PREPARE(db, createZrtpIdOwn, strlen(createZrtpIdOwn)+1, &stmt, NULL)); - - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - return initializeRemoteTables(db, errString); - - cleanup: - sqlite3_finalize(stmt); - return rc; -} - -static int insertRemoteZidRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid, - const remoteZidRecord_t *remZid, char* errString) -{ - sqlite3 *db = (sqlite3*)vdb; - sqlite3_stmt *stmt; - int rc = 0; - - char b64RemoteZid[IDENTIFIER_LEN*2] = {0}; - char b64LocalZid[IDENTIFIER_LEN*2] = {0}; - - /* Get B64 code for remoteZid first */ - b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2); - - /* Get B64 code for localZid now */ - b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2); - - SQLITE_CHK(SQLITE_PREPARE(db, insertZrtpIdRemote, strlen(insertZrtpIdRemote)+1, &stmt, NULL)); - - /* For *_bind_* methods: column index starts with 1 (one), not zero */ - SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_text(stmt, 12, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_int(stmt, 2, remZid->flags)); - SQLITE_CHK(sqlite3_bind_blob(stmt, 3, remZid->rs1, RS_LENGTH, SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 4, remZid->rs1LastUse)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 5, remZid->rs1Ttl)); - SQLITE_CHK(sqlite3_bind_blob(stmt, 6, remZid->rs2, RS_LENGTH, SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 7, remZid->rs2LastUse)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 8, remZid->rs2Ttl)); - SQLITE_CHK(sqlite3_bind_blob(stmt, 9, remZid->mitmKey, RS_LENGTH, SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 10, remZid->mitmLastUse)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 11, remZid->secureSince)); - SQLITE_CHK(sqlite3_bind_int(stmt, 13, remZid->preshCounter)); - - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - return SQLITE_OK; - - cleanup: - sqlite3_finalize(stmt); - return rc; - -} - -static int updateRemoteZidRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid, - const remoteZidRecord_t *remZid, char* errString) -{ - sqlite3 *db = (sqlite3*)vdb; - sqlite3_stmt *stmt; - int rc; - - char b64RemoteZid[IDENTIFIER_LEN*2] = {0}; - char b64LocalZid[IDENTIFIER_LEN*2] = {0}; - - /* Get B64 code for remoteZid first */ - b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2); - - /* Get B64 code for localZid now */ - b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2); - - SQLITE_CHK(SQLITE_PREPARE(db, updateZrtpIdRemote, strlen(updateZrtpIdRemote)+1, &stmt, NULL)); - - /* For *_bind_* methods: column index starts with 1 (one), not zero */ - /* Select for update with the following keys */ - SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_text(stmt, 12, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC)); - - /* Update the following values */ - SQLITE_CHK(sqlite3_bind_int(stmt, 2, remZid->flags)); - SQLITE_CHK(sqlite3_bind_blob(stmt, 3, remZid->rs1, RS_LENGTH, SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 4, remZid->rs1LastUse)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 5, remZid->rs1Ttl)); - SQLITE_CHK(sqlite3_bind_blob(stmt, 6, remZid->rs2, RS_LENGTH, SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 7, remZid->rs2LastUse)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 8, remZid->rs2Ttl)); - SQLITE_CHK(sqlite3_bind_blob(stmt, 9, remZid->mitmKey, RS_LENGTH, SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 10, remZid->mitmLastUse)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 11, remZid->secureSince)); - SQLITE_CHK(sqlite3_bind_int(stmt, 13, remZid->preshCounter)); - - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - return SQLITE_OK; - - cleanup: - sqlite3_finalize(stmt); - return rc; -} - -static int readRemoteZidRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid, - remoteZidRecord_t *remZid, char* errString) -{ - sqlite3 *db = (sqlite3*)vdb; - sqlite3_stmt *stmt; - int rc; - int found = 0; - - char b64RemoteZid[IDENTIFIER_LEN*2] = {0}; - char b64LocalZid[IDENTIFIER_LEN*2] = {0}; - - /* Get B64 code for remoteZid */ - b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2); - - /* Get B64 code for localZid */ - b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2); - - SQLITE_CHK(SQLITE_PREPARE(db, selectZrtpIdRemoteAll, strlen(selectZrtpIdRemoteAll)+1, &stmt, NULL)); - SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_text(stmt, 2, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC)); - - /* Getting data from result set: column index starts with 0 (zero), not one */ - while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { - remZid->flags = sqlite3_column_int(stmt, 0); - memcpy(remZid->rs1, sqlite3_column_blob(stmt, 1), RS_LENGTH); - remZid->rs1LastUse = sqlite3_column_int64(stmt, 2); - remZid->rs1Ttl = sqlite3_column_int64(stmt, 3); - memcpy(remZid->rs2, sqlite3_column_blob(stmt, 4), RS_LENGTH); - remZid->rs2LastUse = sqlite3_column_int64(stmt, 5); - remZid->rs2Ttl = sqlite3_column_int64(stmt, 6); - memcpy(remZid->mitmKey, sqlite3_column_blob(stmt, 7), RS_LENGTH); - remZid->mitmLastUse = sqlite3_column_int64(stmt, 8); - remZid->secureSince = sqlite3_column_int64(stmt, 9); - remZid->preshCounter = sqlite3_column_int(stmt, 10); - found++; - } - sqlite3_finalize(stmt); - - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - if (found == 0) { - remZid->flags = 0; - } - else if (found > 1) { - if (errString) - snprintf(errString, DB_CACHE_ERR_BUFF_SIZE, "ZRTP cache inconsistent. More than one remote ZID found: %d\n", found); - return 1; - } - return SQLITE_OK; - - cleanup: - sqlite3_finalize(stmt); - return rc; -} - - -static int readLocalZid(void *vdb, uint8_t *localZid, const char *accountInfo, char *errString) -{ - sqlite3 *db = (sqlite3*)vdb; - sqlite3_stmt *stmt; - char *zidBase64Text; - int rc = 0; - int found = 0; - int type = localZidWithAccount; - - if (accountInfo == NULL || !strcmp(accountInfo, defaultAccountString)) { - accountInfo = defaultAccountString; - type = localZidStandard; - } - - /* Find a localZid record for this combination */ - SQLITE_CHK(SQLITE_PREPARE(db, selectZrtpIdOwn, strlen(selectZrtpIdOwn)+1, &stmt, NULL)); - - SQLITE_CHK(sqlite3_bind_int(stmt, 1, type)); - SQLITE_CHK(sqlite3_bind_text(stmt, 2, accountInfo, strlen(accountInfo), SQLITE_STATIC)); - - /* Loop over result set and count it. However, use only the localZid of first row */ - while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { - if (found == 0) { - zidBase64Text = (char *)sqlite3_column_text(stmt, 0); - b64Decode(zidBase64Text, strlen(zidBase64Text), localZid, IDENTIFIER_LEN); - } - found++; - } - sqlite3_finalize(stmt); - - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - /* No matching record found, create new local ZID for this combination and store in DB */ - if (found == 0) { - char b64zid[IDENTIFIER_LEN+IDENTIFIER_LEN] = {0}; - int b64len = 0; - - /* create a 12 byte random value, convert to base 64, insert in zrtpIdOwn table */ - randomZRTP(localZid, IDENTIFIER_LEN); - b64len = b64Encode(localZid, IDENTIFIER_LEN, b64zid, IDENTIFIER_LEN+IDENTIFIER_LEN); - - SQLITE_CHK(SQLITE_PREPARE(db, insertZrtpIdOwn, strlen(insertZrtpIdOwn)+1, &stmt, NULL)); - - SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64zid, b64len, SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_int(stmt, 2, type)); - SQLITE_CHK(sqlite3_bind_text(stmt, 3, accountInfo, strlen(accountInfo), SQLITE_STATIC)); - - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - } - else if (found > 1) { - if (errString) - snprintf(errString, DB_CACHE_ERR_BUFF_SIZE, - "ZRTP cache inconsistent. Found %d matching local ZID for account: %s\n", found, accountInfo); - return 1; - } - return SQLITE_OK; - - cleanup: - sqlite3_finalize(stmt); - return rc; -} - -/* - * SQLite use the following table structure to manage some internal data - * - * CREATE TABLE sqlite_master ( - * type TEXT, - * name TEXT, - * tbl_name TEXT, - * rootpage INTEGER, - * sql TEXT - * ); - */ - -static int openCache(const char* name, void **vpdb, char *errString) -{ - sqlite3_stmt *stmt; - int found = 0; - sqlite3 **pdb = (sqlite3**)vpdb; - sqlite3 *db; - -#ifdef SQLITE_USE_V2 - int rc = sqlite3_open_v2(name, pdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL); -#else - int rc = sqlite3_open(name, pdb); -#endif - db = *pdb; - if (rc) { - ERRMSG; - return(rc); - } - - /* check if ZRTP cache tables are already available, look if zrtpIdOwn is available */ - SQLITE_CHK(SQLITE_PREPARE(db, lookupTables, strlen(lookupTables)+1, &stmt, NULL)); - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - - if (rc == SQLITE_ROW) { - found++; - } - else if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - /* If table zrtpOwnId not found then we have an empty cache DB */ - if (found == 0) { - rc = createTables(db, errString); - if (rc) - return rc; - } - return SQLITE_OK; - - cleanup: - sqlite3_finalize(stmt); - return rc; -} - -static int closeCache(void *vdb) -{ - - sqlite3 *db = (sqlite3*)vdb; - sqlite3_close(db); - return SQLITE_OK; -} - -static int clearCache(void *vdb, char *errString) -{ - - sqlite3 *db = (sqlite3*)vdb; - sqlite3_stmt * stmt; - int rc; - - rc = SQLITE_PREPARE(db, dropZrtpIdOwn, strlen(dropZrtpIdOwn)+1, &stmt, NULL); - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - - rc = createTables(db, errString); - if (rc) - return rc; - return SQLITE_OK; -} - -static int insertZidNameRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid, - const char *accountInfo, zidNameRecord_t *zidName, char* errString) -{ - sqlite3 *db = (sqlite3*)vdb; - sqlite3_stmt *stmt; - int rc = 0; - char b64RemoteZid[IDENTIFIER_LEN*2] = {0}; - char b64LocalZid[IDENTIFIER_LEN*2] = {0}; - - if (accountInfo == NULL) { - accountInfo = defaultAccountString; - } - - /* Get B64 code for remoteZid */ - b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2); - - /* Get B64 code for localZid */ - b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2); - - SQLITE_CHK(SQLITE_PREPARE(db, insertZrtpNames, strlen(insertZrtpNames)+1, &stmt, NULL)); - - /* For *_bind_* methods: column index starts with 1 (one), not zero */ - SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_text(stmt, 2, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_text(stmt, 3, accountInfo, strlen(accountInfo), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_int(stmt, 4, zidName->flags)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 5, (int64_t)time(NULL))); - if (zidName->name != NULL) { - SQLITE_CHK(sqlite3_bind_text(stmt, 6, zidName->name, strlen(zidName->name), SQLITE_STATIC)); - } - else { - SQLITE_CHK(sqlite3_bind_text(stmt, 6, "_NO_NAME_", 9, SQLITE_STATIC)); - } - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - return SQLITE_OK; - - cleanup: - sqlite3_finalize(stmt); - return rc; - -} - - -static int updateZidNameRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid, - const char *accountInfo, zidNameRecord_t *zidName, char* errString) -{ - sqlite3 *db = (sqlite3*)vdb; - sqlite3_stmt *stmt; - int rc = 0; - char b64RemoteZid[IDENTIFIER_LEN*2] = {0}; - char b64LocalZid[IDENTIFIER_LEN*2] = {0}; - - if (accountInfo == NULL) { - accountInfo = defaultAccountString; - } - - /* Get B64 code for remoteZid */ - b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2); - - /* Get B64 code for localZid */ - b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2); - - SQLITE_CHK(SQLITE_PREPARE(db, updateZrtpNames, strlen(updateZrtpNames)+1, &stmt, NULL)); - - /* For *_bind_* methods: column index starts with 1 (one), not zero */ - /* Select for update with the following values */ - SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_text(stmt, 2, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_text(stmt, 3, accountInfo, strlen(accountInfo), SQLITE_STATIC)); - - /* Update the following vaulues */ - SQLITE_CHK(sqlite3_bind_int(stmt, 4, zidName->flags)); - SQLITE_CHK(sqlite3_bind_int64(stmt, 5, (int64_t)time(NULL))); - if (zidName->name != NULL) { - SQLITE_CHK(sqlite3_bind_text(stmt, 6, zidName->name, strlen(zidName->name), SQLITE_STATIC)); - } - else { - SQLITE_CHK(sqlite3_bind_text(stmt, 6, "_NO_NAME_", 9, SQLITE_STATIC)); - } - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - return SQLITE_OK; - - cleanup: - sqlite3_finalize(stmt); - return rc; - -} - -static int readZidNameRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid, - const char *accountInfo, zidNameRecord_t *zidName, char* errString) -{ - sqlite3 *db = (sqlite3*)vdb; - sqlite3_stmt *stmt; - int rc; - int found = 0; - - char b64RemoteZid[IDENTIFIER_LEN*2] = {0}; - char b64LocalZid[IDENTIFIER_LEN*2] = {0}; - - if (accountInfo == NULL) { - accountInfo = defaultAccountString; - } - /* Get B64 code for remoteZid */ - b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2); - - /* Get B64 code for localZid */ - b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2); - - SQLITE_CHK(SQLITE_PREPARE(db, selectZrtpNames, strlen(selectZrtpNames)+1, &stmt, NULL)); - - SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_text(stmt, 2, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC)); - SQLITE_CHK(sqlite3_bind_text(stmt, 3, accountInfo, strlen(accountInfo), SQLITE_STATIC)); - - /* Getting data from result set: column index starts with 0 (zero), not one */ - while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { - zidName->flags = sqlite3_column_int(stmt, 0); - strncpy(zidName->name, (const char*)sqlite3_column_text(stmt, 2), zidName->nameLength); - zidName->nameLength = sqlite3_column_bytes(stmt, 2); /* Return number of bytes in string */ - found++; - } - sqlite3_finalize(stmt); - - if (rc != SQLITE_DONE) { - ERRMSG; - return rc; - } - if (found == 0) - zidName->flags = 0; - else if (found > 1) { - if (errString) - snprintf(errString, DB_CACHE_ERR_BUFF_SIZE, "ZRTP name cache inconsistent. More than one ZID name found: %d\n", found); - return 1; - } - return SQLITE_OK; - - cleanup: - sqlite3_finalize(stmt); - return rc; -} - -void getDbCacheOps(dbCacheOps_t *ops) -{ - ops->openCache = openCache; - ops->closeCache = closeCache; - ops->cleanCache = clearCache; - - ops->readLocalZid = readLocalZid; - - ops->readRemoteZidRecord = readRemoteZidRecord; - ops->updateRemoteZidRecord = updateRemoteZidRecord; - ops->insertRemoteZidRecord = insertRemoteZidRecord; - - ops->readZidNameRecord = readZidNameRecord; - ops->updateZidNameRecord = updateZidNameRecord; - ops->insertZidNameRecord = insertZidNameRecord; -} - -- GitLab