From 5aa37bf3747829cd75812b32d8a177dbae1ab834 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Wed, 9 Sep 2026 23:28:46 +0200 Subject: [PATCH] Reconstruction of des.exe/undes.exe --- .gitignore | 3 + CMakeLists.txt | 102 ++ MSDOS/asm/des-main.asm | 815 ++++++++++++++ MSDOS/asm/undes-main.asm | 598 +++++++++++ README.md | 39 +- SHA256SUMS.txt | 3 + cryptlib-api-map.md | 40 + des.c | 205 ++++ des_common.c | 122 +++ des_common.h | 37 + gcc-syntax-check.txt | 0 reconstruction-notes.md | 162 +++ third_party/cryptl99.zip | Bin 0 -> 151902 bytes third_party/cryptlib-0.99/DMakefile | 120 +++ third_party/cryptlib-0.99/SCOptions | 35 + third_party/cryptlib-0.99/SMakefile | 115 ++ third_party/cryptlib-0.99/crypt.bas | 215 ++++ third_party/cryptlib-0.99/crypt.c | 1049 +++++++++++++++++++ third_party/cryptlib-0.99/crypt.h | 421 ++++++++ third_party/cryptlib-0.99/cryptnt.def | 23 + third_party/cryptlib-0.99/cryptnt.mak | 391 +++++++ third_party/cryptlib-0.99/cryptnt.rc | 33 + third_party/cryptlib-0.99/cryptos2.def | 24 + third_party/cryptlib-0.99/cryptwin.def | 24 + third_party/cryptlib-0.99/cryptwin.mak | 255 +++++ third_party/cryptlib-0.99/cryptwin.rc | 33 + third_party/cryptlib-0.99/docs.txt | 613 +++++++++++ third_party/cryptlib-0.99/idea/idea.c | 410 ++++++++ third_party/cryptlib-0.99/idea/idea.h | 34 + third_party/cryptlib-0.99/idea/idea68k.s | 173 +++ third_party/cryptlib-0.99/idea/idea8086.asm | 285 +++++ third_party/cryptlib-0.99/lib_3des.c | 443 ++++++++ third_party/cryptlib-0.99/lib_des.c | 486 +++++++++ third_party/cryptlib-0.99/lib_idea.c | 442 ++++++++ third_party/cryptlib-0.99/lib_mdc.c | 460 ++++++++ third_party/cryptlib-0.99/lib_null.c | 68 ++ third_party/cryptlib-0.99/lib_rc4.c | 134 +++ third_party/cryptlib-0.99/lib_safr.c | 489 +++++++++ third_party/cryptlib-0.99/libdes/3ecb_enc.c | 36 + third_party/cryptlib-0.99/libdes/copyrigh | 50 + third_party/cryptlib-0.99/libdes/des.h | 98 ++ third_party/cryptlib-0.99/libdes/des_locl.h | 204 ++++ third_party/cryptlib-0.99/libdes/ecb_enc.c | 112 ++ third_party/cryptlib-0.99/libdes/pcbc_enc.c | 83 ++ third_party/cryptlib-0.99/libdes/podd.h | 25 + third_party/cryptlib-0.99/libdes/set_key.c | 198 ++++ third_party/cryptlib-0.99/libdes/sk.h | 146 +++ third_party/cryptlib-0.99/libdes/spr.h | 152 +++ third_party/cryptlib-0.99/libdes/version.h | 9 + third_party/cryptlib-0.99/makefile | 271 +++++ third_party/cryptlib-0.99/mdc/shs.c | 540 ++++++++++ third_party/cryptlib-0.99/mdc/shs.h | 35 + third_party/cryptlib-0.99/rc4/rc4.asm | 137 +++ third_party/cryptlib-0.99/rc4/rc4.c | 65 ++ third_party/cryptlib-0.99/rc4/rc4.h | 23 + third_party/cryptlib-0.99/safer/safer.c | 203 ++++ third_party/cryptlib-0.99/safer/safer.h | 114 ++ third_party/cryptlib-0.99/test.c | 519 +++++++++ third_party/cryptlib-0.99/testdes.h | 928 ++++++++++++++++ third_party/cryptlib-0.99/testidea.h | 56 + third_party/cryptlib-0.99/testrc4.h | 162 +++ third_party/cryptlib-0.99/testsafr.h | 36 + undes.c | 193 ++++ validation.md | 50 + 64 files changed, 13344 insertions(+), 2 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 MSDOS/asm/des-main.asm create mode 100644 MSDOS/asm/undes-main.asm create mode 100644 SHA256SUMS.txt create mode 100644 cryptlib-api-map.md create mode 100644 des.c create mode 100644 des_common.c create mode 100644 des_common.h create mode 100644 gcc-syntax-check.txt create mode 100644 reconstruction-notes.md create mode 100644 third_party/cryptl99.zip create mode 100644 third_party/cryptlib-0.99/DMakefile create mode 100644 third_party/cryptlib-0.99/SCOptions create mode 100644 third_party/cryptlib-0.99/SMakefile create mode 100644 third_party/cryptlib-0.99/crypt.bas create mode 100644 third_party/cryptlib-0.99/crypt.c create mode 100644 third_party/cryptlib-0.99/crypt.h create mode 100644 third_party/cryptlib-0.99/cryptnt.def create mode 100644 third_party/cryptlib-0.99/cryptnt.mak create mode 100644 third_party/cryptlib-0.99/cryptnt.rc create mode 100644 third_party/cryptlib-0.99/cryptos2.def create mode 100644 third_party/cryptlib-0.99/cryptwin.def create mode 100644 third_party/cryptlib-0.99/cryptwin.mak create mode 100644 third_party/cryptlib-0.99/cryptwin.rc create mode 100644 third_party/cryptlib-0.99/docs.txt create mode 100644 third_party/cryptlib-0.99/idea/idea.c create mode 100644 third_party/cryptlib-0.99/idea/idea.h create mode 100644 third_party/cryptlib-0.99/idea/idea68k.s create mode 100644 third_party/cryptlib-0.99/idea/idea8086.asm create mode 100644 third_party/cryptlib-0.99/lib_3des.c create mode 100644 third_party/cryptlib-0.99/lib_des.c create mode 100644 third_party/cryptlib-0.99/lib_idea.c create mode 100644 third_party/cryptlib-0.99/lib_mdc.c create mode 100644 third_party/cryptlib-0.99/lib_null.c create mode 100644 third_party/cryptlib-0.99/lib_rc4.c create mode 100644 third_party/cryptlib-0.99/lib_safr.c create mode 100644 third_party/cryptlib-0.99/libdes/3ecb_enc.c create mode 100644 third_party/cryptlib-0.99/libdes/copyrigh create mode 100644 third_party/cryptlib-0.99/libdes/des.h create mode 100644 third_party/cryptlib-0.99/libdes/des_locl.h create mode 100644 third_party/cryptlib-0.99/libdes/ecb_enc.c create mode 100644 third_party/cryptlib-0.99/libdes/pcbc_enc.c create mode 100644 third_party/cryptlib-0.99/libdes/podd.h create mode 100644 third_party/cryptlib-0.99/libdes/set_key.c create mode 100644 third_party/cryptlib-0.99/libdes/sk.h create mode 100644 third_party/cryptlib-0.99/libdes/spr.h create mode 100644 third_party/cryptlib-0.99/libdes/version.h create mode 100644 third_party/cryptlib-0.99/makefile create mode 100644 third_party/cryptlib-0.99/mdc/shs.c create mode 100644 third_party/cryptlib-0.99/mdc/shs.h create mode 100644 third_party/cryptlib-0.99/rc4/rc4.asm create mode 100644 third_party/cryptlib-0.99/rc4/rc4.c create mode 100644 third_party/cryptlib-0.99/rc4/rc4.h create mode 100644 third_party/cryptlib-0.99/safer/safer.c create mode 100644 third_party/cryptlib-0.99/safer/safer.h create mode 100644 third_party/cryptlib-0.99/test.c create mode 100644 third_party/cryptlib-0.99/testdes.h create mode 100644 third_party/cryptlib-0.99/testidea.h create mode 100644 third_party/cryptlib-0.99/testrc4.h create mode 100644 third_party/cryptlib-0.99/testsafr.h create mode 100644 undes.c create mode 100644 validation.md diff --git a/.gitignore b/.gitignore index e257658..a973259 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ *.out *.app +build/ +*.bak +.qtcreator diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..fcadac0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,102 @@ +cmake_minimum_required(VERSION 3.16) + +project(des_undes VERSION 1.1.0 LANGUAGES C) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) + +set(CRYPTLIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cryptlib-0.99") + +# CRYPTLIB 0.99 registers all algorithms in crypt.c at startup, so all of the +# original algorithm backends must be linked even though DES/UNDES itself uses +# only CRYPT_ALGO_3DES + CRYPT_MODE_CBC. +add_library(cryptlib099 STATIC + ${CRYPTLIB_DIR}/crypt.c + ${CRYPTLIB_DIR}/lib_3des.c + ${CRYPTLIB_DIR}/lib_des.c + ${CRYPTLIB_DIR}/lib_idea.c + ${CRYPTLIB_DIR}/lib_mdc.c + ${CRYPTLIB_DIR}/lib_null.c + ${CRYPTLIB_DIR}/lib_rc4.c + ${CRYPTLIB_DIR}/lib_safr.c + ${CRYPTLIB_DIR}/idea/idea.c + ${CRYPTLIB_DIR}/libdes/3ecb_enc.c + ${CRYPTLIB_DIR}/libdes/ecb_enc.c + ${CRYPTLIB_DIR}/libdes/pcbc_enc.c + ${CRYPTLIB_DIR}/libdes/set_key.c + ${CRYPTLIB_DIR}/rc4/rc4.c + ${CRYPTLIB_DIR}/safer/safer.c + ${CRYPTLIB_DIR}/mdc/shs.c +) + +target_include_directories(cryptlib099 PUBLIC + ${CRYPTLIB_DIR} +) + + +# The original makefile used __UNIX__ for Unix builds. +if(UNIX) + target_compile_definitions(cryptlib099 PRIVATE __UNIX__) +endif() + +add_library(des_common STATIC des_common.c) +target_include_directories(des_common PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CRYPTLIB_DIR} +) +target_link_libraries(des_common PUBLIC cryptlib099) + +add_executable(des des.c) +add_executable(undes undes.c) + +target_link_libraries(des PRIVATE des_common) +target_link_libraries(undes PRIVATE des_common) + +# des.c and undes.c deliberately retain the original DOS-style , read() +# and fileno() calls. POSIX systems have these declarations in , so +# provide a tiny generated compatibility header without changing the recovered +# source files. +if(UNIX) + set(COMPAT_DIR "${CMAKE_CURRENT_BINARY_DIR}/compat") + file(MAKE_DIRECTORY "${COMPAT_DIR}") + file(WRITE "${COMPAT_DIR}/io.h" "#ifndef DES_COMPAT_IO_H\n#define DES_COMPAT_IO_H\n#include \n#endif\n") + target_include_directories(des PRIVATE "${COMPAT_DIR}") + target_include_directories(undes PRIVATE "${COMPAT_DIR}") +endif() + +# Modern Microsoft C uses underscored names for these POSIX-compatible calls. +#if(MSVC) +# target_compile_definitions(des PRIVATE +# _CRT_SECURE_NO_WARNINGS +# fileno=_fileno +# read=_read +# ) +# target_compile_definitions(undes PRIVATE +# _CRT_SECURE_NO_WARNINGS +# fileno=_fileno +# read=_read +# ) +# target_compile_definitions(cryptlib099 PRIVATE __WINDOWS__ _CRT_SECURE_NO_WARNINGS) +#endif() + +if(MSVC) + target_compile_definitions(cryptlib099 PRIVATE + _CRT_SECURE_NO_WARNINGS + ) + + target_compile_definitions(des PRIVATE + _CRT_SECURE_NO_WARNINGS + fileno=_fileno + read=_read + ) + + target_compile_definitions(undes PRIVATE + _CRT_SECURE_NO_WARNINGS + fileno=_fileno + read=_read + ) +endif() + + +install(TARGETS des undes RUNTIME DESTINATION bin) diff --git a/MSDOS/asm/des-main.asm b/MSDOS/asm/des-main.asm new file mode 100644 index 0000000..169ba4d --- /dev/null +++ b/MSDOS/asm/des-main.asm @@ -0,0 +1,815 @@ + +/mnt/data/des.img: file format binary + + +Disassembly of section .data: + +000004b0 <.data+0x4b0>: + 4b0: c2 33 d2 ret 0xd233 + 4b3: d3 e8 shr ax,cl + 4b5: cb retf + 4b6: 55 push bp + 4b7: 8b ec mov bp,sp + 4b9: 81 ec 3c 05 sub sp,0x53c + 4bd: 56 push si + 4be: 57 push di + 4bf: 1e push ds + 4c0: b8 46 0d mov ax,0xd46 + 4c3: 8e d8 mov ds,ax + 4c5: 83 7e 06 02 cmp WORD PTR [bp+0x6],0x2 + 4c9: 74 03 je 0x4ce + 4cb: e9 a0 00 jmp 0x56e + 4ce: 1e push ds + 4cf: b8 0c 00 mov ax,0xc + 4d2: 50 push ax + 4d3: c4 5e 08 les bx,DWORD PTR [bp+0x8] + 4d6: 26 ff 77 06 push WORD PTR es:[bx+0x6] + 4da: 26 ff 77 04 push WORD PTR es:[bx+0x4] + 4de: 9a 0f 00 b7 0b call 0xbb7:0xf + 4e3: 83 c4 08 add sp,0x8 + 4e6: 0b c0 or ax,ax + 4e8: 75 43 jne 0x52d + 4ea: b8 5f 0d mov ax,0xd5f + 4ed: 8e c0 mov es,ax + 4ef: 26 ff 36 04 00 push WORD PTR es:0x4 + 4f4: 26 ff 36 02 00 push WORD PTR es:0x2 + 4f9: 1e push ds + 4fa: b8 18 00 mov ax,0x18 + 4fd: 50 push ax + 4fe: 9a 06 00 d7 0b call 0xbd7:0x6 + 503: 83 c4 08 add sp,0x8 + 506: b8 5f 0d mov ax,0xd5f + 509: 8e c0 mov es,ax + 50b: 26 ff 36 0c 00 push WORD PTR es:0xc + 510: 26 ff 36 0a 00 push WORD PTR es:0xa + 515: 1e push ds + 516: b8 1d 00 mov ax,0x1d + 519: 50 push ax + 51a: 9a 06 00 d7 0b call 0xbd7:0x6 + 51f: 83 c4 08 add sp,0x8 + 522: 6a 00 push 0x0 + 524: 9a 0b 00 55 0a call 0xa55:0xb + 529: 44 inc sp + 52a: 44 inc sp + 52b: eb 41 jmp 0x56e + 52d: 1e push ds + 52e: b8 20 00 mov ax,0x20 + 531: 50 push ax + 532: c4 5e 08 les bx,DWORD PTR [bp+0x8] + 535: 26 ff 77 06 push WORD PTR es:[bx+0x6] + 539: 26 ff 77 04 push WORD PTR es:[bx+0x4] + 53d: 9a 0f 00 b7 0b call 0xbb7:0xf + 542: 83 c4 08 add sp,0x8 + 545: 0b c0 or ax,ax + 547: 75 25 jne 0x56e + 549: b8 5f 0d mov ax,0xd5f + 54c: 8e c0 mov es,ax + 54e: 26 ff 36 04 00 push WORD PTR es:0x4 + 553: 26 ff 36 02 00 push WORD PTR es:0x2 + 558: 1e push ds + 559: b8 2a 00 mov ax,0x2a + 55c: 50 push ax + 55d: 9a 06 00 d7 0b call 0xbd7:0x6 + 562: 83 c4 08 add sp,0x8 + 565: 6a 00 push 0x0 + 567: 9a 0b 00 55 0a call 0xa55:0xb + 56c: 44 inc sp + 56d: 44 inc sp + 56e: 83 7e 06 04 cmp WORD PTR [bp+0x6],0x4 + 572: 74 3e je 0x5b2 + 574: 1e push ds + 575: b8 90 00 mov ax,0x90 + 578: 50 push ax + 579: 1e push ds + 57a: b8 7b 00 mov ax,0x7b + 57d: 50 push ax + 57e: 1e push ds + 57f: b8 64 00 mov ax,0x64 + 582: 50 push ax + 583: 1e push ds + 584: b8 3b 00 mov ax,0x3b + 587: 50 push ax + 588: 1e push ds + 589: b8 2e 00 mov ax,0x2e + 58c: 50 push ax + 58d: b8 e0 11 mov ax,0x11e0 + 590: 50 push ax + 591: b8 2a 00 mov ax,0x2a + 594: 50 push ax + 595: 9a 08 00 9b 0c call 0xc9b:0x8 + 59a: 83 c4 18 add sp,0x18 + 59d: 83 7e 06 01 cmp WORD PTR [bp+0x6],0x1 + 5a1: 75 04 jne 0x5a7 + 5a3: 33 c0 xor ax,ax + 5a5: eb 03 jmp 0x5aa + 5a7: b8 02 00 mov ax,0x2 + 5aa: 50 push ax + 5ab: 9a 0b 00 55 0a call 0xa55:0xb + 5b0: 44 inc sp + 5b1: 44 inc sp + 5b2: c4 5e 08 les bx,DWORD PTR [bp+0x8] + 5b5: 26 c4 5f 04 les bx,DWORD PTR es:[bx+0x4] + 5b9: 8c 46 f6 mov WORD PTR [bp-0xa],es + 5bc: 89 5e f4 mov WORD PTR [bp-0xc],bx + 5bf: c4 5e 08 les bx,DWORD PTR [bp+0x8] + 5c2: 26 c4 5f 08 les bx,DWORD PTR es:[bx+0x8] + 5c6: 8c 46 ee mov WORD PTR [bp-0x12],es + 5c9: 89 5e ec mov WORD PTR [bp-0x14],bx + 5cc: c4 5e 08 les bx,DWORD PTR [bp+0x8] + 5cf: 26 c4 5f 0c les bx,DWORD PTR es:[bx+0xc] + 5d3: 8c 46 f2 mov WORD PTR [bp-0xe],es + 5d6: 89 5e f0 mov WORD PTR [bp-0x10],bx + 5d9: 1e push ds + 5da: b8 b5 00 mov ax,0xb5 + 5dd: 50 push ax + 5de: ff 76 ee push WORD PTR [bp-0x12] + 5e1: ff 76 ec push WORD PTR [bp-0x14] + 5e4: 9a 0f 00 b7 0b call 0xbb7:0xf + 5e9: 83 c4 08 add sp,0x8 + 5ec: 0b c0 or ax,ax + 5ee: 74 3b je 0x62b + 5f0: ff 76 f2 push WORD PTR [bp-0xe] + 5f3: ff 76 f0 push WORD PTR [bp-0x10] + 5f6: ff 76 ee push WORD PTR [bp-0x12] + 5f9: ff 76 ec push WORD PTR [bp-0x14] + 5fc: 9a 0f 00 b7 0b call 0xbb7:0xf + 601: 83 c4 08 add sp,0x8 + 604: 0b c0 or ax,ax + 606: 75 23 jne 0x62b + 608: 1e push ds + 609: b8 bb 00 mov ax,0xbb + 60c: 50 push ax + 60d: 1e push ds + 60e: b8 b7 00 mov ax,0xb7 + 611: 50 push ax + 612: b8 e0 11 mov ax,0x11e0 + 615: 50 push ax + 616: b8 2a 00 mov ax,0x2a + 619: 50 push ax + 61a: 9a 08 00 9b 0c call 0xc9b:0x8 + 61f: 83 c4 0c add sp,0xc + 622: 6a 01 push 0x1 + 624: 9a 0b 00 55 0a call 0xa55:0xb + 629: 44 inc sp + 62a: 44 inc sp + 62b: 1e push ds + 62c: b8 e7 00 mov ax,0xe7 + 62f: 50 push ax + 630: ff 76 ee push WORD PTR [bp-0x12] + 633: ff 76 ec push WORD PTR [bp-0x14] + 636: 9a 0f 00 b7 0b call 0xbb7:0xf + 63b: 83 c4 08 add sp,0x8 + 63e: 0b c0 or ax,ax + 640: 75 0c jne 0x64e + 642: c7 46 fa e0 11 mov WORD PTR [bp-0x6],0x11e0 + 647: c7 46 f8 02 00 mov WORD PTR [bp-0x8],0x2 + 64c: eb 19 jmp 0x667 + 64e: 1e push ds + 64f: b8 e9 00 mov ax,0xe9 + 652: 50 push ax + 653: ff 76 ee push WORD PTR [bp-0x12] + 656: ff 76 ec push WORD PTR [bp-0x14] + 659: 9a 45 02 b0 0a call 0xab0:0x245 + 65e: 83 c4 08 add sp,0x8 + 661: 89 56 fa mov WORD PTR [bp-0x6],dx + 664: 89 46 f8 mov WORD PTR [bp-0x8],ax + 667: 1e push ds + 668: b8 ec 00 mov ax,0xec + 66b: 50 push ax + 66c: ff 76 f2 push WORD PTR [bp-0xe] + 66f: ff 76 f0 push WORD PTR [bp-0x10] + 672: 9a 0f 00 b7 0b call 0xbb7:0xf + 677: 83 c4 08 add sp,0x8 + 67a: 0b c0 or ax,ax + 67c: 75 0c jne 0x68a + 67e: c7 46 fe e0 11 mov WORD PTR [bp-0x2],0x11e0 + 683: c7 46 fc 16 00 mov WORD PTR [bp-0x4],0x16 + 688: eb 19 jmp 0x6a3 + 68a: 1e push ds + 68b: b8 ee 00 mov ax,0xee + 68e: 50 push ax + 68f: ff 76 f2 push WORD PTR [bp-0xe] + 692: ff 76 f0 push WORD PTR [bp-0x10] + 695: 9a 45 02 b0 0a call 0xab0:0x245 + 69a: 83 c4 08 add sp,0x8 + 69d: 89 56 fe mov WORD PTR [bp-0x2],dx + 6a0: 89 46 fc mov WORD PTR [bp-0x4],ax + 6a3: ff 76 ee push WORD PTR [bp-0x12] + 6a6: ff 76 ec push WORD PTR [bp-0x14] + 6a9: ff 76 fa push WORD PTR [bp-0x6] + 6ac: ff 76 f8 push WORD PTR [bp-0x8] + 6af: 9a 8c 00 a0 00 call 0xa0:0x8c + 6b4: 83 c4 08 add sp,0x8 + 6b7: ff 76 f2 push WORD PTR [bp-0xe] + 6ba: ff 76 f0 push WORD PTR [bp-0x10] + 6bd: ff 76 fe push WORD PTR [bp-0x2] + 6c0: ff 76 fc push WORD PTR [bp-0x4] + 6c3: 9a 8c 00 a0 00 call 0xa0:0x8c + 6c8: 83 c4 08 add sp,0x8 + 6cb: ff 76 fe push WORD PTR [bp-0x2] + 6ce: ff 76 fc push WORD PTR [bp-0x4] + 6d1: 6a 01 push 0x1 + 6d3: 6a 04 push 0x4 + 6d5: b8 5f 0d mov ax,0xd5f + 6d8: 50 push ax + 6d9: b8 06 00 mov ax,0x6 + 6dc: 50 push ax + 6dd: 9a 0a 00 60 0b call 0xb60:0xa + 6e2: 83 c4 0c add sp,0xc + 6e5: c7 86 ba fe 03 00 mov WORD PTR [bp-0x146],0x3 + 6eb: c7 86 bc fe 03 00 mov WORD PTR [bp-0x144],0x3 + 6f1: 68 00 40 push 0x4000 + 6f4: 9a 0e 00 5d 0a call 0xa5d:0xe + 6f9: 44 inc sp + 6fa: 44 inc sp + 6fb: 89 56 e2 mov WORD PTR [bp-0x1e],dx + 6fe: 89 46 e0 mov WORD PTR [bp-0x20],ax + 701: 89 56 ea mov WORD PTR [bp-0x16],dx + 704: 89 46 e8 mov WORD PTR [bp-0x18],ax + 707: 8b 46 e0 mov ax,WORD PTR [bp-0x20] + 70a: 0b 46 e2 or ax,WORD PTR [bp-0x1e] + 70d: 75 1e jne 0x72d + 70f: 1e push ds + 710: b8 f1 00 mov ax,0xf1 + 713: 50 push ax + 714: b8 e0 11 mov ax,0x11e0 + 717: 50 push ax + 718: b8 2a 00 mov ax,0x2a + 71b: 50 push ax + 71c: 9a 08 00 9b 0c call 0xc9b:0x8 + 721: 83 c4 08 add sp,0x8 + 724: 6a 01 push 0x1 + 726: 9a 0b 00 55 0a call 0xa55:0xb + 72b: 44 inc sp + 72c: 44 inc sp + 72d: c4 5e e0 les bx,DWORD PTR [bp-0x20] + 730: 83 c3 08 add bx,0x8 + 733: 8c 46 e6 mov WORD PTR [bp-0x1a],es + 736: 89 5e e4 mov WORD PTR [bp-0x1c],bx + 739: 9a 38 07 b3 00 call 0xb3:0x738 + 73e: 16 push ss + 73f: 8d 86 be fe lea ax,[bp-0x142] + 743: 50 push ax + 744: ff b6 bc fe push WORD PTR [bp-0x144] + 748: ff b6 ba fe push WORD PTR [bp-0x146] + 74c: 9a 66 05 b3 00 call 0xb3:0x566 + 751: 83 c4 08 add sp,0x8 + 754: 8b 86 ca fe mov ax,WORD PTR [bp-0x136] + 758: 89 46 d6 mov WORD PTR [bp-0x2a],ax + 75b: 8b 86 d0 fe mov ax,WORD PTR [bp-0x130] + 75f: 89 46 d8 mov WORD PTR [bp-0x28],ax + 762: 33 ff xor di,di + 764: eb 0b jmp 0x771 + 766: c4 5e f4 les bx,DWORD PTR [bp-0xc] + 769: 26 8a 01 mov al,BYTE PTR es:[bx+di] + 76c: 88 83 d6 fe mov BYTE PTR [bp+di-0x12a],al + 770: 47 inc di + 771: 3b 7e d6 cmp di,WORD PTR [bp-0x2a] + 774: 7d 09 jge 0x77f + 776: c4 5e f4 les bx,DWORD PTR [bp-0xc] + 779: 26 80 39 00 cmp BYTE PTR es:[bx+di],0x0 + 77d: 75 e7 jne 0x766 + 77f: eb 06 jmp 0x787 + 781: c6 83 d6 fe 00 mov BYTE PTR [bp+di-0x12a],0x0 + 786: 47 inc di + 787: 3b 7e d6 cmp di,WORD PTR [bp-0x2a] + 78a: 7c f5 jl 0x781 + 78c: ff b6 bc fe push WORD PTR [bp-0x144] + 790: ff b6 ba fe push WORD PTR [bp-0x146] + 794: 16 push ss + 795: 8d 86 1e fc lea ax,[bp-0x3e2] + 799: 50 push ax + 79a: 9a 56 07 b3 00 call 0xb3:0x756 + 79f: 83 c4 08 add sp,0x8 + 7a2: ff 76 d6 push WORD PTR [bp-0x2a] + 7a5: 16 push ss + 7a6: 8d 86 d6 fe lea ax,[bp-0x12a] + 7aa: 50 push ax + 7ab: 16 push ss + 7ac: 8d 86 1e fc lea ax,[bp-0x3e2] + 7b0: 50 push ax + 7b1: 9a c5 09 b3 00 call 0xb3:0x9c5 + 7b6: 83 c4 0a add sp,0xa + 7b9: c7 46 dc 01 00 mov WORD PTR [bp-0x24],0x1 + 7be: c4 5e f8 les bx,DWORD PTR [bp-0x8] + 7c1: 26 8a 47 04 mov al,BYTE PTR es:[bx+0x4] + 7c5: 98 cbw + 7c6: 89 46 de mov WORD PTR [bp-0x22],ax + 7c9: 68 f8 3f push 0x3ff8 + 7cc: ff 76 e6 push WORD PTR [bp-0x1a] + 7cf: ff 76 e4 push WORD PTR [bp-0x1c] + 7d2: ff 76 de push WORD PTR [bp-0x22] + 7d5: 9a 05 00 50 0b call 0xb50:0x5 + 7da: 83 c4 08 add sp,0x8 + 7dd: 89 46 da mov WORD PTR [bp-0x26],ax + 7e0: ff 76 da push WORD PTR [bp-0x26] + 7e3: 9a 0d 00 a0 00 call 0xa0:0xd + 7e8: 44 inc sp + 7e9: 44 inc sp + 7ea: e9 93 01 jmp 0x980 + 7ed: 81 7e da f8 3f cmp WORD PTR [bp-0x26],0x3ff8 + 7f2: 75 4f jne 0x843 + 7f4: c4 5e e8 les bx,DWORD PTR [bp-0x18] + 7f7: 26 8b 47 08 mov ax,WORD PTR es:[bx+0x8] + 7fb: 99 cwd + 7fc: 33 c2 xor ax,dx + 7fe: 2b c2 sub ax,dx + 800: f7 d8 neg ax + 802: 99 cwd + 803: c4 5e e8 les bx,DWORD PTR [bp-0x18] + 806: 26 89 57 02 mov WORD PTR es:[bx+0x2],dx + 80a: 26 89 07 mov WORD PTR es:[bx],ax + 80d: c4 5e e8 les bx,DWORD PTR [bp-0x18] + 810: 26 8b 07 mov ax,WORD PTR es:[bx] + 813: 26 0b 47 02 or ax,WORD PTR es:[bx+0x2] + 817: 75 0e jne 0x827 + 819: c4 5e e8 les bx,DWORD PTR [bp-0x18] + 81c: 26 c7 47 02 ff ff mov WORD PTR es:[bx+0x2],0xffff + 822: 26 c7 07 ff ff mov WORD PTR es:[bx],0xffff + 827: c4 5e e8 les bx,DWORD PTR [bp-0x18] + 82a: 26 8b 47 0c mov ax,WORD PTR es:[bx+0xc] + 82e: 99 cwd + 82f: 33 c2 xor ax,dx + 831: 2b c2 sub ax,dx + 833: f7 d8 neg ax + 835: 99 cwd + 836: c4 5e e8 les bx,DWORD PTR [bp-0x18] + 839: 26 89 57 06 mov WORD PTR es:[bx+0x6],dx + 83d: 26 89 47 04 mov WORD PTR es:[bx+0x4],ax + 841: eb 28 jmp 0x86b + 843: 8b 46 da mov ax,WORD PTR [bp-0x26] + 846: 99 cwd + 847: c4 5e e8 les bx,DWORD PTR [bp-0x18] + 84a: 26 89 57 02 mov WORD PTR es:[bx+0x2],dx + 84e: 26 89 07 mov WORD PTR es:[bx],ax + 851: c4 5e e8 les bx,DWORD PTR [bp-0x18] + 854: 26 8b 47 08 mov ax,WORD PTR es:[bx+0x8] + 858: 99 cwd + 859: 33 c2 xor ax,dx + 85b: 2b c2 sub ax,dx + 85d: f7 d8 neg ax + 85f: 99 cwd + 860: c4 5e e8 les bx,DWORD PTR [bp-0x18] + 863: 26 89 57 06 mov WORD PTR es:[bx+0x6],dx + 867: 26 89 47 04 mov WORD PTR es:[bx+0x4],ax + 86b: 68 00 40 push 0x4000 + 86e: ff 76 e2 push WORD PTR [bp-0x1e] + 871: ff 76 e0 push WORD PTR [bp-0x20] + 874: 16 push ss + 875: 8d 86 1e fc lea ax,[bp-0x3e2] + 879: 50 push ax + 87a: 9a 1e 0c b3 00 call 0xb3:0xc1e + 87f: 83 c4 0a add sp,0xa + 882: 83 7e dc 00 cmp WORD PTR [bp-0x24],0x0 + 886: 75 03 jne 0x88b + 888: e9 ad 00 jmp 0x938 + 88b: 16 push ss + 88c: 8d 86 c4 fa lea ax,[bp-0x53c] + 890: 50 push ax + 891: 16 push ss + 892: 8d 86 1e fc lea ax,[bp-0x3e2] + 896: 50 push ax + 897: 9a ec 06 b3 00 call 0xb3:0x6ec + 89c: 83 c4 08 add sp,0x8 + 89f: 8b 86 d6 fa mov ax,WORD PTR [bp-0x52a] + 8a3: 89 86 1c fb mov WORD PTR [bp-0x4e4],ax + 8a7: 16 push ss + 8a8: 8d 86 dc fa lea ax,[bp-0x524] + 8ac: 50 push ax + 8ad: 16 push ss + 8ae: 8d 86 1e fc lea ax,[bp-0x3e2] + 8b2: 50 push ax + 8b3: 9a a9 0b b3 00 call 0xb3:0xba9 + 8b8: 83 c4 08 add sp,0x8 + 8bb: ff 76 fe push WORD PTR [bp-0x2] + 8be: ff 76 fc push WORD PTR [bp-0x4] + 8c1: 6a 01 push 0x1 + 8c3: ff b6 1c fb push WORD PTR [bp-0x4e4] + 8c7: 16 push ss + 8c8: 8d 86 dc fa lea ax,[bp-0x524] + 8cc: 50 push ax + 8cd: 9a 0a 00 60 0b call 0xb60:0xa + 8d2: 83 c4 0c add sp,0xc + 8d5: ff 76 fe push WORD PTR [bp-0x2] + 8d8: ff 76 fc push WORD PTR [bp-0x4] + 8db: 9a 4a 00 a0 00 call 0xa0:0x4a + 8e0: 83 c4 04 add sp,0x4 + 8e3: 33 f6 xor si,si + 8e5: eb 09 jmp 0x8f0 + 8e7: 8a 82 d6 fe mov al,BYTE PTR [bp+si-0x12a] + 8eb: 88 82 1e fb mov BYTE PTR [bp+si-0x4e2],al + 8ef: 46 inc si + 8f0: 3b 76 d6 cmp si,WORD PTR [bp-0x2a] + 8f3: 7c f2 jl 0x8e7 + 8f5: 68 00 01 push 0x100 + 8f8: 16 push ss + 8f9: 8d 86 1e fb lea ax,[bp-0x4e2] + 8fd: 50 push ax + 8fe: 16 push ss + 8ff: 8d 86 1e fc lea ax,[bp-0x3e2] + 903: 50 push ax + 904: 9a 1e 0c b3 00 call 0xb3:0xc1e + 909: 83 c4 0a add sp,0xa + 90c: ff 76 fe push WORD PTR [bp-0x2] + 90f: ff 76 fc push WORD PTR [bp-0x4] + 912: 6a 01 push 0x1 + 914: 68 00 01 push 0x100 + 917: 16 push ss + 918: 8d 86 1e fb lea ax,[bp-0x4e2] + 91c: 50 push ax + 91d: 9a 0a 00 60 0b call 0xb60:0xa + 922: 83 c4 0c add sp,0xc + 925: ff 76 fe push WORD PTR [bp-0x2] + 928: ff 76 fc push WORD PTR [bp-0x4] + 92b: 9a 4a 00 a0 00 call 0xa0:0x4a + 930: 83 c4 04 add sp,0x4 + 933: c7 46 dc 00 00 mov WORD PTR [bp-0x24],0x0 + 938: ff 76 fe push WORD PTR [bp-0x2] + 93b: ff 76 fc push WORD PTR [bp-0x4] + 93e: 6a 01 push 0x1 + 940: 68 00 40 push 0x4000 + 943: ff 76 e2 push WORD PTR [bp-0x1e] + 946: ff 76 e0 push WORD PTR [bp-0x20] + 949: 9a 0a 00 60 0b call 0xb60:0xa + 94e: 83 c4 0c add sp,0xc + 951: ff 76 fe push WORD PTR [bp-0x2] + 954: ff 76 fc push WORD PTR [bp-0x4] + 957: 9a 4a 00 a0 00 call 0xa0:0x4a + 95c: 83 c4 04 add sp,0x4 + 95f: 68 f8 3f push 0x3ff8 + 962: ff 76 e6 push WORD PTR [bp-0x1a] + 965: ff 76 e4 push WORD PTR [bp-0x1c] + 968: ff 76 de push WORD PTR [bp-0x22] + 96b: 9a 05 00 50 0b call 0xb50:0x5 + 970: 83 c4 08 add sp,0x8 + 973: 89 46 da mov WORD PTR [bp-0x26],ax + 976: ff 76 da push WORD PTR [bp-0x26] + 979: 9a 0d 00 a0 00 call 0xa0:0xd + 97e: 44 inc sp + 97f: 44 inc sp + 980: 83 7e da 00 cmp WORD PTR [bp-0x26],0x0 + 984: 74 03 je 0x989 + 986: e9 64 fe jmp 0x7ed + 989: 6a 00 push 0x0 + 98b: ff 76 e2 push WORD PTR [bp-0x1e] + 98e: ff 76 e0 push WORD PTR [bp-0x20] + 991: 16 push ss + 992: 8d 86 1e fc lea ax,[bp-0x3e2] + 996: 50 push ax + 997: 9a 1e 0c b3 00 call 0xb3:0xc1e + 99c: 83 c4 0a add sp,0xa + 99f: 16 push ss + 9a0: 8d 86 1e fc lea ax,[bp-0x3e2] + 9a4: 50 push ax + 9a5: 9a 40 09 b3 00 call 0xb3:0x940 + 9aa: 83 c4 04 add sp,0x4 + 9ad: 9a 46 07 b3 00 call 0xb3:0x746 + 9b2: ff 76 e2 push WORD PTR [bp-0x1e] + 9b5: ff 76 e0 push WORD PTR [bp-0x20] + 9b8: 9a 04 00 5e 0c call 0xc5e:0x4 + 9bd: 83 c4 04 add sp,0x4 + 9c0: 8b 56 fa mov dx,WORD PTR [bp-0x6] + 9c3: 8b 46 f8 mov ax,WORD PTR [bp-0x8] + 9c6: bb 02 00 mov bx,0x2 + 9c9: b9 e0 11 mov cx,0x11e0 + 9cc: 3b d1 cmp dx,cx + 9ce: 75 04 jne 0x9d4 + 9d0: 3b c3 cmp ax,bx + 9d2: 74 0e je 0x9e2 + 9d4: ff 76 fa push WORD PTR [bp-0x6] + 9d7: ff 76 f8 push WORD PTR [bp-0x8] + 9da: 9a 09 00 33 0b call 0xb33:0x9 + 9df: 83 c4 04 add sp,0x4 + 9e2: 8b 56 fe mov dx,WORD PTR [bp-0x2] + 9e5: 8b 46 fc mov ax,WORD PTR [bp-0x4] + 9e8: bb 16 00 mov bx,0x16 + 9eb: b9 e0 11 mov cx,0x11e0 + 9ee: 3b d1 cmp dx,cx + 9f0: 75 04 jne 0x9f6 + 9f2: 3b c3 cmp ax,bx + 9f4: 74 0e je 0xa04 + 9f6: ff 76 fe push WORD PTR [bp-0x2] + 9f9: ff 76 fc push WORD PTR [bp-0x4] + 9fc: 9a 09 00 33 0b call 0xb33:0x9 + a01: 83 c4 04 add sp,0x4 + a04: 33 c0 xor ax,ax + a06: eb 00 jmp 0xa08 + a08: 1f pop ds + a09: 5f pop di + a0a: 5e pop si + a0b: c9 leave + a0c: cb retf + a0d: 55 push bp + a0e: 8b ec mov bp,sp + a10: 1e push ds + a11: b8 56 0d mov ax,0xd56 + a14: 8e d8 mov ds,ax + a16: 83 7e 06 ff cmp WORD PTR [bp+0x6],0xffff + a1a: 75 2b jne 0xa47 + a1c: 1e push ds + a1d: b8 0a 00 mov ax,0xa + a20: 50 push ax + a21: b8 e0 11 mov ax,0x11e0 + a24: 50 push ax + a25: b8 2a 00 mov ax,0x2a + a28: 50 push ax + a29: 9a 08 00 9b 0c call 0xc9b:0x8 + a2e: 83 c4 08 add sp,0x8 + a31: 1e push ds + a32: b8 31 00 mov ax,0x31 + a35: 50 push ax + a36: 9a 0d 00 b6 0c call 0xcb6:0xd + a3b: 83 c4 04 add sp,0x4 + a3e: 6a 03 push 0x3 + a40: 9a 0b 00 55 0a call 0xa55:0xb + a45: 44 inc sp + a46: 44 inc sp + a47: 1f pop ds + a48: 5d pop bp + a49: cb retf + a4a: 55 push bp + a4b: 8b ec mov bp,sp + a4d: 1e push ds + a4e: b8 56 0d mov ax,0xd56 + a51: 8e d8 mov ds,ax + a53: c4 5e 06 les bx,DWORD PTR [bp+0x6] + a56: 26 f7 47 02 10 00 test WORD PTR es:[bx+0x2],0x10 + a5c: 74 2b je 0xa89 + a5e: 1e push ds + a5f: b8 3a 00 mov ax,0x3a + a62: 50 push ax + a63: b8 e0 11 mov ax,0x11e0 + a66: 50 push ax + a67: b8 2a 00 mov ax,0x2a + a6a: 50 push ax + a6b: 9a 08 00 9b 0c call 0xc9b:0x8 + a70: 83 c4 08 add sp,0x8 + a73: 1e push ds + a74: b8 62 00 mov ax,0x62 + a77: 50 push ax + a78: 9a 0d 00 b6 0c call 0xcb6:0xd + a7d: 83 c4 04 add sp,0x4 + a80: 6a 03 push 0x3 + a82: 9a 0b 00 55 0a call 0xa55:0xb + a87: 44 inc sp + a88: 44 inc sp + a89: 1f pop ds + a8a: 5d pop bp + a8b: cb retf + a8c: 55 push bp + a8d: 8b ec mov bp,sp + a8f: 1e push ds + a90: b8 56 0d mov ax,0xd56 + a93: 8e d8 mov ds,ax + a95: 8b 46 06 mov ax,WORD PTR [bp+0x6] + a98: 0b 46 08 or ax,WORD PTR [bp+0x8] + a9b: 75 31 jne 0xace + a9d: ff 76 0c push WORD PTR [bp+0xc] + aa0: ff 76 0a push WORD PTR [bp+0xa] + aa3: 1e push ds + aa4: b8 6b 00 mov ax,0x6b + aa7: 50 push ax + aa8: b8 e0 11 mov ax,0x11e0 + aab: 50 push ax + aac: b8 2a 00 mov ax,0x2a + aaf: 50 push ax + ab0: 9a 08 00 9b 0c call 0xc9b:0x8 + ab5: 83 c4 0c add sp,0xc + ab8: 1e push ds + ab9: b8 88 00 mov ax,0x88 + abc: 50 push ax + abd: 9a 0d 00 b6 0c call 0xcb6:0xd + ac2: 83 c4 04 add sp,0x4 + ac5: 6a 03 push 0x3 + ac7: 9a 0b 00 55 0a call 0xa55:0xb + acc: 44 inc sp + acd: 44 inc sp + ace: 1f pop ds + acf: 5d pop bp + ad0: cb retf + ad1: 55 push bp + ad2: 8b ec mov bp,sp + ad4: 56 push si + ad5: 1e push ds + ad6: b8 5f 0d mov ax,0xd5f + ad9: 8e d8 mov ds,ax + adb: 33 f6 xor si,si + add: eb 01 jmp 0xae0 + adf: 46 inc si + ae0: 8b de mov bx,si + ae2: c1 e3 02 shl bx,0x2 + ae5: 8b 97 10 00 mov dx,WORD PTR [bx+0x10] + ae9: 8b 87 0e 00 mov ax,WORD PTR [bx+0xe] + aed: 3b 56 08 cmp dx,WORD PTR [bp+0x8] + af0: 75 05 jne 0xaf7 + af2: 3b 46 06 cmp ax,WORD PTR [bp+0x6] + af5: 74 13 je 0xb0a + af7: 8b de mov bx,si + af9: c1 e3 02 shl bx,0x2 + afc: 83 bf 10 00 ff cmp WORD PTR [bx+0x10],0xffff + b01: 75 dc jne 0xadf + b03: 83 bf 0e 00 ff cmp WORD PTR [bx+0xe],0xffff + b08: 75 d5 jne 0xadf + b0a: 8b de mov bx,si + b0c: c1 e3 02 shl bx,0x2 + b0f: 83 bf 10 00 ff cmp WORD PTR [bx+0x10],0xffff + b14: 75 25 jne 0xb3b + b16: 83 bf 0e 00 ff cmp WORD PTR [bx+0xe],0xffff + b1b: 75 1e jne 0xb3b + b1d: 1e push ds + b1e: b8 5c 05 mov ax,0x55c + b21: 50 push ax + b22: b8 e0 11 mov ax,0x11e0 + b25: 50 push ax + b26: b8 2a 00 mov ax,0x2a + b29: 50 push ax + b2a: 9a 08 00 9b 0c call 0xc9b:0x8 + b2f: 83 c4 08 add sp,0x8 + b32: 6a 01 push 0x1 + b34: 9a 0b 00 55 0a call 0xa55:0xb + b39: 44 inc sp + b3a: 44 inc sp + b3b: 1f pop ds + b3c: 5e pop si + b3d: 5d pop bp + b3e: cb retf + b3f: 55 push bp + b40: 8b ec mov bp,sp + b42: 81 ec 9e 02 sub sp,0x29e + b46: 1e push ds + b47: b8 b8 0d mov ax,0xdb8 + b4a: 8e d8 mov ds,ax + b4c: 83 3e 08 00 00 cmp WORD PTR ds:0x8,0x0 + b51: 75 24 jne 0xb77 + b53: 6a 40 push 0x40 + b55: 6a 00 push 0x0 + b57: 1e push ds + b58: b8 0a 00 mov ax,0xa + b5b: 50 push ax + b5c: 9a 38 00 c0 0b call 0xbc0:0x38 + b61: 83 c4 08 add sp,0x8 + b64: 1e push ds + b65: b8 0a 00 mov ax,0xa + b68: 50 push ax + b69: 9a 4e 00 c1 0c call 0xcc1:0x4e + b6e: 83 c4 04 add sp,0x4 + b71: c7 06 08 00 01 00 mov WORD PTR ds:0x8,0x1 + b77: c7 46 fe 02 00 mov WORD PTR [bp-0x2],0x2 + b7c: 16 push ss + b7d: 8d 46 fe lea ax,[bp-0x2] + b80: 50 push ax + b81: 6a 04 push 0x4 + b83: 6a 01 push 0x1 + b85: 16 push ss + b86: 8d 86 62 fd lea ax,[bp-0x29e] + b8a: 50 push ax + b8b: 9a 41 08 b3 00 call 0xb3:0x841 + b90: 83 c4 0c add sp,0xc + b93: 6a 40 push 0x40 + b95: 1e push ds + b96: b8 0a 00 mov ax,0xa + b99: 50 push ax + b9a: 16 push ss + b9b: 8d 86 62 fd lea ax,[bp-0x29e] + b9f: 50 push ax + ba0: 9a c5 09 b3 00 call 0xb3:0x9c5 + ba5: 83 c4 0a add sp,0xa + ba8: c7 46 ac 01 00 mov WORD PTR [bp-0x54],0x1 + bad: 6a 40 push 0x40 + baf: 1e push ds + bb0: b8 0a 00 mov ax,0xa + bb3: 50 push ax + bb4: 16 push ss + bb5: 8d 86 62 fd lea ax,[bp-0x29e] + bb9: 50 push ax + bba: 9a 1e 0c b3 00 call 0xb3:0xc1e + bbf: 83 c4 0a add sp,0xa + bc2: 16 push ss + bc3: 8d 86 62 fd lea ax,[bp-0x29e] + bc7: 50 push ax + bc8: 9a 40 09 b3 00 call 0xb3:0x940 + bcd: 83 c4 04 add sp,0x4 + bd0: ff 76 0a push WORD PTR [bp+0xa] + bd3: 1e push ds + bd4: b8 0a 00 mov ax,0xa + bd7: 50 push ax + bd8: ff 76 08 push WORD PTR [bp+0x8] + bdb: ff 76 06 push WORD PTR [bp+0x6] + bde: 9a 02 00 be 0b call 0xbbe:0x2 + be3: 83 c4 0a add sp,0xa + be6: 1f pop ds + be7: c9 leave + be8: cb retf + be9: 55 push bp + bea: 8b ec mov bp,sp + bec: 83 ec 04 sub sp,0x4 + bef: 56 push si + bf0: 1e push ds + bf1: b8 b8 0d mov ax,0xdb8 + bf4: 8e d8 mov ds,ax + bf6: 8b 76 0a mov si,WORD PTR [bp+0xa] + bf9: 8b c6 mov ax,si + bfb: c1 e8 02 shr ax,0x2 + bfe: 8b f0 mov si,ax + c00: eb 71 jmp 0xc73 + c02: c4 5e 06 les bx,DWORD PTR [bp+0x6] + c05: 26 8b 57 02 mov dx,WORD PTR es:[bx+0x2] + c09: 26 8b 07 mov ax,WORD PTR es:[bx] + c0c: 89 56 fe mov WORD PTR [bp-0x2],dx + c0f: 89 46 fc mov WORD PTR [bp-0x4],ax + c12: 8b 56 fe mov dx,WORD PTR [bp-0x2] + c15: 8b 46 fc mov ax,WORD PTR [bp-0x4] + c18: 25 00 ff and ax,0xff00 + c1b: 81 e2 00 ff and dx,0xff00 + c1f: b1 08 mov cl,0x8 + c21: 9a 97 04 00 00 call 0x0:0x497 + c26: 8b 4e fe mov cx,WORD PTR [bp-0x2] + c29: 8b 5e fc mov bx,WORD PTR [bp-0x4] + c2c: 81 e3 ff 00 and bx,0xff + c30: 81 e1 ff 00 and cx,0xff + c34: 52 push dx + c35: 50 push ax + c36: 8b c3 mov ax,bx + c38: 8b d1 mov dx,cx + c3a: b1 08 mov cl,0x8 + c3c: 9a 78 04 00 00 call 0x0:0x478 + c41: 5b pop bx + c42: 59 pop cx + c43: 0b d8 or bx,ax + c45: 0b ca or cx,dx + c47: 89 4e fe mov WORD PTR [bp-0x2],cx + c4a: 89 5e fc mov WORD PTR [bp-0x4],bx + c4d: 8b 56 fe mov dx,WORD PTR [bp-0x2] + c50: 8b 46 fc mov ax,WORD PTR [bp-0x4] + c53: 8b d0 mov dx,ax + c55: 33 c0 xor ax,ax + c57: 8b 4e fe mov cx,WORD PTR [bp-0x2] + c5a: 8b 5e fc mov bx,WORD PTR [bp-0x4] + c5d: 8b d9 mov bx,cx + c5f: 33 c9 xor cx,cx + c61: 0b c3 or ax,bx + c63: 0b d1 or dx,cx + c65: c4 5e 06 les bx,DWORD PTR [bp+0x6] + c68: 26 89 57 02 mov WORD PTR es:[bx+0x2],dx + c6c: 26 89 07 mov WORD PTR es:[bx],ax + c6f: 83 46 06 04 add WORD PTR [bp+0x6],0x4 + c73: 8b c6 mov ax,si + c75: 4e dec si + c76: 0b c0 or ax,ax + c78: 75 88 jne 0xc02 + c7a: 1f pop ds + c7b: 5e pop si + c7c: c9 leave + c7d: cb retf + c7e: 55 push bp + c7f: 8b ec mov bp,sp + c81: 83 ec 02 sub sp,0x2 + c84: 56 push si + c85: 1e push ds + c86: b8 b8 0d mov ax,0xdb8 + c89: 8e d8 mov ds,ax + c8b: 8b 76 0a mov si,WORD PTR [bp+0xa] + c8e: 8b c6 mov ax,si + c90: d1 e8 shr ax,1 + c92: 8b f0 mov si,ax + c94: eb 21 jmp 0xcb7 + c96: c4 5e 06 les bx,DWORD PTR [bp+0x6] + c99: 26 8b 07 mov ax,WORD PTR es:[bx] + c9c: 89 46 fe mov WORD PTR [bp-0x2],ax + c9f: 8b 46 fe mov ax,WORD PTR [bp-0x2] + ca2: c1 e0 08 shl ax,0x8 + ca5: 8b 56 fe mov dx,WORD PTR [bp-0x2] + ca8: c1 ea 08 shr dx,0x8 + cab: 0b c2 or ax,dx + cad: c4 5e 06 les bx,DWORD PTR [bp+0x6] + cb0: 26 89 07 mov WORD PTR es:[bx],ax + cb3: 83 46 06 02 add WORD PTR [bp+0x6],0x2 + cb7: 8b c6 mov ax,si + cb9: 4e dec si + cba: 0b c0 or ax,ax + cbc: 75 d8 jne 0xc96 + cbe: 1f pop ds + cbf: 5e pop si + cc0: c9 leave + cc1: cb retf + cc2: 55 push bp + cc3: 8b ec mov bp,sp + cc5: 1e push ds + cc6: b8 b8 0d mov ax,0xdb8 + cc9: 8e d8 mov ds,ax + ccb: c4 5e 06 les bx,DWORD PTR [bp+0x6] + cce: 26 8b 07 mov ax,WORD PTR es:[bx] + cd1: 26 0b 47 02 or ax,WORD PTR es:[bx+0x2] + cd5: 74 37 je 0xd0e + cd7: ff 76 0a push WORD PTR [bp+0xa] + cda: 6a 00 push 0x0 + cdc: c4 5e 06 les bx,DWORD PTR [bp+0x6] + cdf: 26 ff 77 02 push WORD PTR es:[bx+0x2] + ce3: 26 ff 37 push WORD PTR es:[bx] + ce6: 9a 38 00 c0 0b call 0xbc0:0x38 + ceb: 83 c4 08 add sp,0x8 + cee: c4 5e 06 les bx,DWORD PTR [bp+0x6] + cf1: 26 ff 77 02 push WORD PTR es:[bx+0x2] + cf5: 26 ff 37 push WORD PTR es:[bx] + cf8: 9a 04 00 5e 0c call 0xc5e:0x4 + cfd: 83 c4 04 add sp,0x4 diff --git a/MSDOS/asm/undes-main.asm b/MSDOS/asm/undes-main.asm new file mode 100644 index 0000000..4606b31 --- /dev/null +++ b/MSDOS/asm/undes-main.asm @@ -0,0 +1,598 @@ + +/mnt/data/undes.img: file format binary + + +Disassembly of section .data: + +000004b0 <.data+0x4b0>: + 4b0: c2 33 d2 ret 0xd233 + 4b3: d3 e8 shr ax,cl + 4b5: cb retf + 4b6: 55 push bp + 4b7: 8b ec mov bp,sp + 4b9: 81 ec 26 05 sub sp,0x526 + 4bd: 56 push si + 4be: 57 push di + 4bf: 1e push ds + 4c0: b8 49 0d mov ax,0xd49 + 4c3: 8e d8 mov ds,ax + 4c5: 83 7e 06 02 cmp WORD PTR [bp+0x6],0x2 + 4c9: 74 03 je 0x4ce + 4cb: e9 a0 00 jmp 0x56e + 4ce: 1e push ds + 4cf: b8 0c 00 mov ax,0xc + 4d2: 50 push ax + 4d3: c4 5e 08 les bx,DWORD PTR [bp+0x8] + 4d6: 26 ff 77 06 push WORD PTR es:[bx+0x6] + 4da: 26 ff 77 04 push WORD PTR es:[bx+0x4] + 4de: 9a 01 00 bb 0b call 0xbbb:0x1 + 4e3: 83 c4 08 add sp,0x8 + 4e6: 0b c0 or ax,ax + 4e8: 75 43 jne 0x52d + 4ea: b8 65 0d mov ax,0xd65 + 4ed: 8e c0 mov es,ax + 4ef: 26 ff 36 0a 00 push WORD PTR es:0xa + 4f4: 26 ff 36 08 00 push WORD PTR es:0x8 + 4f9: 1e push ds + 4fa: b8 18 00 mov ax,0x18 + 4fd: 50 push ax + 4fe: 9a 08 00 da 0b call 0xbda:0x8 + 503: 83 c4 08 add sp,0x8 + 506: b8 65 0d mov ax,0xd65 + 509: 8e c0 mov es,ax + 50b: 26 ff 36 12 00 push WORD PTR es:0x12 + 510: 26 ff 36 10 00 push WORD PTR es:0x10 + 515: 1e push ds + 516: b8 1d 00 mov ax,0x1d + 519: 50 push ax + 51a: 9a 08 00 da 0b call 0xbda:0x8 + 51f: 83 c4 08 add sp,0x8 + 522: 6a 00 push 0x0 + 524: 9a 0d 00 58 0a call 0xa58:0xd + 529: 44 inc sp + 52a: 44 inc sp + 52b: eb 41 jmp 0x56e + 52d: 1e push ds + 52e: b8 20 00 mov ax,0x20 + 531: 50 push ax + 532: c4 5e 08 les bx,DWORD PTR [bp+0x8] + 535: 26 ff 77 06 push WORD PTR es:[bx+0x6] + 539: 26 ff 77 04 push WORD PTR es:[bx+0x4] + 53d: 9a 01 00 bb 0b call 0xbbb:0x1 + 542: 83 c4 08 add sp,0x8 + 545: 0b c0 or ax,ax + 547: 75 25 jne 0x56e + 549: b8 65 0d mov ax,0xd65 + 54c: 8e c0 mov es,ax + 54e: 26 ff 36 0a 00 push WORD PTR es:0xa + 553: 26 ff 36 08 00 push WORD PTR es:0x8 + 558: 1e push ds + 559: b8 2a 00 mov ax,0x2a + 55c: 50 push ax + 55d: 9a 08 00 da 0b call 0xbda:0x8 + 562: 83 c4 08 add sp,0x8 + 565: 6a 00 push 0x0 + 567: 9a 0d 00 58 0a call 0xa58:0xd + 56c: 44 inc sp + 56d: 44 inc sp + 56e: 83 7e 06 04 cmp WORD PTR [bp+0x6],0x4 + 572: 74 3e je 0x5b2 + 574: 1e push ds + 575: b8 96 00 mov ax,0x96 + 578: 50 push ax + 579: 1e push ds + 57a: b8 7f 00 mov ax,0x7f + 57d: 50 push ax + 57e: 1e push ds + 57f: b8 66 00 mov ax,0x66 + 582: 50 push ax + 583: 1e push ds + 584: b8 3b 00 mov ax,0x3b + 587: 50 push ax + 588: 1e push ds + 589: b8 2e 00 mov ax,0x2e + 58c: 50 push ax + 58d: b8 e6 11 mov ax,0x11e6 + 590: 50 push ax + 591: b8 30 00 mov ax,0x30 + 594: 50 push ax + 595: 9a 0a 00 9e 0c call 0xc9e:0xa + 59a: 83 c4 18 add sp,0x18 + 59d: 83 7e 06 01 cmp WORD PTR [bp+0x6],0x1 + 5a1: 75 04 jne 0x5a7 + 5a3: 33 c0 xor ax,ax + 5a5: eb 03 jmp 0x5aa + 5a7: b8 02 00 mov ax,0x2 + 5aa: 50 push ax + 5ab: 9a 0d 00 58 0a call 0xa58:0xd + 5b0: 44 inc sp + 5b1: 44 inc sp + 5b2: c4 5e 08 les bx,DWORD PTR [bp+0x8] + 5b5: 26 c4 5f 04 les bx,DWORD PTR es:[bx+0x4] + 5b9: 8c 46 f6 mov WORD PTR [bp-0xa],es + 5bc: 89 5e f4 mov WORD PTR [bp-0xc],bx + 5bf: c4 5e 08 les bx,DWORD PTR [bp+0x8] + 5c2: 26 c4 5f 08 les bx,DWORD PTR es:[bx+0x8] + 5c6: 8c 46 ee mov WORD PTR [bp-0x12],es + 5c9: 89 5e ec mov WORD PTR [bp-0x14],bx + 5cc: c4 5e 08 les bx,DWORD PTR [bp+0x8] + 5cf: 26 c4 5f 0c les bx,DWORD PTR es:[bx+0xc] + 5d3: 8c 46 f2 mov WORD PTR [bp-0xe],es + 5d6: 89 5e f0 mov WORD PTR [bp-0x10],bx + 5d9: 1e push ds + 5da: b8 bb 00 mov ax,0xbb + 5dd: 50 push ax + 5de: ff 76 ee push WORD PTR [bp-0x12] + 5e1: ff 76 ec push WORD PTR [bp-0x14] + 5e4: 9a 01 00 bb 0b call 0xbbb:0x1 + 5e9: 83 c4 08 add sp,0x8 + 5ec: 0b c0 or ax,ax + 5ee: 74 3b je 0x62b + 5f0: ff 76 f2 push WORD PTR [bp-0xe] + 5f3: ff 76 f0 push WORD PTR [bp-0x10] + 5f6: ff 76 ee push WORD PTR [bp-0x12] + 5f9: ff 76 ec push WORD PTR [bp-0x14] + 5fc: 9a 01 00 bb 0b call 0xbbb:0x1 + 601: 83 c4 08 add sp,0x8 + 604: 0b c0 or ax,ax + 606: 75 23 jne 0x62b + 608: 1e push ds + 609: b8 c1 00 mov ax,0xc1 + 60c: 50 push ax + 60d: 1e push ds + 60e: b8 bd 00 mov ax,0xbd + 611: 50 push ax + 612: b8 e6 11 mov ax,0x11e6 + 615: 50 push ax + 616: b8 30 00 mov ax,0x30 + 619: 50 push ax + 61a: 9a 0a 00 9e 0c call 0xc9e:0xa + 61f: 83 c4 0c add sp,0xc + 622: 6a 01 push 0x1 + 624: 9a 0d 00 58 0a call 0xa58:0xd + 629: 44 inc sp + 62a: 44 inc sp + 62b: 1e push ds + 62c: b8 ed 00 mov ax,0xed + 62f: 50 push ax + 630: ff 76 ee push WORD PTR [bp-0x12] + 633: ff 76 ec push WORD PTR [bp-0x14] + 636: 9a 01 00 bb 0b call 0xbbb:0x1 + 63b: 83 c4 08 add sp,0x8 + 63e: 0b c0 or ax,ax + 640: 75 0c jne 0x64e + 642: c7 46 fa e6 11 mov WORD PTR [bp-0x6],0x11e6 + 647: c7 46 f8 08 00 mov WORD PTR [bp-0x8],0x8 + 64c: eb 19 jmp 0x667 + 64e: 1e push ds + 64f: b8 ef 00 mov ax,0xef + 652: 50 push ax + 653: ff 76 ee push WORD PTR [bp-0x12] + 656: ff 76 ec push WORD PTR [bp-0x14] + 659: 9a 47 02 b3 0a call 0xab3:0x247 + 65e: 83 c4 08 add sp,0x8 + 661: 89 56 fa mov WORD PTR [bp-0x6],dx + 664: 89 46 f8 mov WORD PTR [bp-0x8],ax + 667: 1e push ds + 668: b8 f2 00 mov ax,0xf2 + 66b: 50 push ax + 66c: ff 76 f2 push WORD PTR [bp-0xe] + 66f: ff 76 f0 push WORD PTR [bp-0x10] + 672: 9a 01 00 bb 0b call 0xbbb:0x1 + 677: 83 c4 08 add sp,0x8 + 67a: 0b c0 or ax,ax + 67c: 75 0c jne 0x68a + 67e: c7 46 fe e6 11 mov WORD PTR [bp-0x2],0x11e6 + 683: c7 46 fc 1c 00 mov WORD PTR [bp-0x4],0x1c + 688: eb 19 jmp 0x6a3 + 68a: 1e push ds + 68b: b8 f4 00 mov ax,0xf4 + 68e: 50 push ax + 68f: ff 76 f2 push WORD PTR [bp-0xe] + 692: ff 76 f0 push WORD PTR [bp-0x10] + 695: 9a 47 02 b3 0a call 0xab3:0x247 + 69a: 83 c4 08 add sp,0x8 + 69d: 89 56 fe mov WORD PTR [bp-0x2],dx + 6a0: 89 46 fc mov WORD PTR [bp-0x4],ax + 6a3: ff 76 ee push WORD PTR [bp-0x12] + 6a6: ff 76 ec push WORD PTR [bp-0x14] + 6a9: ff 76 fa push WORD PTR [bp-0x6] + 6ac: ff 76 f8 push WORD PTR [bp-0x8] + 6af: 9a 8e 00 a3 00 call 0xa3:0x8e + 6b4: 83 c4 08 add sp,0x8 + 6b7: ff 76 f2 push WORD PTR [bp-0xe] + 6ba: ff 76 f0 push WORD PTR [bp-0x10] + 6bd: ff 76 fe push WORD PTR [bp-0x2] + 6c0: ff 76 fc push WORD PTR [bp-0x4] + 6c3: 9a 8e 00 a3 00 call 0xa3:0x8e + 6c8: 83 c4 08 add sp,0x8 + 6cb: c7 86 7a fd 03 00 mov WORD PTR [bp-0x286],0x3 + 6d1: c7 86 7c fd 03 00 mov WORD PTR [bp-0x284],0x3 + 6d7: c7 86 ea fe 01 00 mov WORD PTR [bp-0x116],0x1 + 6dd: 68 00 40 push 0x4000 + 6e0: 9a 00 00 61 0a call 0xa61:0x0 + 6e5: 44 inc sp + 6e6: 44 inc sp + 6e7: 89 96 e0 fe mov WORD PTR [bp-0x120],dx + 6eb: 89 86 de fe mov WORD PTR [bp-0x122],ax + 6ef: c4 9e de fe les bx,DWORD PTR [bp-0x122] + 6f3: 83 c3 08 add bx,0x8 + 6f6: 8c 86 e4 fe mov WORD PTR [bp-0x11c],es + 6fa: 89 9e e2 fe mov WORD PTR [bp-0x11e],bx + 6fe: 8b 86 de fe mov ax,WORD PTR [bp-0x122] + 702: 0b 86 e0 fe or ax,WORD PTR [bp-0x120] + 706: 75 1e jne 0x726 + 708: 1e push ds + 709: b8 f7 00 mov ax,0xf7 + 70c: 50 push ax + 70d: b8 e6 11 mov ax,0x11e6 + 710: 50 push ax + 711: b8 30 00 mov ax,0x30 + 714: 50 push ax + 715: 9a 0a 00 9e 0c call 0xc9e:0xa + 71a: 83 c4 08 add sp,0x8 + 71d: 6a 01 push 0x1 + 71f: 9a 0d 00 58 0a call 0xa58:0xd + 724: 44 inc sp + 725: 44 inc sp + 726: c4 9e de fe les bx,DWORD PTR [bp-0x122] + 72a: 8c 86 e8 fe mov WORD PTR [bp-0x118],es + 72e: 89 9e e6 fe mov WORD PTR [bp-0x11a],bx + 732: 9a 2a 07 b7 00 call 0xb7:0x72a + 737: 16 push ss + 738: 8d 86 7e fd lea ax,[bp-0x282] + 73c: 50 push ax + 73d: ff b6 7c fd push WORD PTR [bp-0x284] + 741: ff b6 7a fd push WORD PTR [bp-0x286] + 745: 9a 58 05 b7 00 call 0xb7:0x558 + 74a: 83 c4 08 add sp,0x8 + 74d: 8b 86 8a fd mov ax,WORD PTR [bp-0x276] + 751: 89 86 d6 fe mov WORD PTR [bp-0x12a],ax + 755: 8b 86 90 fd mov ax,WORD PTR [bp-0x270] + 759: 89 86 d8 fe mov WORD PTR [bp-0x128],ax + 75d: 33 ff xor di,di + 75f: eb 0b jmp 0x76c + 761: c4 5e f4 les bx,DWORD PTR [bp-0xc] + 764: 26 8a 01 mov al,BYTE PTR es:[bx+di] + 767: 88 83 96 fd mov BYTE PTR [bp+di-0x26a],al + 76b: 47 inc di + 76c: 3b be d6 fe cmp di,WORD PTR [bp-0x12a] + 770: 7d 09 jge 0x77b + 772: c4 5e f4 les bx,DWORD PTR [bp-0xc] + 775: 26 80 39 00 cmp BYTE PTR es:[bx+di],0x0 + 779: 75 e6 jne 0x761 + 77b: eb 06 jmp 0x783 + 77d: c6 83 96 fd 00 mov BYTE PTR [bp+di-0x26a],0x0 + 782: 47 inc di + 783: 3b be d6 fe cmp di,WORD PTR [bp-0x12a] + 787: 7c f4 jl 0x77d + 789: b8 65 0d mov ax,0xd65 + 78c: 8e c0 mov es,ax + 78e: 26 c7 06 0e 00 ff ff mov WORD PTR es:0xe,0xffff + 795: 26 c7 06 0c 00 ff ff mov WORD PTR es:0xc,0xffff + 79c: c4 5e f8 les bx,DWORD PTR [bp-0x8] + 79f: 26 8a 47 04 mov al,BYTE PTR es:[bx+0x4] + 7a3: 98 cbw + 7a4: 89 86 dc fe mov WORD PTR [bp-0x124],ax + 7a8: 6a 04 push 0x4 + 7aa: b8 65 0d mov ax,0xd65 + 7ad: 50 push ax + 7ae: b8 0c 00 mov ax,0xc + 7b1: 50 push ax + 7b2: ff b6 dc fe push WORD PTR [bp-0x124] + 7b6: 9a 07 00 53 0b call 0xb53:0x7 + 7bb: 83 c4 08 add sp,0x8 + 7be: 89 86 da fe mov WORD PTR [bp-0x126],ax + 7c2: ff b6 da fe push WORD PTR [bp-0x126] + 7c6: 9a 0f 00 a3 00 call 0xa3:0xf + 7cb: 44 inc sp + 7cc: 44 inc sp + 7cd: b8 65 0d mov ax,0xd65 + 7d0: 8e c0 mov es,ax + 7d2: 26 ff 36 0e 00 push WORD PTR es:0xe + 7d7: 26 ff 36 0c 00 push WORD PTR es:0xc + 7dc: 9a 03 00 b0 00 call 0xb0:0x3 + 7e1: 83 c4 04 add sp,0x4 + 7e4: ff b6 7c fd push WORD PTR [bp-0x284] + 7e8: ff b6 7a fd push WORD PTR [bp-0x286] + 7ec: 16 push ss + 7ed: 8d 86 de fa lea ax,[bp-0x522] + 7f1: 50 push ax + 7f2: 9a 48 07 b7 00 call 0xb7:0x748 + 7f7: 83 c4 08 add sp,0x8 + 7fa: ff b6 d6 fe push WORD PTR [bp-0x12a] + 7fe: 16 push ss + 7ff: 8d 86 96 fd lea ax,[bp-0x26a] + 803: 50 push ax + 804: 16 push ss + 805: 8d 86 de fa lea ax,[bp-0x522] + 809: 50 push ax + 80a: 9a b7 09 b7 00 call 0xb7:0x9b7 + 80f: 83 c4 0a add sp,0xa + 812: 16 push ss + 813: 8d 86 7e fd lea ax,[bp-0x282] + 817: 50 push ax + 818: 16 push ss + 819: 8d 86 de fa lea ax,[bp-0x522] + 81d: 50 push ax + 81e: 9a de 06 b7 00 call 0xb7:0x6de + 823: 83 c4 08 add sp,0x8 + 826: 8b 86 90 fd mov ax,WORD PTR [bp-0x270] + 82a: 89 86 d8 fe mov WORD PTR [bp-0x128],ax + 82e: ff b6 d8 fe push WORD PTR [bp-0x128] + 832: 16 push ss + 833: 8d 86 96 fe lea ax,[bp-0x16a] + 837: 50 push ax + 838: ff b6 dc fe push WORD PTR [bp-0x124] + 83c: 9a 07 00 53 0b call 0xb53:0x7 + 841: 83 c4 08 add sp,0x8 + 844: 89 86 da fe mov WORD PTR [bp-0x126],ax + 848: ff b6 da fe push WORD PTR [bp-0x126] + 84c: 9a 0f 00 a3 00 call 0xa3:0xf + 851: 44 inc sp + 852: 44 inc sp + 853: ff b6 d8 fe push WORD PTR [bp-0x128] + 857: 16 push ss + 858: 8d 86 96 fe lea ax,[bp-0x16a] + 85c: 50 push ax + 85d: 16 push ss + 85e: 8d 86 de fa lea ax,[bp-0x522] + 862: 50 push ax + 863: 9a 90 0a b7 00 call 0xb7:0xa90 + 868: 83 c4 0a add sp,0xa + 86b: 68 00 01 push 0x100 + 86e: 16 push ss + 86f: 8d 86 ec fe lea ax,[bp-0x114] + 873: 50 push ax + 874: ff b6 dc fe push WORD PTR [bp-0x124] + 878: 9a 07 00 53 0b call 0xb53:0x7 + 87d: 83 c4 08 add sp,0x8 + 880: 89 86 da fe mov WORD PTR [bp-0x126],ax + 884: ff b6 da fe push WORD PTR [bp-0x126] + 888: 9a 0f 00 a3 00 call 0xa3:0xf + 88d: 44 inc sp + 88e: 44 inc sp + 88f: 68 00 40 push 0x4000 + 892: ff b6 e0 fe push WORD PTR [bp-0x120] + 896: ff b6 de fe push WORD PTR [bp-0x122] + 89a: ff b6 dc fe push WORD PTR [bp-0x124] + 89e: 9a 07 00 53 0b call 0xb53:0x7 + 8a3: 83 c4 08 add sp,0x8 + 8a6: 89 86 da fe mov WORD PTR [bp-0x126],ax + 8aa: ff b6 da fe push WORD PTR [bp-0x126] + 8ae: 9a 0f 00 a3 00 call 0xa3:0xf + 8b3: 44 inc sp + 8b4: 44 inc sp + 8b5: e9 f5 00 jmp 0x9ad + 8b8: 68 00 40 push 0x4000 + 8bb: ff b6 e0 fe push WORD PTR [bp-0x120] + 8bf: ff b6 de fe push WORD PTR [bp-0x122] + 8c3: 16 push ss + 8c4: 8d 86 de fa lea ax,[bp-0x522] + 8c8: 50 push ax + 8c9: 9a ec 0c b7 00 call 0xb7:0xcec + 8ce: 83 c4 0a add sp,0xa + 8d1: c4 9e e6 fe les bx,DWORD PTR [bp-0x11a] + 8d5: 26 8b 57 02 mov dx,WORD PTR es:[bx+0x2] + 8d9: 26 8b 07 mov ax,WORD PTR es:[bx] + 8dc: 89 96 dc fa mov WORD PTR [bp-0x524],dx + 8e0: 89 86 da fa mov WORD PTR [bp-0x526],ax + 8e4: 83 be dc fa 00 cmp WORD PTR [bp-0x524],0x0 + 8e9: 7f 15 jg 0x900 + 8eb: 7c 07 jl 0x8f4 + 8ed: 83 be da fa 00 cmp WORD PTR [bp-0x526],0x0 + 8f2: 73 0c jae 0x900 + 8f4: c7 86 dc fa 00 00 mov WORD PTR [bp-0x524],0x0 + 8fa: c7 86 da fa f8 3f mov WORD PTR [bp-0x526],0x3ff8 + 900: 83 be ea fe 00 cmp WORD PTR [bp-0x116],0x0 + 905: 74 56 je 0x95d + 907: 68 00 01 push 0x100 + 90a: 16 push ss + 90b: 8d 86 ec fe lea ax,[bp-0x114] + 90f: 50 push ax + 910: 16 push ss + 911: 8d 86 de fa lea ax,[bp-0x522] + 915: 50 push ax + 916: 9a ec 0c b7 00 call 0xb7:0xcec + 91b: 83 c4 0a add sp,0xa + 91e: 33 f6 xor si,si + 920: eb 01 jmp 0x923 + 922: 46 inc si + 923: 3b b6 d6 fe cmp si,WORD PTR [bp-0x12a] + 927: 7d 0a jge 0x933 + 929: 8a 82 ec fe mov al,BYTE PTR [bp+si-0x114] + 92d: 3a 82 96 fd cmp al,BYTE PTR [bp+si-0x26a] + 931: 74 ef je 0x922 + 933: 3b b6 d6 fe cmp si,WORD PTR [bp-0x12a] + 937: 74 1e je 0x957 + 939: 1e push ds + 93a: b8 0e 01 mov ax,0x10e + 93d: 50 push ax + 93e: b8 e6 11 mov ax,0x11e6 + 941: 50 push ax + 942: b8 30 00 mov ax,0x30 + 945: 50 push ax + 946: 9a 0a 00 9e 0c call 0xc9e:0xa + 94b: 83 c4 08 add sp,0x8 + 94e: 6a 01 push 0x1 + 950: 9a 0d 00 58 0a call 0xa58:0xd + 955: 44 inc sp + 956: 44 inc sp + 957: c7 86 ea fe 00 00 mov WORD PTR [bp-0x116],0x0 + 95d: ff 76 fe push WORD PTR [bp-0x2] + 960: ff 76 fc push WORD PTR [bp-0x4] + 963: 6a 01 push 0x1 + 965: ff b6 da fa push WORD PTR [bp-0x526] + 969: ff b6 e4 fe push WORD PTR [bp-0x11c] + 96d: ff b6 e2 fe push WORD PTR [bp-0x11e] + 971: 9a 0c 00 63 0b call 0xb63:0xc + 976: 83 c4 0c add sp,0xc + 979: ff 76 fe push WORD PTR [bp-0x2] + 97c: ff 76 fc push WORD PTR [bp-0x4] + 97f: 9a 4c 00 a3 00 call 0xa3:0x4c + 984: 83 c4 04 add sp,0x4 + 987: 68 00 40 push 0x4000 + 98a: ff b6 e0 fe push WORD PTR [bp-0x120] + 98e: ff b6 de fe push WORD PTR [bp-0x122] + 992: ff b6 dc fe push WORD PTR [bp-0x124] + 996: 9a 07 00 53 0b call 0xb53:0x7 + 99b: 83 c4 08 add sp,0x8 + 99e: 89 86 da fe mov WORD PTR [bp-0x126],ax + 9a2: ff b6 da fe push WORD PTR [bp-0x126] + 9a6: 9a 0f 00 a3 00 call 0xa3:0xf + 9ab: 44 inc sp + 9ac: 44 inc sp + 9ad: 83 be da fe 00 cmp WORD PTR [bp-0x126],0x0 + 9b2: 74 03 je 0x9b7 + 9b4: e9 01 ff jmp 0x8b8 + 9b7: 6a 00 push 0x0 + 9b9: ff b6 e0 fe push WORD PTR [bp-0x120] + 9bd: ff b6 de fe push WORD PTR [bp-0x122] + 9c1: 16 push ss + 9c2: 8d 86 de fa lea ax,[bp-0x522] + 9c6: 50 push ax + 9c7: 9a ec 0c b7 00 call 0xb7:0xcec + 9cc: 83 c4 0a add sp,0xa + 9cf: 16 push ss + 9d0: 8d 86 de fa lea ax,[bp-0x522] + 9d4: 50 push ax + 9d5: 9a 32 09 b7 00 call 0xb7:0x932 + 9da: 83 c4 04 add sp,0x4 + 9dd: 9a 38 07 b7 00 call 0xb7:0x738 + 9e2: ff b6 e0 fe push WORD PTR [bp-0x120] + 9e6: ff b6 de fe push WORD PTR [bp-0x122] + 9ea: 9a 06 00 61 0c call 0xc61:0x6 + 9ef: 83 c4 04 add sp,0x4 + 9f2: 8b 56 fa mov dx,WORD PTR [bp-0x6] + 9f5: 8b 46 f8 mov ax,WORD PTR [bp-0x8] + 9f8: bb 08 00 mov bx,0x8 + 9fb: b9 e6 11 mov cx,0x11e6 + 9fe: 3b d1 cmp dx,cx + a00: 75 04 jne 0xa06 + a02: 3b c3 cmp ax,bx + a04: 74 0e je 0xa14 + a06: ff 76 fa push WORD PTR [bp-0x6] + a09: ff 76 f8 push WORD PTR [bp-0x8] + a0c: 9a 0b 00 36 0b call 0xb36:0xb + a11: 83 c4 04 add sp,0x4 + a14: 8b 56 fe mov dx,WORD PTR [bp-0x2] + a17: 8b 46 fc mov ax,WORD PTR [bp-0x4] + a1a: bb 1c 00 mov bx,0x1c + a1d: b9 e6 11 mov cx,0x11e6 + a20: 3b d1 cmp dx,cx + a22: 75 04 jne 0xa28 + a24: 3b c3 cmp ax,bx + a26: 74 0e je 0xa36 + a28: ff 76 fe push WORD PTR [bp-0x2] + a2b: ff 76 fc push WORD PTR [bp-0x4] + a2e: 9a 0b 00 36 0b call 0xb36:0xb + a33: 83 c4 04 add sp,0x4 + a36: 33 c0 xor ax,ax + a38: eb 00 jmp 0xa3a + a3a: 1f pop ds + a3b: 5f pop di + a3c: 5e pop si + a3d: c9 leave + a3e: cb retf + a3f: 55 push bp + a40: 8b ec mov bp,sp + a42: 1e push ds + a43: b8 5d 0d mov ax,0xd5d + a46: 8e d8 mov ds,ax + a48: 83 7e 06 ff cmp WORD PTR [bp+0x6],0xffff + a4c: 75 2b jne 0xa79 + a4e: 1e push ds + a4f: b8 00 00 mov ax,0x0 + a52: 50 push ax + a53: b8 e6 11 mov ax,0x11e6 + a56: 50 push ax + a57: b8 30 00 mov ax,0x30 + a5a: 50 push ax + a5b: 9a 0a 00 9e 0c call 0xc9e:0xa + a60: 83 c4 08 add sp,0x8 + a63: 1e push ds + a64: b8 27 00 mov ax,0x27 + a67: 50 push ax + a68: 9a 0f 00 b9 0c call 0xcb9:0xf + a6d: 83 c4 04 add sp,0x4 + a70: 6a 03 push 0x3 + a72: 9a 0d 00 58 0a call 0xa58:0xd + a77: 44 inc sp + a78: 44 inc sp + a79: 1f pop ds + a7a: 5d pop bp + a7b: cb retf + a7c: 55 push bp + a7d: 8b ec mov bp,sp + a7f: 1e push ds + a80: b8 5d 0d mov ax,0xd5d + a83: 8e d8 mov ds,ax + a85: c4 5e 06 les bx,DWORD PTR [bp+0x6] + a88: 26 f7 47 02 10 00 test WORD PTR es:[bx+0x2],0x10 + a8e: 74 2b je 0xabb + a90: 1e push ds + a91: b8 30 00 mov ax,0x30 + a94: 50 push ax + a95: b8 e6 11 mov ax,0x11e6 + a98: 50 push ax + a99: b8 30 00 mov ax,0x30 + a9c: 50 push ax + a9d: 9a 0a 00 9e 0c call 0xc9e:0xa + aa2: 83 c4 08 add sp,0x8 + aa5: 1e push ds + aa6: b8 58 00 mov ax,0x58 + aa9: 50 push ax + aaa: 9a 0f 00 b9 0c call 0xcb9:0xf + aaf: 83 c4 04 add sp,0x4 + ab2: 6a 03 push 0x3 + ab4: 9a 0d 00 58 0a call 0xa58:0xd + ab9: 44 inc sp + aba: 44 inc sp + abb: 1f pop ds + abc: 5d pop bp + abd: cb retf + abe: 55 push bp + abf: 8b ec mov bp,sp + ac1: 1e push ds + ac2: b8 5d 0d mov ax,0xd5d + ac5: 8e d8 mov ds,ax + ac7: 8b 46 06 mov ax,WORD PTR [bp+0x6] + aca: 0b 46 08 or ax,WORD PTR [bp+0x8] + acd: 75 31 jne 0xb00 + acf: ff 76 0c push WORD PTR [bp+0xc] + ad2: ff 76 0a push WORD PTR [bp+0xa] + ad5: 1e push ds + ad6: b8 61 00 mov ax,0x61 + ad9: 50 push ax + ada: b8 e6 11 mov ax,0x11e6 + add: 50 push ax + ade: b8 30 00 mov ax,0x30 + ae1: 50 push ax + ae2: 9a 0a 00 9e 0c call 0xc9e:0xa + ae7: 83 c4 0c add sp,0xc + aea: 1e push ds + aeb: b8 7e 00 mov ax,0x7e + aee: 50 push ax + aef: 9a 0f 00 b9 0c call 0xcb9:0xf + af4: 83 c4 04 add sp,0x4 + af7: 6a 03 push 0x3 + af9: 9a 0d 00 58 0a call 0xa58:0xd + afe: 44 inc sp + aff: 44 inc sp + b00: 1f pop ds + b01: 5d pop bp + b02: cb retf + b03: 55 push bp + b04: 8b ec mov bp,sp + b06: 56 push si + b07: 1e push ds + b08: b8 65 0d mov ax,0xd65 + b0b: 8e d8 mov ds,ax + b0d: 33 f6 xor si,si + b0f: eb 01 jmp 0xb12 + b11: 46 inc si + b12: 8b de mov bx,si + b14: c1 e3 02 shl bx,0x2 + b17: 8b 97 16 00 mov dx,WORD PTR [bx+0x16] + b1b: 8b 87 14 00 mov ax,WORD PTR [bx+0x14] + b1f: 3b cmp dx,WORD PTR [bp+0x8] diff --git a/README.md b/README.md index 12fc265..e7363f2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,38 @@ -# des_undes +# DES/UNDES V1.1.0 source reconstruction — v2 -Old des/undes code based on libdes-3.14. \ No newline at end of file +This directory contains a revised C reconstruction of `des.exe` and +`undes.exe` after comparison with the original `cryptl99.zip` dependency. + +## Main files + +- `des.c` — reconstructed encryption program +- `undes.c` — reconstructed decryption program +- `des_common.c`, `des_common.h` — reconstructed common support +- `reconstruction-notes.md` — evidence, file format and remaining uncertainty +- `cryptlib-api-map.md` — exact CRYPTLIB 0.99 function mapping +- `validation.md` — build/round-trip sanity check +- `asm/` — disassembly used for the reconstruction +- `third_party/cryptl99.zip` — user-supplied original archive +- `third_party/cryptlib-0.99/` — extracted dependency source + +## What changed from the first reconstruction + +The supplied CRYPTLIB source resolves several earlier uncertainties and one +important mistake: + +1. The real API names are lower-case (`initLibrary`, + `queryAlgoModeInformation`, `retrieveIV`, etc.). +2. The executable uses `CRYPT_ALGO_3DES`, not `CRYPT_ALGO_DES`. +3. The mode is `CRYPT_MODE_CBC`. +4. The effective queried key size is 14 bytes. +5. The queried/stored IV is 4 bytes, not 8 bytes. +6. The archive contains exactly libdes 3.14, matching the embedded executable + version string. + +## Status + +The control flow and file-format reconstruction is high confidence. The code +is intended primarily as a faithful readable reconstruction. It has not been +claimed to be byte-for-byte recompilable to the original executables because +that would require the exact original compiler flags, source layout, linker +configuration and original identifiers. diff --git a/SHA256SUMS.txt b/SHA256SUMS.txt new file mode 100644 index 0000000..3aafd83 --- /dev/null +++ b/SHA256SUMS.txt @@ -0,0 +1,3 @@ +d118d9b9a618d7e758229642c0585e005b0ab4d458ef369f44d1f4de7012c034 /mnt/data/des.exe +2e54e8820857a1391ac6ce12444f11f75a8a65bfcc58226edd51d6f495c4aa84 /mnt/data/undes.exe +3cd4d36c75916a2c6050b75bd3ad2706e284d3993fbaa68fbde4343a7056f629 /mnt/data/cryptl99.zip diff --git a/cryptlib-api-map.md b/cryptlib-api-map.md new file mode 100644 index 0000000..624b6eb --- /dev/null +++ b/cryptlib-api-map.md @@ -0,0 +1,40 @@ +# CRYPTLIB 0.99 API mapping + +The supplied `cryptl99.zip` removes the remaining uncertainty about the +CRYPTLIB calls. The executable's call shapes, local structure offsets and the +source in `crypt.h`/`crypt.c` all agree. + +| Operation | CRYPTLIB 0.99 function | des.exe target | undes.exe target | +|---|---|---:|---:| +| Initialise library | `initLibrary()` | `00B3:0738` | `00B7:072A` | +| End library | `endLibrary()` | `00B3:0746` | `00B7:0738` | +| Query algorithm/mode | `queryAlgoModeInformation()` | `00B3:0566` | `00B7:0558` | +| Query context | `queryContextInformation()` | `00B3:06EC` | `00B7:06DE` | +| Initialise context | `initCryptContext()` | `00B3:0756` | `00B7:0748` | +| Destroy context | `destroyCryptContext()` | `00B3:0940` | `00B7:0932` | +| Load key | `loadCryptContext()` | `00B3:09C5` | `00B7:09B7` | +| Retrieve IV | `retrieveIV()` | `00B3:0BA9` | — | +| Load IV | `loadIV()` | — | `00B7:0A90` | +| Encrypt | `encryptBuffer()` | `00B3:0C1E` | — | +| Decrypt | `decryptBuffer()` | — | `00B7:0CEC` | + +## Algorithm values + +Both mains store the integer value `3` for the algorithm and `3` for the mode. +In the supplied `crypt.h` these are: + +```c +CRYPT_ALGO_3DES == 3 +CRYPT_MODE_CBC == 3 +``` + +So DES/UNDES V1.1.0 uses **two-key triple DES in CBC mode**. + +The `CRYPT_QUERY_INFO` offsets used by the machine code also match the supplied +header in the 16-bit large memory model. The program reads: + +- `keySize` = 14 bytes (112 bits) +- `ivSize` = 4 bytes (32 bits) + +Those are exactly the recommended values in the CRYPTLIB 0.99 `3DES-CBC` +capability entry. diff --git a/des.c b/des.c new file mode 100644 index 0000000..b36805c --- /dev/null +++ b/des.c @@ -0,0 +1,205 @@ +/* + * DES V1.1.0 - reconstructed from des.exe + * Original executable: (C) 1998 H.N.M. Dijkema, GPL + * + * IMPORTANT: despite the program name, the executable selects + * CRYPT_ALGO_3DES + CRYPT_MODE_CBC, i.e. two-key triple DES in CBC mode. + * + * This is reconstructed source, not the original source text. Control flow, + * constants, CRYPTLIB calls and file-format behaviour are derived from the + * 16-bit Turbo C executable and verified against CRYPTLIB 0.99 source. + */ + +#include +#include +#include +#include +#include "crypt.h" +#include "des_common.h" + +int main( int argc, char **argv ) +{ + char *password; + char *inputName; + char *outputName; + FILE *input; + FILE *output; + unsigned char *buffer; + unsigned char *payload; + BYTE key[ CRYPT_MAX_KEYSIZE ]; + BYTE iv[ CRYPT_MAX_IVSIZE ]; + BYTE passwordBlock[ CRYPT_MAX_KEYSIZE ]; + CRYPT_INFO cryptInfo; + CRYPT_QUERY_INFO queryInfo; + CRYPT_ALGO algorithm = CRYPT_ALGO_3DES; + CRYPT_MODE mode = CRYPT_MODE_CBC; + DES_INT32 fileVersion = DES_FILE_VERSION; + int keySize; + int ivSize; + int bytesRead; + int firstTime; + int inputFd; + int i; + + if( argc == 2 ) + { + if( strcmp( argv[ 1 ], "--copyright" ) == 0 ) + { + printf( "%s\n\n", desProgramVersion ); + printf( "%s", desCopyrightText ); + exit( 0 ); + } + + if( strcmp( argv[ 1 ], "--version" ) == 0 ) + { + printf( "%s\n", desProgramVersion ); + exit( 0 ); + } + } + + if( argc != 4 ) + { + fprintf( stderr, + "usage: des \n" + " des --copyright\n" + " des --version\n" + " '-' for file --> stdin/stdout\n" ); + exit( argc == 1 ? 0 : 2 ); + } + + password = argv[ 1 ]; + inputName = argv[ 2 ]; + outputName = argv[ 3 ]; + + if( strcmp( inputName, "-" ) != 0 && + strcmp( inputName, outputName ) == 0 ) + { + fprintf( stderr, " and cannot be the same\n" ); + exit( 1 ); + } + + input = ( strcmp( inputName, "-" ) == 0 ) ? + stdin : fopen( inputName, "rb" ); + output = ( strcmp( outputName, "-" ) == 0 ) ? + stdout : fopen( outputName, "wb" ); + + checkOpen( input, inputName ); + checkOpen( output, outputName ); + + /* The executable writes exactly four bytes here. */ + fwrite( &fileVersion, 4, 1, output ); + + algorithm = CRYPT_ALGO_3DES; + mode = CRYPT_MODE_CBC; + + buffer = (unsigned char *) malloc( DES_BUFFER_SIZE ); + if( buffer == NULL ) + { + fprintf( stderr, "Cannot allocate buffer\n" ); + exit( 1 ); + } + + payload = buffer + DES_PREFIX_SIZE; + + initLibrary(); + + queryAlgoModeInformation( algorithm, mode, &queryInfo ); + keySize = queryInfo.keySize; /* 14 bytes for 3DES-CBC in 0.99 */ + ivSize = queryInfo.ivSize; /* 4 bytes for 3DES-CBC in 0.99 */ + + i = 0; + while( i < keySize && password[ i ] != '\0' ) + { + key[ i ] = (BYTE) password[ i ]; + i++; + } + while( i < keySize ) + key[ i++ ] = 0; + + initCryptContext( &cryptInfo, algorithm, mode ); + loadCryptContext( &cryptInfo, key, keySize ); + + firstTime = TRUE; + inputFd = fileno( input ); + + bytesRead = read( inputFd, payload, DES_PAYLOAD_SIZE ); + checkRead( bytesRead ); + + while( bytesRead != 0 ) + { + DES_INT32 marker; + + if( bytesRead == DES_PAYLOAD_SIZE ) + { + marker = negativeMarker( payload ); + if( marker == 0 ) + marker = (DES_INT32) -1; + + memcpy( buffer, &marker, 4 ); + marker = negativeMarker( payload + 4 ); + memcpy( buffer + 4, &marker, 4 ); + } + else + { + marker = (DES_INT32) bytesRead; + memcpy( buffer, &marker, 4 ); + marker = negativeMarker( payload ); + memcpy( buffer + 4, &marker, 4 ); + } + + /* The executable always encrypts the complete 16 KiB buffer. */ + encryptBuffer( &cryptInfo, buffer, DES_BUFFER_SIZE ); + + if( firstTime ) + { + /* + * CRYPTLIB generates the IV on the first encryptBuffer() call. + * Therefore it can only be retrieved after that call. + */ + queryContextInformation( &cryptInfo, &queryInfo ); + ivSize = queryInfo.ivSize; + retrieveIV( &cryptInfo, iv ); + + fwrite( iv, ivSize, 1, output ); + checkWrite( output ); + fflush( output ); + + /* + * Only keySize bytes are assigned. The remaining bytes of this + * 256-byte stack buffer are intentionally left as they were in the + * original executable; UNDES compares only the first keySize bytes. + */ + for( i = 0; i < keySize; i++ ) + passwordBlock[ i ] = key[ i ]; + + encryptBuffer( &cryptInfo, passwordBlock, CRYPT_MAX_KEYSIZE ); + fwrite( passwordBlock, CRYPT_MAX_KEYSIZE, 1, output ); + checkWrite( output ); + fflush( output ); + + firstTime = FALSE; + } + + fwrite( buffer, DES_BUFFER_SIZE, 1, output ); + checkWrite( output ); + fflush( output ); + + bytesRead = read( inputFd, payload, DES_PAYLOAD_SIZE ); + checkRead( bytesRead ); + } + + /* Courtesy close call used by CRYPTLIB block-cipher examples. */ + encryptBuffer( &cryptInfo, buffer, 0 ); + + destroyCryptContext( &cryptInfo ); + endLibrary(); + + free( buffer ); + + if( input != stdin ) + fclose( input ); + if( output != stdout ) + fclose( output ); + + return( 0 ); +} diff --git a/des_common.c b/des_common.c new file mode 100644 index 0000000..86e4c98 --- /dev/null +++ b/des_common.c @@ -0,0 +1,122 @@ +/* + * Common support reconstructed from DES/UNDES V1.1.0 executables. + * Original program copyright: (C) 1998 H.N.M. Dijkema, GPL. + * + * This is reconstructed source, not the original source text. The helper + * behaviour and strings below are derived directly from des.exe/undes.exe. + */ + +#include +#include +#include +#include "des_common.h" + +DES_INT32 desKnownVersions[] = { + DES_FILE_VERSION, + (DES_INT32) -1 +}; + +const char *desProgramVersion = + "DES/UNDES V1.1.0, (C) 1998 H.N.M. Dijkema (GPL)"; + +const char *desCopyrightText = + " Copyright (C) 1998 H.N.M. Dijkema\n" + "\n" + " This product includes software developed by Eric Young (eay@mincom.oz.au)\n" + "\n" + " This program is free software; you can redistribute it and/or modify\n" + " it under the terms of the GNU General Public License as published by\n" + " the Free Software Foundation; either version 2 of the License, or\n" + " (at your option) any later version.\n" + "\n" + " This program is distributed in the hope that it will be useful,\n" + " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + " GNU General Public License for more details.\n" + "\n" + " You should have received a copy of the GNU General Public License\n" + " along with this program; if not, write to the Free Software\n" + " Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" + "\n" + " You can contact the author by electronic mail, hnmdijkema@freemail.nl\n" + "\n" + "\n" + "Acknowledgements\n" + "----------------\n" + "The author of CRYPTLIB, Peter Putmann of University of Auckland\n" + "cryptl99.zip Free encryption library for DOS/UNIX/Windows\n" + "\n" + "The DES and 3DES encryption code was contributed by Eric Young\n" + " and is part of his libdes package.\n" + "The primary ftp site for the full libdes is\n" + " ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/libdes-x.xx.tar.gz.\n" + "\n"; + +void checkRead( int result ) +{ + if( result == -1 ) + { + fprintf( stderr, "\nFATAL : error reading input stream\n" ); + perror( "MESSAGE " ); + exit( 3 ); + } +} + +void checkWrite( FILE *stream ) +{ + if( ferror( stream ) ) + { + fprintf( stderr, "\nFATAL : error writing output stream\n" ); + perror( "MESSAGE " ); + exit( 3 ); + } +} + +void checkOpen( FILE *stream, const char *name ) +{ + if( stream == NULL ) + { + fprintf( stderr, "\nFATAL : Cannot open '%s'\n", name ); + perror( "MESSAGE " ); + exit( 3 ); + } +} + +void checkVersion( DES_INT32 version ) +{ + int i = 0; + + while( desKnownVersions[ i ] != version && + desKnownVersions[ i ] != (DES_INT32) -1 ) + i++; + + if( desKnownVersions[ i ] == (DES_INT32) -1 ) + { + fprintf( stderr, + "I don't know the version of this file, can't decrypt this\n" ); + exit( 1 ); + } +} + +/* + * The compiler output proves that the marker is formed from a signed 16-bit + * word: abs(word), followed by negation and sign-extension to 32 bits. + */ +DES_INT32 negativeMarker( const unsigned char *p ) +{ + DES_INT16 value; + DES_UINT16 magnitude; + DES_UINT16 negated; + + memcpy( &value, p, sizeof( value ) ); + + /* Emulate 16-bit Turbo C arithmetic exactly, including -32768. */ + if( value < 0 ) + magnitude = (DES_UINT16) ( -(DES_INT32) value ); + else + magnitude = (DES_UINT16) value; + + negated = (DES_UINT16) ( 0U - magnitude ); + memcpy( &value, &negated, sizeof( value ) ); + return( (DES_INT32) value ); +} diff --git a/des_common.h b/des_common.h new file mode 100644 index 0000000..f442aab --- /dev/null +++ b/des_common.h @@ -0,0 +1,37 @@ +#ifndef DES_COMMON_H +#define DES_COMMON_H + +#include +#include "crypt.h" + +/* + * Types which have the same width as Turbo C 2.x int/long when this source + * is inspected or built on a modern compiler. + */ +#ifdef __TURBOC__ +typedef int DES_INT16; +typedef unsigned int DES_UINT16; +typedef long DES_INT32; +#else +#include +typedef int16_t DES_INT16; +typedef uint16_t DES_UINT16; +typedef int32_t DES_INT32; +#endif + +#define DES_BUFFER_SIZE 0x4000 +#define DES_PREFIX_SIZE 8 +#define DES_PAYLOAD_SIZE ( DES_BUFFER_SIZE - DES_PREFIX_SIZE ) +#define DES_FILE_VERSION ((DES_INT32) 0x2775L) + +extern DES_INT32 desKnownVersions[]; +extern const char *desProgramVersion; +extern const char *desCopyrightText; + +void checkRead( int result ); +void checkWrite( FILE *stream ); +void checkOpen( FILE *stream, const char *name ); +void checkVersion( DES_INT32 version ); +DES_INT32 negativeMarker( const unsigned char *p ); + +#endif diff --git a/gcc-syntax-check.txt b/gcc-syntax-check.txt new file mode 100644 index 0000000..e69de29 diff --git a/reconstruction-notes.md b/reconstruction-notes.md new file mode 100644 index 0000000..9087404 --- /dev/null +++ b/reconstruction-notes.md @@ -0,0 +1,162 @@ +# Reconstruction notes — DES/UNDES V1.1.0 + +## Confidence + +The main program logic is now reconstructed with high confidence. The supplied +`cryptl99.zip` is especially useful because it contains the exact CRYPTLIB 0.99 +API and libdes 3.14 source that was linked into the executables. + +This is **not** the original source text. Original variable names, comments, +whitespace and file decomposition were not retained in the executable. Names +such as `firstTime`, `passwordBlock`, `negativeMarker`, and the split into +`des_common.c`/`.h` are descriptive reconstruction choices. + +## Compiler and memory model + +Both programs are 16-bit MS-DOS MZ executables and contain the runtime string: + +`Turbo-C - Copyright (c) 1988 Borland Intl.` + +The generated code uses far data pointers extensively, and `malloc()` returns a +segment:offset pointer. That is consistent with a Turbo C large-memory-model +build. + +## Exact crypto dependency + +The executables contain: + +`libdes v 3.14 - eay` + +The supplied CRYPTLIB archive contains the same `libdes/version.h` string, plus +`crypt.h`, `crypt.c`, `lib_3des.c` and the relevant libdes sources. This is the +actual dependency family used by the executables rather than merely a later +compatible library. + +## Important correction: it is 3DES + +The machine code assigns value 3 to both the algorithm and mode variables. +According to the supplied `crypt.h`: + +- `CRYPT_ALGO_3DES` = 3 +- `CRYPT_MODE_CBC` = 3 + +Therefore the encryption is **two-key 3DES-CBC**, despite the executable being +called `des.exe`. + +`crypt.c` defines the recommended 3DES-CBC parameters as: + +- key size: 112 bits = 14 bytes +- IV size: 32 bits = 4 bytes +- DES block size: 64 bits = 8 bytes + +The main routine obtains both sizes through `queryAlgoModeInformation()`. + +## Password handling + +The command-line password is copied directly into a 14-byte key buffer and is +zero-padded if shorter. Characters after byte 14 do not influence encryption. +There is no password hash or KDF in the DES/UNDES layer. + +CRYPTLIB's `des3InitKey()` then constructs the two DES key schedules from that +user-key buffer. `des_check_key` in the bundled libdes defaults to zero, so +parity/weak-key checking is not enabled by default. + +## File layout + +For a non-empty encrypted input the file is: + +```text +Offset Size Meaning +0 4 file version: 0x00002775 +4 4 CRYPTLIB-recommended CBC IV +8 256 encrypted password-check block +264 16384 encrypted data block 1 +16648 16384 encrypted data block 2 +... ... +``` + +For an empty input, `des.exe` writes only the four-byte version. Because no +`encryptBuffer()` call with data occurs, no IV or password-check block is +written. + +## Data-block layout before encryption + +Each 16384-byte encrypted data block consists of: + +```text +0..3 signed 32-bit length marker +4..7 signed 32-bit secondary marker +8..16383 at most 16376 bytes input data +``` + +For a partial final block, the first field is the positive plaintext byte count. +For a full block it is a negative value; `undes.exe` interprets any negative +value as exactly 16376 plaintext bytes. + +The full-block negative value is formed from the absolute value of the first +signed 16-bit word of the plaintext and then negated. If that produces zero, +`-1` is stored instead. The second field is also a negative marker derived from +a signed 16-bit plaintext word. `undes.exe` does not use this second field. + +The exact purpose of the secondary marker cannot be established from the +executables alone; its computation is established, its design intent is not. + +## CBC ordering on the first block + +An unusual but confirmed detail is the first-block ordering. + +`des.exe` performs the cryptographic operations in this order: + +1. encrypt first 16 KiB data block +2. retrieve the now-generated IV +3. encrypt the 256-byte password-check block + +but writes: + +1. IV +2. encrypted password-check block +3. encrypted first data block + +`undes.exe` reads the stored password block and first data block, then decrypts +in cryptographic order: + +1. decrypt first data block +2. decrypt password-check block + +This preserves the CBC state exactly. The apparent storage/processing order +mismatch is therefore intentional in the program logic, not a decompiler error. + +## Password-check block + +Before encryption, the first 14 bytes of the 256-byte password-check block are +the derived 14-byte key. The executable does not initialise the remaining 242 +bytes before encrypting the block. During decryption only the first 14 bytes +are compared. + +## Uninitialised bytes in the final data block + +`des.exe` always encrypts the complete 16384-byte buffer. If the final input +chunk is shorter than 16376 bytes, the unused tail is not explicitly cleared +first. This is also visible in the machine code. UNDES writes only the number +of plaintext bytes stored in the first 32-bit field. + +## Error handling and robustness + +Read errors are detected only when `read()` returns `-1`; short reads are not +rejected. `undes.exe` does not authenticate ciphertext and does not validate a +positive decrypted length against 16376 before passing it to `fwrite()`. These +are normal limitations for small DOS-era utility code, but they matter if old +encrypted files are corrupted or attacker-controlled. + +## Remaining uncertainty + +The following cannot be recovered exactly without original source/debug +symbols: + +- original variable/function names for the DES/UNDES-specific code; +- original comments and formatting; +- exact source-file decomposition; +- the design rationale for the secondary 32-bit marker; +- the symbolic name/formula originally used for file version `0x2775`. + +The actual program behaviour no longer depends on guessed CRYPTLIB API names. diff --git a/third_party/cryptl99.zip b/third_party/cryptl99.zip new file mode 100644 index 0000000000000000000000000000000000000000..ddebfe193cdd4dd72c05a73a6db154ee713e561f GIT binary patch literal 151902 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

SQC017!U#cc-T@(1Tp^Gw_++9}zg>5Zr` zC&FpqYR5$mcBUPbByv^ai%?;T2Zcck#?~=eE(=H)LX`)9M-R*WF8Yq@LM9RH&sHjf=ecjk#1@*3OjmZT#~q8Hs4iK*HS<3*SL^+< zODRATDi;@)#D>&@foVv;r<|<*r^HYG0h>=znG;g76E{xmM^YvTQAR^N7!gAU#Btz@ zP$_pa`79^{XzNbhFR~-GrRpjukLn(#X4(IR?IajaiM3k$n-%D-D{*Dj)9QL+5qR;= zylQ8c!S|%I~dhHU%A=>dzgC0t1 z&f6Cb>~BeHv>JldI`_RE`2`-VF*Hlk3x>5{XvY+fmXWf`U_UA_O9Qom(J0-4DuGu4 zX0-ymPXV#eD3&G;f2B5!Q*Tp2*_Qmh9!84oi*Wh$o*Tj^8C%{thP&jF2lYz`h-Xq9qqacCs8eM- zSINo72{)BQDY=T-=U?BO&OKO>&F3gQew~G*>_iSQ6A8+9X{HoQT9L8dFd*1Rou*`0cu@um^(I2)Z^sRU*Ct4NHtq9~3=$LV zTs)ee8A+`S;$azsGU zr@5l)RHLdv@&sCi2x|lbXHVF#7DJ8%M%dPC*_M;lDkv`n)P1uu@EsOl{_9xYnOBv^ zw}#x-NXE&|G1gJ<7m5yP+K?C}Q`AZDsa~j_I8xAx+9Ut@)gw__LAnJsb3O5iDh0O9 zEO4Ag&@LcMkB0gU<#S(?*Sc&1omdj8gFyX=(|AjJqVi+#n7X^`KC85uQ*zNy8IdZz z&bkPf7l+=~XO=$jpt?oBcPLs%JR^xa2|j}UgH|5J-a!%YM^XP0@5mf`bLEcqTLXtE zWwZg$l{b7$sZpea_lE-9^5MjIItRG1x%RW*u>MB&{rd-VRp)>DD;`rt~1yakj@r-x?~beF>rYq{?>8wol2zEOGx$B=;}AD9e% z(iH}0+Xw{S6y@c~TWgz;IR&oVdwR&Lgm{}fq+?LKTFx{W6KCNjZ3>=4JDv>t~oERQ`WL-O~p>4-r zklr#JT-}~Su_Ct)?i-_xaX9fyixD22Te}38QM&{(#AAqSmy-_{#=7b^jk{9R1qt-ME|^F& zI&K+x_b*;D9>NmlMTyKKpMEjliL1H*HWmomdab_`W-E-r^5fy2IQ(Ztx?L?B!$Z)z znh4RhHuna9^Hfz}(@X!Z+Q3i}?D-zX57vILyahJsA@s#N;r!ttgss{;Sj4am;{}qT z&g#sXzu1vheEim0__IQYN*g5`AUn|zi$f~sXtGNc7KzH&dE$MsroHC*wo`F|Bg}KT&7F1xr+wzITzxqPH{loB+(k5KPo;jBXI?41bZqER3vk27f(hQxpTIglA5poVsBUg9zmH z=a{TpDZ>?_qnTlG0FfQ}@$MBs%l|oXWn<&0;OPo*dNFujBk6l<@~rQY%TXN&z|mK? zybgY6W#rY>I*RA|s)2_|GO{MFwt98HgVe>1E~RM%7=}L4rRRpj`n+*XjUGYo80l4Q zT_FEiT!>v{&3i;z=>y%37-qln5$V+=MQm~yB`f<5+-TgMCba6CW)*4~%dr}>U;@gR)7;f(Y!9Qm>`s)P#5Y*vB_)>Eh; zKFDgyRD>g>=Xl|~F=3z%7*}d>g|eDLe<#u32Q!r&Su*%@0VOm$Mu4%Ur!l7+eZ%lt zwC-)g*|cOwy&3G#oH`)=;j&S+C_~zl#5L4(a{$hC!Lh|?TGMh0+caL~`k`Z>c}UM) zSM|%VVl1L)pqL1s%~yi+GV#&+5<88Cet&N;erkoWqhk@DBf1myh4h=$5`Ar$18RkT z1>UJ(C}1vBYA9isZh5a#cZ0qD4UY!~)nd&a{RI`x5+EK6tGH5>1l~SGR$1aB$RZ6? z1k7rzLX{wppsc<>&5?F%wAi=76x9n?eSb&p1veSon~a}A6X~ggcnl3YgOZdG*wzRj zD(t@pG0tDsPoTaK8VwQ}{WFRc(fS8?B%ICfZ^J}yry3rydiZ3dSWf|UR{d5O>&$qc z`*zF$)M1q&{R(AAnTn*i>=Bb)ra!}F%;%p^qiCHj8YWtdusmrngWK>EZ(mYpQT-2) zG_n4UW74>+-=eT;?5SI4qsrvC2y|Uo%Ot(ZZqq6=ob5wF&34G>|D0U-tPz{RJ9A^) z{92m$HMcgJR@U;IRJ>6N`BToQeeuF_VH@}%kJ6>QZ-4hyUte{w?AUfU@iWR?Vei__ zsM{&x*(>Io4T@XMc)lr?@W(dutGMKqPj#pV7k*C{XKm<=9A$=x;yoeHN6CAN6s23q z=3r3a;(!GgQ79D(s<|*d&m{M;==>?fpt02s_P#dlPwM!9HN*rMI~uAc_F|9+_YSog zen)HD*J!HgVG>o!2{qzKX}5#;*FYx&O-tEvNFKvRN3@9YZ^o_~NTZ*?0%WNR)Ofd2 z1txoJ!kgZw-u2m|vN|tE&?Js9NX6t39E+C5>F4c{nn|TP{`%<&6El5*1bnq;ZN?a1 zjRdE3Ith%PUAa4gZt#h5=IqeGn9k*mrq>Evpj6oCAGfd{OAZ8$Zdv zoD4|rFw}ucCF?5*X+s_uA?1R|Y-d?h0_tAZfbD=?5g;OJxgazh+ZK0QIk)OeGM1xM zXU))O%j`6+7Xb{0(Rk*s6s&T^??IF`cKguszQ#1mC`N+oGk$@oMqihfTIT$J`#2vY z3mDp~xZ*~bF6sFTA^7A64eMb8(R+8t;Ewzg#hyF zqZNht1eRe@j0(#>1I? z7Me`LVjlpzzm-e{eBf2()P_cil zRvqn<)~~O90BtUR*I)B&IkOXpP(n;7%SRt0QgCCpYy7I<(O!dV8$)Q9+`A~Ylh`9g zG6w}wdc8en{+D)1aVY#IlVYi7t#ndY4zo@HrN3N2XY5DC43}77UxR>Q^!;_d{+!M7 z_wcT8aW3@mvrDcWb{tJ&mZaYd1u+a_KBoPtk^?7p=?s7Pd>^6s%T?(qBkue$+p2GA zscbrOsR{3yRTy7=u()Nc^BP*4*_WzG#h-~Dv*!%V1WPpL(&P<_U$SDY}z9(rPUw-{jS(7Vyuj0XOI_om@^5i z(xBQ4Oaq=|F?*4}5R{hgYKSD^3dF3FDA<2bAj!U+^Vo(rqx%YnU)P7P_SjKRVn=%bBH?~D2Ni1n)s=-vfdK{{X*p6m)nX{ zE<;%O0RBKBhl7Y(z9Bz4bf+~$TkR$k!_yf-NIEeQ4&|s3+X%F8n?h_2EY1YQxr|rE zt=fc7rlaf9VPQDsV=pwtWj{kAFuYDi3xX=x4rMph{d>vn_mZZ%A=`b;PSH_gz9uF% zPK`I7xN)rbeJnk{GQwWZ-#RP)?SMWIy-==0_q{gM{935bf)BN-nJNuK4PU382*IvA zB0fkcMBNvVfkC3pfLq+5hvbl3XXKyc2(U$vgl#&KjnL8B-x@b6zD|`9I~PR`jD-$> zL?1+=4;-h<)C6M*Xl$-T@%I|>dwPMv+Q3%aBm zy7`UhN66?$Y$?K1h7?@&C4b~GLb)ve>70N|AE}l<>MdTy=h4d~dI`FuOURJOwoS!W zKzh-)R1&g=<14YNhJp0oC@u|XOs!G^I9wlWE1@m9zn9>DGp-9aC@mWRoo7SYW=9>y z(%V$l`JBp&CVnI31qJ%ufH%UDAW4OIiAYX8W#!v24Cq@<<&o&#;1nKz+=;g;vygbI z5o+XoVd+)ghx}q2@_bAC=uz#OsSuWOA}+(aVXQ;?g&+Xiz8^RHLw7g;J~t~6s^%NZOg^1tbVyZ zX|XLL!9q$TDh&rw|Fm-OpK(IW7hFl<5jY9)u@CJFZdZ4-=LMLrvMAFx_L~|K_6S<0L9#WGO_eon z+)iiTX%jvJ&_ZxvVfO-I8ZLr8ONoLBJHSBf{+fD-(VJ;G{qan~-a2ogWi;XDf_F;P z-{vKDx!Cb!yCGW0<@K+_nOrWMSe`vyb6^7J+D=#E`;-aXf*b2+50_L_hlVYleo0SR zGXumLB9Nwc+AbJUd9w+blwGtORnsVH1BcLz^A#<*`YsSneOgvRhCWm9Dn{~<9h*fr zj=mKtdW0YctO^(T`MPdWEm-jrI)K*-8^i@^8KoueC6k<1ZNPhlfnL1O?4LeW!IO8f zV6hTH;-r9A1td#yo9PMK#?Ul{$ityBw!d`=Z@ibl8zBB0AT9R71@^#fe_M&THd=*D zbqiYPq0pCIz1VDhW+=pLF95Vhude5U~Ml8M<3gs|Sh%2m|2mbNQ@!A-)c|>7fq` za~N+Z>2LU*{BH=j1YE&TYtA`zSC&jHmmeRaBt~KBbF6ZBvHzm$or5d;f`8H2$%$=e zVxQO(+n!*e6Wg{mvF%KfiEU$I+nLzD`Tp*GuU@^X`^U!W?oaRDUA3zAUXAs!DDzfb z#PnThq2{@vddUYn1wF+FVurzV1^*Pd+EJI=5Fr4Am$J-?=81-3PtDYWDDS$_S+P1-AF3iisz@mHu0Be(fW?~{ zLG0Xd6(X%Aa$k`m zdA`e-^(=pU@v~9Kqx-7h>NidL;)j^r&~ZYm<R6-&Fw(!y7gzVJ+`H z7--WIV;C^XoNDT@lt4Y)dXLLD{xCY|MDcLhtsuNH$l^l^e8_m%&kB9iVrqyZpt@%6 zJsC2DU`?^jHJJ^#L9GjySiLC!IKiCAsdw3E06E1Vd8rgXGd;%ZqM@l{jxUZ5a2>mW zb+2%TCYhV#VU=X>O+JVbHX%N7OfkzZCKtjf);d-ItT7T zE_mh~QWn3mDN6pwD0;~KW|jsve60$Q>2Uj5#z9% zC)ts{Ud54m$BGH(QpNTB^*cX!9K*OKa?J@N>jSb|R1aeMjW^!RJ5w|*f}Vlv1$0)v?6^`2G*$#(T69HyC@)p-VrIZ? zXV;*N3C_S5yi9L}f%l}TPdyFw8y z_nHR+8b;#rUC2Bg*EVtK1;Xt`9ZLVLr|)Z=da(8H9(0`5!?>Pq1nIM z1O=w}z4 z2dLZTyQ(J(T6Kj}0>fxNk#EGKd(xC~Osc7O-l!@}rx@L5peL~v0%``K5!MYI=%4>e zjf3NdiE{?1bJ#Ozm-m!X+5+A78bUOg&f2M4;}WGuB5O&ez8e(c5W!$DN8D^| z50Qj4kC0S<9UrpQFc+hi-WJyyr}}DEL1-;n1W>7~ntwh_QGdeQ!OVD2_y>+){uLs~ z>xP-Bw(lvvrB?CA;Ir**z8Xg~5*oQC_FF8hn47RX=@nh5V;!+~_!DB@p=^5^oi`=ZJ=v2J-=MThSC-xB+mt5HMq^1>}Sn4f;KAGD- zY-F)L@UHpE$XTe{|Je^msH54`e{iEqBXbn#I)d+7r(_qffi}r7PNUyT%4V7^Qs##?q{Nqu84JolU;gePRBs zyl0{#0?gg#0PA{bsVSg48u}rKvqj2vtsfx{paBkVjNh2`yts?3Oj(Hh!M3} z0A-zE_!dPc%fixk*aNmv%8o4GtuboTVIOEkT0w4L(6_85NMK``$CxBW|I2c03VTyP zI?ZDZ5>=#`2khF-!R}=d67>}3@fPsmwtPA5mhA^ebwnaM`V7nH;%;weICt;_ne%u4 z?cq91$$0QuNtD*afb?P=1cxE6nj?zhSil3gU)}|fZ(y5>%I2j1qUv};{26AN!>R9f zf9Xz1o;+{s5%%u{bm2|e*In6__lAJ^{A;+I?7}yRiu%M`Jcvx9lH!QMxzRbwm(=gz z;fUhO+Oh1+TRhoW5MpUb6tr}IeHQ|?zw5h;c;X**XB~**ov*29PAY0QEPa<@ORF~w z$d^qS0iRJ^>n;PtD^Vc(BUW(i8k@e0Dv7 zb)}7#dVpVc`0F{Iw16u|m> zwRQBVxrb%$aE4qe^y1`@Yk7@~iiptr>`g#0pG`d0niiS9>

2B2{N}ChNAl1{?zhj*BN15z&nHzp9sb`IeiU1l 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�a`)cb=ME!J=iJ;7FjpGB<<8$6$1~-} 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 literal 0 HcmV?d00001 diff --git a/third_party/cryptlib-0.99/DMakefile b/third_party/cryptlib-0.99/DMakefile new file mode 100644 index 0000000..c8925bf --- /dev/null +++ b/third_party/cryptlib-0.99/DMakefile @@ -0,0 +1,120 @@ +#**************************************************************************** +#* * +#* Makefile for the encryption library * +#* * +#**************************************************************************** + +CC = dcc -v -c + +PROJ = crypt +LIBNAME = $(PROJ).lib + +# Where object files go (/tmp is a good place) +OUTPATH = DObjs/ +# Extension for object files +OBJ = .o + +# Linker (just use the C compiler) +LD = dcc -v +# Echo to screen command +ECHO = echo +# The make command +MAKE = dmake + +# The object files which make up the library + +OBJS = $(OUTPATH)crypt$(OBJ) $(OUTPATH)lib_3des$(OBJ) $(OUTPATH)lib_des$(OBJ) $(OUTPATH)lib_idea$(OBJ) $(OUTPATH)lib_mdc$(OBJ) $(OUTPATH)lib_null$(OBJ) $(OUTPATH)lib_rc4$(OBJ) $(OUTPATH)idea$(OBJ) $(OUTPATH)3ecb_enc$(OBJ) $(OUTPATH)ecb_enc$(OBJ) $(OUTPATH)pcbc_enc$(OBJ) $(OUTPATH)set_key$(OBJ) $(OUTPATH)rc4$(OBJ) $(OUTPATH)shs$(OBJ) + +#**************************************************************************** +#* * +#* If no args are given, print a usage message and exit * +#* * +#**************************************************************************** + +default: $(LIBNAME) + +love: + @$(ECHO) "Nicht wahr?" + @$(ECHO) + +#**************************************************************************** +#* * +#* Rules to build the encryption library * +#* * +#**************************************************************************** + +# Main directory + +$(OUTPATH)crypt$(OBJ): crypt.h crypt.c + $(CC) -o %(left) crypt.c + +$(OUTPATH)lib_3des$(OBJ): crypt.h libdes/des.h lib_3des.c + $(CC) -o %(left) lib_3des.c + +$(OUTPATH)lib_des$(OBJ): crypt.h testdes.h libdes/des.h lib_des.c + $(CC) -o %(left) lib_des.c + +$(OUTPATH)lib_idea$(OBJ): crypt.h idea/idea.h testidea.h lib_idea.c + $(CC) -o %(left) lib_idea.c + +$(OUTPATH)lib_mdc$(OBJ): crypt.h mdc/shs.h lib_mdc.c + $(CC) -o %(left) lib_mdc.c + +$(OUTPATH)lib_null$(OBJ): crypt.h lib_null.c + $(CC) -o %(left) lib_null.c + +$(OUTPATH)lib_rc4$(OBJ): crypt.h testrc4.h rc4/rc4.h lib_rc4.c + $(CC) -o %(left) lib_rc4.c + +$(OUTPATH)test$(OBJ): crypt.h test.c + $(CC) -o %(left) test.c + +# idea subdirectory + +$(OUTPATH)idea$(OBJ): idea/idea.h idea/idea.c + $(CC) -o %(left) idea/idea.c + +# libdes subdirectory + +$(OUTPATH)3ecb_enc$(OBJ): libdes/des.h libdes/des_locl.h libdes/3ecb_enc.c + $(CC) -o %(left) libdes/3ecb_enc.c + +$(OUTPATH)ecb_enc$(OBJ): libdes/des.h libdes/des_locl.h libdes/spr.h libdes/version.h libdes/ecb_enc.c + $(CC) -o %(left) libdes/ecb_enc.c + +$(OUTPATH)pcbc_enc$(OBJ): libdes/des.h libdes/des_locl.h libdes/pcbc_enc.c + $(CC) -o %(left) libdes/pcbc_enc.c + +$(OUTPATH)set_key$(OBJ): libdes/des.h libdes/des_locl.h libdes/podd.h libdes/sk.h libdes/set_key.c + $(CC) -o %(left) libdes/set_key.c + +# rc4 subdirectory + +$(OUTPATH)rc4$(OBJ): rc4/rc4.h rc4/rc4.c + $(CC) -o %(left) rc4/rc4.c + +# mdc subdirectory + +$(OUTPATH)shs$(OBJ): mdc/shs.h mdc/shs.c + $(CC) -o %(left) mdc/shs.c + +# Create the library. The test program is also listed as a dependancy +# since we need to use OS-specific compiler options for it which a +# simple 'make test' won't give us (yuck). + +$(LIBNAME): $(OBJS) $(OUTPATH)test$(OBJ) + join as $(LIBNAME) $(OBJS) + +# Link everything into a test program + +test: $(LIBNAME) $(OUTPATH)test$(OBJ) + $(LD) -o testcrypt $(OUTPATH)test$(OBJ) -l$(PROJ) + +#**************************************************************************** +#* * +#* Cleanup after make has finished * +#* * +#**************************************************************************** + +clean: + delete force #?.o testcrypt $(LIBNAME) diff --git a/third_party/cryptlib-0.99/SCOptions b/third_party/cryptlib-0.99/SCOptions new file mode 100644 index 0000000..2e1a6ef --- /dev/null +++ b/third_party/cryptlib-0.99/SCOptions @@ -0,0 +1,35 @@ +Ansi +Batch +Debug=Line +Error=All +ErrorRexx +Ignore=178 +Ignore=306 +IncludeDir=A31: +LinkOpts=NoAlvs +MemSize=Huge +MultiCharacterConstants +NoIcons +NoMultipleIncludes +NoStackCheck +OnError=Continue +NoOptimize +OptimizerComplexity=10 +OptimizerDepth=10 +OptimizerInlineLocal +OptimizerRecurDepth=10 +NoOptimizerScheduler +OptimizerTime +Parameters=Registers +SmallCode +SmallData +Startup=cres +Strict +StringMerge +Verbose +Define=_STRICT_ANSI +Define=__ANSI__ +Define=USE_BUILTIN_MATH +Define=AMIGA +Define=STDC_HEADERS +Define=KULTUR diff --git a/third_party/cryptlib-0.99/SMakefile b/third_party/cryptlib-0.99/SMakefile new file mode 100644 index 0000000..8a5c2fe --- /dev/null +++ b/third_party/cryptlib-0.99/SMakefile @@ -0,0 +1,115 @@ +#**************************************************************************** +#* * +#* Makefile for the encryption library * +#* * +#**************************************************************************** + +CC = sc + +PROJ = crypt +LIBNAME = $(PROJ).lib + +OUTPATH = SObjs/ # Where object files go (/tmp is a good place) +OBJ = .o # Extension for object files + +LD = $(CC) link # Linker (just use the C compiler) +ECHO = echo # Echo to screen command +MAKE = smake # The make command + +# The object files which make up the library + +OBJS = $(OUTPATH)crypt$(OBJ) $(OUTPATH)lib_3des$(OBJ) $(OUTPATH)lib_des$(OBJ) $(OUTPATH)lib_idea$(OBJ) $(OUTPATH)lib_mdc$(OBJ) $(OUTPATH)lib_null$(OBJ) $(OUTPATH)lib_rc4$(OBJ) $(OUTPATH)idea$(OBJ) $(OUTPATH)3ecb_enc$(OBJ) $(OUTPATH)ecb_enc$(OBJ) $(OUTPATH)pcbc_enc$(OBJ) $(OUTPATH)set_key$(OBJ) $(OUTPATH)rc4$(OBJ) $(OUTPATH)shs$(OBJ) + +#**************************************************************************** +#* * +#* If no args are given, print a usage message and exit * +#* * +#**************************************************************************** + +default: $(LIBNAME) + +love: + @$(ECHO) "Nicht wahr?" + @$(ECHO) + +#**************************************************************************** +#* * +#* Rules to build the encryption library * +#* * +#**************************************************************************** + +# Main directory + +$(OUTPATH)crypt$(OBJ): crypt.h crypt.c + $(CC) objname $@ crypt.c + +$(OUTPATH)lib_3des$(OBJ): crypt.h libdes/des.h lib_3des.c + $(CC) objname $@ lib_3des.c + +$(OUTPATH)lib_des$(OBJ): crypt.h testdes.h libdes/des.h lib_des.c + $(CC) objname $@ lib_des.c + +$(OUTPATH)lib_idea$(OBJ): crypt.h idea/idea.h testidea.h lib_idea.c + $(CC) objname $@ lib_idea.c + +$(OUTPATH)lib_mdc$(OBJ): crypt.h mdc/shs.h lib_mdc.c + $(CC) objname $@ lib_mdc.c + +$(OUTPATH)lib_null$(OBJ): crypt.h lib_null.c + $(CC) objname $@ lib_null.c + +$(OUTPATH)lib_rc4$(OBJ): crypt.h testrc4.h rc4/rc4.h lib_rc4.c + $(CC) objname $@ lib_rc4.c + +$(OUTPATH)test$(OBJ): crypt.h test.c + $(CC) objname $@ test.c + +# idea subdirectory + +$(OUTPATH)idea$(OBJ): idea/idea.h idea/idea.c + $(CC) objname $@ idea/idea.c + +# libdes subdirectory + +$(OUTPATH)3ecb_enc$(OBJ): libdes/des.h libdes/des_locl.h libdes/3ecb_enc.c + $(CC) objname $@ libdes/3ecb_enc.c + +$(OUTPATH)ecb_enc$(OBJ): libdes/des.h libdes/des_locl.h libdes/spr.h libdes/version.h libdes/ecb_enc.c + $(CC) objname $@ libdes/ecb_enc.c + +$(OUTPATH)pcbc_enc$(OBJ): libdes/des.h libdes/des_locl.h libdes/pcbc_enc.c + $(CC) objname $@ libdes/pcbc_enc.c + +$(OUTPATH)set_key$(OBJ): libdes/des.h libdes/des_locl.h libdes/podd.h libdes/sk.h libdes/set_key.c + $(CC) objname $@ libdes/set_key.c + +# rc4 subdirectory + +$(OUTPATH)rc4$(OBJ): rc4/rc4.h rc4/rc4.c + $(CC) objname $@ rc4/rc4.c + +# mdc subdirectory + +$(OUTPATH)shs$(OBJ): mdc/shs.h mdc/shs.c + $(CC) objname $@ mdc/shs.c + +# Create the library. The test program is also listed as a dependancy +# since we need to use OS-specific compiler options for it which a +# simple 'make test' won't give us (yuck). + +$(LIBNAME): $(OBJS) $(OUTPATH)test$(OBJ) + oml -n -b $(LIBNAME) r $(OBJS) + +# Link everything into a test program + +test: $(LIBNAME) $(OUTPATH)test$(OBJ) + @$(LD) pname testcrypt $(OUTPATH)test$(OBJ) lib $(LIBNAME) + +#**************************************************************************** +#* * +#* Cleanup after make has finished * +#* * +#**************************************************************************** + +clean: + delete force \#?.o testcrypt $(LIBNAME) diff --git a/third_party/cryptlib-0.99/crypt.bas b/third_party/cryptlib-0.99/crypt.bas new file mode 100644 index 0000000..36f2f34 --- /dev/null +++ b/third_party/cryptlib-0.99/crypt.bas @@ -0,0 +1,215 @@ +' A warning to parents that this programming language is unsuited for small +' children + +Option Explicit + +'**************************************************************************** +'* * +'* Encryption Algorithm Types/Modes * +'* * +'**************************************************************************** + +' The encryption algorithms we can use + +Global Const CRYPT_ALGO_NONE = 0 ' No encryption +Global Const CRYPT_ALGO_MDCSHS = 1 ' MDC/SHS +Global Const CRYPT_ALGO_DES = 2 ' DES +Global Const CRYPT_ALGO_3DES = 3 ' Two-key triple DES +Global Const CRYPT_ALGO_IDEA = 4 ' IDEA +Global Const CRYPT_ALGO_RC4 = 5 ' RC4 +Global Const CRYPT_ALGO_SAFER = 6 ' SAFER and SAFER-SK +Global Const CRYPT_ALGO_LAST = 7 ' Last possible crypt algo value + +' The encryption modes we can use + +Global Const CRYPT_MODE_NONE = 0 ' No encryption +Global Const CRYPT_MODE_STREAM = 1 ' Stream cipher +Global Const CRYPT_MODE_ECB = 2 ' ECB +Global Const CRYPT_MODE_CBC = 3 ' CBC +Global Const CRYPT_MODE_CFB = 4 ' CFB +Global Const CRYPT_MODE_OFB = 5 ' OFB +Global Const CRYPT_MODE_PCBC = 6 ' PCBC +Global Const CRYPT_MODE_LAST = 6 ' Last possible crypt algo value + +'**************************************************************************** +'* * +'* Library-Wide Constants and Definitions * +'* * +'**************************************************************************** + +' The maximum user key size - 2048 bits + +Global Const CRYPT_MAX_KEYSIZE = 256 + +' The maximum IV size - 256 bits + +Global Const CRYPT_MAX_IVSIZE = 64 + +' The maximum speed ratio for an encryption algorithm + +Global Const CRYPT_MAX_SPEED = 1000 + +'**************************************************************************** +'* * +'* Data Structures * +'* * +'**************************************************************************** + +' An encryption context. Note the order of the BYTE[] fields in this +' structure, which ensures they're aligned to the machine word size + +Type CRYPT_INFO + ' Basic information on the encryption we're using (a pointer to an + ' internal data structure) + capabilityInfo As Long ' The encryption capability data + + ' User keying information. The user key is the key as entered by the + ' user, the transformed user key is (for those algoriths which do this) + ' the user key transformed by whatever key preprocessing method is used, + ' stored in canonical form. The IV is the initial IV stored in canonical + ' form + userKey As String * MAX_KEYSIZE ' User encryption key + transUserKey As String * MAX_KEYSIZE ' Transformed user key + iv As String * MAX_IVSIZE ' Initial IV + userKeyLength As Integer ' User encryption key length in bytes + ivLength As Integer ' IV length in bytes + keySet As Integer ' Whether the key is set up + ivSet As Integer ' Whether the IV is set up + + ' Keying information. The key is the raw encryption key stored in + ' whatever form is required by the algorithm. This may be simply an + ' endianness-adjusted form of the transformed key (in the case of + ' algorithms like MDC/SHS) or a processed form of the user key (in the + ' case of algorithms like DES or IDEA). The IV is the current working + ' IV stored in an endianness-adjusted form. The ivCount is the number + ' of bytes of IV in use, and may be used for various chaining modes. + ' These fields may be unused if the algorithm is implemented in hardware + key As Long ' Pointer to internal working key + currentIV As String * MAX_IVSIZE ' Internal working IV + keyLength As Integer ' Internal key length in bytes + ivCount As Integer ' Internal IV count for chaining modes + + ' Private data needed by the algorithm + privateData As Long ' For private use +End Type + +' Extra algorithm-specific information stored within a crypt context + +Type CRYPT_INFO_MDCSHS + keySetupIterations As Integer ' No.iterations for user key setup +End Type + +Type CRYPT_INFO_SAFER + rounds As Integer ' Number of encryption rounds + currentRounds As Integer ' Internal number of rounds for this key + useSaferSK As Integer ' Whether to use strengthened-key version +End Type + +' Results returned from the encryption capability query + +Type CRYPT_QUERY_INFO + ' The algorithm, encryption mode, and algorithm name. Note that the + ' algorithm name is a pointer to a C string, which current versions of + ' Visual Basic can't handle when they're inside a structure. To use it, + ' you need to extract it into a String in the VB program + cryptAlgo As Integer ' The encryption algorithm + cryptMode As Integer ' The encryption mode + algoName As Long ' The algorithm name + + ' The algorithm parameters + blockSize As Integer ' The basic block size of the algorithm + minKeySize As Integer ' Minimum key size in bytes + keySize As Integer ' Recommended key size in bytes + maxKeySize As Integer ' Maximum key size in bytes + minIVsize As Integer ' Minimum IV size in bytes + ivSize As Integer ' Recommended IV size in bytes + maxIVsize As Integer ' Maximum IV size in bytes + + ' Various algorithm characteristics + speed As Integer ' Speed relative to block copy +End Type + +'**************************************************************************** +'* * +'* Status Codes * +'* * +'**************************************************************************** + +' No error in function call + +Global Const CRYPT_OK = 0 ' No error + +' Generic internal error + +Global Const CRYPT_ERROR = -1 ' Nonspecific error + +' Failed self-test in encryption code + +Global Const CRYPT_SELFTEST = -2 ' Failed self-test + +' Error in parameters passed to function + +Global Const CRYPT_BADPARM = -3 ' Generic bad argument to function +Global Const CRYPT_BADPARM1 = -4 ' Bad argument, parameter 1 +Global Const CRYPT_BADPARM2 = -5 ' Bad argument, parameter 2 +Global Const CRYPT_BADPARM3 = -6 ' Bad argument, parameter 3 +Global Const CRYPT_BADPARM4 = -7 ' Bad argument, parameter 4 +Global Const CRYPT_BADPARM5 = -8 ' Bad argument, parameter 5 +Global Const CRYPT_BADPARM6 = -9 ' Bad argument, parameter 6 +Global Const CRYPT_BADPARM7 = -10 ' Bad argument, parameter 7 +Global Const CRYPT_BADPARM8 = -11 ' Bad argument, parameter 8 +Global Const CRYPT_BADPARM9 = -12 ' Bad argument, parameter 9 +Global Const CRYPT_BADPARM10 = -13 ' Bad argument, parameter 10 +Global Const CRYPT_BADPARM11 = -14 ' Bad argument, parameter 11 +Global Const CRYPT_BADPARM12 = -15 ' Bad argument, parameter 12 +Global Const CRYPT_BADPARM13 = -16 ' Bad argument, parameter 13 +Global Const CRYPT_BADPARM14 = -17 ' Bad argument, parameter 14 +Global Const CRYPT_BADPARM15 = -18 ' Bad argument, parameter 15 + +' Errors due to insufficient resources + +Global Const CRYPT_NOMEM = -19 ' Out of memory +Global Const CRYPT_NOTINITED = -20 ' Data has not been initialised +Global Const CRYPT_INITED = -21 ' Data has already been initialised +Global Const CRYPT_NOALGO = -22 ' Algorithm unavailable +Global Const CRYPT_NOMODE = -23 ' Encryption mode unavailable +Global Const CRYPT_NOKEY = -24 ' Key not initialised +Global Const CRYPT_NOIV = -25 ' IV not initialised + +'**************************************************************************** +'* * +'* Public Functions * +'* * +'**************************************************************************** + +' Initialise and shut down the encryption library + +Declare Function initLibrary Lib "Crypt.Dll" () As Integer +Declare Function endLibrary Lib "Crypt.Dll" () As Integer + +' Query the capabilities of the encryption library + +Declare Function queryModeAvailability Lib "Crypt.Dll" (ByVal cryptAlgo As Integer, ByVal cryptMode As Integer) As Integer +Declare Function queryAlgoAvailability Lib "Crypt.Dll" (ByVal cryptAlgo As Integer) As Integer +Declare Function queryAlgoModeInformation Lib "Crypt.Dll" (ByVal cryptAlgo As Integer, ByVal cryptMode As Integer, cryptQueryInfo As CRYPT_QUERY_INFO) As Integer +Declare Function queryContextInformation Lib "Crypt.Dll" (cryptInfo As CRYPT_INFO, cryptQueryInfo As CRYPT_QUERY_INFO) As Integer + +' Initialise and destroy an encryption context + +Declare Function initCryptContext Lib "Crypt.Dll" (cryptInfo As CRYPT_INFO, ByVal cryptAlgo As Integer, ByVal cryptMode As Integer) As Integer +Declare Function initCryptContextEx Lib "Crypt.Dll" (cryptInfo As CRYPT_INFO, ByVal cryptAlgo As Integer, ByVal cryptMode As Integer, cryptInfoEx As Any) As Integer +Declare Function destroyCryptContext Lib "Crypt.Dll" (cryptInfo As CRYPT_INFO) As Integer + +' Load a user key into a crypt context + +Declare Function loadCryptContext Lib "Crypt.Dll" (cryptInfo As CRYPT_INFO, ByVal key As String, ByVal keyLength As Integer) As Integer + +' Load/retreive an IV into/from a crypt context + +Declare Function loadIV Lib "Crypt.Dll" (cryptInfo As CRYPT_INFO, ByVal iv As String, ByVal length As Integer) As Integer +Declare Function retrieveIV Lib "Crypt.Dll" (cryptInfo As CRYPT_INFO, ByVal iv As String) As Integer + +' Encrypt/decrypt a block of memory + +Declare Function encryptBuffer Lib "Crypt.Dll" (cryptInfo As CRYPT_INFO, ByVal buffer As String, ByVal length As Integer) As Integer +Declare Function decryptBuffer Lib "Crypt.Dll" (cryptInfo As CRYPT_INFO, ByVal buffer As String, ByVal length As Integer) As Integer diff --git a/third_party/cryptlib-0.99/crypt.c b/third_party/cryptlib-0.99/crypt.c new file mode 100644 index 0000000..418844c --- /dev/null +++ b/third_party/cryptlib-0.99/crypt.c @@ -0,0 +1,1049 @@ +#include +#include +#include +#include +#include "crypt.h" + +/**************************************************************************** +* * +* General Work Routines * +* * +****************************************************************************/ + +/* Get an IV value. It doesn't matter much what it is, as long as it's + completely different for each call. We use the first built-in encrypt + capability we find (actually we just assume it's there to save some time) */ + +static void getIV( void *iv, int ivLength ) + { + static BOOLEAN initialised = FALSE; + static BYTE ivBuffer[ CRYPT_MAX_IVSIZE ]; + CRYPT_INFO cryptInfo; + CRYPT_INFO_MDCSHS cryptInfoEx; + + if( !initialised ) + { + /* Seed the data with a value which is guaranteed to be different + each time (unless the entire program is rerun more than twice a + second, which is doubtful) */ + memset( ivBuffer, 0, CRYPT_MAX_IVSIZE ); + time( ( time_t * ) ivBuffer ); + initialised = TRUE; + } + + /* Use an extended setup call to only perform 2 setup iterations for + speed, since we're not concerned about security */ + cryptInfoEx.keySetupIterations = 2; + + /* Shuffle the bits and return them to the user. Since the encryption + will force a call to getIV() again, we cheat a bit by poking around + the cryptInfo internals to fool encryptBuffer() into thinking the IV + is already set */ + initCryptContextEx( &cryptInfo, CRYPT_ALGO_MDCSHS, CRYPT_MODE_CFB, + &cryptInfoEx ); + loadCryptContext( &cryptInfo, ivBuffer, CRYPT_MAX_IVSIZE ); + cryptInfo.ivSet = TRUE; /* Nasty hack to stop recursion */ + encryptBuffer( &cryptInfo, ivBuffer, CRYPT_MAX_IVSIZE ); + destroyCryptContext( &cryptInfo ); + memcpy( iv, ivBuffer, ivLength ); + } + +#ifdef LITTLE_ENDIAN + +/* Byte-reverse an array of 16- and 32-bit words to/from network byte order + to account for processor endianness. These routines assume the given + count is a multiple of 16 or 32 bits. They are safe even for CPU's with + a word size > 32 bits since on a little-endian CPU the important 32 bits + are stored first, so that by zeroizing the first 32 bits and oring the + reversed value back in we don't need to rely on the processor only writing + 32 bits into memory */ + +void longReverse( LONG *buffer, int count ) + { +#ifdef _BIG_WORDS + BYTE *bufPtr = ( BYTE * ) buffer, temp; + + count /= 4; /* sizeof( LONG ) != 4 */ + while( count-- ) + { + #if 0 + LONG temp; + + /* This code is cursed */ + temp = value = *buffer & 0xFFFFFFFFUL; + value = ( ( value & 0xFF00FF00UL ) >> 8 ) | \ + ( ( value & 0x00FF00FFUL ) << 8 ); + value = ( ( value << 16 ) | ( value >> 16 ) ) ^ temp; + *buffer ^= value; + buffer = ( LONG * ) ( ( BYTE * ) buffer + 4 ); + #endif /* 0 */ + /* There's really no nice way to do this - the above code generates + misaligned accesses on processors with a word size > 32 bits, so + we have to work at the byte level (either that or turn misaligned + access warnings off by trapping the signal the access corresponds + to. However a context switch per memory access is probably + somewhat slower than the current byte-twiddling mess) */ + temp = bufPtr[ 3 ]; + bufPtr[ 3 ] = bufPtr[ 0 ]; + bufPtr[ 0 ] = temp; + temp = bufPtr[ 2 ]; + bufPtr[ 2 ] = bufPtr[ 1 ]; + bufPtr[ 1 ] = temp; + bufPtr += 4; + } +#else + LONG value; + + count /= sizeof( LONG ); + while( count-- ) + { + value = *buffer; + value = ( ( value & 0xFF00FF00UL ) >> 8 ) | \ + ( ( value & 0x00FF00FFUL ) << 8 ); + *buffer++ = ( value << 16 ) | ( value >> 16 ); + } +#endif /* _BIG_WORDS */ + } + +void wordReverse( WORD *buffer, int count ) + { + WORD value; + + count /= sizeof( WORD ); + while( count-- ) + { + value = *buffer; + *buffer++ = ( value << 8 ) | ( value >> 8 ); + } + } +#endif /* LITTLE_ENDIAN */ + +/* A safe free function which scrubs memory and zeroes the pointer */ + +void secureFree( void **pointer, int count ) + { + if( *pointer != NULL ) + { + /* Scrub the memory, free it, and zero the pointer */ + memset( *pointer, 0, count ); + free( *pointer ); + *pointer = NULL; + } + } + +/**************************************************************************** +* * +* Capability Management Functions * +* * +****************************************************************************/ + +/* The parameters of most encryption algorithms are traditionally specified + in bytes, so we define a shorter form of the bitsToBytes() macro to allow + the capability information to be specified in bits */ + +#define bits(x) bitsToBytes(x) + +/* The functions used to implement the null encryption routines */ + +int nullSelfTest( void ); +int nullInit( CRYPT_INFO *cryptInfo ); +int nullInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ); +int nullEnd( CRYPT_INFO *cryptInfo ); +int nullInitKey( CRYPT_INFO *cryptInfo ); +int nullInitIV( CRYPT_INFO *cryptInfo ); +int nullEncrypt( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int nullDecrypt( CRYPT_INFO *cryptInfo, void *buffer, int length ); + +/* The functions used to implement the MDC/SHS encryption routines */ + +int mdcshsSelfTest( void ); +int mdcshsInit( CRYPT_INFO *cryptInfo ); +int mdcshsInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ); +int mdcshsEnd( CRYPT_INFO *cryptInfo ); +int mdcshsInitKey( CRYPT_INFO *cryptInfo ); +int mdcshsInitIV( CRYPT_INFO *cryptInfo ); +int mdcshsEncrypt( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int mdcshsDecrypt( CRYPT_INFO *cryptInfo, void *buffer, int length ); + +/* The functions used to implement the DES encryption routines */ + +int desSelfTest( void ); +int desInit( CRYPT_INFO *cryptInfo ); +int desInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ); +int desEnd( CRYPT_INFO *cryptInfo ); +int desInitKey( CRYPT_INFO *cryptInfo ); +int desEncryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int desDecryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int desEncryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int desDecryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int desEncryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int desDecryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int desEncryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int desDecryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int desEncryptPCBC( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int desDecryptPCBC( CRYPT_INFO *cryptInfo, void *buffer, int length ); + +/* The functions used to implement the two-key triple DES encryption + routines */ + +int des3SelfTest( void ); +int des3Init( CRYPT_INFO *cryptInfo ); +int des3InitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ); +int des3End( CRYPT_INFO *cryptInfo ); +int des3InitKey( CRYPT_INFO *cryptInfo ); +int des3EncryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int des3DecryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int des3EncryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int des3DecryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int des3EncryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int des3DecryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int des3EncryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int des3DecryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); + +/* The functions used to implement the IDEA encryption routines */ + +int ideaSelfTest( void ); +int ideaInit( CRYPT_INFO *cryptInfo ); +int ideaInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ); +int ideaEnd( CRYPT_INFO *cryptInfo ); +int ideaInitKey( CRYPT_INFO *cryptInfo ); +int ideaEncryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int ideaDecryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int ideaEncryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int ideaDecryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int ideaEncryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int ideaDecryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int ideaEncryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int ideaDecryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); + +/* The functions used to implement the RC4 encryption routines */ + +int rc4SelfTest( void ); +int rc4Init( CRYPT_INFO *cryptInfo ); +int rc4InitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ); +int rc4End( CRYPT_INFO *cryptInfo ); +int rc4InitKey( CRYPT_INFO *cryptInfo ); +int rc4Encrypt( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int rc4Decrypt( CRYPT_INFO *cryptInfo, void *buffer, int length ); + +/* The functions used to implement the SAFER and SAFER_SK encryption + routines */ + +int saferSelfTest( void ); +int saferInit( CRYPT_INFO *cryptInfo ); +int saferInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ); +int saferEnd( CRYPT_INFO *cryptInfo ); +int saferInitKey( CRYPT_INFO *cryptInfo ); +int saferEncryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int saferDecryptECB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int saferEncryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int saferDecryptCBC( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int saferEncryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int saferDecryptCFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int saferEncryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int saferDecryptOFB( CRYPT_INFO *cryptInfo, void *buffer, int length ); + +/* The encryption library intrinsic capability list */ + +static CAPABILITY_INFO intrinsicCapabilities[] = { + /* The no-encryption capability */ + { CRYPT_ALGO_NONE, CRYPT_MODE_NONE, 0, "None", CRYPT_MAX_SPEED, + 0, 0, 0, + 0, 0, 0, + nullSelfTest, nullInit, nullInitEx, nullEnd, nullInitKey, nullInitIV, + nullEncrypt, nullDecrypt, CRYPT_ERROR, NULL }, + + /* The MDC/SHS capabilities */ + { CRYPT_ALGO_MDCSHS, CRYPT_MODE_CFB, bits( 8 ), "MDC/SHS", CRYPT_ERROR, + bits( 40 ), bits( 512 ), bits( 2048 ), + bits( 32 ), bits( 64 ), bits( 160 ), + mdcshsSelfTest, mdcshsInit, mdcshsInitEx, mdcshsEnd, + mdcshsInitKey, mdcshsInitIV, mdcshsEncrypt, mdcshsDecrypt, + CRYPT_ERROR, NULL }, + + /* The DES capabilities */ + { CRYPT_ALGO_DES, CRYPT_MODE_ECB, bits( 64 ), "DES-ECB", CRYPT_ERROR, + bits( 40 ), bits( 56 ), bits( 56 ), + bits( 0 ), bits( 0 ), bits( 0 ), + desSelfTest, desInit, desInitEx, desEnd, desInitKey, NULL, + desEncryptECB, desDecryptECB, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_DES, CRYPT_MODE_CBC, bits( 64 ), "DES-CBC", CRYPT_ERROR, + bits( 40 ), bits( 56 ), bits( 56 ), + bits( 16 ), bits( 32 ), bits( 64 ), + desSelfTest, desInit, desInitEx, desEnd, desInitKey, NULL, + desEncryptCBC, desDecryptCBC, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_DES, CRYPT_MODE_CFB, bits( 8 ), "DES-CFB", CRYPT_ERROR, + bits( 40 ), bits( 56 ), bits( 56 ), + bits( 16 ), bits( 32 ), bits( 64 ), + desSelfTest, desInit, desInitEx, desEnd, desInitKey, NULL, + desEncryptCFB, desDecryptCFB, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_DES, CRYPT_MODE_OFB, bits( 8 ), "DES-OFB", CRYPT_ERROR, + bits( 40 ), bits( 56 ), bits( 56 ), + bits( 16 ), bits( 32 ), bits( 64 ), + desSelfTest, desInit, desInitEx, desEnd, desInitKey, NULL, + desEncryptOFB, desDecryptOFB, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_DES, CRYPT_MODE_PCBC, bits( 64 ), "DES-PCBC", CRYPT_ERROR, + bits( 40 ), bits( 56 ), bits( 56 ), + bits( 16 ), bits( 32 ), bits( 64 ), + desSelfTest, desInit, desInitEx, desEnd, desInitKey, NULL, + desEncryptPCBC, desDecryptPCBC, CRYPT_ERROR, NULL }, + + /* The two-key triple DES capabilities */ + { CRYPT_ALGO_3DES, CRYPT_MODE_ECB, bits( 64 ), "3DES-ECB", CRYPT_ERROR, + bits( 40 ), bits( 112 ), bits( 112 ), + bits( 0 ), bits( 0 ), bits( 0 ), + des3SelfTest, des3Init, des3InitEx, des3End, des3InitKey, NULL, + des3EncryptECB, des3DecryptECB, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_3DES, CRYPT_MODE_CBC, bits( 64 ), "3DES-CBC", CRYPT_ERROR, + bits( 40 ), bits( 112 ), bits( 112 ), + bits( 16 ), bits( 32 ), bits( 64 ), + des3SelfTest, des3Init, des3InitEx, des3End, des3InitKey, NULL, + des3EncryptCBC, des3DecryptCBC, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_3DES, CRYPT_MODE_CFB, bits( 64 ), "3DES-CFB", CRYPT_ERROR, + bits( 40 ), bits( 112 ), bits( 112 ), + bits( 16 ), bits( 32 ), bits( 64 ), + des3SelfTest, des3Init, des3InitEx, des3End, des3InitKey, NULL, + des3EncryptCFB, des3DecryptCFB, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_3DES, CRYPT_MODE_OFB, bits( 64 ), "3DES-OFB", CRYPT_ERROR, + bits( 40 ), bits( 112 ), bits( 112 ), + bits( 16 ), bits( 32 ), bits( 64 ), + des3SelfTest, des3Init, des3InitEx, des3End, des3InitKey, NULL, + des3EncryptOFB, des3DecryptOFB, CRYPT_ERROR, NULL }, + + /* The IDEA capabilities */ + { CRYPT_ALGO_IDEA, CRYPT_MODE_ECB, bits( 64 ), "IDEA-ECB", CRYPT_ERROR, + bits( 40 ), bits( 128 ), bits( 128 ), + bits( 0 ), bits( 0 ), bits( 0 ), + ideaSelfTest, ideaInit, ideaInitEx, ideaEnd, ideaInitKey, NULL, + ideaEncryptECB, ideaDecryptECB, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_IDEA, CRYPT_MODE_CBC, bits( 64 ), "IDEA-CBC", CRYPT_ERROR, + bits( 40 ), bits( 128 ), bits( 128 ), + bits( 16 ), bits( 32 ), bits( 64 ), + ideaSelfTest, ideaInit, ideaInitEx, ideaEnd, ideaInitKey, NULL, + ideaEncryptCBC, ideaDecryptCBC, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_IDEA, CRYPT_MODE_CFB, bits( 8 ), "IDEA-CFB", CRYPT_ERROR, + bits( 40 ), bits( 128 ), bits( 128 ), + bits( 16 ), bits( 32 ), bits( 64 ), + ideaSelfTest, ideaInit, ideaInitEx, ideaEnd, ideaInitKey, NULL, + ideaEncryptCFB, ideaDecryptCFB, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_IDEA, CRYPT_MODE_OFB, bits( 8 ), "IDEA-OFB", CRYPT_ERROR, + bits( 40 ), bits( 128 ), bits( 128 ), + bits( 16 ), bits( 32 ), bits( 64 ), + ideaSelfTest, ideaInit, ideaInitEx, ideaEnd, ideaInitKey, NULL, + ideaEncryptOFB, ideaDecryptOFB, CRYPT_ERROR, NULL }, + + /* The RC4 capabilities */ + { CRYPT_ALGO_RC4, CRYPT_MODE_STREAM, bits( 8 ), "RC4", CRYPT_ERROR, + bits( 40 ), bits( 128 ), bits( 256 ), + bits( 0 ), bits( 0 ), bits( 0 ), + rc4SelfTest, rc4Init, rc4InitEx, rc4End, rc4InitKey, NULL, + rc4Encrypt, rc4Decrypt, CRYPT_ERROR, NULL }, + + /* The SAFER capabilities */ + { CRYPT_ALGO_SAFER, CRYPT_MODE_ECB, bits( 64 ), "SAFER-ECB", CRYPT_ERROR, + bits( 40 ), bits( 64 ), bits( 128 ), + bits( 0 ), bits( 0 ), bits( 0 ), + saferSelfTest, saferInit, saferInitEx, saferEnd, saferInitKey, NULL, + saferEncryptECB, saferDecryptECB, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_SAFER, CRYPT_MODE_CBC, bits( 64 ), "SAFER-CBC", CRYPT_ERROR, + bits( 40 ), bits( 64 ), bits( 128 ), + bits( 16 ), bits( 32 ), bits( 64 ), + saferSelfTest, saferInit, saferInitEx, saferEnd, saferInitKey, NULL, + saferEncryptCBC, saferDecryptCBC, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_SAFER, CRYPT_MODE_CFB, bits( 8 ), "SAFER-CFB", CRYPT_ERROR, + bits( 40 ), bits( 64 ), bits( 128 ), + bits( 16 ), bits( 32 ), bits( 64 ), + saferSelfTest, saferInit, saferInitEx, saferEnd, saferInitKey, NULL, + saferEncryptCFB, saferDecryptCFB, CRYPT_ERROR, NULL }, + { CRYPT_ALGO_SAFER, CRYPT_MODE_OFB, bits( 8 ), "SAFER-OFB", CRYPT_ERROR, + bits( 40 ), bits( 64 ), bits( 128 ), + bits( 16 ), bits( 32 ), bits( 64 ), + saferSelfTest, saferInit, saferInitEx, saferEnd, saferInitKey, NULL, + saferEncryptOFB, saferDecryptOFB, CRYPT_ERROR, NULL }, + + /* The end-of-list marker */ + { CRYPT_ALGO_NONE, CRYPT_MODE_NONE, CRYPT_ERROR, "", 0, + 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, CRYPT_ERROR, NULL } + }; + +/* The list of crypt library capability records. Even if initCapabilities() + is never called we still have a minimum non-encryption method available */ + +static CAPABILITY_INFO *capabilityListHead = intrinsicCapabilities; +static CAPABILITY_INFO *capabilityListTail = intrinsicCapabilities; +static CAPABILITY_INFO *intrinsicCapabilityListEnd = NULL; + +/* Free the capability list */ + +static void freeCapabilityList( void ) + { + CAPABILITY_INFO *capabilityListPtr = intrinsicCapabilityListEnd; + void *capabilityToFree; + + /* Mark the list as being empty */ + intrinsicCapabilityListEnd = NULL; + + /* Free the capability record list list */ + while( capabilityListPtr != NULL ) + { + capabilityToFree = capabilityListPtr; + capabilityListPtr = capabilityListPtr->next; + secureFree( &capabilityToFree, sizeof( CAPABILITY_INFO ) ); + } + } + +/* Initialise the intrinsic encryption library capability list */ + +static int initCapabilities( void ) + { + CAPABILITY_INFO *capabilityInfoPtr; + CRYPT_ALGO cryptAlgo = CRYPT_ERROR; + int i; + + /* Add the built-in encryption capabilities */ + for( i = 0; intrinsicCapabilities[ i + 1 ].blockSize != CRYPT_ERROR; i++ ) + intrinsicCapabilities[ i ].next = &intrinsicCapabilities[ i + 1 ]; + + /* Perform the self-test for each encryption algorithm */ + for( capabilityInfoPtr = capabilityListHead; + capabilityInfoPtr != NULL; + capabilityInfoPtr = capabilityInfoPtr->next ) + { + CAPABILITY_INFO *capabilitySelfTestPtr; + int status; + + /* If we've already encountered this algorithm, don't try the + self-test again */ + if( capabilityInfoPtr->cryptAlgo == cryptAlgo ) + continue; + cryptAlgo = capabilityInfoPtr->cryptAlgo; + + /* Perform the self-test for this algorithm type */ + status = capabilityInfoPtr->selfTestFunction(); + + /* Set the test status for each capability using this algorithm */ + for( capabilitySelfTestPtr = capabilityInfoPtr; + capabilitySelfTestPtr != NULL; + capabilitySelfTestPtr = capabilitySelfTestPtr->next ) + if( capabilitySelfTestPtr->cryptAlgo == capabilityInfoPtr->cryptAlgo ) + capabilitySelfTestPtr->selfTestStatus = status; + } + + return( CRYPT_OK ); + } + +/* Add a capability record to the library */ + +static int addCapability( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, \ + int blockSize, char *name, int speed, \ + int minKeySize, int keySize, int maxKeySize ) + { + CAPABILITY_INFO *newElement; + + /* Check the passed-in parameters */ + if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST ) + return( CRYPT_BADPARM1 ); + if( cryptMode < CRYPT_MODE_NONE || cryptMode > CRYPT_MODE_LAST ) + return( CRYPT_BADPARM2 ); + if( blockSize < 0 ) + return( CRYPT_BADPARM3 ); + if( name == NULL ) + return( CRYPT_BADPARM4 ); + if( ( speed != CRYPT_ERROR && speed < 0 ) || speed > CRYPT_MAX_SPEED ) + return( CRYPT_BADPARM5 ); + if( minKeySize < 0 ) + return( CRYPT_BADPARM6 ); + if( keySize < minKeySize ) + return( CRYPT_BADPARM7 ); + if( maxKeySize < keySize ) + return( CRYPT_BADPARM8 ); + + /* Allocate memory for the new capability and its associated message */ + if( ( newElement = ( CAPABILITY_INFO * ) malloc( sizeof( CAPABILITY_INFO ) ) ) == NULL ) + return( CRYPT_NOMEM ); + memset( newElement, 0, sizeof( CAPABILITY_INFO ) ); + if( ( newElement->name = ( char * ) malloc( strlen( name ) + 1 ) ) == NULL ) + { + free( newElement ); + return( CRYPT_NOMEM ); + } + + /* Copy the information across */ + newElement->cryptAlgo = cryptAlgo; + newElement->cryptMode = cryptMode; + newElement->blockSize = blockSize; + strcpy( newElement->name, name ); + newElement->minKeySize = minKeySize; + newElement->keySize = keySize; + newElement->maxKeySize = maxKeySize; + newElement->next = NULL; + + /* Link it into the list */ + if( capabilityListHead == NULL ) + capabilityListHead = newElement; + else + capabilityListTail->next = newElement; + capabilityListTail = newElement; + + return( CRYPT_OK ); + } + +/* Find the capability record for a given encryption algorithm */ + +static CAPABILITY_INFO *findCapabilityInfo( CRYPT_ALGO cryptAlgo, \ + CRYPT_MODE cryptMode ) + { + CAPABILITY_INFO *capabilityInfoPtr; + + /* Try and find information on the required algorithm */ + for( capabilityInfoPtr = capabilityListHead; + capabilityInfoPtr != NULL; + capabilityInfoPtr = capabilityInfoPtr->next ) + if( capabilityInfoPtr->cryptAlgo == cryptAlgo && + ( capabilityInfoPtr->cryptMode == cryptMode || + cryptMode == CRYPT_MODE_NONE ) ) + return( capabilityInfoPtr ); + + /* Nothing available */ + return( NULL ); + } + +/**************************************************************************** +* * +* Capability Query Functions * +* * +****************************************************************************/ + +/* Determine whether a given encryption mode is available */ + +CRET queryModeAvailability( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode ) + { + /* Perform basic error checking */ + if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST ) + return( CRYPT_BADPARM1 ); + if( cryptMode < CRYPT_MODE_NONE || cryptMode > CRYPT_MODE_LAST ) + return( CRYPT_BADPARM2 ); + + /* Make sure the library has been initalised */ + if( capabilityListHead == NULL ) + return( CRYPT_NOTINITED ); + + /* See if we have any information on this encryption algo/mode */ + if( findCapabilityInfo( cryptAlgo, cryptMode ) == NULL ) + return( ( findCapabilityInfo( cryptAlgo, CRYPT_MODE_NONE ) == NULL ) ? \ + CRYPT_NOALGO : CRYPT_NOMODE ); + + return( CRYPT_OK ); + } + +CRET queryAlgoAvailability( CRYPT_ALGO cryptAlgo ) + { + return( queryModeAvailability( cryptAlgo, CRYPT_MODE_NONE ) ); + } + +/* Get information on a given encrytion algorithm */ + +CRET queryAlgoModeInformation( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, \ + CRYPT_QUERY_INFO CPTR cryptQueryInfo ) + { + CAPABILITY_INFO *capabilityInfo; + + /* Perform basic error checking */ + if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST ) + return( CRYPT_BADPARM1 ); + if( cryptMode < CRYPT_MODE_NONE || cryptMode > CRYPT_MODE_LAST ) + return( CRYPT_BADPARM2 ); + if( cryptQueryInfo == NULL ) + return( CRYPT_BADPARM3 ); + + /* Make sure the library has been initalised */ + if( capabilityListHead == NULL ) + return( CRYPT_NOTINITED ); + + /* Clear the fields in the query structure */ + memset( cryptQueryInfo, 0, sizeof( CRYPT_QUERY_INFO ) ); + + /* Find the information record on this algorithm */ + if( ( capabilityInfo = findCapabilityInfo( cryptAlgo, cryptMode ) ) == NULL ) + { + cryptQueryInfo->algoName = ""; + cryptQueryInfo->blockSize = CRYPT_ERROR; + cryptQueryInfo->minKeySize = CRYPT_ERROR; + cryptQueryInfo->keySize = CRYPT_ERROR; + cryptQueryInfo->maxKeySize = CRYPT_ERROR; + cryptQueryInfo->minIVsize = CRYPT_ERROR; + cryptQueryInfo->ivSize = CRYPT_ERROR; + cryptQueryInfo->maxIVsize = CRYPT_ERROR; + cryptQueryInfo->speed = CRYPT_ERROR; + return( ( findCapabilityInfo( cryptAlgo, CRYPT_MODE_NONE ) == NULL ) ? \ + CRYPT_NOALGO : CRYPT_NOMODE ); + } + + /* Return the appropriate information */ + cryptQueryInfo->cryptAlgo = cryptAlgo; + cryptQueryInfo->cryptMode = cryptMode; + cryptQueryInfo->algoName = capabilityInfo->name; + cryptQueryInfo->blockSize = capabilityInfo->blockSize; + cryptQueryInfo->minKeySize = capabilityInfo->minKeySize; + cryptQueryInfo->keySize = capabilityInfo->keySize; + cryptQueryInfo->maxKeySize = capabilityInfo->maxKeySize; + cryptQueryInfo->minIVsize = capabilityInfo->minIVsize; + cryptQueryInfo->ivSize = capabilityInfo->ivSize; + cryptQueryInfo->maxIVsize = capabilityInfo->maxIVsize; + cryptQueryInfo->speed = capabilityInfo->speed; + return( CRYPT_OK ); + } + +/* Get information on the algorithm used by a given encryption context */ + +CRET queryContextInformation( CRYPT_INFO CPTR cryptInfo, + CRYPT_QUERY_INFO CPTR cryptQueryInfo ) + { + /* Perform basic error checking */ + if( cryptInfo == NULL ) + return( CRYPT_BADPARM1 ); + if( cryptInfo->capabilityInfo == NULL ) + return( CRYPT_NOTINITED ); + + return( queryAlgoModeInformation( cryptInfo->capabilityInfo->cryptAlgo, + cryptInfo->capabilityInfo->cryptMode, cryptQueryInfo ) ); + } + +/* Initialise and shut down the encryption library */ + +CRET initLibrary( void ) + { + return( initCapabilities() ); + } + +CRET endLibrary( void ) + { + freeCapabilityList(); + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* Encryption Context Management Functions * +* * +****************************************************************************/ + +/* A magic value to detect whether an encryption context has been + initialised yet */ + +#define CRYPT_MAGIC 0xC0EDBABEL + +/* Initialise and perform an extended initialisation of an encryption + context */ + +CRET initCryptContext( CRYPT_INFO CPTR cryptInfo, CRYPT_ALGO cryptAlgo, \ + CRYPT_MODE cryptMode ) + { + /* Perform basic error checking */ + if( cryptInfo == NULL ) + return( CRYPT_BADPARM1 ); + if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST ) + return( CRYPT_BADPARM2 ); + if( cryptMode < CRYPT_MODE_NONE || cryptMode > CRYPT_MODE_LAST ) + return( CRYPT_BADPARM3 ); + + /* Set all fields to zero */ + memset( cryptInfo, 0, sizeof( CRYPT_INFO ) ); + + /* Set up the pointer to the capability information */ + if( ( cryptInfo->capabilityInfo = findCapabilityInfo( cryptAlgo, cryptMode ) ) == NULL ) + return( ( queryAlgoAvailability( cryptAlgo ) ) ? \ + CRYPT_NOMODE : CRYPT_NOALGO ); + + /* Make sure the algorithm self-test went OK */ + if( cryptInfo->capabilityInfo->selfTestStatus != CRYPT_OK ) + return( CRYPT_SELFTEST ); + + /* Perform any algorithm-specific initialization */ + if( cryptInfo->capabilityInfo->initFunction != NULL ) + { + int status; + + status = cryptInfo->capabilityInfo->initFunction( cryptInfo ); + if( isStatusError( status ) ) + return( status ); + } + + /* Set up the IV information to the default values. This can be + overridden later if required */ + cryptInfo->ivLength = cryptInfo->capabilityInfo->ivSize; + + /* Set the check value. Note that we set it after the capability info + has been set, so that a check on this value will also tell us whether + the capability info is present */ + cryptInfo->checkValue = CRYPT_MAGIC; + + return( CRYPT_OK ); + } + +CRET initCryptContextEx( CRYPT_INFO CPTR cryptInfo, CRYPT_ALGO cryptAlgo, \ + CRYPT_MODE cryptMode, void *cryptInfoEx ) + { + /* Perform basic error checking */ + if( cryptInfo == NULL ) + return( CRYPT_BADPARM1 ); + if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST ) + return( CRYPT_BADPARM2 ); + if( cryptMode < CRYPT_MODE_NONE || cryptMode > CRYPT_MODE_LAST ) + return( CRYPT_BADPARM3 ); + if( cryptInfoEx == NULL ) + return( CRYPT_BADPARM4 ); + + /* Set all fields to zero */ + memset( cryptInfo, 0, sizeof( CRYPT_INFO ) ); + + /* Set up the pointer to the capability information */ + if( ( cryptInfo->capabilityInfo = findCapabilityInfo( cryptAlgo, cryptMode ) ) == NULL ) + return( ( queryAlgoAvailability( cryptAlgo ) ) ? \ + CRYPT_NOMODE : CRYPT_NOALGO ); + + /* Make sure the algorithm self-test went OK */ + if( cryptInfo->capabilityInfo->selfTestStatus != CRYPT_OK ) + return( CRYPT_SELFTEST ); + + /* Perform any algorithm-specific initialization */ + if( cryptInfo->capabilityInfo->initExFunction != NULL ) + { + int status; + + status = cryptInfo->capabilityInfo->initExFunction( cryptInfo, cryptInfoEx ); + if( isStatusError( status ) ) + return( status ); + } + + /* Set up the IV information to the default values. This can be + overridden later if required */ + cryptInfo->ivLength = cryptInfo->capabilityInfo->ivSize; + + /* Set the check value. Note that we set it after the capability info + has been set, so that a check on this value will also tell us whether + the capability info is present */ + cryptInfo->checkValue = CRYPT_MAGIC; + + return( CRYPT_OK ); + } + +/* Destroy an encryption context */ + +CRET destroyCryptContext( CRYPT_INFO CPTR cryptInfo ) + { + /* Perform basic error checking */ + if( cryptInfo == NULL ) + return( CRYPT_BADPARM1 ); + if( cryptInfo->checkValue != CRYPT_MAGIC || + cryptInfo->capabilityInfo == NULL ) + return( CRYPT_NOTINITED ); + + /* Perform any algorithm-specific shutdown */ + if( cryptInfo->capabilityInfo->endFunction != NULL ) + { + int status; + + status = cryptInfo->capabilityInfo->endFunction( cryptInfo ); + if( isStatusError( status ) ) + return( status ); + } + + /* Clear all data in the encryption context */ + memset( cryptInfo, 0, sizeof( CRYPT_INFO ) ); + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* Keying Functions * +* * +****************************************************************************/ + +/* Load a user key into an encryption context */ + +CRET loadCryptContext( CRYPT_INFO CPTR cryptInfo, void CPTR userKey, + int userKeyLength ) + { + int status; + + /* Perform basic error checking */ + if( cryptInfo == NULL ) + return( CRYPT_BADPARM1 ); + if( userKey == NULL ) + return( CRYPT_BADPARM2 ); + if( cryptInfo->checkValue != CRYPT_MAGIC ) + return( CRYPT_NOTINITED ); + if( userKeyLength < cryptInfo->capabilityInfo->minKeySize || + userKeyLength > cryptInfo->capabilityInfo->maxKeySize ) + return( CRYPT_BADPARM3 ); + if( cryptInfo->capabilityInfo->initKeyFunction == NULL ) + return( CRYPT_NOALGO ); + + /* Load the user encryption key into the crypt context */ + memcpy( cryptInfo->userKey, userKey, userKeyLength ); + cryptInfo->userKeyLength = userKeyLength; + + /* Remember that we need to set an IV before we encrypt anything */ + cryptInfo->ivSet = FALSE; + + /* Call the encryption routine for this algorithm/mode */ + if( ( status = cryptInfo->capabilityInfo->initKeyFunction( cryptInfo ) ) != CRYPT_OK ) + return( status ); + + /* Record the fact that the key has been initialized */ + cryptInfo->keySet = TRUE; + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* IV Handling Functions * +* * +****************************************************************************/ + +/* Load an IV key into an encryption context */ + +CRET loadIV( CRYPT_INFO CPTR cryptInfo, void CPTR iv, int ivLength ) + { + /* Perform basic error checking */ + if( cryptInfo == NULL ) + return( CRYPT_BADPARM1 ); + if( cryptInfo->checkValue != CRYPT_MAGIC ) + return( CRYPT_NOTINITED ); + if( ivLength < cryptInfo->capabilityInfo->minIVsize || + ivLength > cryptInfo->capabilityInfo->maxIVsize ) + return( CRYPT_BADPARM3 ); + + /* Set the IV length and check whether we'll be using a user-supplied + IV */ + cryptInfo->ivLength = ivLength; + cryptInfo->ivCount = 0; + if( iv != NULL ) + { + /* Load the IV of the required length. If the required IV size is + less than the maximum possible IV size, we pad it with zeroes */ + memset( cryptInfo->iv, 0, CRYPT_MAX_IVSIZE ); + memcpy( cryptInfo->iv, iv, cryptInfo->ivLength ); + memcpy( cryptInfo->currentIV, cryptInfo->iv, CRYPT_MAX_IVSIZE ); + cryptInfo->ivSet = TRUE; + } + if( cryptInfo->capabilityInfo->initIVFunction != NULL ) + { + int status; + + status = cryptInfo->capabilityInfo->initIVFunction( cryptInfo ); + if( isStatusError( status ) ) + return( status ); + } + + return( CRYPT_OK ); + } + +/* Retrieve an IV from an encryption context */ + +CRET retrieveIV( CRYPT_INFO CPTR cryptInfo, void CPTR iv ) + { + /* Perform basic error checking */ + if( cryptInfo == NULL ) + return( CRYPT_BADPARM1 ); + if( iv == NULL ) + return( CRYPT_BADPARM2 ); + if( cryptInfo->checkValue != CRYPT_MAGIC ) + return( CRYPT_NOTINITED ); + + /* Make sure the IV has been set */ + if( cryptInfo->ivSet == FALSE ) + return( CRYPT_NOIV ); + + /* Copy the IV data of the required length to the output buffer */ + memcpy( iv, cryptInfo->iv, cryptInfo->ivLength ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* Encrypt/Decrypt Routines * +* * +****************************************************************************/ + +/* Encrypt a block of memory */ + +CRET encryptBuffer( CRYPT_INFO CPTR cryptInfo, void CPTR buffer, int length ) + { + /* Perform basic error checking */ + if( cryptInfo == NULL ) + return( CRYPT_BADPARM1 ); + if( buffer == NULL ) + return( CRYPT_BADPARM2 ); + if( length < 0 ) + return( CRYPT_BADPARM3 ); + if( !cryptInfo->keySet ) + return( CRYPT_NOKEY ); + if( cryptInfo->checkValue != CRYPT_MAGIC ) + return( CRYPT_NOTINITED ); + if( cryptInfo->capabilityInfo->encryptFunction == NULL ) + return( CRYPT_NOALGO ); + + /* If there's no IV set, generate one ourselves */ + if( !cryptInfo->ivSet ) + { + BYTE iv[ CRYPT_MAX_IVSIZE ]; + int status; + + getIV( iv, cryptInfo->ivLength ); + status = loadIV( cryptInfo, iv, cryptInfo->ivLength ); + if( isStatusError( status ) ) + return( CRYPT_ERROR ); + } + + /* Call the encryption routine for this algorithm/mode */ + return( cryptInfo->capabilityInfo->encryptFunction( cryptInfo, buffer, length ) ); + } + +/* Decrypt a block of memory */ + +CRET decryptBuffer( CRYPT_INFO CPTR cryptInfo, void CPTR buffer, int length ) + { + /* Perform basic error checking */ + if( cryptInfo == NULL ) + return( CRYPT_BADPARM1 ); + if( buffer == NULL ) + return( CRYPT_BADPARM2 ); + if( length < 0 ) + return( CRYPT_BADPARM3 ); + if( !cryptInfo->keySet ) + return( CRYPT_NOKEY ); + if( cryptInfo->checkValue != CRYPT_MAGIC ) + return( CRYPT_NOTINITED ); + if( cryptInfo->capabilityInfo->decryptFunction == NULL ) + return( CRYPT_NOALGO ); + + /* Make sure the IV has been set */ + if( cryptInfo->ivSet == FALSE ) + return( CRYPT_NOIV ); + + /* Call the decryption routine for this algorithm/mode */ + return( cryptInfo->capabilityInfo->decryptFunction( cryptInfo, buffer, length ) ); + } + +/**************************************************************************** +* * +* Dynamic Library Update Support * +* * +****************************************************************************/ + +/* Add a new encryption capability to the library. This routine is quite + powerful, but what a kludge! */ + +CRET addCryptCapability( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, \ + int blockSize, char *name, int speed, \ + int minKeySize, int keySize, int maxKeySize ) + { + int status; + + /* Add the basic capability information */ + status = addCapability( cryptAlgo, cryptMode, blockSize, name, + speed, minKeySize, keySize, maxKeySize ); + if( isStatusError( status ) ) + return( status ); + + /* Add the handlers */ +/* Not implemented yet */ + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* OS-Specific Support Routines * +* * +****************************************************************************/ + +#if defined( __WINDOWS__ ) && !( defined( WIN32 ) || defined( _WIN32 ) ) + +/* Whether LibMain() has been called before */ + +static BOOLEAN libMainCalled = FALSE; +static HWND hInst; + +/* The main function for the DLL */ + +int CALLBACK LibMain( HINSTANCE hInstance, WORD wDataSeg, WORD wHeapSize, \ + LPSTR lpszCmdLine ) + { + /* Rot bilong kargo */ + if( wHeapSize > 0 ) + UnlockData( 0 ); /* Allow heap to move */ + + /* If we've been called before, return with an error message */ + if( libMainCalled ) + return( FALSE ); + libMainCalled = TRUE; + + /* Initialise the library */ + if( initLibrary() != CRYPT_OK ) + return( FALSE ); + + /* Remember the proc instance for later */ + hInst = hInstance; + + return( TRUE ); + } + +/* Shut down the DLL */ + +int CALLBACK WEP( int nSystemExit ) + { + switch( nSystemExit ) + { + case WEP_SYSTEM_EXIT: + /* System is shutting down */ + break; + + case WEP_FREE_DLL: + /* DLL reference count = 0, DLL-only shutdown */ + break; + } + + /* Shut down the encryption library if necessary */ + endLibrary(); + + return( TRUE ); + } + +#elif defined( __WINDOWS__ ) && ( defined( WIN32 ) || defined( _WIN32 ) ) + +/* Whether LibMain() has been called before */ + +static BOOLEAN libMainCalled = FALSE; +static HWND hInst; + +int LibMain( HANDLE hInstance, ULONG ulReasonCalled, LPVOID lpReserved ) + { + /* If we've been called before, return with an error message */ + if( libMainCalled ) + return( FALSE ); + libMainCalled = TRUE; + + /* Initialise the library */ + if( initLibrary() != CRYPT_OK ) + return( FALSE ); + + /* Remember the proc instance for later */ + hInst = hInstance; + + return( TRUE ); + } + +int CALLBACK WEP( int nSystemExit ) + { + /* Shut down the encryption library if necessary */ + endLibrary(); + + return( TRUE ); + } +#endif /* __WINDOWS__ */ diff --git a/third_party/cryptlib-0.99/crypt.h b/third_party/cryptlib-0.99/crypt.h new file mode 100644 index 0000000..6650399 --- /dev/null +++ b/third_party/cryptlib-0.99/crypt.h @@ -0,0 +1,421 @@ +#ifndef _CRYPT_DEFINED + +#define _CRYPT_DEFINED + +/* Fixup for Windoze support. We need to include windows.h for various types + and prototypes needed for DLL's, and then fix up a type clash with a + Windows predefined type - for some bizarre reason BYTE and WORD are + unsigned, but LONG is signed */ + +#if defined( __WINDOWS__ ) + #include + #undef LONG +#endif /* __WINDOWS__ */ + +/* Some encryption algorithms which rely on longints having 32 bits won't + work on 64- or 128-bit machines due to problems with sign extension and + whatnot. The following define can be used to enable special handling for + processors with a > 32 bit word size */ + +#include +#if LONG_MAX > 0xFFFFFFFFUL + #define _BIG_WORDS +#endif /* LONG > 32 bits */ + +/* Some useful types. We have to jump through all sorts of hoops for Windoze, + not helped by the fact that the method of detecting Windoze at compile + time changes with different versions of Visual C */ + +#if defined(_MSC_VER) +typedef int BOOLEAN; +#elif !( defined( WIN32 ) || defined( _WIN32 ) ) +typedef int BOOLEAN; +#endif /* !( WIN32 || _WIN32 ) */ +typedef unsigned char BYTE; +#ifndef __WINDOWS__ + typedef unsigned short WORD; +#endif /* __WINDOWS__ */ +#if defined( __WINDOWS__ ) && ( defined( WIN32 ) || defined( _WIN32 ) ) + #pragma warning( disable : 4142 ) + typedef unsigned long LONG; + #pragma warning( default : 4142 ) + #ifdef _WIN32 + /* Visual C 2.1 doesn't seem to like LONG being typedef'd to unsigned + no matter what you do, so we rely on the preprocessor to get rid of + the problem. Visual C 2.1 defined _WIN32 whereas 2.0 defined WIN32, + so we can use this to tell the two apart */ + #define LONG unsigned long + #endif /* _WIN32 */ +#else + typedef unsigned long LONG; +#endif /* __WINDOWS__ && ( WIN32 || _WIN32 ) */ + +/* Boolean consants */ + +#ifndef TRUE + #define FALSE 0 + #define TRUE !FALSE +#endif /* TRUE */ + +/* Machine-dependant types to allow use in special library types such as + DLL's */ + +#if defined( __WINDOWS__ ) && !( defined( WIN32 ) || defined( _WIN32 ) ) + #define CPTR FAR * /* DLL pointer */ + #define CRET int FAR PASCAL _export /* DLL return value */ +#else + #define CPTR * /* General pointer */ + #define CRET int /* General return value */ +#endif /* __WINDOWS__ && !( WIN32 || _WIN32 ) */ + +/* Determine the processor endianness. Thanks to Shawn Clifford + for this trick. + + NB: A number of compilers aren't tough enough for this test */ + +#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) + +#if defined(_MSC_VER) + + /* + * All architectures currently supported by MSVC/Windows + * use little-endian byte ordering. + */ +#if defined(_M_IX86) || \ + defined(_M_X64) || \ + defined(_M_AMD64) || \ + defined(_M_ARM) || \ + defined(_M_ARM64) || \ + defined(_M_ARM64EC) + +#define LITTLE_ENDIAN + +#else +#error Cannot determine processor endianness for MSVC +#endif + +#elif defined(AMIGA) + +#define BIG_ENDIAN + +#elif defined(__GNUC__) + +#ifdef BYTES_BIG_ENDIAN +#define BIG_ENDIAN +#else +#define LITTLE_ENDIAN +#endif + +#else + +#error Cannot determine processor endianness - edit crypt.h and recompile + +#endif + +#endif + +/**************************************************************************** +* * +* Encryption Algorithm Types/Modes * +* * +****************************************************************************/ + +/* The encryption algorithms we can use */ + +typedef enum { + CRYPT_ALGO_NONE, /* No encryption */ + CRYPT_ALGO_MDCSHS, /* MDC/SHS */ + CRYPT_ALGO_DES, /* DES */ + CRYPT_ALGO_3DES, /* Two-key triple DES */ + CRYPT_ALGO_IDEA, /* IDEA */ + CRYPT_ALGO_RC4, /* RC4 */ + CRYPT_ALGO_SAFER, /* SAFER */ + + CRYPT_ALGO_LAST /* Last possible crypt algo value */ + } CRYPT_ALGO; + +/* The encryption modes we can use */ + +typedef enum { + /* No encryption */ + CRYPT_MODE_NONE, /* No encryption */ + + /* Stream cipher modes */ + CRYPT_MODE_STREAM, /* Stream cipher */ + +/* Block cipher modes */ + CRYPT_MODE_ECB, /* ECB */ + CRYPT_MODE_CBC, /* CBC */ + CRYPT_MODE_CFB, /* CFB */ + CRYPT_MODE_OFB, /* OFB */ + CRYPT_MODE_PCBC, /* PCBC */ + + CRYPT_MODE_LAST /* Last possible crypt algo value */ + } CRYPT_MODE; + +/**************************************************************************** +* * +* Library-Wide Constants and Definitions * +* * +****************************************************************************/ + +/* The maximum user key size - 2048 bits */ + +#define CRYPT_MAX_KEYSIZE 256 + +/* The maximum IV size - 256 bits */ + +#define CRYPT_MAX_IVSIZE 64 + +/* The maximum speed ratio for an encryption algorithm */ + +#define CRYPT_MAX_SPEED 1000 + +/* A magic value indicating that the default setting for this parameter + should be used */ + +#define CRYPT_USE_DEFAULT -1 + +/* Macros to convert to and from the bit counts used for some encryption + parameters */ + +#define bitsToBytes(bits) ( ( bits ) >> 3 ) +#define bytesToBits(bytes) ( ( bytes ) << 3 ) + +/**************************************************************************** +* * +* Data Structures * +* * +****************************************************************************/ + +/* The structure used to store internal information about the crypto library + capabilities. This information is used internally by the library and is + not available to users */ + +struct CI; /* Forward declaration for nested struct */ + +typedef struct CA { + /* Basic identification information for the algorithm */ + CRYPT_ALGO cryptAlgo; /* The encryption algorithm */ + CRYPT_MODE cryptMode; /* The encryption mode */ + int blockSize; /* The basic block size of the algorithm */ + char *name; /* Algorithm name */ + int speed; /* Speed relative to block copy */ + + /* Keying information */ + int minKeySize; /* Minimum key size in bytes */ + int keySize; /* Recommended key size in bytes */ + int maxKeySize; /* Maximum key size in bytes */ + + /* IV information */ + int minIVsize; /* Minimum IV size in bytes */ + int ivSize; /* Recommended IV size in bytes */ + int maxIVsize; /* Maximum IV size in bytes */ + + /* The functions for implementing the algorithm */ + int ( *selfTestFunction )( void ); + int ( *initFunction )( struct CI CPTR cryptInfo ); + int ( *initExFunction )( struct CI CPTR cryptInfo, void CPTR cryptInfoEx ); + int ( *endFunction )( struct CI CPTR cryptInfo ); + int ( *initKeyFunction )( struct CI CPTR cryptInfo ); + int ( *initIVFunction )( struct CI CPTR cryptInfo ); + int ( *encryptFunction )( struct CI CPTR cryptInfo, void CPTR buffer, int length ); + int ( *decryptFunction )( struct CI CPTR cryptInfo, void CPTR buffer, int length ); + + /* The results of the self-test for this algorithm */ + int selfTestStatus; + + /* The next record in the list */ + struct CA *next; /* Pointer to the next record */ + } CAPABILITY_INFO; + +/* An encryption context. Note the order of the BYTE[] fields in this + structure, which ensures they're aligned to the machine word size */ + +typedef struct CI { + /* Basic information on the encryption we're using */ + CAPABILITY_INFO *capabilityInfo;/* The encryption capability data */ + + /* User keying information. The user key is the key as entered by the + user, the transformed user key is (for those algoriths which do + this) the user key transformed by whatever key preprocessing method + is used, stored in canonical form. The IV is the initial IV stored + in canonical form */ + BYTE userKey[ CRYPT_MAX_KEYSIZE ]; /* User encryption key */ + BYTE transUserKey[ CRYPT_MAX_KEYSIZE ]; /* Transformed user key */ + BYTE iv[ CRYPT_MAX_IVSIZE ]; /* Initial IV */ + int userKeyLength; /* User encryption key length in bytes */ + int ivLength; /* IV length in bytes */ + BOOLEAN keySet; /* Whether the key is set up */ + BOOLEAN ivSet; /* Whether the IV is set up */ + + /* Keying information. The key is the raw encryption key stored in + whatever form is required by the algorithm. This may be simply an + endianness-adjusted form of the transformed key (in the case of + algorithms like MDC/SHS) or a processed form of the user key (in the + case of algorithms like DES or IDEA). The IV is the current working + IV stored in an endianness-adjusted form. The ivCount is the number + of bytes of IV in use, and may be used for various chaining modes. + These fields may be unused if the algorithm is implemented in hardware */ + void *key; /* Internal working key */ + BYTE currentIV[ CRYPT_MAX_IVSIZE ]; /* Internal working IV */ + int keyLength; /* Internal key length in bytes */ + int ivCount; /* Internal IV count for chaining modes */ + + /* Private data needed by the algorithm */ + void *privateData; /* For private use */ + + /* A check value so we can determine whether the crypt context has been + initialised or not. This is needed because passing in an + uninitialised block of memory as a crypt context can lead to problems + when we try to dereference wild pointers */ + LONG checkValue; + } CRYPT_INFO; + +/* Extra algorithm-specific information stored within a crypt context. Set + the parameter values to CRYPT_USE_DEFAULT to use the default values for + this algorithm */ + +typedef struct { + int keySetupIterations; /* No.iterations for user key setup */ + } CRYPT_INFO_MDCSHS; + +typedef struct { + int rounds; /* Number of encryption rounds */ + int currentRounds; /* Internal number of rounds for this key */ + BOOLEAN useSaferSK; /* Whether to use strengthened-key version */ + } CRYPT_INFO_SAFER; + +/* Results returned from the encryption capability query */ + +typedef struct { + /* The algorithm, encryption mode, and algorithm name */ + CRYPT_ALGO cryptAlgo; /* The encryption algorithm */ + CRYPT_MODE cryptMode; /* The encryption mode */ + char *algoName; /* The algorithm name */ + + /* The algorithm parameters */ + int blockSize; /* The basic block size of the algorithm */ + int minKeySize; /* Minimum key size in bytes */ + int keySize; /* Recommended key size in bytes */ + int maxKeySize; /* Maximum key size in bytes */ + int minIVsize; /* Minimum IV size in bytes */ + int ivSize; /* Recommended IV size in bytes */ + int maxIVsize; /* Maximum IV size in bytes */ + + /* Various algorithm characteristics */ + int speed; /* Speed relative to block copy */ + } CRYPT_QUERY_INFO; + +/**************************************************************************** +* * +* Status Codes * +* * +****************************************************************************/ + +/* No error in function call */ + +#define CRYPT_OK 0 /* No error */ + +/* Generic internal error */ + +#define CRYPT_ERROR -1 /* Nonspecific error */ + +/* Failed self-test in encryption code */ + +#define CRYPT_SELFTEST -2 /* Failed self-test */ + +/* Error in parameters passed to function */ + +#define CRYPT_BADPARM -3 /* Generic bad argument to function */ +#define CRYPT_BADPARM1 -4 /* Bad argument, parameter 1 */ +#define CRYPT_BADPARM2 -5 /* Bad argument, parameter 2 */ +#define CRYPT_BADPARM3 -6 /* Bad argument, parameter 3 */ +#define CRYPT_BADPARM4 -7 /* Bad argument, parameter 4 */ +#define CRYPT_BADPARM5 -8 /* Bad argument, parameter 5 */ +#define CRYPT_BADPARM6 -9 /* Bad argument, parameter 6 */ +#define CRYPT_BADPARM7 -10 /* Bad argument, parameter 7 */ +#define CRYPT_BADPARM8 -11 /* Bad argument, parameter 8 */ +#define CRYPT_BADPARM9 -12 /* Bad argument, parameter 9 */ +#define CRYPT_BADPARM10 -13 /* Bad argument, parameter 10 */ +#define CRYPT_BADPARM11 -14 /* Bad argument, parameter 11 */ +#define CRYPT_BADPARM12 -15 /* Bad argument, parameter 12 */ +#define CRYPT_BADPARM13 -16 /* Bad argument, parameter 13 */ +#define CRYPT_BADPARM14 -17 /* Bad argument, parameter 14 */ +#define CRYPT_BADPARM15 -18 /* Bad argument, parameter 15 */ + +/* Errors due to insufficient resources */ + +#define CRYPT_NOMEM -19 /* Out of memory */ +#define CRYPT_NOTINITED -20 /* Data has not been initialised */ +#define CRYPT_INITED -21 /* Data has already been initialised */ +#define CRYPT_NOALGO -22 /* Algorithm unavailable */ +#define CRYPT_NOMODE -23 /* Encryption mode unavailable */ +#define CRYPT_NOKEY -24 /* Key not initialised */ +#define CRYPT_NOIV -25 /* IV not initialised */ + +/* A macro to detect an error return value */ + +#define isStatusError(status) ( ( status ) < CRYPT_OK ) +#define isStatusOK(status) ( ( status ) == CRYPT_OK ) + +/**************************************************************************** +* * +* Private Functions * +* * +****************************************************************************/ + +/* Functions to convert the endianness from the canonical form to the + internal form. These are only needed on little-endian machines */ + +#ifdef LITTLE_ENDIAN + void longReverse( LONG *buffer, int count ); + void wordReverse( WORD *buffer, int count ); +#else + #define longReverse(x,y) + #define wordReverse(x,y) +#endif /* LITTLE_ENDIAN */ + +/* A free() which sanitises the memory before it frees it */ + +void secureFree( void **pointer, int count ); + +/**************************************************************************** +* * +* Public Functions * +* * +****************************************************************************/ + +/* Initialise and shut down the encryption library */ + +CRET initLibrary( void ); +CRET endLibrary( void ); + +/* Query the capabilities of the encryption library */ + +CRET queryModeAvailability( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode ); +CRET queryAlgoAvailability( CRYPT_ALGO cryptAlgo ); +CRET queryAlgoModeInformation( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, CRYPT_QUERY_INFO CPTR cryptQueryInfo ); +CRET queryContextInformation( CRYPT_INFO CPTR cryptInfo, CRYPT_QUERY_INFO CPTR cryptQueryInfo ); + +/* Initialise and destroy an encryption context */ + +CRET initCryptContext( CRYPT_INFO CPTR cryptInfo, CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode ); +CRET initCryptContextEx( CRYPT_INFO CPTR cryptInfo, CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, void *cryptInfoEx ); +CRET destroyCryptContext( CRYPT_INFO CPTR cryptInfo ); + +/* Load a user key into a crypt context */ + +CRET loadCryptContext( CRYPT_INFO CPTR cryptInfo, void CPTR key, int keyLength ); + +/* Load/retreive an IV into/from a crypt context */ + +CRET loadIV( CRYPT_INFO CPTR cryptInfo, void CPTR iv, int length ); +CRET retrieveIV( CRYPT_INFO CPTR cryptInfo, void CPTR iv ); + +/* Encrypt/decrypt a block of memory */ + +CRET encryptBuffer( CRYPT_INFO CPTR cryptInfo, void CPTR buffer, int length ); +CRET decryptBuffer( CRYPT_INFO CPTR cryptInfo, void CPTR buffer, int length ); + +#endif /* _CRYPT_DEFINED */ diff --git a/third_party/cryptlib-0.99/cryptnt.def b/third_party/cryptlib-0.99/cryptnt.def new file mode 100644 index 0000000..c3dc108 --- /dev/null +++ b/third_party/cryptlib-0.99/cryptnt.def @@ -0,0 +1,23 @@ +; Definition file for Crypt DLL + +LIBRARY CRYPTNT +DESCRIPTION 'Encryption DLL' +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE SINGLE +HEAPSIZE 8192 +EXPORTS initLibrary + endLibrary + queryModeAvailability + queryAlgoAvailability + queryAlgoModeInformation + queryContextInformation + initCryptContext + initCryptContextEx + destroyCryptContext + loadCryptContext + loadIV + retrieveIV + encryptBuffer + decryptBuffer + +IMPORTS diff --git a/third_party/cryptlib-0.99/cryptnt.mak b/third_party/cryptlib-0.99/cryptnt.mak new file mode 100644 index 0000000..2956545 --- /dev/null +++ b/third_party/cryptlib-0.99/cryptnt.mak @@ -0,0 +1,391 @@ +# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +!IF "$(CFG)" == "" +CFG=Win32 Debug +!MESSAGE No configuration specified. Defaulting to Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "CRYPTNT.MAK" CFG="Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "Win32 Debug" +MTL=MkTypLib.exe +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "WinRel" +# PROP BASE Intermediate_Dir "WinRel" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +OUTDIR=.\WinRel +INTDIR=.\WinRel + +ALL : .\cryptnt.dll $(OUTDIR)/CRYPTNT.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE CPP /nologo /MT /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__WINDOWS__" /c +# SUBTRACT CPP /YX /Fr +CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\ + "__WINDOWS__" /Fo$(INTDIR)/ /c +CPP_OBJS=.\WinRel/ +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo$(INTDIR)/"CRYPTNT.res" /d "NDEBUG" +BSC32=bscmake.exe +BSC32_SBRS= \ + +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"CRYPTNT.bsc" + +$(OUTDIR)/CRYPTNT.bsc : $(OUTDIR) $(BSC32_SBRS) +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /NOLOGO /SUBSYSTEM:windows /DLL /MACHINE:I386 +# ADD LINK32 kernel32.lib user32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /NOLOGO /VERSION:0,99 /SUBSYSTEM:windows /DLL /PDB:none /MACHINE:I386 /OUT:"cryptnt.dll" +LINK32_FLAGS=kernel32.lib user32.lib winspool.lib comdlg32.lib advapi32.lib\ + shell32.lib /NOLOGO /VERSION:0,99 /SUBSYSTEM:windows /DLL /PDB:none\ + /MACHINE:I386 /DEF:".\CRYPTNT.DEF" /OUT:"cryptnt.dll"\ + /IMPLIB:$(OUTDIR)/"CRYPTNT.lib" +DEF_FILE=.\CRYPTNT.DEF +LINK32_OBJS= \ + $(INTDIR)/SHS.OBJ \ + $(INTDIR)/LIB_IDEA.OBJ \ + $(INTDIR)/SET_KEY.OBJ \ + $(INTDIR)/CRYPTNT.res \ + $(INTDIR)/3ECB_ENC.OBJ \ + $(INTDIR)/IDEA.OBJ \ + $(INTDIR)/CRYPT.OBJ \ + $(INTDIR)/LIB_MDC.OBJ \ + $(INTDIR)/LIB_RC4.OBJ \ + $(INTDIR)/LIB_3DES.OBJ \ + $(INTDIR)/LIB_NULL.OBJ \ + $(INTDIR)/LIB_DES.OBJ \ + $(INTDIR)/RC4.OBJ \ + $(INTDIR)/ECB_ENC.OBJ \ + $(INTDIR)/PCBC_ENC.OBJ \ + $(INTDIR)/SAFER.OBJ \ + $(INTDIR)/LIB_SAFR.OBJ + +.\cryptnt.dll : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "WinDebug" +# PROP BASE Intermediate_Dir "WinDebug" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +OUTDIR=.\WinDebug +INTDIR=.\WinDebug + +ALL : .\cryptnt.dll $(OUTDIR)/CRYPTNT.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +# ADD BASE CPP /nologo /MT /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /c +# ADD CPP /nologo /MT /W3 /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__WINDOWS__" /c +# SUBTRACT CPP /YX /Fr +CPP_PROJ=/nologo /MT /W3 /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D\ + "__WINDOWS__" /Fo$(INTDIR)/ /Fd$(OUTDIR)/"CRYPTNT.pdb" /c +CPP_OBJS=.\WinDebug/ +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo$(INTDIR)/"CRYPTNT.res" /d "_DEBUG" +BSC32=bscmake.exe +BSC32_SBRS= \ + +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"CRYPTNT.bsc" + +$(OUTDIR)/CRYPTNT.bsc : $(OUTDIR) $(BSC32_SBRS) +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /NOLOGO /SUBSYSTEM:windows /DLL /DEBUG /MACHINE:I386 +# ADD LINK32 kernel32.lib user32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /NOLOGO /VERSION:0,99 /SUBSYSTEM:windows /DLL /PDB:none /DEBUG /MACHINE:I386 /OUT:"cryptnt.dll" +LINK32_FLAGS=kernel32.lib user32.lib winspool.lib comdlg32.lib advapi32.lib\ + shell32.lib /NOLOGO /VERSION:0,99 /SUBSYSTEM:windows /DLL /PDB:none /DEBUG\ + /MACHINE:I386 /DEF:".\CRYPTNT.DEF" /OUT:"cryptnt.dll"\ + /IMPLIB:$(OUTDIR)/"CRYPTNT.lib" +DEF_FILE=.\CRYPTNT.DEF +LINK32_OBJS= \ + $(INTDIR)/SHS.OBJ \ + $(INTDIR)/LIB_IDEA.OBJ \ + $(INTDIR)/SET_KEY.OBJ \ + $(INTDIR)/CRYPTNT.res \ + $(INTDIR)/3ECB_ENC.OBJ \ + $(INTDIR)/IDEA.OBJ \ + $(INTDIR)/CRYPT.OBJ \ + $(INTDIR)/LIB_MDC.OBJ \ + $(INTDIR)/LIB_RC4.OBJ \ + $(INTDIR)/LIB_3DES.OBJ \ + $(INTDIR)/LIB_NULL.OBJ \ + $(INTDIR)/LIB_DES.OBJ \ + $(INTDIR)/RC4.OBJ \ + $(INTDIR)/ECB_ENC.OBJ \ + $(INTDIR)/PCBC_ENC.OBJ \ + $(INTDIR)/SAFER.OBJ \ + $(INTDIR)/LIB_SAFR.OBJ + +.\cryptnt.dll : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Group "Source Files" + +################################################################################ +# Begin Source File + +SOURCE=.\MDC\SHS.C +DEP_SHS_C=\ + .\CRYPT.H\ + .\MDC\SHS.H + +$(INTDIR)/SHS.OBJ : $(SOURCE) $(DEP_SHS_C) $(INTDIR) + $(CPP) $(CPP_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIB_IDEA.C +DEP_LIB_I=\ + .\CRYPT.H\ + .\IDEA\IDEA.H\ + .\TESTIDEA.H + +$(INTDIR)/LIB_IDEA.OBJ : $(SOURCE) $(DEP_LIB_I) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIBDES\SET_KEY.C +DEP_SET_K=\ + .\LIBDES\DES_LOCL.H\ + .\LIBDES\PODD.H\ + .\LIBDES\SK.H\ + .\LIBDES\DES.H + +$(INTDIR)/SET_KEY.OBJ : $(SOURCE) $(DEP_SET_K) $(INTDIR) + $(CPP) $(CPP_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\CRYPTNT.RC + +$(INTDIR)/CRYPTNT.res : $(SOURCE) $(INTDIR) + $(RSC) $(RSC_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\CRYPTNT.DEF +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIBDES\3ECB_ENC.C +DEP_3ECB_=\ + .\LIBDES\DES_LOCL.H\ + .\LIBDES\DES.H + +$(INTDIR)/3ECB_ENC.OBJ : $(SOURCE) $(DEP_3ECB_) $(INTDIR) + $(CPP) $(CPP_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\IDEA\IDEA.C +DEP_IDEA_=\ + .\CRYPT.H\ + .\IDEA\IDEA.H + +$(INTDIR)/IDEA.OBJ : $(SOURCE) $(DEP_IDEA_) $(INTDIR) + $(CPP) $(CPP_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\CRYPT.C +DEP_CRYPT=\ + .\CRYPT.H + +$(INTDIR)/CRYPT.OBJ : $(SOURCE) $(DEP_CRYPT) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIB_MDC.C +DEP_LIB_M=\ + .\CRYPT.H\ + .\MDC\SHS.H + +$(INTDIR)/LIB_MDC.OBJ : $(SOURCE) $(DEP_LIB_M) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIB_RC4.C +DEP_LIB_R=\ + .\CRYPT.H\ + .\RC4\RC4.H\ + .\TESTRC4.H + +$(INTDIR)/LIB_RC4.OBJ : $(SOURCE) $(DEP_LIB_R) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIB_3DES.C +DEP_LIB_3=\ + .\CRYPT.H\ + .\LIBDES\DES.H + +$(INTDIR)/LIB_3DES.OBJ : $(SOURCE) $(DEP_LIB_3) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIB_NULL.C +DEP_LIB_N=\ + .\CRYPT.H + +$(INTDIR)/LIB_NULL.OBJ : $(SOURCE) $(DEP_LIB_N) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIB_DES.C +DEP_LIB_D=\ + .\CRYPT.H\ + .\LIBDES\DES.H\ + .\TESTDES.H + +$(INTDIR)/LIB_DES.OBJ : $(SOURCE) $(DEP_LIB_D) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\RC4\RC4.C +DEP_RC4_C=\ + .\RC4\RC4.H + +$(INTDIR)/RC4.OBJ : $(SOURCE) $(DEP_RC4_C) $(INTDIR) + $(CPP) $(CPP_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIBDES\ECB_ENC.C +DEP_ECB_E=\ + .\LIBDES\DES_LOCL.H\ + .\LIBDES\SPR.H\ + .\LIBDES\VERSION.H\ + .\LIBDES\DES.H + +$(INTDIR)/ECB_ENC.OBJ : $(SOURCE) $(DEP_ECB_E) $(INTDIR) + $(CPP) $(CPP_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIBDES\PCBC_ENC.C +DEP_PCBC_=\ + .\LIBDES\DES_LOCL.H\ + .\LIBDES\DES.H + +$(INTDIR)/PCBC_ENC.OBJ : $(SOURCE) $(DEP_PCBC_) $(INTDIR) + $(CPP) $(CPP_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SAFER\SAFER.C +DEP_SAFER=\ + .\SAFER\SAFER.H + +$(INTDIR)/SAFER.OBJ : $(SOURCE) $(DEP_SAFER) $(INTDIR) + $(CPP) $(CPP_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIB_SAFR.C +DEP_LIB_S=\ + .\CRYPT.H\ + .\SAFER\SAFER.H\ + .\TESTSAFR.H + +$(INTDIR)/LIB_SAFR.OBJ : $(SOURCE) $(DEP_LIB_S) $(INTDIR) + +# End Source File +# End Group +# End Project +################################################################################ diff --git a/third_party/cryptlib-0.99/cryptnt.rc b/third_party/cryptlib-0.99/cryptnt.rc new file mode 100644 index 0000000..a83584f --- /dev/null +++ b/third_party/cryptlib-0.99/cryptnt.rc @@ -0,0 +1,33 @@ +; Resource file for the Windows 32-bit encryption library + +#include + +VS_VERSION_INFO VERSIONINFO +FILEVERSION 0,0,0,99 +PRODUCTVERSION 0,0,0,99 +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS_NT +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 ; US English, Windoze charset + END + + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" ; US English, Windoze charset data + BEGIN + VALUE "CompanyName", "Peter Gutmann et al.\0" + VALUE "FileDescription", "Encryption library.\0" + VALUE "FileVersion", "0.99\0" + VALUE "InternalName", "CRYPT.DLL\0" + VALUE "LegalCopyright", "Copyright \251 Peter Gutmann, Eric Young, Colin Plumb 1994, 1995.\0" + VALUE "OriginalFilename", "CRYPT.DLL\0" + VALUE "ProductName", "Encryption library.\0" + VALUE "ProductVersion", "0.99\0" + END + END +END diff --git a/third_party/cryptlib-0.99/cryptos2.def b/third_party/cryptlib-0.99/cryptos2.def new file mode 100644 index 0000000..6cecd9e --- /dev/null +++ b/third_party/cryptlib-0.99/cryptos2.def @@ -0,0 +1,24 @@ +; Definition file for Crypt DLL + +LIBRARY CRYPT +DESCRIPTION 'Encryption DLL' +EXETYPE WINDOWS 3 +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE SINGLE +HEAPSIZE 8192 +EXPORTS initLibrary + endLibrary + queryModeAvailability + queryAlgoAvailability + queryAlgoModeInformation + queryContextInformation + initCryptContext + initCryptContextEx + destroyCryptContext + loadCryptContext + loadIV + retrieveIV + encryptBuffer + decryptBuffer + +IMPORTS diff --git a/third_party/cryptlib-0.99/cryptwin.def b/third_party/cryptlib-0.99/cryptwin.def new file mode 100644 index 0000000..6cecd9e --- /dev/null +++ b/third_party/cryptlib-0.99/cryptwin.def @@ -0,0 +1,24 @@ +; Definition file for Crypt DLL + +LIBRARY CRYPT +DESCRIPTION 'Encryption DLL' +EXETYPE WINDOWS 3 +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE SINGLE +HEAPSIZE 8192 +EXPORTS initLibrary + endLibrary + queryModeAvailability + queryAlgoAvailability + queryAlgoModeInformation + queryContextInformation + initCryptContext + initCryptContextEx + destroyCryptContext + loadCryptContext + loadIV + retrieveIV + encryptBuffer + decryptBuffer + +IMPORTS diff --git a/third_party/cryptlib-0.99/cryptwin.mak b/third_party/cryptlib-0.99/cryptwin.mak new file mode 100644 index 0000000..fe61831 --- /dev/null +++ b/third_party/cryptlib-0.99/cryptwin.mak @@ -0,0 +1,255 @@ +# Microsoft Visual C++ generated build script - Do not modify + +PROJ = CRYPTWIN +DEBUG = 0 +PROGTYPE = 1 +CALLER = +ARGS = +DLLS = +D_RCDEFINES = -d_DEBUG +R_RCDEFINES = -dNDEBUG +ORIGIN = MSVC +ORIGIN_VER = 1.00 +PROJPATH = C:\WORK\CRYPT\ +USEMFC = 0 +CC = cl +CPP = cl +CXX = cl +CCREATEPCHFLAG = +CPPCREATEPCHFLAG = +CUSEPCHFLAG = +CPPUSEPCHFLAG = +FIRSTC = CRYPT.C +FIRSTCPP = +RC = rc +CFLAGS_D_WDLL = /nologo /G2 /W3 /Zi /ALw /Od /D "_DEBUG" /D "__WINDOWS__" /GD /Fd"CRYPT.PDB" +CFLAGS_R_WDLL = /nologo /G2 /W3 /ALw /O1 /D "NDEBUG" /D "__WINDOWS__" /GD +LFLAGS_D_WDLL = /NOLOGO /NOD /NOE /PACKC:61440 /ALIGN:16 /ONERROR:NOEXE /CO +LFLAGS_R_WDLL = /NOLOGO /NOD /NOE /PACKC:61440 /ALIGN:16 /ONERROR:NOEXE +LIBS_D_WDLL = oldnames libw ldllcew +LIBS_R_WDLL = oldnames libw ldllcew +RCFLAGS = /nologo +RESFLAGS = /nologo +RUNFLAGS = +DEFFILE = CRYPTWIN.DEF +OBJS_EXT = +LIBS_EXT = +!if "$(DEBUG)" == "1" +CFLAGS = $(CFLAGS_D_WDLL) +LFLAGS = $(LFLAGS_D_WDLL) +LIBS = $(LIBS_D_WDLL) +MAPFILE = nul +RCDEFINES = $(D_RCDEFINES) +!else +CFLAGS = $(CFLAGS_R_WDLL) +LFLAGS = $(LFLAGS_R_WDLL) +LIBS = $(LIBS_R_WDLL) +MAPFILE = nul +RCDEFINES = $(R_RCDEFINES) +!endif +!if [if exist MSVC.BND del MSVC.BND] +!endif +SBRS = CRYPT.SBR \ + LIB_3DES.SBR \ + LIB_IDEA.SBR \ + LIB_DES.SBR \ + LIB_MDC.SBR \ + LIB_NULL.SBR \ + LIB_RC4.SBR \ + IDEA.SBR \ + 3ECB_ENC.SBR \ + ECB_ENC.SBR \ + PCBC_ENC.SBR \ + SET_KEY.SBR \ + RC4.SBR \ + SHS.SBR \ + SAFER.SBR \ + LIB_SAFR.SBR + + +CRYPT_DEP = c:\work\crypt\crypt.h + + +LIB_3DES_DEP = c:\work\crypt\crypt.h \ + c:\work\crypt\libdes/des.h + + +LIB_IDEA_DEP = c:\work\crypt\crypt.h \ + c:\work\crypt\idea/idea.h \ + c:\work\crypt\testidea.h + + +LIB_DES_DEP = c:\work\crypt\crypt.h \ + c:\work\crypt\libdes/des.h \ + c:\work\crypt\testdes.h + + +LIB_MDC_DEP = c:\work\crypt\crypt.h \ + c:\work\crypt\mdc/shs.h + + +LIB_NULL_DEP = c:\work\crypt\crypt.h + + +LIB_RC4_DEP = c:\work\crypt\crypt.h \ + c:\work\crypt\rc4/rc4.h \ + c:\work\crypt\testrc4.h + + +CRYPTWIN_RCDEP = + +IDEA_DEP = c:\work\crypt\crypt.h \ + c:\work\crypt\idea\idea.h \ + idea/idea.h + + +3ECB_ENC_DEP = c:\work\crypt\libdes\des_locl.h \ + c:\work\crypt\libdes\des.h \ + libdes/des.h \ + libdes/des_locl.h + + +ECB_ENC_DEP = c:\work\crypt\libdes\des_locl.h \ + c:\work\crypt\libdes\des.h \ + libdes/des.h \ + c:\work\crypt\libdes\spr.h \ + c:\work\crypt\libdes\version.h \ + libdes/des_locl.h \ + libdes/spr.h \ + libdes/version.h + + +PCBC_ENC_DEP = c:\work\crypt\libdes\des_locl.h \ + c:\work\crypt\libdes\des.h \ + libdes/des.h \ + libdes/des_locl.h + + +SET_KEY_DEP = c:\work\crypt\libdes\des_locl.h \ + c:\work\crypt\libdes\des.h \ + libdes/des.h \ + c:\work\crypt\libdes\podd.h \ + c:\work\crypt\libdes\sk.h \ + libdes/des_locl.h \ + libdes/podd.h \ + libdes/sk.h + + +RC4_DEP = c:\work\crypt\rc4\rc4.h \ + rc4/rc4.h + + +SHS_DEP = c:\work\crypt\crypt.h \ + c:\work\crypt\mdc\shs.h \ + mdc/shs.h + + +SAFER_DEP = c:\work\crypt\safer\safer.h \ + safer/safer.h + + +LIB_SAFR_DEP = c:\work\crypt\crypt.h \ + c:\work\crypt\safer/safer.h \ + c:\work\crypt\testsafr.h + + +all: $(PROJ).DLL + +CRYPT.OBJ: CRYPT.C $(CRYPT_DEP) + $(CC) $(CFLAGS) $(CCREATEPCHFLAG) /c CRYPT.C + +LIB_3DES.OBJ: LIB_3DES.C $(LIB_3DES_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIB_3DES.C + +LIB_IDEA.OBJ: LIB_IDEA.C $(LIB_IDEA_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIB_IDEA.C + +LIB_DES.OBJ: LIB_DES.C $(LIB_DES_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIB_DES.C + +LIB_MDC.OBJ: LIB_MDC.C $(LIB_MDC_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIB_MDC.C + +LIB_NULL.OBJ: LIB_NULL.C $(LIB_NULL_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIB_NULL.C + +LIB_RC4.OBJ: LIB_RC4.C $(LIB_RC4_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIB_RC4.C + +CRYPTWIN.RES: CRYPTWIN.RC $(CRYPTWIN_RCDEP) + $(RC) $(RCFLAGS) $(RCDEFINES) -r CRYPTWIN.RC + +IDEA.OBJ: IDEA\IDEA.C $(IDEA_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c IDEA\IDEA.C + +3ECB_ENC.OBJ: LIBDES\3ECB_ENC.C $(3ECB_ENC_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIBDES\3ECB_ENC.C + +ECB_ENC.OBJ: LIBDES\ECB_ENC.C $(ECB_ENC_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIBDES\ECB_ENC.C + +PCBC_ENC.OBJ: LIBDES\PCBC_ENC.C $(PCBC_ENC_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIBDES\PCBC_ENC.C + +SET_KEY.OBJ: LIBDES\SET_KEY.C $(SET_KEY_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIBDES\SET_KEY.C + +RC4.OBJ: RC4\RC4.C $(RC4_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c RC4\RC4.C + +SHS.OBJ: MDC\SHS.C $(SHS_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c MDC\SHS.C + +SAFER.OBJ: SAFER\SAFER.C $(SAFER_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c SAFER\SAFER.C + +LIB_SAFR.OBJ: LIB_SAFR.C $(LIB_SAFR_DEP) + $(CC) $(CFLAGS) $(CUSEPCHFLAG) /c LIB_SAFR.C + + +$(PROJ).DLL:: CRYPTWIN.RES + +$(PROJ).DLL:: CRYPT.OBJ LIB_3DES.OBJ LIB_IDEA.OBJ LIB_DES.OBJ LIB_MDC.OBJ LIB_NULL.OBJ \ + LIB_RC4.OBJ IDEA.OBJ 3ECB_ENC.OBJ ECB_ENC.OBJ PCBC_ENC.OBJ SET_KEY.OBJ RC4.OBJ SHS.OBJ \ + SAFER.OBJ LIB_SAFR.OBJ $(OBJS_EXT) $(DEFFILE) + echo >NUL @<<$(PROJ).CRF +CRYPT.OBJ + +LIB_3DES.OBJ + +LIB_IDEA.OBJ + +LIB_DES.OBJ + +LIB_MDC.OBJ + +LIB_NULL.OBJ + +LIB_RC4.OBJ + +IDEA.OBJ + +3ECB_ENC.OBJ + +ECB_ENC.OBJ + +PCBC_ENC.OBJ + +SET_KEY.OBJ + +RC4.OBJ + +SHS.OBJ + +SAFER.OBJ + +LIB_SAFR.OBJ + +$(OBJS_EXT) +$(PROJ).DLL +$(MAPFILE) +G:\MSVC15\LIB\+ +G:\MSVC15\MFC\LIB\+ +$(LIBS) +$(DEFFILE); +<< + link $(LFLAGS) @$(PROJ).CRF + $(RC) $(RESFLAGS) CRYPTWIN.RES $@ + @copy $(PROJ).CRF MSVC.BND + implib /nowep $(PROJ).LIB $(PROJ).DLL + +$(PROJ).DLL:: CRYPTWIN.RES + if not exist MSVC.BND $(RC) $(RESFLAGS) CRYPTWIN.RES $@ + +run: $(PROJ).DLL + $(PROJ) $(RUNFLAGS) + + +$(PROJ).BSC: $(SBRS) + bscmake @<< +/o$@ $(SBRS) +<< diff --git a/third_party/cryptlib-0.99/cryptwin.rc b/third_party/cryptlib-0.99/cryptwin.rc new file mode 100644 index 0000000..56949fc --- /dev/null +++ b/third_party/cryptlib-0.99/cryptwin.rc @@ -0,0 +1,33 @@ +; Resource file for the encryption library + +#include + +VS_VERSION_INFO VERSIONINFO +FILEVERSION 0,0,0,99 +PRODUCTVERSION 0,0,0,99 +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS_DOS_WINDOWS16 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 ; US English, Windoze charset + END + + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" ; US English, Windoze charset data + BEGIN + VALUE "CompanyName", "Peter Gutmann et al.\0" + VALUE "FileDescription", "Encryption library.\0" + VALUE "FileVersion", "0.99\0" + VALUE "InternalName", "CRYPT.DLL\0" + VALUE "LegalCopyright", "Copyright \251 Peter Gutmann, Eric Young, Colin Plumb 1994, 1995.\0" + VALUE "OriginalFilename", "CRYPT.DLL\0" + VALUE "ProductName", "Encryption library.\0" + VALUE "ProductVersion", "0.99\0" + END + END +END diff --git a/third_party/cryptlib-0.99/docs.txt b/third_party/cryptlib-0.99/docs.txt new file mode 100644 index 0000000..7305312 --- /dev/null +++ b/third_party/cryptlib-0.99/docs.txt @@ -0,0 +1,613 @@ +After much procrastinating I'm finally ready to release the initial version of +my encryption library. I wrote this in response to random requests I keep +seeing in various newsgroups for encryption libraries, usually with no +responses. This library provides a (hopefully) universal interface to all +kinds of conventional-key encryption algorithms in an easy-to-use manner. The +library is divided into two parts: + + 1. Routines to query the library capabilities. + 2. Routines to perform the en/decryption. + +The library currently provides the following encryption algorithms and modes: + + MDC/SHS CFB + DES ECB, CBC, CFB, OFB, PCBC + 3DES ECB, CBC, CFB, OFB + IDEA ECB, CBC, CFB, OFB + RC4 + SAFER ECB, CBC, CFB, OFB + SAFER-SK ECB, CBC, CFB, OFB + +Notes: + +1. The Visual Basic interface hasn't been tested much. If someone could do + a Delphi interface and a VBX or OCX version that'd be nice. + +2. A proper configure script with everything would be nice for Unix users. + Anyone want to create one of these? + +3. Optimised asm implementations of some of the routines would be useful. + There are 80x86 and 68K asm routines included for IDEA and RC4, but I + haven't had time to tie them into the code yet. I have 386+ asm code for + SHA, but need to tie that in as well. Volunteers? + + +Requirements for a Standard Encryption Library +---------------------------------------------- + +- It should be idiot-proof. + + It's quite difficult to implement insecure encryption using this code without + actually trying. + +- It should provide extensive error checking. + + Each parameter and function call is checked for errors before any actions are + performed, with error reporting down to the level of individual parameters. + +- It should be portable. + + The library is written entirely in ANSI C, with hooks for certain OS-specific + oddities such as Windows/OS/2 dynamic link libraries. The only external + routines used are ones from and one call from . + +- It should be extendable. + + The library provides the capability to add encryption capabilities at runtime + (currently only partially implemented, since the interface is somewhat messy + - you need to pass in about 15 parameters to do it). + +- It should be free of silly restrictions. + + This software is distributed as copyrighted freeware, with copyrights on + individual encryption modules being held by the contributing authors. You + are free to use the code in any way you want, with the following + restrictions: + + If you make any changes to the code, you should send a copy of the changes + to the author or authors to allow them to integrate the changes into the + code. This is to allow a central consistent version to be maintained. + + If you use the library as part of a product, you should offer a copy to the + author or authors of the library routines you are using. This is to let + the authors know that their work is being usefully applied. + + Any commercial software you create with this code may not be merely a set + or subset of the encryption libraries, with or without minor added + functionality. This is to stop people adding their own wrappers and + selling it as "their" encryption product. + + These terms are pretty much identical the the library GPL, which seem to be + about the least restrictive usage terms around apart from outright public + domain software. + +- It should be buzzword-complete. + + The library is written in C, but is basically laid out as a C++ class + library. It can work as a static library, a shared library, or a dynamic + link library. It'll even work with things like Visual Basic. + + +Library Basics +-------------- + +Like the standard C file I/O libraries which work with FILE objects, this +library works with an "encryption context" of type CRYPT_INFO. To encrypt +data, you create an encryption context, load a user key into it, en/decrypt +data, and destroy it when you've finished. This concept lends itself to +implementation either as a C++ class or as C routines. Throughout this +document all examples are given in C, translation to C++ is a simple step. + +The overall library structure is as follows: + + Library core Plug-in + modules + +---------------+------------+ + | | MDC/SHS | + | +------------+ + | | DES | + | +------------+ + / \ | Crypt | Triple DES | + User / ---- \ | +------------+ + Programs \ ---- / | Library | IDEA | + \ / | +------------+ + | API | RC4 | + | +------------+ + | | Safer | + | +------------+ + | | others | + +---------------+------------+ + +The library API serves as an interface to a range of plug-in encryption modules +which allow encryption algorithms to be added in a fairly transparent manner. +The standardised API allows any of the algorithms and modes supported by the +library to be used with a minimum of coding effort. As such the main function +of the library is to provide a standard, portable, easy-to-use interface +between the underlying encryption routines and the user software. + + +Portability +----------- + +All data made accessible through the library API is in big-endian format. The +library automatically takes care of endianness conversion to the form used by +the local system in a manner invisible to the end user. + +All code is plain ANSI C, with no machine or OS-specific functions or calls +being used. + + +Creating/Destroying Encryption Contexts +--------------------------------------- + +When you create an encryption context, you must specify the encryption +algorithm and mode you want to use for that context. The encryption algorithms +and modes are given in the crypt.h file, and are updated along with the library +itself. For example, to create and destroy an encryption context for DES in +CBC mode, you would use the following code: + + CRYPT_INFO cryptInfo; + + initCryptContext( &cryptInfo, CRYPT_ALGO_DES, CRYPT_MODE_CBC ); + + /* Perform en/decryption */ + + endCryptContext( &cryptInfo ); + +The initCryptContext() and endCryptContext() functions take care of issues like +initialization, memory management, and erasure of data after use. + + +Loading Keys into Encryption Contexts +------------------------------------- + +Once an encryption context has been created, you need to load a key into it. +This is done with the loadCryptContext() function. For example to load the key +"Secret key" into the previously-created encryption context you would use: + + loadCryptContext( &cryptInfo, "Secret key", 10 ); + +Some hardware modules which enforce red/black seperation will not allow +plaintext keys to pass across the library interface. In this case the key +parameter passed to loadCryptContext() will be a key selector or key encryption +key to be passed to the underlying hardware. For example to pass a key +selector to a key stored inside a DES hardware module you would use: + + loadCryptContext( &cryptInfo, &keySelector, sizeof( keySelector ) ); + +You can also load an IV into the context, although for encryption you would +usually leave this to the library to perform automatically. To load an IV you +would use: + + loadIV( &cryptInfo, iv, ivSize ); + +To retrieve an IV which has been generated by the library you would use: + + retrieveIV( &cryptInfo, iv ); + +The loadCryptContext(), loadIV(), and retrieveIV() functions take care of +issues like initialization, memory management, endianness conversion, and key +setup. + +If you need to reserver space for keys and IV's, you can use the +CRYPT_MAX_KEYSIZE and CRYPT_MAX_IVSIZE defines from crypt.h to determine the +mount of memory you need. No key or IV used by the library will ever need more +storage than the settings given in these defines. + + +Encrypting/Decrypting Data +-------------------------- + +Now that the encryption context and (if necessary) IV are set up, you're ready +to encrypt or decrypt data. To encrypt or decrypt a block of data you use: + + encryptBuffer( &cryptInfo, buffer, length ); + +and: + + decryptBuffer( &cryptInfo, buffer, length ); + +If a block encryption mode is being used, these functions will recognise a call +with length == 0 as a courtesy call to indicate that this is the last data +block and will take whatever special action is necessary for this case. + + +Extended Initialization +----------------------- + +The initCryptContext() has a companion function initCryptContextEx() which may +be used to perform an extended, algorithm-specific initialisation. The second +parameter passed to the function is an algorithm-dependant structure used to +specify extra information to be used in the initalisation. Not all algorithms +will support extended initialisation parameters. If they are supported, the +structures have the name CRYPT_INFO_, and are laid out as +follows: + +Structure CRYPT_INFO_MDCSHS: + + /* The number of iterations used during the key setup process triggered + by a loadCryptContext() call. Using a high value (500 or more) will + greatly slow down password-guessing attacks by making the key setup + process painfully slow. Values in the range of 50-100 are recommended for + most systems */ + int keySetupIterations; + +Structure CRYPT_INFO_SAFER: + + /* The number of rounds of encryption. The default settings are 6 rounds for + SAFER-K64, 8 rounds for SAFER-SK64, and 10 rounds for SAFER-K128 and + SAFER-SK128 */ + int rounds; + + /* Whether to use SAFER or SAFER-SK. The default is to use the original + algorithm SAFER. SAFER-SK is a version which improves the key schedule to + eliminate some possible weaknesses when SAFER is used as a keyed hash + function */ + BOOLEAN useSaferSK; + + +Error Checking +-------------- + +When the library is initialised, each of the built-in encryption algorithms +goes through a self-test procedure which checks the implementation using +standard test vectors and methods given with the algorithm specification +(typically FIPS publications, ANSI standards, or standard reference +implementations). This self-test is used to verify that each encryption +algorithm is performing as required. + +Each function in the library performs extensive error checking (although +monitoring of error codes has been left out in the following code samples for +readability). The file TEST.C, included with the crypt library, includes +better error handling than the short examples below. + +For functions which complete with no error, the library will return CRYPT_OK. +For functions which complete with some form of error internal to the library +itself, the library will return CRYPT_ERROR (this situation should never occur +and should be reported to the library authors). + +If the encryption code or hardware fails an internal self-test, the library +will return CRYPT_SELFTEST if an attempt is made to use the encryption module +which failed the self-test. + +If there is a problem with a parameter passed to a library function, the +library will return one of CRYPT_BADPARM1 ... CRYPT_BADPARM15 depending on the +parameter in error, or simply CRYPT_BADPARM if it cannot resolve the exact +parameter error type. + +General resource and programming errors are flagged by the return values +CRYPT_NOMEM for a lack of memory, CRYPT_NOTINITED if you try to use an +encryption context hasn't been initialised yet or which has been destroyed, +CRYPT_INITED when you try to re-initialise an encryption context or re-load an +encryption key, CRYPT_NOALGO or CRYPT_NOMODE if the requested encryption +algorithm or mode is unavailable, CRYPT_NOKEY if the encryption key hasn't been +loaded into an encryption context, and CRYPT_NOIV if the IV hasn't been loaded +into an encryption context. + +The macros isStatusError() and isStatusOK() can be used to determine whether a +return value denotes an error condition, for example: + + int status; + + status = initCryptContext( &cryptInfo, CRYPT_ALGO_IDEA, CRYPT_MODE_CFB ); + if( isStatusError( status ) ) + /* Perform error processing */ + + +Examples +-------- + +The following examples have had error checking removed for readability. See +the test code in TEST.C for an example with full error checking. + +To encrypt a buffer using DES in CFB mode with the password 0x12345678ABCDEF: + + CRYPT_INFO cryptInfo; + BYTE key[] = { 0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD, 0xEF }; + + /* Load the key, encrypt the buffer (the IV is automatically generated + if we don't specify one, it can be obtained with retrieveIV()), and + destroy the encryption context */ + initCryptContext( &cryptInfo, CRYPT_ALGO_DES, CRYPT_MODE_CFB ); + loadCryptContext( &cryptInfo, key, sizeof( key ) ); + encryptBuffer( &cryptInfo, buffer, length ); + destroyCryptContext( &cryptInfo ); + +To hash an arbitrary-size passphrase down to the one used by a particular +cryptosystem (in this case triple DES) using MDC/SHS: + + CRYPT_QUERY_INFO cryptQueryInfo; + CRYPT_INFO cryptInfo; + BYTE key[ 100 ]; + int keySize, ivSize; + + /* Find out how long we can make the key */ + queryAlgoModeInformation( CRYPT_ALGO_3DES, CRYPT_MODE_CBC, + &cryptQueryInfo ); + keySize = cryptQueryInfo->maxKeySize; /* Use all we can */ + ivSize = cryptQueryInfo->ivSize; + + /* Encrypt a null data block using a null IV with the passphrase as the + key. This works vaguely like the Unix password encryption except + that we don't have a salt (which would be the IV) */ + memset( key, 0, keySize ); + initCryptContext( &cryptInfo, CRYPT_ALGO_MDCSHS, CRYPT_MODE_CFB ); + loadCryptContext( &cryptInfo, passphrase, strlen( passphrase ) ); + loadIV( &cryptInfo, key, ivSize ); + encryptBuffer( &cryptInfo, key, keySize ); + destroyCryptContext( &cryptInfo ); + +To encrypt a file using triple DES in CBC mode with the key generated in the +previous example: + + BOOLEAN firstTime = TRUE; + + /* Load the previously-generated key */ + initCryptContext( &cryptInfo, CRYPT_ALGO_3DES, CRYPT_MODE_CBC ); + loadCryptContext( &cryptInfo, key, keySize ); + + /* Copy the data across, encrypting as we go */ + while( ( length = fread( buffer, 1, BUFSIZE, inFile ) ) != 0 ) + { + /* Encrypt the data in the buffer */ + encryptBuffer( &cryptInfo, buffer, length ); + + /* If it's the first block, retrieve the IV and prepend it to the + output data. Note the since we've let the library generate the + IV for us automatically, we can't retrieve it until after the first + encryptBuffer() call */ + if( firstTime ) + { + CRYPT_QUERY_INFO cryptQueryInfo; + BYTE iv[ CRYPT_MAX_IVSIZE ]; + int ivSize; + + /* Find out how long the IV we're using is */ + queryContextInformation( &cryptInfo, &cryptQueryInfo ); + ivSize = cryptQueryInfo->ivSize; + + /* Retrieve the IV and write it to the output file */ + retrieveIV( &cryptInfo, iv ); + fwrite( iv, 1, ivSize, outFile ); + + firstTime = FALSE; + } + + /* Write the encrypted data to the output file */ + fwrite( buffer, 1, length, outFile ); + } + + /* Since CBC is a block cipher, we perform a courtesy close call to let + the encryption routines handle the last block */ + encryptBuffer( &cryptInfo, buffer, 0 ); + + destroyCryptContext( &cryptInfo ); + +To decrypt the previously encrypted file with the key generated in the previous +example: + + CRYPT_QUERY_INFO cryptQueryInfo; + BYTE iv[ CRYPT_MAX_IVSIZE ]; + int ivSize; + + /* Load the previously-generated key */ + initCryptContext( &cryptInfo, CRYPT_ALGO_3DES, CRYPT_MODE_CBC ); + loadCryptContext( &cryptInfo, key, keySize ); + + /* Find out how long the IV we're using is */ + queryContextInformation( &cryptInfo, &cryptQueryInfo ); + ivSize = cryptQueryInfo->ivSize; + + /* Read the IV from the input file and load it into the encryption + context */ + fread( iv, 1, ivSize, inFile ); + loadIV( &cryptInfo, iv, ivSize ); + + /* Copy the data across, decrypting as we go */ + while( ( length = fread( buffer, 1, BUFSIZE, inFile ) ) != 0 ) + { + /* Encrypt the data in the buffer */ + decryptBuffer( &cryptInfo, buffer, length ); + + /* Write the decrypted data to the output file */ + fwrite( buffer, 1, length, outFile ); + } + + /* Since CBC is a block cipher, we perform a courtesy close call to let + the encryption routines handle the last block */ + decryptBuffer( &cryptInfo, buffer, 0 ); + + destroyCryptContext( &cryptInfo ); + +A longer usage example including proper error checking and with various other +test routines can be found in the file test.c included with the code. + + +Querying the Encryption Library Capabilities +-------------------------------------------- + +The previous examples showed the use of the queryAlgoModeInformation() and +queryContextInformation() calls to retrieve information about the +characteristics of a particular algorithm as implemented by the encryption +library. There are four such calls in total, of which two query the existence +of an implementation of an algorithm or algorithm/mode combination, and two +return information about the implementation. + +The library can be interrogated about the existence of a particular encryption +algorithm or algorithm and encryption mode combination with: + + status = queryAlgoAvailability( algorithm ); + +or: + + status = queryModeAvailability( algorithm, mode ); + +In addition to requesting information on the availability of an encryption +algorithm and mode, you can request extra information to be returned in a +CRYPT_QUERY_INFO structure with: + + status = queryAlgoModeInformation( algorithm, mode, &cryptQueryInfo ); + +or + + status = queryContextInformation( &cryptInfo, &cryptQueryInfo ); + +with the former being used to request information on a given algorithm/mode +combination and the latter being used to request information about the +encryption context being used. + +The CRYPT_QUERY_INFO structure contains the following fields: + + /* The encryption algorithm, encryption mode, and general algorithm name + as an ASCII string */ + CRYPT_ALGO cryptAlgo; + CRYPT_MODE cryptMode; + char *algoName; + + /* The algorithm block size in bytes, the minimum, recommended, and + maximum key size in bytes, and the minimum, recommended, and maximum + IV size in bytes */ + int blockSize; + int minKeySize; + int keySize; + int maxKeySize; + int minIVsize; + int ivSize; + int maxIVsize; + + /* The algorithm speed relative to a block copy operation. This value + ranges from 1 ... CRYPT_MAX_SPEED, or CRYPT_ERROR if no speed rating is + available */ + int speed; + + +Algorithm-Specific Notes +------------------------ + +MDCSHS: + + None + +DES: + + loadCryptContext() will return a bad parameter code if the DES key parity is + wrong or if the key is a weak key (CRYPT_BADPARM2 in this case). + + encryptBuffer() and decryptBuffer() will return a bad parameter code if the + encryption mode is ECB, CBC, or PCBC and the encrypted data length is not a + multiple of the block size (CRYPT_BADPARM3 in this case). + +Triple DES: + + loadCryptContext() will return a bad parameter code if the DES key parity is + wrong or if the key is a weak key (CRYPT_BADPARM2 in this case). + + encryptBuffer() and decryptBuffer() will return a bad parameter code if the + encryption mode is ECB or CBC and the encrypted data length is not a multiple + of the block size (CRYPT_BADPARM3 in this case). + +IDEA: + + encryptBuffer() and decryptBuffer() will return a bad parameter code if the + encryption mode is ECB or CBC and the encrypted data length is not a multiple + of the block size (CRYPT_BADPARM3 in this case). + + The IDEA algorithm is patented by Ascom Systec AG, CH-5506 Maegenwil, + Switzerland, ph. +41 64 56 59 45, email idea@ascom.ch, and cannot be used + commercially without a license. As of June 1995, the licensing terms were + 120 SFr (about US$90) per user for 1-10 users, 80 Sfr (about US$60) per user + for 11-20 users, and 60 Sfr (about US$46) per user for 21-100 users. + +RC4: + + None + +SAFER: +SAFER-SK: + + encryptBuffer() and decryptBuffer() will return a bad parameter code if the + encryption mode is ECB or CBC and the encrypted data length is not a multiple + of the block size (CRYPT_BADPARM3 in this case). + + +Plug-In Module Implementation +----------------------------- + +These notes are rather brief since there is a lot of ground to cover, and the +easiest way to see what is required is to look at the crypt.c code and the way +it interfaces to the lib_XXX.c code, which may be regarded as standard +implementations of a plug-in module (the triple DES and IDEA modules are +probably the best examples). Basically, implementors must provide the +following services in their plug-in modules: + +int selfTestFunction( void ); + + Perform a self-test on the encryption hardware/software module. This + function is called once before any other function is called. + +int initFunction( CRYPT_INFO *cryptInfo ); + + Initialise the appropriate private CRYPT_INFO fields. + +int initExFunction( CRYPT_INFO *cryptInfo, void *cryptInfoEx ); + + Initialiase the appropriate private CRYPT_INFO fields based on the extended + information given in the second parameter. + +int endFunction( CRYPT_INFO *cryptInfo ); + + Clear the appropriate private CRYPT_INFO fields. + +int initKeyFunction( CRYPT_INFO *cryptInfo ); + + Initialise the internal key based on the user key. Typically this might + perform one or more of the following: + + Hash the user key down to the size of the key used by the algorithm + + Perform some type of key schedule operation + + Perform endianness conversion for the current operating environment + + Load the key into external crypto hardware. + + Perform a key selection in external hardware based on the specified key + selector. + + For algorithms with asymmetric internal keys, both an encryption and a + decryption key will have to be generated, as a crypt context may be used for + encryption or decryption. + +int initIVFunction( CRYPT_INFO *cryptInfo ); + + Initialise the IV. Typically this might perform one or more of the + following: + + Perform endianness conversion for the current operating environment + + Load the IV into external crypto hardware. + +int encryptFunction( CRYPT_INFO *cryptInfo, void *buffer, int length ); +int decryptFunction( CRYPT_INFO *cryptInfo, void *buffer, int length ); + + Encrypt/decrypt a block of data based on the algorithm and keying information + in CRYPT_INFO. Some algorithms may require special handling for the last + block (eg block truncation in CBC) so both routines should recognise a call + with length = 0 to indicate the end of the encrypted data block. + + +Acknowledgements +---------------- + +The DES and 3DES encryption code was contributed by Eric Young + and is part of his libdes package. The primary ftp +site for the full libdes is +ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/libdes-x.xx.tar.gz. libdes is now also +shipped with SSLeay. The primary site for this is +ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/SSLeay-x.xx.tar.gz. + +The IDEA code was contributed by Colin Plumb. + +The SAFER code was written by Richard De Moliner of +the Signal and Information Processing Laboratory, Swiss Federal Institute of +Technology. diff --git a/third_party/cryptlib-0.99/idea/idea.c b/third_party/cryptlib-0.99/idea/idea.c new file mode 100644 index 0000000..7efcda0 --- /dev/null +++ b/third_party/cryptlib-0.99/idea/idea.c @@ -0,0 +1,410 @@ +/* + * idea.c - C source code for IDEA block cipher. + * IDEA (International Data Encryption Algorithm), formerly known as + * IPES (Improved Proposed Encryption Standard). + * Algorithm developed by Xuejia Lai and James L. Massey, of ETH Zurich. + * This implementation modified and derived from original C code + * developed by Xuejia Lai. + * Zero-based indexing added, names changed from IPES to IDEA. + * CFB functions added. Random number routines added. + * + * Extensively optimized and restructured by Colin Plumb. + * + * There are two adjustments that can be made to this code to + * speed it up. Defaults may be used for PCs. Only the -DIDEA32 + * pays off significantly if selectively set or not set. + * Experiment to see what works best for your machine. + * + * Multiplication: default is inline, -DAVOID_JUMPS uses a + * different version that does not do any conditional + * jumps (a few percent worse on a SPARC), while + * -DSMALL_CACHE takes it out of line to stay + * within a small on-chip code cache. + * Variables: normally, 16-bit variables are used, but some + * machines (notably RISCs) do not have 16-bit registers, + * so they do a great deal of masking. -DIDEA32 uses "int" + * register variables and masks explicitly only where + * necessary. On a SPARC, for example, this boosts + * performace by 30%. + * + * The IDEA(tm) block cipher is covered by patents held by ETH and a + * Swiss company called Ascom-Tech AG. The Swiss patent number is + * PCT/CH91/00117, the European patent number is EP 0 482 154 B1, and + * the U.S. patent number is US005214703. IDEA(tm) is a trademark of + * Ascom-Tech AG. There is no license fee required for noncommercial + * use. Commercial users may obtain licensing details from Dieter + * Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502 Solothurn, + * Switzerland, Tel +41 65 242885, Fax +41 65 235761. + * + * The IDEA block cipher uses a 64-bit block size, and a 128-bit key + * size. It breaks the 64-bit cipher block into four 16-bit words + * because all of the primitive inner operations are done with 16-bit + * arithmetic. It likewise breaks the 128-bit cipher key into eight + * 16-bit words. + * + * For further information on the IDEA cipher, see the book: + * Xuejia Lai, "On the Design and Security of Block Ciphers", + * ETH Series on Information Processing (ed. J.L. Massey) Vol 1, + * Hartung-Gorre Verlag, Konstanz, Switzerland, 1992. ISBN + * 3-89191-573-X. + * + * This code runs on arrays of bytes by taking pairs in big-endian + * order to make the 16-bit words that IDEA uses internally. This + * produces the same result regardless of the byte order of the + * native CPU. + */ + +#include +#ifdef _MSC_VER + #include "../crypt.h" + #include "idea.h" +#else + #include "crypt.h" + #include "idea/idea.h" +#endif /* _MSC_VER */ + +#ifdef BIG_ENDIAN /* This code uses slightly different names */ + #define HIGHFIRST +#endif /* BIG_ENDIAN */ + +#ifdef IDEA32 /* Use >16-bit temporaries */ +#define low16(x) ((x) & 0xFFFF) +typedef unsigned int uint16; /* at LEAST 16 bits, maybe more */ +#else +#define low16(x) (x) /* this is only ever applied to uint16's */ +typedef word16 uint16; +#endif + +#ifdef _GNUC_ +/* __const__ simply means there are no side effects for this function, + * which is useful info for the gcc optimizer + */ +#define CONST __const__ +#else +#define CONST +#endif + +/* + * Multiplication, modulo (2**16)+1 + * Note that this code is structured on the assumption that + * untaken branches are cheaper than taken branches, and the + * compiler doesn't schedule branches. + */ +#ifdef SMALL_CACHE +CONST static uint16 +mul(register uint16 a, register uint16 b) +{ + register word32 p; + + p = (word32)a * b; + if (p) { + b = low16(p); + a = p>>16; + return (b - a) + (b < a); + } else if (a) { + return 1-b; + } else { + return 1-a; + } +} /* mul */ +#endif /* SMALL_CACHE */ + +/* + * Compute the multiplicative inverse of x, modulo 65537, using Euclid's + * algorithm. It is unrolled twice to avoid swapping the registers each + * iteration, and some subtracts of t have been changed to adds. + */ +CONST static uint16 +mulInv(uint16 x) +{ + uint16 t0, t1; + uint16 q, y; + + if (x <= 1) + return x; /* 0 and 1 are self-inverse */ + t1 = 0x10001L / x; /* Since x >= 2, this fits into 16 bits */ + y = 0x10001L % x; + if (y == 1) + return ( uint16 ) low16(1-t1); + t0 = 1; + do { + q = x / y; + x = x % y; + t0 += q * t1; + if (x == 1) + return t0; + q = y / x; + y = y % x; + t1 += q * t0; + } while (y != 1); + return ( uint16 ) low16(1-t1); +} /* mukInv */ + +/* + * Expand a 128-bit user key to a working encryption key EK + */ +void +ideaExpandKey(byte const *userkey, word16 *EK) +{ + int i,j; + + for (j=0; j<8; j++) { + EK[j] = (userkey[0]<<8) + userkey[1]; + userkey += 2; + } + for (i=0; j < IDEAKEYLEN; j++) { + i++; + EK[i+7] = (EK[i & 7] << 9) | (EK[i+1 & 7] >> 7); + EK += i & 8; + i &= 7; + } +} /* ideaExpandKey */ + +/* + * Compute IDEA decryption key DK from an expanded IDEA encryption key EK + * Note that the input and output may be the same. Thus, the key is + * inverted into an internal buffer, and then copied to the output. + */ +void +#ifdef _DCC +ideaInvertKey(word16 *EK, word16 DK[IDEAKEYLEN]) +#else +ideaInvertKey(word16 const *EK, word16 DK[IDEAKEYLEN]) +#endif +{ + int i; + uint16 t1, t2, t3; + word16 temp[IDEAKEYLEN]; + word16 *p = temp + IDEAKEYLEN; + + t1 = mulInv(*EK++); + t2 = - ( int ) *EK++; + t3 = - ( int ) *EK++; + *--p = mulInv(*EK++); + *--p = t3; + *--p = t2; + *--p = t1; + + for (i = 0; i < IDEAROUNDS-1; i++) { + t1 = *EK++; + *--p = *EK++; + *--p = t1; + + t1 = mulInv(*EK++); + t2 = - ( int ) *EK++; + t3 = - ( int ) *EK++; + *--p = mulInv(*EK++); + *--p = t2; + *--p = t3; + *--p = t1; + } + t1 = *EK++; + *--p = *EK++; + *--p = t1; + + t1 = mulInv(*EK++); + t2 = - ( int ) *EK++; + t3 = - ( int ) *EK++; + *--p = mulInv(*EK++); + *--p = t3; + *--p = t2; + *--p = t1; +/* Copy and destroy temp copy */ + memcpy(DK, temp, sizeof(temp)); + burn(temp); +} /* ideaInvertKey */ + +/* + * MUL(x,y) computes x = x*y, modulo 0x10001. Requires two temps, + * t16 and t32. x is modified, and must me a side-effect-free lvalue. + * y may be anything, but unlike x, must be strictly 16 bits even if + * low16() is #defined. + * All of these are equivalent - see which is faster on your machine + */ +#ifdef SMALL_CACHE +#define MUL(x,y) (x = mul(low16(x),y)) +#else /* !SMALL_CACHE */ +#ifdef AVOID_JUMPS +#define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1), \ + t32 = (word32)x*t16 + x + t16 + 1, x = low16(t32), \ + t16 = t32>>16, x = (x-t16) + (x>16, \ + x = (x-t16)+(x>8) | (x1<<8); + x2 = (x2>>8) | (x2<<8); + x3 = (x3>>8) | (x3<<8); + x4 = (x4>>8) | (x4<<8); +#endif + do { + MUL(x1,*key++); + x2 += *key++; + x3 += *key++; + MUL(x4, *key++); + + s3 = x3; + x3 ^= x1; + MUL(x3, *key++); + s2 = x2; + x2 ^= x4; + x2 += x3; + MUL(x2, *key++); + x3 += x2; + + x1 ^= x2; x4 ^= x3; + + x2 ^= s3; x3 ^= s2; + } while (--r); + MUL(x1, *key++); + x3 += *key++; + x2 += *key++; + MUL(x4, *key); + + out = (word16 *)outbuf; +#ifdef HIGHFIRST + *out++ = x1; + *out++ = x3; + *out++ = x2; + *out = x4; +#else /* !HIGHFIRST */ + x1 = low16(x1); + x2 = low16(x2); + x3 = low16(x3); + x4 = low16(x4); + *out++ = (x1>>8) | (x1<<8); + *out++ = (x3>>8) | (x3<<8); + *out++ = (x2>>8) | (x2<<8); + *out = (x4>>8) | (x4<<8); +#endif +} /* ideaCipher */ + +/*-------------------------------------------------------------*/ + +#ifdef TEST + +#include +#include +/* + * This is the number of Kbytes of test data to encrypt. + * It defaults to 1 MByte. + */ +#ifndef BLOCKS +#ifndef KBYTES +#define KBYTES 1024 +#endif +#define BLOCKS (64*KBYTES) +#endif + +int +main(void) +{ /* Test driver for IDEA cipher */ + int i, j, k; + byte userkey[16]; + word16 EK[IDEAKEYLEN], DK[IDEAKEYLEN]; + byte XX[8], YY[8], ZZ[8]; + clock_t start, end; + long l; + + /* Make a sample user key for testing... */ + for(i=0; i<16; i++) + userkey[i] = i+1; + + /* Compute encryption subkeys from user key... */ + ideaExpandKey(userkey, EK); + printf("\nEncryption key subblocks: "); + for (j=0; j>16) +; if( p<0 ) p= p + 0x00010001 ; +; } +; return (unsigned)(p & 0xffff) ; +;} +; +; +;Note the method of reducing a 32 bit word modulo 2^16-1. We +;subtract the high word from the low word, and add the modulus +;back if the result is less than 0. [Lai] contains a proof that +;this works, and you can convince yourself fairly easily. +; +;To speed up this routine, we note that the tests for a=0 and b=0 +;will rarely be false. With the possible exception of the first 2 +;of the 34 multiplications, 0 should be no more likely than any of +;the other 65535 numbers. Note that if (and only if) either a or +;b is 0 then q will also be 0, and we can check for this in one +;instruction if our processor sets a zero flag for multiplication +;(as the 68000 does but 80x86 does not). +; +;Fortunately p will also be zero after the subtraction if and only +;if either a or b is 0. Proof: r will be zero when the high order +;word of q equals the low order word, and that happens when q is +;divisible by 00010001 hex. Since 00010001h = 2^16+1 is prime, +;this happens if either a or b is a multiple of 2^16+1, and 0 is +;the only such multiple which will fit in a 16 bit word. +; +;The speed-up strategy is to proceed under the assumption that a +;and b are not 0, check to be sure in one instruction, and +;recompute if the assumption was wrong. Here's some 8086 +;assembler code: +; +; mov ax, [a] +; mul [b] ; ax is implied. q is now in DX AX +; sub ax, dx ; mod 2^16+1 +; jnz not0 ; Jump if neither op was 0. Usually taken. +; +; mov ax, 1 ; recompute result knowing one op is 0. +; sub ax, [a] +; sub ax, [b] +; jmp out ; Just jump over adding the carry. +;not0: +; adc ax, 0 ; If r<0 add 1, otherwise do nothing. +;out: ; Result is now in ax +; +; +;Note that when r<0 we add 1 instead of 2^16+1 since the 2^16 part +;overflows out of the result. The "adc ax, 0" does all the work +;of checking for a negative result and adding the modulus if +;needed. +; +;The multiplication takes 9 instructions, 4 of which are rarely +;executed. I believe similar tricks are possible on many +;processors. The one drawback to the check-after-multiply tactic +;is that we can't let the multiply overwrite the only copy of an +;operand. +; +;Note that most software implementations of IDEA will run at +;slightly different speeds when 0's come up in the multiply +;routine. The reference implementation is faster on 0, this one +;is faster on non-zero. This may be a problem for some real-time +;stuff, and also suggests an attack based on timing. +; +;Finally, below is an implementation of the complete encryption +;function in 8086 assembler, to replace the cipher_idea() function +;in PGP. It takes the same parameters as the function from PGP, +;and uses the c language calling conventions. I tested it using +;the debug features of the idea.c file in PGP. You will need to +;add segment/assume directives. This version uses no global data +;and should be reentrant. +; +;The handling of zero multipliers is outside the inner loop so +;that a short conditional jump can loop back to the beginning. +;Forward conditional jumps are usually not taken and backward +;jumps are usually taken, which is consistent with 586 branch +;prediction (or so I've heard). Stalls where the output of one +;instruction is needed for the next seem unavoidable. +; +;Last I heard, IDEA was patent pending. My code is up for grabs, +;although I would get a kick out being credited if you use it. +;On the other hand Colin's code is already tested and ready +;to assemble and link with PGP. +; +;--Bryan +; +;____________________CODE STARTS BELOW THIS LINE_________ + +; Called as: asmcrypt( inbuff, outbuff, zkey ) just like PGP + +PROC _asmcrypt + + ; establish parameter and local space on stack + ; follow c language calling conventions + + ARG inblock:Word, outblock:Word, zkey:Word + LOCAL sx1:Word,sx4:Word,skk:Word,done8:Word =stacksize + + push bp + mov bp, sp + sub sp, stacksize + + ; push ax ; My compiler assumes these are not saved. + ; push bx + ; push cx + ; push dx + + push si + push di + +; Put the 16 bit sub-blocks in registers and/or local variables + mov si, [inblock] + mov ax, [si] + mov [sx1], ax ; x1 is in ax and sx1 + mov di, [si+2] ; x2 is in di + mov bx, [si+4] ; x3 is in bx + mov dx, [si+6] + mov [sx4], dx ; x4 is in sx4 + + mov si, [zkey] ; si points to next subkey + mov [done8], si + add [done8], 96 ; we will be finished with 8 rounds + ; when si=done8 + +@@loop: ; 8 rounds of this + add di, [si+2] ; x2+=zkey[2] is in di + add bx, [si+4] ; x3+=zkey[4] is in bx + + mul [Word si] ;x1 *= zkey[0] + sub ax, dx + jz @@x1 ; if 0, use special case multiply + adc ax, 0 +@@x1out: + mov [sx1], ax ; x1 is in ax and sx1 + + xor ax, bx ; ax= x1^x3 + mul [Word si+8] ; compute kk + sub ax, dx ; if 0, use special case multiply + jz @@kk + adc ax, 0 +@@kkout: + mov cx, ax ; kk is in cx + + mov ax, [sx4] ; x4 *= zkey[6] + mul [Word si+6] + sub ax, dx + jz @@x4 ; if 0, use special case multiply + adc ax, 0 +@@x4out: + mov [sx4], ax ; x4 is in sx4 and ax + + xor ax, di ; x4^x2 + add ax, cx ; kk+(x2^x4) + mul [Word si+10] ; compute t1 + sub ax, dx + jz @@t1 ; if 0, use special case multiply + adc ax, 0 +@@t1out: ; t1 is in ax + + add cx, ax ; t2 is in cx kk+t1 + + xor [sx4], cx ; x4 in sx4 + xor di, cx ; new x3 in di + xor bx, ax ; new x2 in bx + xchg bx, di ; x2 in di, x3 in bx + xor ax, [sx1] ; x1 in ax + mov [sx1], ax ; and [sx1] + + add si, 12 ; point to next subkey + cmp si, [done8] + jne @@loop + jmp @@out8 + +;------------------------------------------ +; Special case multiplications, when one factor is 0 + +@@x1: mov ax, 1 + sub ax, [sx1] + sub ax, [Word si] + jmp @@x1out + +@@kk: mov ax, [sx1] ; rebuild overwritten operand + xor ax, bx + neg ax + inc ax + sub ax, [si+8] + jmp @@kkout + +@@x4: mov ax, 1 + sub ax, [sx4] + sub ax, [Word si+6] + jmp @@x4out + +@@t1: mov ax, [sx4] ; rebuild + xor ax, di + add ax, cx + neg ax + inc ax + sub ax, [si+10] + jmp @@t1out + +;--------------------------------------------------- +; 8 rounds are done, now that extra pseudo-round + +@@out8: + push di + mov di, [outblock] + + mul [Word si] + sub ax, dx + jnz @@o1n ; jump over special case code + mov ax, 1 + sub ax, [sx1] + sub ax, [si] + jmp @@o1out +@@o1n: adc ax, 0 +@@o1out: mov [di], ax ; final ciphertext block 1 + + mov ax, [sx4] + mul [Word si+6] + sub ax, dx + jnz @@o4n ; jump over special case code + mov ax, 1 + sub ax, [sx4] + sub ax, [si+6] + jmp @@o4out +@@o4n: adc ax, 0 +@@o4out: mov [di+6], ax ; final ciphertext block 4 + + add bx, [si+2] + mov [di+2], bx ; final ciphertext block 2 + pop ax + add ax, [si+4] + mov [di+4], ax ; final ciphertext block 3 + +; Restore the stack and return + + pop di + pop si +; pop dx +; pop cx +; pop bx +; pop ax + + mov sp, bp + pop bp + ret +ENDP _asmcrypt diff --git a/third_party/cryptlib-0.99/lib_3des.c b/third_party/cryptlib-0.99/lib_3des.c new file mode 100644 index 0000000..683264e --- /dev/null +++ b/third_party/cryptlib-0.99/lib_3des.c @@ -0,0 +1,443 @@ +#include +#include +#include +#include +#include +#include "crypt.h" +#include "libdes/des.h" + +/* The DES block size */ + +#define DES_BLOCKSIZE 8 + +/* A structure to hold the two keyscheduled DES keys */ + +typedef struct { + Key_schedule desKey1; /* The first DES key */ + Key_schedule desKey2; /* The second DES key */ + } DES3_KEY; + +/* The size of the keyscheduled DES and 3DES keys */ + +#define DES_KEYSIZE sizeof( Key_schedule ) +#define DES3_KEYSIZE sizeof( DES3_KEY ) + +/**************************************************************************** +* * +* 3DES Self-test Routines * +* * +****************************************************************************/ + +/* Are there any 3DES test vectors? Presumably X9F1 will eventually + publish some... */ + +int des3SelfTest( void ) + { + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* Init/Shutdown Routines * +* * +****************************************************************************/ + +/* Perform auxiliary init and shutdown actions on an encryption context */ + +int des3InitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ) + { + /* Get rid of unused parameter warnings in a compiler-independant manner */ + if( cryptInfoEx ); + + /* Allocate memory for the keyscheduled key */ + if( cryptInfo->key != NULL || cryptInfo->privateData != NULL ) + return( CRYPT_INITED ); + if( ( cryptInfo->key = malloc( DES3_KEYSIZE ) ) == NULL ) + return( CRYPT_NOMEM ); + memset( cryptInfo->key, 0, DES3_KEYSIZE ); + cryptInfo->keyLength = DES3_KEYSIZE; + + return( CRYPT_OK ); + } + +int des3Init( CRYPT_INFO *cryptInfo ) + { + /* Just pass the call through to the extended setup routine */ + return( des3InitEx( cryptInfo, NULL ) ); + } + +int des3End( CRYPT_INFO *cryptInfo ) + { + /* Free any allocated memory */ + secureFree( &cryptInfo->key, cryptInfo->keyLength ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* 3DES En/Decryption Routines * +* * +****************************************************************************/ + +/* Encrypt/decrypt data in ECB mode */ + +int des3EncryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + DES3_KEY *des3Key = ( DES3_KEY * ) cryptInfo->key; + int blockCount = noBytes / DES_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % DES_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + /* Encrypt a block of data */ + des_3ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer, + des3Key->desKey1, des3Key->desKey2, DES_ENCRYPT ); + + /* Move on to next block of data */ + buffer += DES_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +int des3DecryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + DES3_KEY *des3Key = ( DES3_KEY * ) cryptInfo->key; + int blockCount = noBytes / DES_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % DES_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + /* Decrypt a block of data */ + des_3ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer, + des3Key->desKey1, des3Key->desKey2, DES_DECRYPT ); + + /* Move on to next block of data */ + buffer += DES_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in CBC mode */ + +int des3EncryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + DES3_KEY *des3Key = ( DES3_KEY * ) cryptInfo->key; + int blockCount = noBytes / DES_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % DES_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + int i; + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < DES_BLOCKSIZE; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Encrypt a block of data */ + des_3ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer, + des3Key->desKey1, des3Key->desKey2, DES_ENCRYPT ); + + /* Shift ciphertext into IV */ + memcpy( cryptInfo->currentIV, buffer, DES_BLOCKSIZE ); + + /* Move on to next block of data */ + buffer += DES_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +int des3DecryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + DES3_KEY *des3Key = ( DES3_KEY * ) cryptInfo->key; + BYTE temp[ DES_BLOCKSIZE ]; + int blockCount = noBytes / DES_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % DES_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + int i; + + /* Save the ciphertext */ + memcpy( temp, buffer, DES_BLOCKSIZE ); + + /* Decrypt a block of data */ + des_3ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer, + des3Key->desKey1, des3Key->desKey2, DES_DECRYPT ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < DES_BLOCKSIZE; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, temp, DES_BLOCKSIZE ); + + /* Move on to next block of data */ + buffer += DES_BLOCKSIZE; + } + + /* Clear the temporary buffer */ + memset( temp, 0, DES_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in CFB mode */ + +int des3EncryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + DES3_KEY *des3Key = ( DES3_KEY * ) cryptInfo->key; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = DES_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Encrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + memcpy( cryptInfo->currentIV + ivCount, buffer, bytesToUse ); + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + des_3ecb_encrypt( ( C_Block * ) cryptInfo->currentIV, + ( C_Block * ) cryptInfo->currentIV, + des3Key->desKey1, des3Key->desKey2, DES_ENCRYPT ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, buffer, ivCount ); + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % DES_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Decrypt data in CFB mode. Note that the transformation can be made + faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp + all in one loop */ + +int des3DecryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + DES3_KEY *des3Key = ( DES3_KEY * ) cryptInfo->key; + BYTE temp[ DES_BLOCKSIZE ]; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = DES_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Decrypt the data */ + memcpy( temp, buffer, bytesToUse ); + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + memcpy( cryptInfo->currentIV + ivCount, temp, bytesToUse ); + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + des_3ecb_encrypt( ( C_Block * ) cryptInfo->currentIV, + ( C_Block * ) cryptInfo->currentIV, + des3Key->desKey1, des3Key->desKey2, DES_ENCRYPT ); + + /* Save the ciphertext */ + memcpy( temp, buffer, ivCount ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, temp, ivCount ); + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % DES_BLOCKSIZE ); + + /* Clear the temporary buffer */ + memset( temp, 0, DES_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in OFB mode */ + +int des3EncryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + DES3_KEY *des3Key = ( DES3_KEY * ) cryptInfo->key; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = DES_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Encrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + des_3ecb_encrypt( ( C_Block * ) cryptInfo->currentIV, + ( C_Block * ) cryptInfo->currentIV, + des3Key->desKey1, des3Key->desKey2, DES_ENCRYPT ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % DES_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Decrypt data in OFB mode */ + +int des3DecryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + DES3_KEY *des3Key = ( DES3_KEY * ) cryptInfo->key; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = DES_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Decrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + des_3ecb_encrypt( ( C_Block * ) cryptInfo->currentIV, + ( C_Block * ) cryptInfo->currentIV, + des3Key->desKey1, des3Key->desKey2, DES_ENCRYPT ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % DES_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* 3DES Key Management Routines * +* * +****************************************************************************/ + +/* Key schedule two DES keys */ + +int des3InitKey( CRYPT_INFO *cryptInfo ) + { + DES3_KEY *des3Key = ( DES3_KEY * ) cryptInfo->key; + + /* Call the libdes key schedule code. Returns with -1 if the key parity + is wrong, -2 if a weak key is used */ + if( key_sched( ( C_Block * ) cryptInfo->userKey, des3Key->desKey1 ) ) + return( CRYPT_BADPARM ); + if( key_sched( ( C_Block * ) ( cryptInfo->userKey + bitsToBytes( 56 ) ), + des3Key->desKey2 ) ) + return( CRYPT_BADPARM ); + + return( CRYPT_OK ); + } diff --git a/third_party/cryptlib-0.99/lib_des.c b/third_party/cryptlib-0.99/lib_des.c new file mode 100644 index 0000000..368f776 --- /dev/null +++ b/third_party/cryptlib-0.99/lib_des.c @@ -0,0 +1,486 @@ +#include +#include +#include +#include +#include +#include "crypt.h" +#include "libdes/des.h" + +/* The DES key and block size */ + +#define DES_KEYSIZE 7 +#define DES_BLOCKSIZE 8 + +/* The size of the keyscheduled DES key */ + +#define DES_EXPANDED_KEYSIZE sizeof( Key_schedule ) + +/**************************************************************************** +* * +* DES Self-test Routines * +* * +****************************************************************************/ + +#include "testdes.h" + +/* Test the DES implementation against the test vectors given in NBS Special + Publication 500-20, 1980. We need to perform the tests at a very low + level since the encryption library hasn't been intialized yet */ + +static int desTestLoop( DES_TEST *testData, int iterations, int operation ) + { + BYTE temp[ DES_BLOCKSIZE ]; + BYTE key[ DES_EXPANDED_KEYSIZE ]; + int i; + + for( i = 0; i < iterations; i++ ) + { + memcpy( temp, testData[ i ].plaintext, DES_BLOCKSIZE ); + key_sched( ( C_Block * ) testData[ i ].key, + *( ( Key_schedule * ) key ) ); + des_ecb_encrypt( ( C_Block * ) temp, ( C_Block * ) temp, + *( ( Key_schedule * ) key ), operation ); + if( memcmp( testData[ i ].ciphertext, temp, DES_BLOCKSIZE ) ) + return( CRYPT_ERROR ); + } + + return( CRYPT_OK ); + } + +int desSelfTest( void ) + { + /* Check the DES test vectors */ + if( ( desTestLoop( testIP, sizeof( testIP ) / sizeof( DES_TEST ), + DES_ENCRYPT ) != CRYPT_OK ) || \ + ( desTestLoop( testVP, sizeof( testVP ) / sizeof( DES_TEST ), + DES_ENCRYPT ) != CRYPT_OK ) || \ + ( desTestLoop( testKP, sizeof( testKP ) / sizeof( DES_TEST ), + DES_ENCRYPT ) != CRYPT_OK ) || \ + ( desTestLoop( testRS, sizeof( testRS ) / sizeof( DES_TEST ), + DES_DECRYPT ) != CRYPT_OK ) || \ + ( desTestLoop( testDP, sizeof( testDP ) / sizeof( DES_TEST ), + DES_ENCRYPT ) != CRYPT_OK ) || \ + ( desTestLoop( testSB, sizeof( testSB ) / sizeof( DES_TEST ), + DES_ENCRYPT ) != CRYPT_OK ) ) + return( CRYPT_SELFTEST ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* Init/Shutdown Routines * +* * +****************************************************************************/ + +/* Perform auxiliary init and shutdown actions on an encryption context */ + +int desInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ) + { + /* Get rid of unused parameter warnings in a compiler-independant manner */ + if( cryptInfoEx ); + + /* Allocate memory for the keyscheduled key */ + if( cryptInfo->key != NULL || cryptInfo->privateData != NULL ) + return( CRYPT_INITED ); + if( ( cryptInfo->key = malloc( DES_EXPANDED_KEYSIZE ) ) == NULL ) + return( CRYPT_NOMEM ); + memset( cryptInfo->key, 0, DES_EXPANDED_KEYSIZE ); + cryptInfo->keyLength = DES_EXPANDED_KEYSIZE; + + return( CRYPT_OK ); + } + +int desInit( CRYPT_INFO *cryptInfo ) + { + /* Just pass the call through to the extended setup routine */ + return( desInitEx( cryptInfo, NULL ) ); + } + +int desEnd( CRYPT_INFO *cryptInfo ) + { + /* Free any allocated memory */ + secureFree( &cryptInfo->key, cryptInfo->keyLength ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* DES En/Decryption Routines * +* * +****************************************************************************/ + +/* Encrypt/decrypt data in ECB mode */ + +int desEncryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + int blockCount = noBytes / DES_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % DES_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + /* Encrypt a block of data */ + des_ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer, + cryptInfo->key, DES_ENCRYPT ); + + /* Move on to next block of data */ + buffer += DES_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +int desDecryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + int blockCount = noBytes / DES_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % DES_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + /* Decrypt a block of data */ + des_ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer, + cryptInfo->key, DES_DECRYPT ); + + /* Move on to next block of data */ + buffer += DES_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in CBC mode */ + +int desEncryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + int blockCount = noBytes / DES_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % DES_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + int i; + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < DES_BLOCKSIZE; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Encrypt a block of data */ + des_ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer, + cryptInfo->key, DES_ENCRYPT ); + + /* Shift ciphertext into IV */ + memcpy( cryptInfo->currentIV, buffer, DES_BLOCKSIZE ); + + /* Move on to next block of data */ + buffer += DES_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +int desDecryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + BYTE temp[ DES_BLOCKSIZE ]; + int blockCount = noBytes / DES_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % DES_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + int i; + + /* Save the ciphertext */ + memcpy( temp, buffer, DES_BLOCKSIZE ); + + /* Decrypt a block of data */ + des_ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer, + cryptInfo->key, DES_DECRYPT ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < DES_BLOCKSIZE; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, temp, DES_BLOCKSIZE ); + + /* Move on to next block of data */ + buffer += DES_BLOCKSIZE; + } + + /* Clear the temporary buffer */ + memset( temp, 0, DES_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in CFB mode */ + +int desEncryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = DES_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Encrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + memcpy( cryptInfo->currentIV + ivCount, buffer, bytesToUse ); + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + des_ecb_encrypt( ( C_Block * ) cryptInfo->currentIV, + ( C_Block * ) cryptInfo->currentIV, + cryptInfo->key, DES_ENCRYPT ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, buffer, ivCount ); + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % DES_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +int desDecryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + BYTE temp[ DES_BLOCKSIZE ]; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = DES_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Decrypt the data */ + memcpy( temp, buffer, bytesToUse ); + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + memcpy( cryptInfo->currentIV + ivCount, temp, bytesToUse ); + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + des_ecb_encrypt( ( C_Block * ) cryptInfo->currentIV, + ( C_Block * ) cryptInfo->currentIV, + cryptInfo->key, DES_ENCRYPT ); + + /* Save the ciphertext */ + memcpy( temp, buffer, ivCount ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, temp, ivCount ); + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % DES_BLOCKSIZE ); + + /* Clear the temporary buffer */ + memset( temp, 0, DES_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in OFB mode */ + +int desEncryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = DES_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Encrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + des_ecb_encrypt( ( C_Block * ) cryptInfo->currentIV, + ( C_Block * ) cryptInfo->currentIV, + cryptInfo->key, DES_ENCRYPT ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % DES_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +int desDecryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = DES_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Decrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + des_ecb_encrypt( ( C_Block * ) cryptInfo->currentIV, + ( C_Block * ) cryptInfo->currentIV, + cryptInfo->key, DES_ENCRYPT ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % DES_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in PCBC mode */ + +int desEncryptPCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + /* Make sure the data length is a multiple of the block size */ + if( noBytes % DES_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + /* Encrypt the entire buffer */ + des_pcbc_encrypt( ( C_Block *) buffer, ( C_Block * ) buffer, + ( long ) noBytes, cryptInfo->key, + ( C_Block * ) cryptInfo->currentIV, DES_ENCRYPT ); + + return( CRYPT_OK ); + } + +int desDecryptPCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + /* Make sure the data length is a multiple of the block size */ + if( noBytes % DES_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + /* Decrypt the entire buffer */ + des_pcbc_encrypt( ( C_Block *) buffer, ( C_Block * ) buffer, + ( long ) noBytes, cryptInfo->key, + ( C_Block * ) cryptInfo->currentIV, DES_DECRYPT ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* DES Key Management Routines * +* * +****************************************************************************/ + +/* Key schedule a DES key */ + +int desInitKey( CRYPT_INFO *cryptInfo ) + { + /* Call the libdes key schedule code. Returns with -1 if the key parity + is wrong, -2 if a weak key is used */ + if( key_sched( ( C_Block * ) cryptInfo->userKey, + *( ( Key_schedule * ) cryptInfo->key ) ) ) + return( CRYPT_BADPARM ); + + return( CRYPT_OK ); + } diff --git a/third_party/cryptlib-0.99/lib_idea.c b/third_party/cryptlib-0.99/lib_idea.c new file mode 100644 index 0000000..45dee11 --- /dev/null +++ b/third_party/cryptlib-0.99/lib_idea.c @@ -0,0 +1,442 @@ +#include +#include +#include +#include +#include +#include "crypt.h" +#include "idea/idea.h" + +/* The IDEA key and block size */ + +#define IDEA_KEYSIZE IDEAKEYSIZE +#define IDEA_BLOCKSIZE IDEABLOCKSIZE + +/* A structure to hold the two expanded IDEA keys */ + +typedef struct { + WORD eKey[ IDEAKEYLEN ]; /* The encryption key */ + WORD dKey[ IDEAKEYLEN ]; /* The decryption key */ + } IDEA_KEY; + +/* The size of the expanded IDEA keys */ + +#define IDEA_EXPANDED_KEYSIZE sizeof( IDEA_KEY ) + +/**************************************************************************** +* * +* IDEA Self-test Routines * +* * +****************************************************************************/ + +#include "testidea.h" + +/* Test the IDEA code against the test vectors from the ETH reference + implementation */ + +int ideaSelfTest( void ) + { + BYTE temp[ IDEA_BLOCKSIZE ]; + WORD key[ IDEAKEYLEN ]; + int i; + + for( i = 0; i < sizeof( testIdea ) / sizeof( IDEA_TEST ); i++ ) + { + memcpy( temp, testIdea[ i ].plaintext, IDEA_BLOCKSIZE ); + ideaExpandKey( testIdea[ i ].key, key ); + ideaCipher( temp, temp, key ); + if( memcmp( testIdea[ i ].ciphertext, temp, IDEA_BLOCKSIZE ) ) + return( CRYPT_ERROR ); + } + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* Init/Shutdown Routines * +* * +****************************************************************************/ + +/* Perform auxiliary init and shutdown actions on an encryption context */ + +int ideaInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ) + { + /* Get rid of unused parameter warnings in a compiler-independant manner */ + if( cryptInfoEx ); + + /* Allocate memory for the keyscheduled key */ + if( cryptInfo->key != NULL || cryptInfo->privateData != NULL ) + return( CRYPT_INITED ); + if( ( cryptInfo->key = malloc( IDEA_EXPANDED_KEYSIZE ) ) == NULL ) + return( CRYPT_NOMEM ); + memset( cryptInfo->key, 0, IDEA_EXPANDED_KEYSIZE ); + cryptInfo->keyLength = IDEA_EXPANDED_KEYSIZE; + + return( CRYPT_OK ); + } + +int ideaInit( CRYPT_INFO *cryptInfo ) + { + /* Just pass the call through to the extended setup routine */ + return( ideaInitEx( cryptInfo, NULL ) ); + } + +int ideaEnd( CRYPT_INFO *cryptInfo ) + { + /* Free any allocated memory */ + secureFree( &cryptInfo->key, cryptInfo->keyLength ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* IDEA En/Decryption Routines * +* * +****************************************************************************/ + +/* Encrypt/decrypt data in ECB mode */ + +int ideaEncryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key; + int blockCount = noBytes / IDEA_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % IDEA_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + /* Encrypt a block of data */ + ideaCipher( buffer, buffer, ideaKey->eKey ); + + /* Move on to next block of data */ + buffer += IDEA_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +int ideaDecryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key; + int blockCount = noBytes / IDEA_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % IDEA_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + /* Decrypt a block of data */ + ideaCipher( buffer, buffer, ideaKey->dKey ); + + /* Move on to next block of data */ + buffer += IDEA_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in CBC mode */ + +int ideaEncryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key; + int blockCount = noBytes / IDEA_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % IDEA_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + int i; + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < IDEA_BLOCKSIZE; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Encrypt a block of data */ + ideaCipher( buffer, buffer, ideaKey->eKey ); + + /* Shift ciphertext into IV */ + memcpy( cryptInfo->currentIV, buffer, IDEA_BLOCKSIZE ); + + /* Move on to next block of data */ + buffer += IDEA_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +int ideaDecryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key; + BYTE temp[ IDEA_BLOCKSIZE ]; + int blockCount = noBytes / IDEA_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % IDEA_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + int i; + + /* Save the ciphertext */ + memcpy( temp, buffer, IDEA_BLOCKSIZE ); + + /* Decrypt a block of data */ + ideaCipher( buffer, buffer, ideaKey->dKey ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < IDEA_BLOCKSIZE; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, temp, IDEA_BLOCKSIZE ); + + /* Move on to next block of data */ + buffer += IDEA_BLOCKSIZE; + } + + /* Clear the temporary buffer */ + memset( temp, 0, IDEA_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in CFB mode */ + +int ideaEncryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = IDEA_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Encrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + memcpy( cryptInfo->currentIV + ivCount, buffer, bytesToUse ); + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > IDEA_BLOCKSIZE ) ? IDEA_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + ideaCipher( cryptInfo->currentIV, cryptInfo->currentIV, ideaKey->eKey ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, buffer, ivCount ); + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % IDEA_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Decrypt data in CFB mode. Note that the transformation can be made + faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp + all in one loop */ + +int ideaDecryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key; + BYTE temp[ IDEA_BLOCKSIZE ]; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = IDEA_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Decrypt the data */ + memcpy( temp, buffer, bytesToUse ); + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + memcpy( cryptInfo->currentIV + ivCount, temp, bytesToUse ); + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > IDEA_BLOCKSIZE ) ? IDEA_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + ideaCipher( cryptInfo->currentIV, cryptInfo->currentIV, ideaKey->eKey ); + + /* Save the ciphertext */ + memcpy( temp, buffer, ivCount ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, temp, ivCount ); + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % IDEA_BLOCKSIZE ); + + /* Clear the temporary buffer */ + memset( temp, 0, IDEA_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in OFB mode */ + +int ideaEncryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = IDEA_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Encrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > IDEA_BLOCKSIZE ) ? IDEA_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + ideaCipher( cryptInfo->currentIV, cryptInfo->currentIV, ideaKey->eKey ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % IDEA_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Decrypt data in OFB mode */ + +int ideaDecryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = IDEA_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Decrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > IDEA_BLOCKSIZE ) ? IDEA_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + ideaCipher( cryptInfo->currentIV, cryptInfo->currentIV, ideaKey->eKey ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % IDEA_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* IDEA Key Management Routines * +* * +****************************************************************************/ + +/* Key schedule an IDEA key */ + +int ideaInitKey( CRYPT_INFO *cryptInfo ) + { + IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key; + + /* Generate an expanded IDEA key and its inverse */ + ideaExpandKey( cryptInfo->userKey, ideaKey->eKey ); + ideaInvertKey( ideaKey->eKey, ideaKey->dKey ); + + return( CRYPT_OK ); + } diff --git a/third_party/cryptlib-0.99/lib_mdc.c b/third_party/cryptlib-0.99/lib_mdc.c new file mode 100644 index 0000000..6c2d68e --- /dev/null +++ b/third_party/cryptlib-0.99/lib_mdc.c @@ -0,0 +1,460 @@ +#include +#include +#include +#include +#include +#include "crypt.h" +#include "mdc/shs.h" + +/* The default key setup iteration count. This gives roughly 0.5s delay on + a 10K dhrystone machine */ + +#define MDCSHS_DEFAULT_ITERATIONS 200 + +/* The size of an MDCSHS key. If we're running on a machine with a > 32 + bit wordsize, we need to store the key as an array of words rather than + an array of bytes which is cast to an array of words */ + +#ifdef _BIG_WORDS + #define MDCSHS_KEY_WORDS ( SHS_DATASIZE / 4 ) + #define MDCSHS_KEYSIZE ( MDCSHS_KEY_WORDS * sizeof( LONG ) ) +#else + #define MDCSHS_KEYSIZE SHS_DATASIZE +#endif /* _BIG_WORDS */ + +/* If we're running on a machine with > 32 bit wordsize we need to jump + through all sorts of hoops to convert data from arrays of bytes to arrays + of longints. The following macros pull bytes out of memory and assemble + them into a longword, and deposit a longword into memory as a series of + bytes. This code really blows on any processors which need to use it */ + +#ifdef _BIG_WORDS + #ifdef BIG_ENDIAN + #define mgetLong(memPtr) \ + ( ( ( LONG ) memPtr[ 0 ] << 24 ) | ( ( LONG ) memPtr[ 1 ] << 16 ) | \ + ( ( LONG ) memPtr[ 2 ] << 8 ) | ( ( LONG ) memPtr[ 3 ] ) ); \ + memPtr += 4 + + #define mputLong(memPtr,data) \ + memPtr[ 0 ] = ( ( data ) >> 24 ) & 0xFF; \ + memPtr[ 1 ] = ( ( data ) >> 16 ) & 0xFF; \ + memPtr[ 2 ] = ( ( data ) >> 8 ) & 0xFF; \ + memPtr[ 3 ] = ( data ) & 0xFF; \ + memPtr += 4 + #else + #define mgetLong(memPtr) \ + ( ( ( LONG ) memPtr[ 0 ] ) | ( ( LONG ) memPtr[ 1 ] << 8 ) | \ + ( ( LONG ) memPtr[ 2 ] << 16 ) | ( ( LONG ) memPtr[ 3 ] << 24 ) ); \ + memPtr += 4 + + #define mputLong(memPtr,data) \ + memPtr[ 0 ] = ( data ) & 0xFF; \ + memPtr[ 1 ] = ( ( data ) >> 8 ) & 0xFF; \ + memPtr[ 2 ] = ( ( data ) >> 16 ) & 0xFF; \ + memPtr[ 3 ] = ( ( data ) >> 24 ) & 0xFF; \ + memPtr += 4 + #endif /* BIG_ENDIAN */ + +/* Versions of the above which are guaranteed to always be big-endian */ + +#define mgetELong(memPtr) \ + ( ( ( LONG ) memPtr[ 0 ] << 24 ) | ( ( LONG ) memPtr[ 1 ] << 16 ) | \ + ( ( LONG ) memPtr[ 2 ] << 8 ) | ( LONG ) memPtr[ 3 ] ); \ + memPtr += 4 + +#define mputELong(memPtr,data) \ + memPtr[ 0 ] = ( ( data ) >> 24 ) & 0xFF; \ + memPtr[ 1 ] = ( ( data ) >> 16 ) & 0xFF; \ + memPtr[ 2 ] = ( ( data ) >> 8 ) & 0xFF; \ + memPtr[ 3 ] = ( data ) & 0xFF; \ + memPtr += 4 + +#endif /* _BIG_WORDS */ + +/* Copy an array of bytes to an array of 32-bit words. We need to take + special precautions when the machine word size is > 32 bits because we + can't just assume BYTE[] == LONG[] */ + +#ifdef _BIG_WORDS + #define copyToLong(dest,src,count) \ + { \ + LONG *destPtr = ( LONG * ) dest; \ + BYTE *srcPtr = src; \ + int i; \ + for( i = 0; i < count / 4; i++ ) \ + { \ + destPtr[ i ] = mgetLong( srcPtr ); \ + } \ + } +#else + #define copyToLong(dest,src,count) \ + memcpy( dest, src, count ) +#endif /* _BIG_WORDS */ + +/**************************************************************************** +* * +* MDC/SHS Self-test Routines * +* * +****************************************************************************/ + +/* Test the SHA output against the test vectors given in FIPS 180 */ + +static LONG shsTestResults[][ 5 ] = { + { 0x0164B8A9L, 0x14CD2A5EL, 0x74C4F7FFL, 0x082C4D97L, 0xF1EDF880L }, + { 0xD2516EE1L, 0xACFA5BAFL, 0x33DFC1C4L, 0x71E43844L, 0x9EF134C8L }, + { 0x3232AFFAL, 0x48628A26L, 0x653B5AAAL, 0x44541FD9L, 0x0D690603L } + }; + +static int compareSHSresults( SHS_INFO *shsInfo, int shsTestLevel ) + { + int i; + + /* Compare the returned digest and required values */ + for( i = 0; i < 5; i++ ) + if( shsInfo->digest[ i ] != shsTestResults[ shsTestLevel ][ i ] ) + return( CRYPT_SELFTEST ); + return( CRYPT_OK ); + } + +int mdcshsSelfTest( void ) + { + SHS_INFO shsInfo; + + /* Test SHA against values given in FIPS 180 */ + shsInit( &shsInfo ); + shsUpdate( &shsInfo, ( BYTE * ) "abc", 3 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 0 ) != CRYPT_OK ) + return( CRYPT_SELFTEST ); + shsInit( &shsInfo ); + shsUpdate( &shsInfo, ( BYTE * ) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 1 ) != CRYPT_OK ) + return( CRYPT_SELFTEST ); +#if 0 + /* We skip the third test since this takes several seconds to execute, + which leads to an unacceptable delay in the library startup time */ + shsInit( &shsInfo ); + for( i = 0; i < 15625; i++ ) + shsUpdate( &shsInfo, ( BYTE * ) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 2 ) != CRYPT_OK ) + return( CRYPT_SELFTEST ); +#endif /* 0 */ + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* Init/Shutdown Routines * +* * +****************************************************************************/ + +/* Perform auxiliary init and shutdown actions on an encryption context */ + +int mdcshsInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ) + { + CRYPT_INFO_MDCSHS *cryptInfoExPtr = ( CRYPT_INFO_MDCSHS * ) cryptInfoEx; + + /* Allocate memory for the key and the algorithm-specific data within + the crypt context and set up any pointers we need */ + if( cryptInfo->key != NULL || cryptInfo->privateData != NULL ) + return( CRYPT_INITED ); + if( ( cryptInfo->key = malloc( MDCSHS_KEYSIZE ) ) == NULL ) + return( CRYPT_NOMEM ); + memset( cryptInfo->key, 0, MDCSHS_KEYSIZE ); + if( ( cryptInfo->privateData = malloc( sizeof( CRYPT_INFO_MDCSHS ) ) ) == NULL ) + { + free( cryptInfo->key ); + cryptInfo->key = NULL; + return( CRYPT_NOMEM ); + } + if( cryptInfoExPtr->keySetupIterations == CRYPT_USE_DEFAULT ) + cryptInfoExPtr->keySetupIterations = MDCSHS_DEFAULT_ITERATIONS; + memcpy( cryptInfo->privateData, cryptInfoEx, sizeof( CRYPT_INFO_MDCSHS ) ); + cryptInfo->keyLength = MDCSHS_KEYSIZE; + + return( CRYPT_OK ); + } + +int mdcshsInit( CRYPT_INFO *cryptInfo ) + { + CRYPT_INFO_MDCSHS cryptInfoEx; + + /* Use the default number of setup iterations */ + memset( &cryptInfoEx, 0, sizeof( CRYPT_INFO_MDCSHS ) ); + cryptInfoEx.keySetupIterations = CRYPT_USE_DEFAULT; + + /* Pass through to the extended setup routine */ + return( mdcshsInitEx( cryptInfo, &cryptInfoEx ) ); + } + +int mdcshsEnd( CRYPT_INFO *cryptInfo ) + { + /* Free any allocated memory */ + secureFree( &cryptInfo->key, cryptInfo->keyLength ); + secureFree( &cryptInfo->privateData, sizeof( CRYPT_INFO_MDCSHS ) ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* MDC/SHS En/Decryption Routines * +* * +****************************************************************************/ + +/* The SHS transformation. What we're doing here isn't totally correct since + we're forcing the IV to big-endian, transforming it, and returning it to + the local endianness, rather than changing the data to the local + endianness and back as we should. However doing it correctly isn't really + possible since we can only endianness-swap 4 bytes at a time which + precludes swapping the data. The use of the temp variable when the IV is + copied back in the _BIG_WORDS case is to eliminate multiple memory + accesses when the four bytes are extracted from ivLong[ n ], since many + compilers won't risk optimising the loads due to possible aliasing + problems. We declare the necessary ivLong array as part of the actual + encryption function to save it having to be instantiated for every use + of shsTransform() */ + +#ifdef _BIG_WORDS + #define shsTransform(cI) { \ + LONG temp; \ + BYTE *ivPtr; \ + ivPtr = ( BYTE * ) cI->currentIV; \ + for( i = 0; i < 5; i++ ) \ + { \ + ivLong[ i ] = mgetELong( ivPtr ); \ + } \ + SHSTransform( ivLong, cI->key ); \ + ivPtr = ( BYTE * ) cI->currentIV; \ + for( i = 0; i < 5; i++ ) \ + { \ + temp = ivLong[ i ]; \ + mputELong( ivPtr, temp ); \ + } \ + } +#else + #define shsTransform(cI) longReverse( ( LONG * ) cI->currentIV, SHS_DIGESTSIZE ); \ + SHSTransform( ( LONG * ) cI->currentIV, ( LONG * ) cI->key ); \ + longReverse( ( LONG * ) cI->currentIV, SHS_DIGESTSIZE ); +#endif /* _BIG_WORDS */ + +void SHSTransform( LONG *digest, LONG *data ); + +/* Encrypt data in CFB mode */ + +int mdcshsEncrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + int i, ivCount = cryptInfo->ivCount; +#ifdef _BIG_WORDS + LONG ivLong[ 5 ]; +#endif /* _BIG_WORDS */ + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = SHS_DIGESTSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Encrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + memcpy( cryptInfo->currentIV + ivCount, buffer, bytesToUse ); + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > SHS_DIGESTSIZE ) ? SHS_DIGESTSIZE : noBytes; + + /* Encrypt the IV */ + shsTransform( cryptInfo ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, buffer, ivCount ); + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % SHS_DIGESTSIZE ); + + return( CRYPT_OK ); + } + +/* Decrypt data in CFB mode. Note that the transformation can be made + faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp + all in one loop */ + +int mdcshsDecrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + BYTE temp[ SHS_DIGESTSIZE ]; + int i, ivCount = cryptInfo->ivCount; +#ifdef _BIG_WORDS + LONG ivLong[ 5 ]; +#endif /* _BIG_WORDS */ + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = SHS_DIGESTSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Decrypt the data */ + memcpy( temp, buffer, bytesToUse ); + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + memcpy( cryptInfo->currentIV + ivCount, temp, bytesToUse ); + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > SHS_DIGESTSIZE ) ? SHS_DIGESTSIZE : noBytes; + + /* Encrypt the IV */ + shsTransform( cryptInfo ); + + /* Save the ciphertext */ + memcpy( temp, buffer, ivCount ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, temp, ivCount ); + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % SHS_DIGESTSIZE ); + + /* Clear the temporary buffer */ + memset( temp, 0, SHS_DIGESTSIZE ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* MDC/SHS Key Management Routines * +* * +****************************************************************************/ + +/* The size of the key buffer. Note that increasing this value will result + in a significant increase in the setup time, so it will be necessary to + make a corresponding decrease in the iteration count */ + +#define KEYBUFFER_SIZE 256 + +/* Initialise an MDC/SHS key. This is done by repeatedly encrypting the + user key as follows: + + IV <- 0 + key <- 0 + repeat + encrypt userkey with key + key <- userkey + + The IV is updated transparently as part of the encryption process */ + +int mdcshsInitKey( CRYPT_INFO *cryptInfo ) + { + BYTE keyData[ KEYBUFFER_SIZE ]; + int keySetupIterations = ( ( CRYPT_INFO_MDCSHS * ) cryptInfo->privateData )->keySetupIterations; + int count; + + /* Copy the key information into the key data buffer. We silently + truncate the key length to the size of the buffer, but this usually + is some hundreds of bytes so it shouldn't be a problem. + We also correct the endianness of the keyData at this point. From + here on all data is in the local endianness format so there is no need + for further corrections */ + memset( keyData, 0, KEYBUFFER_SIZE ); + keyData[ 0 ] = ( BYTE ) ( cryptInfo->userKeyLength >> 8 ); + keyData[ 1 ] = ( BYTE ) cryptInfo->userKeyLength; + cryptInfo->userKeyLength %= KEYBUFFER_SIZE - 2; + memcpy( keyData + 2, cryptInfo->userKey, cryptInfo->userKeyLength ); + + /* Set the initial key and IV to null */ + memset( cryptInfo->currentIV, 0, CRYPT_MAX_IVSIZE ); + memset( cryptInfo->key, 0, MDCSHS_KEYSIZE ); + + /* Convert the endianness of the input data from the canonical form to + the local form */ + longReverse( ( LONG * ) keyData, KEYBUFFER_SIZE ); + + /* "Encrypt" the keyData with the given IV and then set the key to + the encrypted keyData. The act of encryption also sets the IV. + This is particularly important in the case of SHS, since although only + the first SHS_DATASIZE bytes are copied into the key, the IV is + still affected by the entire buffer */ + for( count = 0; count < keySetupIterations; count++ ) + { + mdcshsEncrypt( cryptInfo, keyData, KEYBUFFER_SIZE ); + copyToLong( cryptInfo->key, keyData, SHS_DATASIZE ); + } + + /* Perform one last copy in case they've specified zero iterations and + the loop was never executed. For MDCSHS, the transformed key is the + same as the raw encryption key, so we just copy it over */ + copyToLong( cryptInfo->key, keyData, SHS_DATASIZE ); + +#if 0 + /* Set the key check byte to the last WORD of the encrypted keyData. + This is never used for anything (it's 191 bytes past the end of the + last value used to set the key) so we're not revealing much to an + attacker */ + longReverse( ( LONG * ) ( keyData + KEYBUFFER_SIZE - sizeof( LONG ) ), sizeof( LONG ) ); + cryptInfo->keyCheck = ( ( WORD ) keyData[ KEYBUFFER_SIZE - 2 ] << 8 ) | \ + keyData[ KEYBUFFER_SIZE - 1 ]; +#endif /* 0 */ + + /* Finally, create a copy of the transformed key in the canonical form + in case the user wants to access it */ + memcpy( cryptInfo->transUserKey, keyData, MDCSHS_KEYSIZE ); + longReverse( ( LONG * ) cryptInfo->transUserKey, SHS_DATASIZE ); + + /* Wipe the keyData */ + memset( keyData, 0, KEYBUFFER_SIZE ); + + return( CRYPT_OK ); + } + +/* Initialise the IV */ + +int mdcshsInitIV( CRYPT_INFO *cryptInfo ) + { + /* Convert the working IV from the canonical to the internal form */ + longReverse( ( LONG * ) cryptInfo->currentIV, CRYPT_MAX_IVSIZE ); + + return( CRYPT_OK ); + } diff --git a/third_party/cryptlib-0.99/lib_null.c b/third_party/cryptlib-0.99/lib_null.c new file mode 100644 index 0000000..307fe6f --- /dev/null +++ b/third_party/cryptlib-0.99/lib_null.c @@ -0,0 +1,68 @@ +#include "crypt.h" + +/**************************************************************************** +* * +* Null En/Decryption Routines * +* * +****************************************************************************/ + +int nullSelfTest( void ) + { + return( CRYPT_OK ); + } + +int nullInit( CRYPT_INFO *cryptInfo ) + { + /* Get rid of unused parameter warning in a compiler-independant manner */ + if( cryptInfo ); + + return( CRYPT_OK ); + } + +int nullInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ) + { + /* Get rid of unused parameter warning in a compiler-independant manner */ + if( cryptInfoEx ); + + return( nullInit( cryptInfo ) ); + } + +int nullEnd( CRYPT_INFO *cryptInfo ) + { + /* Get rid of unused parameter warning in a compiler-independant manner */ + if( cryptInfo ); + + return( CRYPT_OK ); + } + +int nullInitKey( CRYPT_INFO *cryptInfo ) + { + /* Get rid of unused parameter warning in a compiler-independant manner */ + if( cryptInfo ); + + return( CRYPT_OK ); + } + +int nullInitIV( CRYPT_INFO *cryptInfo ) + { + /* Get rid of unused parameter warning in a compiler-independant manner */ + if( cryptInfo ); + + return( CRYPT_OK ); + } + +int nullEncrypt( CRYPT_INFO *cryptInfo, void *buffer, int length ) + { + /* Get rid of unused parameter warning in a compiler-independant manner */ + if( cryptInfo || buffer || length ); + + return( CRYPT_OK ); + } + +int nullDecrypt( CRYPT_INFO *cryptInfo, void *buffer, int length ) + { + /* Get rid of unused parameter warning in a compiler-independant manner */ + if( cryptInfo || buffer || length ); + + return( CRYPT_OK ); + } diff --git a/third_party/cryptlib-0.99/lib_rc4.c b/third_party/cryptlib-0.99/lib_rc4.c new file mode 100644 index 0000000..5362d1d --- /dev/null +++ b/third_party/cryptlib-0.99/lib_rc4.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include "crypt.h" +#include "rc4/rc4.h" + +/* The size of the expanded IDEA keys */ + +#define RC4_EXPANDED_KEYSIZE sizeof( RC4KEY ) + +/**************************************************************************** +* * +* RC4 Self-test Routines * +* * +****************************************************************************/ + +#include "testrc4.h" + +/* Test the RC4 code against the test vectors from the BSAFE2 implementation */ + +static int rc4Test( BYTE *key, int keySize, + BYTE *plaintext, BYTE *ciphertext, int length ) + { + BYTE temp[ 512 ]; + RC4KEY rc4key; + + memcpy( temp, plaintext, length ); + rc4ExpandKey( &rc4key, key, keySize ); + rc4Crypt( &rc4key, temp, length ); + if( memcmp( ciphertext, temp, length ) ) + return( CRYPT_ERROR ); + + return( CRYPT_OK ); + } + + +int rc4SelfTest( void ) + { + /* The testing gets somewhat messy here because of the variable-length + arrays, which isn't normally a problem with the fixed-length keys + and data used in the block ciphers */ + if( rc4Test( testRC4key1, sizeof( testRC4key1 ), testRC4plaintext1, + testRC4ciphertext1, sizeof( testRC4plaintext1 ) ) != CRYPT_OK || + rc4Test( testRC4key2, sizeof( testRC4key2 ), testRC4plaintext2, + testRC4ciphertext2, sizeof( testRC4plaintext2 ) ) != CRYPT_OK || + rc4Test( testRC4key3, sizeof( testRC4key3 ), testRC4plaintext3, + testRC4ciphertext3, sizeof( testRC4plaintext3 ) ) != CRYPT_OK || + rc4Test( testRC4key4, sizeof( testRC4key4 ), testRC4plaintext4, + testRC4ciphertext4, sizeof( testRC4plaintext4 ) ) != CRYPT_OK || + rc4Test( testRC4key5, sizeof( testRC4key5 ), testRC4plaintext5, + testRC4ciphertext5, sizeof( testRC4plaintext5 ) ) != CRYPT_OK ) + return( CRYPT_ERROR ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* Init/Shutdown Routines * +* * +****************************************************************************/ + +/* Perform auxiliary init and shutdown actions on an encryption context */ + +int rc4InitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ) + { + /* Get rid of unused parameter warnings in a compiler-independant manner */ + if( cryptInfoEx ); + + /* Allocate memory for the expanded key */ + if( cryptInfo->key != NULL || cryptInfo->privateData != NULL ) + return( CRYPT_INITED ); + if( ( cryptInfo->key = malloc( RC4_EXPANDED_KEYSIZE ) ) == NULL ) + return( CRYPT_NOMEM ); + memset( cryptInfo->key, 0, RC4_EXPANDED_KEYSIZE ); + cryptInfo->keyLength = RC4_EXPANDED_KEYSIZE; + + return( CRYPT_OK ); + } + +int rc4Init( CRYPT_INFO *cryptInfo ) + { + /* Just pass the call through to the extended setup routine */ + return( rc4InitEx( cryptInfo, NULL ) ); + } + +int rc4End( CRYPT_INFO *cryptInfo ) + { + /* Free any allocated memory */ + secureFree( &cryptInfo->key, cryptInfo->keyLength ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* RC4 En/Decryption Routines * +* * +****************************************************************************/ + +/* Encrypt/decrypt data. Since RC4 is a stream cipher, encryption and + decryption are one and the same */ + +int rc4Encrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + rc4Crypt( ( RC4KEY * ) cryptInfo->key, buffer, noBytes ); + + return( CRYPT_OK ); + } + +int rc4Decrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + rc4Crypt( ( RC4KEY * ) cryptInfo->key, buffer, noBytes ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* RC4 Key Management Routines * +* * +****************************************************************************/ + +/* Create an expanded RC4 key */ + +int rc4InitKey( CRYPT_INFO *cryptInfo ) + { + rc4ExpandKey( ( RC4KEY * ) cryptInfo->key, cryptInfo->userKey, + cryptInfo->userKeyLength ); + + return( CRYPT_OK ); + } diff --git a/third_party/cryptlib-0.99/lib_safr.c b/third_party/cryptlib-0.99/lib_safr.c new file mode 100644 index 0000000..2f91f55 --- /dev/null +++ b/third_party/cryptlib-0.99/lib_safr.c @@ -0,0 +1,489 @@ +#include +#include +#include +#include +#include +#include "crypt.h" +#include "safer/safer.h" + +/* The SAFER key and block size */ + +#define SAFER_KEYSIZE SAFER_KEY_LEN +#define SAFER_BLOCKSIZE SAFER_BLOCK_LEN + +#define SAFER_KEY safer_key_t + +/* The size of the expanded SAFER keys */ + +#define SAFER_EXPANDED_KEYSIZE sizeof( SAFER_KEY ) + +/**************************************************************************** +* * +* SAFER Self-test Routines * +* * +****************************************************************************/ + +#include "testsafr.h" + +/* Test the SAFER-SK code against the test vectors from the ETH reference + implementation */ + +int saferSelfTest( void ) + { + BYTE temp[ SAFER_BLOCKSIZE ]; + SAFER_KEY key; + int i; + + Safer_Init_Module(); + for( i = 0; i < sizeof( testSafer ) / sizeof( SAFER_TEST ); i++ ) + { + memcpy( temp, testSafer[ i ].plaintext, SAFER_BLOCKSIZE ); + if( testSafer[ i ].rounds == SAFER_K64_DEFAULT_NOF_ROUNDS ) + Safer_Expand_Userkey( testSafer[ i ].key, \ + testSafer[ i ].key, \ + testSafer[ i ].rounds, TRUE, key ); + else + Safer_Expand_Userkey( testSafer[ i ].key, \ + testSafer[ i ].key + bitsToBytes( 64 ), \ + testSafer[ i ].rounds, TRUE, key ); + Safer_Encrypt_Block( temp, key, temp ); + if( memcmp( testSafer[ i ].ciphertext, temp, SAFER_BLOCKSIZE ) ) + return( CRYPT_ERROR ); + } + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* Init/Shutdown Routines * +* * +****************************************************************************/ + +/* Perform auxiliary init and shutdown actions on an encryption context */ + +int saferInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx ) + { + CRYPT_INFO_SAFER *cryptInfoExPtr = ( CRYPT_INFO_SAFER * ) cryptInfoEx; + + /* Allocate memory for the key and the algorithm-specific data within + the crypt context and set up any pointers we need. We don't process + cryptInfoExPtr->rounds at this point since we set things up when we + perform the saferInitKey() function, as the number of rounds is key- + dependant */ + if( cryptInfo->key != NULL || cryptInfo->privateData != NULL ) + return( CRYPT_INITED ); + if( ( cryptInfo->key = malloc( SAFER_EXPANDED_KEYSIZE ) ) == NULL ) + return( CRYPT_NOMEM ); + memset( cryptInfo->key, 0, SAFER_EXPANDED_KEYSIZE ); + if( ( cryptInfo->privateData = malloc( sizeof( CRYPT_INFO_SAFER ) ) ) == NULL ) + { + free( cryptInfo->key ); + cryptInfo->key = NULL; + return( CRYPT_NOMEM ); + } + if( cryptInfoExPtr->useSaferSK == CRYPT_USE_DEFAULT ) + cryptInfoExPtr->useSaferSK = FALSE; + memcpy( cryptInfo->privateData, cryptInfoEx, sizeof( CRYPT_INFO_SAFER ) ); + cryptInfo->keyLength = SAFER_EXPANDED_KEYSIZE; + + /* Set up the SAFER data tables if necessary */ + Safer_Init_Module(); + + return( CRYPT_OK ); + } + +int saferInit( CRYPT_INFO *cryptInfo ) + { + CRYPT_INFO_SAFER cryptInfoEx; + + /* Use the default number of rounds and the non-enhanced SAFER */ + memset( &cryptInfoEx, 0, sizeof( CRYPT_INFO_MDCSHS ) ); + cryptInfoEx.rounds = CRYPT_USE_DEFAULT; + cryptInfoEx.useSaferSK = CRYPT_USE_DEFAULT; + + /* Pass through to the extended setup routine */ + return( saferInitEx( cryptInfo, &cryptInfoEx ) ); + } + +int saferEnd( CRYPT_INFO *cryptInfo ) + { + /* Free any allocated memory */ + secureFree( &cryptInfo->key, cryptInfo->keyLength ); + secureFree( &cryptInfo->privateData, sizeof( CRYPT_INFO_SAFER ) ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* SAFER En/Decryption Routines * +* * +****************************************************************************/ + +/* Encrypt/decrypt data in ECB mode */ + +int saferEncryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + SAFER_KEY *saferKey = ( SAFER_KEY * ) cryptInfo->key; + int blockCount = noBytes / SAFER_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % SAFER_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + /* Encrypt a block of data */ + Safer_Encrypt_Block( buffer, *saferKey, buffer ); + + /* Move on to next block of data */ + buffer += SAFER_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +int saferDecryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + SAFER_KEY *saferKey = ( SAFER_KEY * ) cryptInfo->key; + int blockCount = noBytes / SAFER_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % SAFER_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + /* Decrypt a block of data */ + Safer_Decrypt_Block( buffer, *saferKey, buffer ); + + /* Move on to next block of data */ + buffer += SAFER_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in CBC mode */ + +int saferEncryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + SAFER_KEY *saferKey = ( SAFER_KEY * ) cryptInfo->key; + int blockCount = noBytes / SAFER_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % SAFER_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + int i; + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < SAFER_BLOCKSIZE; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Encrypt a block of data */ + Safer_Encrypt_Block( buffer, *saferKey, buffer ); + + /* Shift ciphertext into IV */ + memcpy( cryptInfo->currentIV, buffer, SAFER_BLOCKSIZE ); + + /* Move on to next block of data */ + buffer += SAFER_BLOCKSIZE; + } + + return( CRYPT_OK ); + } + +int saferDecryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + SAFER_KEY *saferKey = ( SAFER_KEY * ) cryptInfo->key; + BYTE temp[ SAFER_BLOCKSIZE ]; + int blockCount = noBytes / SAFER_BLOCKSIZE; + + /* Make sure the data length is a multiple of the block size */ + if( noBytes % SAFER_BLOCKSIZE ) + return( CRYPT_BADPARM3 ); + + while( blockCount-- ) + { + int i; + + /* Save the ciphertext */ + memcpy( temp, buffer, SAFER_BLOCKSIZE ); + + /* Decrypt a block of data */ + Safer_Decrypt_Block( buffer, *saferKey, buffer ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < SAFER_BLOCKSIZE; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, temp, SAFER_BLOCKSIZE ); + + /* Move on to next block of data */ + buffer += SAFER_BLOCKSIZE; + } + + /* Clear the temporary buffer */ + memset( temp, 0, SAFER_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in CFB mode */ + +int saferEncryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + SAFER_KEY *saferKey = ( SAFER_KEY * ) cryptInfo->key; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = SAFER_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Encrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + memcpy( cryptInfo->currentIV + ivCount, buffer, bytesToUse ); + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > SAFER_BLOCKSIZE ) ? SAFER_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + Safer_Encrypt_Block( cryptInfo->currentIV, *saferKey, cryptInfo->currentIV ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, buffer, ivCount ); + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % SAFER_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Decrypt data in CFB mode. Note that the transformation can be made + faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp + all in one loop */ + +int saferDecryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + SAFER_KEY *saferKey = ( SAFER_KEY * ) cryptInfo->key; + BYTE temp[ SAFER_BLOCKSIZE ]; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = SAFER_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Decrypt the data */ + memcpy( temp, buffer, bytesToUse ); + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + memcpy( cryptInfo->currentIV + ivCount, temp, bytesToUse ); + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > SAFER_BLOCKSIZE ) ? SAFER_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + Safer_Encrypt_Block( cryptInfo->currentIV, *saferKey, cryptInfo->currentIV ); + + /* Save the ciphertext */ + memcpy( temp, buffer, ivCount ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Shift the ciphertext into the IV */ + memcpy( cryptInfo->currentIV, temp, ivCount ); + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % SAFER_BLOCKSIZE ); + + /* Clear the temporary buffer */ + memset( temp, 0, SAFER_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Encrypt/decrypt data in OFB mode */ + +int saferEncryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + SAFER_KEY *saferKey = ( SAFER_KEY * ) cryptInfo->key; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = SAFER_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Encrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > SAFER_BLOCKSIZE ) ? SAFER_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + Safer_Encrypt_Block( cryptInfo->currentIV, *saferKey, cryptInfo->currentIV ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % SAFER_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/* Decrypt data in OFB mode */ + +int saferDecryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes ) + { + SAFER_KEY *saferKey = ( SAFER_KEY * ) cryptInfo->key; + int i, ivCount = cryptInfo->ivCount; + + /* If there's any encrypted material left in the IV, use it now */ + if( ivCount ) + { + int bytesToUse; + + /* Find out how much material left in the encrypted IV we can use */ + bytesToUse = SAFER_BLOCKSIZE - ivCount; + if( noBytes < bytesToUse ) + bytesToUse = noBytes; + + /* Decrypt the data */ + for( i = 0; i < bytesToUse; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ]; + + /* Adjust the byte count and buffer position */ + noBytes -= bytesToUse; + buffer += bytesToUse; + ivCount += bytesToUse; + } + + while( noBytes ) + { + ivCount = ( noBytes > SAFER_BLOCKSIZE ) ? SAFER_BLOCKSIZE : noBytes; + + /* Encrypt the IV */ + Safer_Encrypt_Block( cryptInfo->currentIV, *saferKey, cryptInfo->currentIV ); + + /* XOR the buffer contents with the encrypted IV */ + for( i = 0; i < ivCount; i++ ) + buffer[ i ] ^= cryptInfo->currentIV[ i ]; + + /* Move on to next block of data */ + noBytes -= ivCount; + buffer += ivCount; + } + + /* Remember how much of the IV is still available for use */ + cryptInfo->ivCount = ( ivCount % SAFER_BLOCKSIZE ); + + return( CRYPT_OK ); + } + +/**************************************************************************** +* * +* SAFER Key Management Routines * +* * +****************************************************************************/ + +/* Key schedule a SAFER key */ + +int saferInitKey( CRYPT_INFO *cryptInfo ) + { + CRYPT_INFO_SAFER *cryptInfoEx = ( CRYPT_INFO_SAFER * ) cryptInfo->privateData; + SAFER_KEY *saferKey = ( SAFER_KEY * ) cryptInfo->key; + BOOLEAN shortKey = cryptInfo->userKeyLength <= bitsToBytes( 64 ); + + /* If the number of rounds has been preset, use this value */ + if( cryptInfoEx->rounds != CRYPT_USE_DEFAULT ) + cryptInfoEx->currentRounds = cryptInfoEx->rounds; + else + /* Determine the number of rounds to use based on the key size */ + if( cryptInfoEx->useSaferSK ) + cryptInfoEx->currentRounds = ( shortKey ) ? \ + SAFER_SK64_DEFAULT_NOF_ROUNDS : SAFER_SK128_DEFAULT_NOF_ROUNDS; + else + cryptInfoEx->currentRounds = ( shortKey ) ? \ + SAFER_K64_DEFAULT_NOF_ROUNDS : SAFER_K128_DEFAULT_NOF_ROUNDS; + + /* Generate an expanded SAFER key */ + if( shortKey ) + Safer_Expand_Userkey( cryptInfo->userKey, \ + cryptInfo->userKey, cryptInfoEx->currentRounds, \ + cryptInfoEx->useSaferSK, *saferKey ); + else + Safer_Expand_Userkey( cryptInfo->userKey, \ + cryptInfo->userKey + bitsToBytes( 64 ), \ + cryptInfoEx->currentRounds, \ + cryptInfoEx->useSaferSK, *saferKey ); + + return( CRYPT_OK ); + } diff --git a/third_party/cryptlib-0.99/libdes/3ecb_enc.c b/third_party/cryptlib-0.99/libdes/3ecb_enc.c new file mode 100644 index 0000000..670e17a --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/3ecb_enc.c @@ -0,0 +1,36 @@ +/* 3ecb_enc.c */ + +/* Copyright (C) 1993 Eric Young - see README for more details */ + +#ifdef _MSC_VER + #include "des_locl.h" +#else + #include "libdes/des_locl.h" +#endif /* _MSC_VER */ + + +int des_3ecb_encrypt(input,output,ks1,ks2,encrypt) +des_cblock *input; +des_cblock *output; +des_key_schedule ks1,ks2; +int encrypt; + { + register unsigned long l0,l1; + register unsigned char *in,*out; + unsigned long ll[2]; + + in=(unsigned char *)input; + out=(unsigned char *)output; + c2l(in,l0); + c2l(in,l1); + ll[0]=l0; + ll[1]=l1; + des_encrypt(ll,ll,ks1,encrypt); + des_encrypt(ll,ll,ks2,!encrypt); + des_encrypt(ll,ll,ks1,encrypt); + l0=ll[0]; + l1=ll[1]; + l2c(l0,out); + l2c(l1,out); + return(0); + } diff --git a/third_party/cryptlib-0.99/libdes/copyrigh b/third_party/cryptlib-0.99/libdes/copyrigh new file mode 100644 index 0000000..dc789d4 --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/copyrigh @@ -0,0 +1,50 @@ +Copyright (C) 1995 Eric Young (eay@mincom.oz.au) +All rights reserved. + +This package is an DES implementation written by Eric Young (eay@mincom.oz.au). +The implementation was written so as to conform with MIT's libdes. + +This library is free for commercial and non-commercial use as long as +the following conditions are aheared to. The following conditions +apply to all code found in this distribution. + +Copyright remains Eric Young's, and as such any Copyright notices in +the code are not to be removed. +If this package is used in a product, Eric Young should be given attribution +as the author of that the SSL library. This can be in the form of a textual +message at program startup or in documentation (online or textual) provided +with the package. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by Eric Young (eay@mincom.oz.au) + +THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +The license and distribution terms for any publically available version or +derivative of this code cannot be changed. i.e. this code cannot simply be +copied and put under another distrubution license +[including the GNU Public License.] + +The reason behind this being stated in this direct manner is past +experience in code simply being copied and the attribution removed +from it and then being distributed as part of other packages. This +implementation was a non-trivial and unpaid effort. diff --git a/third_party/cryptlib-0.99/libdes/des.h b/third_party/cryptlib-0.99/libdes/des.h new file mode 100644 index 0000000..56588ac --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/des.h @@ -0,0 +1,98 @@ +/* des.h */ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). + * All rights reserved. + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * See the COPYRIGHT file in the libdes distribution for more details. + */ + +#ifndef HEADER_DES_H +#define HEADER_DES_H + +typedef unsigned char des_cblock[8]; +typedef struct des_ks_struct + { + union { + des_cblock _; + /* make sure things are correct size on machines with + * 8 byte longs */ + unsigned long pad[2]; + } ks; +#undef _ +#define _ ks._ + } des_key_schedule[16]; + +#define DES_KEY_SZ (sizeof(des_cblock)) +#define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#define DES_CBC_MODE 0 +#define DES_PCBC_MODE 1 + +#define C_Block des_cblock +#define Key_schedule des_key_schedule +#define ENCRYPT DES_ENCRYPT +#define DECRYPT DES_DECRYPT +#define KEY_SZ DES_KEY_SZ +#define string_to_key des_string_to_key +#define read_pw_string des_read_pw_string +#define random_key des_random_key +#define pcbc_encrypt des_pcbc_encrypt +#define set_key des_set_key +#define key_sched des_key_sched +#define ecb_encrypt des_ecb_encrypt +#define cbc_encrypt des_cbc_encrypt +#define cbc_cksum des_cbc_cksum +#define quad_cksum des_quad_cksum + +/* For compatibility with the MIT lib - eay 20/05/92 */ +typedef struct des_ks_struct bit_64; + +extern int des_check_key; /* defaults to false */ +extern int des_rw_mode; /* defaults to DES_PCBC_MODE */ + +int des_3ecb_encrypt(des_cblock *input,des_cblock *output,\ + des_key_schedule ks1,des_key_schedule ks2,int encrypt); +unsigned long des_cbc_cksum(des_cblock *input,des_cblock *output,\ + long length,des_key_schedule schedule,des_cblock *ivec); +int des_cbc_encrypt(des_cblock *input,des_cblock *output,long length,\ + des_key_schedule schedule,des_cblock *ivec,int encrypt); +int des_3cbc_encrypt(des_cblock *input,des_cblock *output,long length,\ + des_key_schedule sk1,des_key_schedule sk2,\ + des_cblock *ivec1,des_cblock *ivec2,int encrypt); +int des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits,\ + long length,des_key_schedule schedule,des_cblock *ivec,int encrypt); +int des_ecb_encrypt(des_cblock *input,des_cblock *output,\ + des_key_schedule ks,int encrypt); +int des_encrypt(unsigned long *input,unsigned long *output, + des_key_schedule ks, int encrypt); +int des_enc_read(int fd,char *buf,int len,des_key_schedule sched,\ + des_cblock *iv); +int des_enc_write(int fd,char *buf,int len,des_key_schedule sched,\ + des_cblock *iv); +#ifdef PERL5 +char *des_crypt(const char *buf,const char *salt); +#else +char *crypt(char *buf,char *salt); +#endif +int des_ofb_encrypt(unsigned char *in,unsigned char *out,\ + int numbits,long length,des_key_schedule schedule,des_cblock *ivec); +int des_pcbc_encrypt(des_cblock *input,des_cblock *output,long length,\ + des_key_schedule schedule,des_cblock *ivec,int encrypt); +unsigned long des_quad_cksum(des_cblock *input,des_cblock *output,\ + long length,int out_count,des_cblock *seed); +void des_random_seed(des_cblock key); +int des_random_key(des_cblock ret); +int des_read_password(des_cblock *key,char *prompt,int verify); +int des_read_2passwords(des_cblock *key1,des_cblock *key2, \ + char *prompt,int verify); +int des_read_pw_string(char *buf,int length,char *prompt,int verify); +void des_set_odd_parity(des_cblock *key); +int des_is_weak_key(des_cblock *key); +int des_set_key(des_cblock *key,des_key_schedule schedule); +int des_key_sched(des_cblock *key,des_key_schedule schedule); +int des_string_to_key(char *str,des_cblock *key); +int des_string_to_2keys(char *str,des_cblock *key1,des_cblock *key2); +#endif diff --git a/third_party/cryptlib-0.99/libdes/des_locl.h b/third_party/cryptlib-0.99/libdes/des_locl.h new file mode 100644 index 0000000..8113e50 --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/des_locl.h @@ -0,0 +1,204 @@ +/* des_locl.h */ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). + * All rights reserved. + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * See the COPYRIGHT file in the libdes distribution for more details. + */ + +#include +#ifdef _MSC_VER + #include "des.h" +#else + #include "libdes/des.h" +#endif /* _MSC_VER */ + +/* Force ANSI usage as the rest of the library assumes ANSI anyway - pcg */ + +#include + +#define bcopy(b1,b2,len) memcpy(b2, b1, (size_t)(len)) +#define bzero(b,len) memset(b, 0, (size_t)(len)) +#define bcmp(b1,b2,len) memcmp(b1, b2, (size_t)(len)) +#define index(s1,char) strchr(s1,char) + +#if !defined(_LIBC) || defined(NOCONST) +#define const +#endif + +#ifdef __STDC__ +#define PROTO +#endif + +#ifdef RAND +#define random() rand() +#define srandom(s) srand(s) +#endif + +#define ITERATIONS 16 +#define HALF_ITERATIONS 8 + +/* used in des_read and des_write */ +#define MAXWRITE (1024*16) +#define BSIZE (MAXWRITE+4) + +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8, \ + l|=((unsigned long)(*((c)++)))<<16, \ + l|=((unsigned long)(*((c)++)))<<24) + +/* NOTE - c is not incremented as per c2l */ +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((unsigned long)(*(--(c))))<<24; \ + case 7: l2|=((unsigned long)(*(--(c))))<<16; \ + case 6: l2|=((unsigned long)(*(--(c))))<< 8; \ + case 5: l2|=((unsigned long)(*(--(c)))); \ + case 4: l1 =((unsigned long)(*(--(c))))<<24; \ + case 3: l1|=((unsigned long)(*(--(c))))<<16; \ + case 2: l1|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l1|=((unsigned long)(*(--(c)))); \ + } \ + } + +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +/* replacements for htonl and ntohl since I have no idea what to do + * when faced with machines with 8 byte longs. */ +#define HDRSIZE 4 + +#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \ + l|=((unsigned long)(*((c)++)))<<16, \ + l|=((unsigned long)(*((c)++)))<< 8, \ + l|=((unsigned long)(*((c)++)))) + +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* The changes to this macro may help or hinder, depending on the + * compiler and the achitecture. gcc2 always seems to do well :-). + * Inspired by Dana How + * DO NOT use the alternative version on machines with 8 byte longs. */ +#ifdef ALT_ECB +#define D_ENCRYPT(L,R,S) \ + u=((R^s[S ])<<2); \ + t= R^s[S+1]; \ + t=((t>>2)+(t<<30)); \ + L^= \ + *(unsigned long *)(des_SP+0x0100+((t )&0xfc))+ \ + *(unsigned long *)(des_SP+0x0300+((t>> 8)&0xfc))+ \ + *(unsigned long *)(des_SP+0x0500+((t>>16)&0xfc))+ \ + *(unsigned long *)(des_SP+0x0700+((t>>24)&0xfc))+ \ + *(unsigned long *)(des_SP+ ((u )&0xfc))+ \ + *(unsigned long *)(des_SP+0x0200+((u>> 8)&0xfc))+ \ + *(unsigned long *)(des_SP+0x0400+((u>>16)&0xfc))+ \ + *(unsigned long *)(des_SP+0x0600+((u>>24)&0xfc)); +#else /* original version */ +#ifdef MSDOS +#define D_ENCRYPT(L,R,S) \ + U.l=R^s[S+1]; \ + T.s[0]=((U.s[0]>>4)|(U.s[1]<<12))&0x3f3f; \ + T.s[1]=((U.s[1]>>4)|(U.s[0]<<12))&0x3f3f; \ + U.l=(R^s[S ])&0x3f3f3f3f; \ + L^= des_SPtrans[1][(T.c[0])]| \ + des_SPtrans[3][(T.c[1])]| \ + des_SPtrans[5][(T.c[2])]| \ + des_SPtrans[7][(T.c[3])]| \ + des_SPtrans[0][(U.c[0])]| \ + des_SPtrans[2][(U.c[1])]| \ + des_SPtrans[4][(U.c[2])]| \ + des_SPtrans[6][(U.c[3])]; +#else +#define D_ENCRYPT(L,R,S) \ + u=(R^s[S ]); \ + t=R^s[S+1]; \ + t=((t>>4)+(t<<28)); \ + L^= des_SPtrans[1][(t )&0x3f]| \ + des_SPtrans[3][(t>> 8)&0x3f]| \ + des_SPtrans[5][(t>>16)&0x3f]| \ + des_SPtrans[7][(t>>24)&0x3f]| \ + des_SPtrans[0][(u )&0x3f]| \ + des_SPtrans[2][(u>> 8)&0x3f]| \ + des_SPtrans[4][(u>>16)&0x3f]| \ + des_SPtrans[6][(u>>24)&0x3f]; +#endif +#endif + + /* IP and FP + * The problem is more of a geometric problem that random bit fiddling. + 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 + 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 + 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 + 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 + + 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 + 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 + 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 + 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 + + The output has been subject to swaps of the form + 0 1 -> 3 1 but the odd and even bits have been put into + 2 3 2 0 + different words. The main trick is to remember that + t=((l>>size)^r)&(mask); + r^=t; + l^=(t<>(n))^(b))&(m)),\ + (b)^=(t),\ + (a)^=((t)<<(n))) + +#define IP(l,r,t) \ + PERM_OP(r,l,t, 4,0x0f0f0f0fL); \ + PERM_OP(l,r,t,16,0x0000ffffL); \ + PERM_OP(r,l,t, 2,0x33333333L); \ + PERM_OP(l,r,t, 8,0x00ff00ffL); \ + PERM_OP(r,l,t, 1,0x55555555L); + +#define FP(l,r,t) \ + PERM_OP(l,r,t, 1,0x55555555L); \ + PERM_OP(r,l,t, 8,0x00ff00ffL); \ + PERM_OP(l,r,t, 2,0x33333333L); \ + PERM_OP(r,l,t,16,0x0000ffffL); \ + PERM_OP(l,r,t, 4,0x0f0f0f0fL); + + diff --git a/third_party/cryptlib-0.99/libdes/ecb_enc.c b/third_party/cryptlib-0.99/libdes/ecb_enc.c new file mode 100644 index 0000000..2071f80 --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/ecb_enc.c @@ -0,0 +1,112 @@ +/* ecb_enc.c */ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). + * All rights reserved. + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * See the COPYRIGHT file in the libdes distribution for more details. + */ + +#ifdef _MSC_VER + #include "des_locl.h" + #include "spr.h" + #include "version.h" +#else + #include "libdes/des_locl.h" + #include "libdes/spr.h" + #include "libdes/version.h" +#endif /* _MSC_VER */ + +int des_ecb_encrypt(input,output,ks,encrypt) +des_cblock *input; +des_cblock *output; +des_key_schedule ks; +int encrypt; + { + register unsigned long l0,l1; + register unsigned char *in,*out; + unsigned long ll[2]; + + in=(unsigned char *)input; + out=(unsigned char *)output; + c2l(in,l0); + c2l(in,l1); + ll[0]=l0; + ll[1]=l1; + des_encrypt(ll,ll,ks,encrypt); + l0=ll[0]; + l1=ll[1]; + l2c(l0,out); + l2c(l1,out); + l0=l1=ll[0]=ll[1]=0; + return(0); + } + +int des_encrypt(input,output,ks,encrypt) +unsigned long *input; +unsigned long *output; +des_key_schedule ks; +int encrypt; + { + register unsigned long l,r,t,u; +#ifdef ALT_ECB + register unsigned char *des_SP=(unsigned char *)des_SPtrans; +#endif +#ifdef MSDOS + union fudge { + unsigned long l; + unsigned short s[2]; + unsigned char c[4]; + } U,T; +#endif + register int i; + register unsigned long *s; + + l=input[0]; + r=input[1]; + + IP(l,r,t); + /* Things have been modified so that the initial rotate is + * done outside the loop. This required the + * des_SPtrans values in sp.h to be rotated 1 bit to the right. + * One perl script later and things have a 5% speed up on a sparc2. + * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> + * for pointing this out. */ + t=(r<<1)|(r>>31); + r=(l<<1)|(l>>31); + l=t; + + /* clear the top bits on machines with 8byte longs */ + l&=0xffffffffL; + r&=0xffffffffL; + + s=(unsigned long *)ks; + /* I don't know if it is worth the effort of loop unrolling the + * inner loop */ + if (encrypt) + { + for (i=0; i<32; i+=4) + { + D_ENCRYPT(l,r,i+0); /* 1 */ + D_ENCRYPT(r,l,i+2); /* 2 */ + } + } + else + { + for (i=30; i>0; i-=4) + { + D_ENCRYPT(l,r,i-0); /* 16 */ + D_ENCRYPT(r,l,i-2); /* 15 */ + } + } + l=(l>>1)|(l<<31); + r=(r>>1)|(r<<31); + /* clear the top bits on machines with 8byte longs */ + l&=0xffffffffL; + r&=0xffffffffL; + + FP(r,l,t); + output[0]=l; + output[1]=r; + l=r=t=u=0; + return(0); + } diff --git a/third_party/cryptlib-0.99/libdes/pcbc_enc.c b/third_party/cryptlib-0.99/libdes/pcbc_enc.c new file mode 100644 index 0000000..e5ff1c4 --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/pcbc_enc.c @@ -0,0 +1,83 @@ +/* pcbc_enc.c */ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). + * All rights reserved. + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * See the COPYRIGHT file in the libdes distribution for more details. + */ + +#ifdef _MSC_VER + #include "des_locl.h" +#else + #include "libdes/des_locl.h" +#endif /* _MSC_VER */ + +int des_pcbc_encrypt(input,output,length,schedule,ivec,encrypt) +des_cblock *input; +des_cblock *output; +long length; +des_key_schedule schedule; +des_cblock *ivec; +int encrypt; + { + register unsigned long sin0,sin1,xor0,xor1,tout0,tout1; + unsigned long tin[2],tout[2]; + unsigned char *in,*out,*iv; + + in=(unsigned char *)input; + out=(unsigned char *)output; + iv=(unsigned char *)ivec; + + if (encrypt) + { + c2l(iv,xor0); + c2l(iv,xor1); + for (; length>0; length-=8) + { + if (length >= 8) + { + c2l(in,sin0); + c2l(in,sin1); + } + else + c2ln(in,sin0,sin1,length); + tin[0]=sin0^xor0; + tin[1]=sin1^xor1; + des_encrypt((unsigned long *)tin,(unsigned long *)tout, + schedule,encrypt); + tout0=tout[0]; + tout1=tout[1]; + xor0=sin0^tout[0]; + xor1=sin1^tout[1]; + l2c(tout0,out); + l2c(tout1,out); + } + } + else + { + c2l(iv,xor0); c2l(iv,xor1); + for (; length>0; length-=8) + { + c2l(in,sin0); + c2l(in,sin1); + tin[0]=sin0; + tin[1]=sin1; + des_encrypt((unsigned long *)tin,(unsigned long *)tout, + schedule,encrypt); + tout0=tout[0]^xor0; + tout1=tout[1]^xor1; + if (length >= 8) + { + l2c(tout0,out); + l2c(tout1,out); + } + else + l2cn(tout0,tout1,out,length); + xor0=tout0^sin0; + xor1=tout1^sin1; + } + } + tin[0]=tin[1]=tout[0]=tout[1]=0; + sin0=sin1=xor0=xor1=tout0=tout1=0; + return(0); + } diff --git a/third_party/cryptlib-0.99/libdes/podd.h b/third_party/cryptlib-0.99/libdes/podd.h new file mode 100644 index 0000000..5306a7c --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/podd.h @@ -0,0 +1,25 @@ +/* podd.h */ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). + * All rights reserved. + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * See the COPYRIGHT file in the libdes distribution for more details. + */ + +static const unsigned char odd_parity[256]={ + 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, + 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, + 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, + 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, + 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, + 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, + 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, +112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, +128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, +145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, +161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, +176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, +193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, +208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, +224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, +241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; diff --git a/third_party/cryptlib-0.99/libdes/set_key.c b/third_party/cryptlib-0.99/libdes/set_key.c new file mode 100644 index 0000000..5981cf2 --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/set_key.c @@ -0,0 +1,198 @@ +/* set_key.c */ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). + * All rights reserved. + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * See the COPYRIGHT file in the libdes distribution for more details. + */ + +/* set_key.c v 1.4 eay 24/9/91 + * 1.4 Speed up by 400% :-) + * 1.3 added register declarations. + * 1.2 unrolled make_key_sched a bit more + * 1.1 added norm_expand_bits + * 1.0 First working version + */ + +#ifdef _MSC_VER + #include "des_locl.h" + #include "podd.h" + #include "sk.h" +#else + #include "libdes/des_locl.h" + #include "libdes/podd.h" + #include "libdes/sk.h" +#endif /* _MSC_VER */ + +static int check_parity(des_cblock *key); + +int des_check_key=0; + +void des_set_odd_parity(key) +des_cblock *key; + { + int i; + + for (i=0; i>(n))^(b))&(m)),\ + * (b)^=(t),\ + * (a)=((a)^((t)<<(n)))) + */ + +#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ + (a)=(a)^(t)^(t>>(16-(n)))) + +static char shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; + +/* return 0 if key parity is odd (correct), + * return -1 if key parity error, + * return -2 if illegal weak key. + */ +int des_set_key(key,schedule) +des_cblock *key; +des_key_schedule schedule; + { + register unsigned long c,d,t,s; + register unsigned char *in; + register unsigned long *k; + register int i; + + if (des_check_key) + { + if (!check_parity(key)) + return(-1); + + if (des_is_weak_key(key)) + return(-2); + } + + k=(unsigned long *)schedule; + in=(unsigned char *)key; + + c2l(in,c); + c2l(in,d); + + /* do PC1 in 60 simple operations */ +/* PERM_OP(d,c,t,4,0x0f0f0f0f); + HPERM_OP(c,t,-2, 0xcccc0000); + HPERM_OP(c,t,-1, 0xaaaa0000); + HPERM_OP(c,t, 8, 0x00ff0000); + HPERM_OP(c,t,-1, 0xaaaa0000); + HPERM_OP(d,t,-8, 0xff000000); + HPERM_OP(d,t, 8, 0x00ff0000); + HPERM_OP(d,t, 2, 0x33330000); + d=((d&0x00aa00aa)<<7)|((d&0x55005500)>>7)|(d&0xaa55aa55); + d=(d>>8)|((c&0xf0000000)>>4); + c&=0x0fffffff; */ + + /* I now do it in 47 simple operations :-) + * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) + * for the inspiration. :-) */ + PERM_OP (d,c,t,4,0x0f0f0f0fL); + HPERM_OP(c,t,-2,0xcccc0000L); + HPERM_OP(d,t,-2,0xcccc0000L); + PERM_OP (d,c,t,1,0x55555555L); + PERM_OP (c,d,t,8,0x00ff00ffL); + PERM_OP (d,c,t,1,0x55555555L); + d= (((d&0x000000ffL)<<16)| (d&0x0000ff00L) | + ((d&0x00ff0000L)>>16)|((c&0xf0000000L)>>4)); + c&=0x0fffffffL; + + for (i=0; i>2)|(c<<26)); d=((d>>2)|(d<<26)); } + else + { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); } + c&=0x0fffffffL; + d&=0x0fffffffL; + /* could be a few less shifts but I am to lazy at this + * point in time to investigate */ + s= des_skb[0][ (c )&0x3f ]| + des_skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)]| + des_skb[2][((c>>13)&0x0f)|((c>>14)&0x30)]| + des_skb[3][((c>>20)&0x01)|((c>>21)&0x06) | + ((c>>22)&0x38)]; + t= des_skb[4][ (d )&0x3f ]| + des_skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)]| + des_skb[6][ (d>>15)&0x3f ]| + des_skb[7][((d>>21)&0x0f)|((d>>22)&0x30)]; + + /* table contained 0213 4657 */ + *(k++)=((t<<16)|(s&0x0000ffffL))&0xffffffffL; + s= ((s>>16)|(t&0xffff0000L)); + + s=(s<<4)|(s>>28); + *(k++)=s&0xffffffffL; + } + return(0); + } + +int des_key_sched(key,schedule) +des_cblock *key; +des_key_schedule schedule; + { + return(des_set_key(key,schedule)); + } diff --git a/third_party/cryptlib-0.99/libdes/sk.h b/third_party/cryptlib-0.99/libdes/sk.h new file mode 100644 index 0000000..25b10bf --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/sk.h @@ -0,0 +1,146 @@ +/* sk.h */ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). + * All rights reserved. + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * See the COPYRIGHT file in the libdes distribution for more details. + */ + +static const unsigned long des_skb[8][64]={ +/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ +0x00000000L,0x00000010L,0x20000000L,0x20000010L, +0x00010000L,0x00010010L,0x20010000L,0x20010010L, +0x00000800L,0x00000810L,0x20000800L,0x20000810L, +0x00010800L,0x00010810L,0x20010800L,0x20010810L, +0x00000020L,0x00000030L,0x20000020L,0x20000030L, +0x00010020L,0x00010030L,0x20010020L,0x20010030L, +0x00000820L,0x00000830L,0x20000820L,0x20000830L, +0x00010820L,0x00010830L,0x20010820L,0x20010830L, +0x00080000L,0x00080010L,0x20080000L,0x20080010L, +0x00090000L,0x00090010L,0x20090000L,0x20090010L, +0x00080800L,0x00080810L,0x20080800L,0x20080810L, +0x00090800L,0x00090810L,0x20090800L,0x20090810L, +0x00080020L,0x00080030L,0x20080020L,0x20080030L, +0x00090020L,0x00090030L,0x20090020L,0x20090030L, +0x00080820L,0x00080830L,0x20080820L,0x20080830L, +0x00090820L,0x00090830L,0x20090820L,0x20090830L, +/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ +0x00000000L,0x02000000L,0x00002000L,0x02002000L, +0x00200000L,0x02200000L,0x00202000L,0x02202000L, +0x00000004L,0x02000004L,0x00002004L,0x02002004L, +0x00200004L,0x02200004L,0x00202004L,0x02202004L, +0x00000400L,0x02000400L,0x00002400L,0x02002400L, +0x00200400L,0x02200400L,0x00202400L,0x02202400L, +0x00000404L,0x02000404L,0x00002404L,0x02002404L, +0x00200404L,0x02200404L,0x00202404L,0x02202404L, +0x10000000L,0x12000000L,0x10002000L,0x12002000L, +0x10200000L,0x12200000L,0x10202000L,0x12202000L, +0x10000004L,0x12000004L,0x10002004L,0x12002004L, +0x10200004L,0x12200004L,0x10202004L,0x12202004L, +0x10000400L,0x12000400L,0x10002400L,0x12002400L, +0x10200400L,0x12200400L,0x10202400L,0x12202400L, +0x10000404L,0x12000404L,0x10002404L,0x12002404L, +0x10200404L,0x12200404L,0x10202404L,0x12202404L, +/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ +0x00000000L,0x00000001L,0x00040000L,0x00040001L, +0x01000000L,0x01000001L,0x01040000L,0x01040001L, +0x00000002L,0x00000003L,0x00040002L,0x00040003L, +0x01000002L,0x01000003L,0x01040002L,0x01040003L, +0x00000200L,0x00000201L,0x00040200L,0x00040201L, +0x01000200L,0x01000201L,0x01040200L,0x01040201L, +0x00000202L,0x00000203L,0x00040202L,0x00040203L, +0x01000202L,0x01000203L,0x01040202L,0x01040203L, +0x08000000L,0x08000001L,0x08040000L,0x08040001L, +0x09000000L,0x09000001L,0x09040000L,0x09040001L, +0x08000002L,0x08000003L,0x08040002L,0x08040003L, +0x09000002L,0x09000003L,0x09040002L,0x09040003L, +0x08000200L,0x08000201L,0x08040200L,0x08040201L, +0x09000200L,0x09000201L,0x09040200L,0x09040201L, +0x08000202L,0x08000203L,0x08040202L,0x08040203L, +0x09000202L,0x09000203L,0x09040202L,0x09040203L, +/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ +0x00000000L,0x00100000L,0x00000100L,0x00100100L, +0x00000008L,0x00100008L,0x00000108L,0x00100108L, +0x00001000L,0x00101000L,0x00001100L,0x00101100L, +0x00001008L,0x00101008L,0x00001108L,0x00101108L, +0x04000000L,0x04100000L,0x04000100L,0x04100100L, +0x04000008L,0x04100008L,0x04000108L,0x04100108L, +0x04001000L,0x04101000L,0x04001100L,0x04101100L, +0x04001008L,0x04101008L,0x04001108L,0x04101108L, +0x00020000L,0x00120000L,0x00020100L,0x00120100L, +0x00020008L,0x00120008L,0x00020108L,0x00120108L, +0x00021000L,0x00121000L,0x00021100L,0x00121100L, +0x00021008L,0x00121008L,0x00021108L,0x00121108L, +0x04020000L,0x04120000L,0x04020100L,0x04120100L, +0x04020008L,0x04120008L,0x04020108L,0x04120108L, +0x04021000L,0x04121000L,0x04021100L,0x04121100L, +0x04021008L,0x04121008L,0x04021108L,0x04121108L, +/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ +0x00000000L,0x10000000L,0x00010000L,0x10010000L, +0x00000004L,0x10000004L,0x00010004L,0x10010004L, +0x20000000L,0x30000000L,0x20010000L,0x30010000L, +0x20000004L,0x30000004L,0x20010004L,0x30010004L, +0x00100000L,0x10100000L,0x00110000L,0x10110000L, +0x00100004L,0x10100004L,0x00110004L,0x10110004L, +0x20100000L,0x30100000L,0x20110000L,0x30110000L, +0x20100004L,0x30100004L,0x20110004L,0x30110004L, +0x00001000L,0x10001000L,0x00011000L,0x10011000L, +0x00001004L,0x10001004L,0x00011004L,0x10011004L, +0x20001000L,0x30001000L,0x20011000L,0x30011000L, +0x20001004L,0x30001004L,0x20011004L,0x30011004L, +0x00101000L,0x10101000L,0x00111000L,0x10111000L, +0x00101004L,0x10101004L,0x00111004L,0x10111004L, +0x20101000L,0x30101000L,0x20111000L,0x30111000L, +0x20101004L,0x30101004L,0x20111004L,0x30111004L, +/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ +0x00000000L,0x08000000L,0x00000008L,0x08000008L, +0x00000400L,0x08000400L,0x00000408L,0x08000408L, +0x00020000L,0x08020000L,0x00020008L,0x08020008L, +0x00020400L,0x08020400L,0x00020408L,0x08020408L, +0x00000001L,0x08000001L,0x00000009L,0x08000009L, +0x00000401L,0x08000401L,0x00000409L,0x08000409L, +0x00020001L,0x08020001L,0x00020009L,0x08020009L, +0x00020401L,0x08020401L,0x00020409L,0x08020409L, +0x02000000L,0x0A000000L,0x02000008L,0x0A000008L, +0x02000400L,0x0A000400L,0x02000408L,0x0A000408L, +0x02020000L,0x0A020000L,0x02020008L,0x0A020008L, +0x02020400L,0x0A020400L,0x02020408L,0x0A020408L, +0x02000001L,0x0A000001L,0x02000009L,0x0A000009L, +0x02000401L,0x0A000401L,0x02000409L,0x0A000409L, +0x02020001L,0x0A020001L,0x02020009L,0x0A020009L, +0x02020401L,0x0A020401L,0x02020409L,0x0A020409L, +/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ +0x00000000L,0x00000100L,0x00080000L,0x00080100L, +0x01000000L,0x01000100L,0x01080000L,0x01080100L, +0x00000010L,0x00000110L,0x00080010L,0x00080110L, +0x01000010L,0x01000110L,0x01080010L,0x01080110L, +0x00200000L,0x00200100L,0x00280000L,0x00280100L, +0x01200000L,0x01200100L,0x01280000L,0x01280100L, +0x00200010L,0x00200110L,0x00280010L,0x00280110L, +0x01200010L,0x01200110L,0x01280010L,0x01280110L, +0x00000200L,0x00000300L,0x00080200L,0x00080300L, +0x01000200L,0x01000300L,0x01080200L,0x01080300L, +0x00000210L,0x00000310L,0x00080210L,0x00080310L, +0x01000210L,0x01000310L,0x01080210L,0x01080310L, +0x00200200L,0x00200300L,0x00280200L,0x00280300L, +0x01200200L,0x01200300L,0x01280200L,0x01280300L, +0x00200210L,0x00200310L,0x00280210L,0x00280310L, +0x01200210L,0x01200310L,0x01280210L,0x01280310L, +/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ +0x00000000L,0x04000000L,0x00040000L,0x04040000L, +0x00000002L,0x04000002L,0x00040002L,0x04040002L, +0x00002000L,0x04002000L,0x00042000L,0x04042000L, +0x00002002L,0x04002002L,0x00042002L,0x04042002L, +0x00000020L,0x04000020L,0x00040020L,0x04040020L, +0x00000022L,0x04000022L,0x00040022L,0x04040022L, +0x00002020L,0x04002020L,0x00042020L,0x04042020L, +0x00002022L,0x04002022L,0x00042022L,0x04042022L, +0x00000800L,0x04000800L,0x00040800L,0x04040800L, +0x00000802L,0x04000802L,0x00040802L,0x04040802L, +0x00002800L,0x04002800L,0x00042800L,0x04042800L, +0x00002802L,0x04002802L,0x00042802L,0x04042802L, +0x00000820L,0x04000820L,0x00040820L,0x04040820L, +0x00000822L,0x04000822L,0x00040822L,0x04040822L, +0x00002820L,0x04002820L,0x00042820L,0x04042820L, +0x00002822L,0x04002822L,0x00042822L,0x04042822L +}; diff --git a/third_party/cryptlib-0.99/libdes/spr.h b/third_party/cryptlib-0.99/libdes/spr.h new file mode 100644 index 0000000..3a1afad --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/spr.h @@ -0,0 +1,152 @@ +/* spr.h */ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). + * All rights reserved. + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * See the COPYRIGHT file in the libdes distribution for more details. + */ + +static const unsigned long des_SPtrans[8][64]={ +/* nibble 0 */ +0x00820200L, 0x00020000L, 0x80800000L, 0x80820200L, +0x00800000L, 0x80020200L, 0x80020000L, 0x80800000L, +0x80020200L, 0x00820200L, 0x00820000L, 0x80000200L, +0x80800200L, 0x00800000L, 0x00000000L, 0x80020000L, +0x00020000L, 0x80000000L, 0x00800200L, 0x00020200L, +0x80820200L, 0x00820000L, 0x80000200L, 0x00800200L, +0x80000000L, 0x00000200L, 0x00020200L, 0x80820000L, +0x00000200L, 0x80800200L, 0x80820000L, 0x00000000L, +0x00000000L, 0x80820200L, 0x00800200L, 0x80020000L, +0x00820200L, 0x00020000L, 0x80000200L, 0x00800200L, +0x80820000L, 0x00000200L, 0x00020200L, 0x80800000L, +0x80020200L, 0x80000000L, 0x80800000L, 0x00820000L, +0x80820200L, 0x00020200L, 0x00820000L, 0x80800200L, +0x00800000L, 0x80000200L, 0x80020000L, 0x00000000L, +0x00020000L, 0x00800000L, 0x80800200L, 0x00820200L, +0x80000000L, 0x80820000L, 0x00000200L, 0x80020200L, + +/* nibble 1 */ +0x10042004L, 0x00000000L, 0x00042000L, 0x10040000L, +0x10000004L, 0x00002004L, 0x10002000L, 0x00042000L, +0x00002000L, 0x10040004L, 0x00000004L, 0x10002000L, +0x00040004L, 0x10042000L, 0x10040000L, 0x00000004L, +0x00040000L, 0x10002004L, 0x10040004L, 0x00002000L, +0x00042004L, 0x10000000L, 0x00000000L, 0x00040004L, +0x10002004L, 0x00042004L, 0x10042000L, 0x10000004L, +0x10000000L, 0x00040000L, 0x00002004L, 0x10042004L, +0x00040004L, 0x10042000L, 0x10002000L, 0x00042004L, +0x10042004L, 0x00040004L, 0x10000004L, 0x00000000L, +0x10000000L, 0x00002004L, 0x00040000L, 0x10040004L, +0x00002000L, 0x10000000L, 0x00042004L, 0x10002004L, +0x10042000L, 0x00002000L, 0x00000000L, 0x10000004L, +0x00000004L, 0x10042004L, 0x00042000L, 0x10040000L, +0x10040004L, 0x00040000L, 0x00002004L, 0x10002000L, +0x10002004L, 0x00000004L, 0x10040000L, 0x00042000L, + +/* nibble 2 */ +0x41000000L, 0x01010040L, 0x00000040L, 0x41000040L, +0x40010000L, 0x01000000L, 0x41000040L, 0x00010040L, +0x01000040L, 0x00010000L, 0x01010000L, 0x40000000L, +0x41010040L, 0x40000040L, 0x40000000L, 0x41010000L, +0x00000000L, 0x40010000L, 0x01010040L, 0x00000040L, +0x40000040L, 0x41010040L, 0x00010000L, 0x41000000L, +0x41010000L, 0x01000040L, 0x40010040L, 0x01010000L, +0x00010040L, 0x00000000L, 0x01000000L, 0x40010040L, +0x01010040L, 0x00000040L, 0x40000000L, 0x00010000L, +0x40000040L, 0x40010000L, 0x01010000L, 0x41000040L, +0x00000000L, 0x01010040L, 0x00010040L, 0x41010000L, +0x40010000L, 0x01000000L, 0x41010040L, 0x40000000L, +0x40010040L, 0x41000000L, 0x01000000L, 0x41010040L, +0x00010000L, 0x01000040L, 0x41000040L, 0x00010040L, +0x01000040L, 0x00000000L, 0x41010000L, 0x40000040L, +0x41000000L, 0x40010040L, 0x00000040L, 0x01010000L, + +/* nibble 3 */ +0x00100402L, 0x04000400L, 0x00000002L, 0x04100402L, +0x00000000L, 0x04100000L, 0x04000402L, 0x00100002L, +0x04100400L, 0x04000002L, 0x04000000L, 0x00000402L, +0x04000002L, 0x00100402L, 0x00100000L, 0x04000000L, +0x04100002L, 0x00100400L, 0x00000400L, 0x00000002L, +0x00100400L, 0x04000402L, 0x04100000L, 0x00000400L, +0x00000402L, 0x00000000L, 0x00100002L, 0x04100400L, +0x04000400L, 0x04100002L, 0x04100402L, 0x00100000L, +0x04100002L, 0x00000402L, 0x00100000L, 0x04000002L, +0x00100400L, 0x04000400L, 0x00000002L, 0x04100000L, +0x04000402L, 0x00000000L, 0x00000400L, 0x00100002L, +0x00000000L, 0x04100002L, 0x04100400L, 0x00000400L, +0x04000000L, 0x04100402L, 0x00100402L, 0x00100000L, +0x04100402L, 0x00000002L, 0x04000400L, 0x00100402L, +0x00100002L, 0x00100400L, 0x04100000L, 0x04000402L, +0x00000402L, 0x04000000L, 0x04000002L, 0x04100400L, + +/* nibble 4 */ +0x02000000L, 0x00004000L, 0x00000100L, 0x02004108L, +0x02004008L, 0x02000100L, 0x00004108L, 0x02004000L, +0x00004000L, 0x00000008L, 0x02000008L, 0x00004100L, +0x02000108L, 0x02004008L, 0x02004100L, 0x00000000L, +0x00004100L, 0x02000000L, 0x00004008L, 0x00000108L, +0x02000100L, 0x00004108L, 0x00000000L, 0x02000008L, +0x00000008L, 0x02000108L, 0x02004108L, 0x00004008L, +0x02004000L, 0x00000100L, 0x00000108L, 0x02004100L, +0x02004100L, 0x02000108L, 0x00004008L, 0x02004000L, +0x00004000L, 0x00000008L, 0x02000008L, 0x02000100L, +0x02000000L, 0x00004100L, 0x02004108L, 0x00000000L, +0x00004108L, 0x02000000L, 0x00000100L, 0x00004008L, +0x02000108L, 0x00000100L, 0x00000000L, 0x02004108L, +0x02004008L, 0x02004100L, 0x00000108L, 0x00004000L, +0x00004100L, 0x02004008L, 0x02000100L, 0x00000108L, +0x00000008L, 0x00004108L, 0x02004000L, 0x02000008L, + +/* nibble 5 */ +0x20000010L, 0x00080010L, 0x00000000L, 0x20080800L, +0x00080010L, 0x00000800L, 0x20000810L, 0x00080000L, +0x00000810L, 0x20080810L, 0x00080800L, 0x20000000L, +0x20000800L, 0x20000010L, 0x20080000L, 0x00080810L, +0x00080000L, 0x20000810L, 0x20080010L, 0x00000000L, +0x00000800L, 0x00000010L, 0x20080800L, 0x20080010L, +0x20080810L, 0x20080000L, 0x20000000L, 0x00000810L, +0x00000010L, 0x00080800L, 0x00080810L, 0x20000800L, +0x00000810L, 0x20000000L, 0x20000800L, 0x00080810L, +0x20080800L, 0x00080010L, 0x00000000L, 0x20000800L, +0x20000000L, 0x00000800L, 0x20080010L, 0x00080000L, +0x00080010L, 0x20080810L, 0x00080800L, 0x00000010L, +0x20080810L, 0x00080800L, 0x00080000L, 0x20000810L, +0x20000010L, 0x20080000L, 0x00080810L, 0x00000000L, +0x00000800L, 0x20000010L, 0x20000810L, 0x20080800L, +0x20080000L, 0x00000810L, 0x00000010L, 0x20080010L, + +/* nibble 6 */ +0x00001000L, 0x00000080L, 0x00400080L, 0x00400001L, +0x00401081L, 0x00001001L, 0x00001080L, 0x00000000L, +0x00400000L, 0x00400081L, 0x00000081L, 0x00401000L, +0x00000001L, 0x00401080L, 0x00401000L, 0x00000081L, +0x00400081L, 0x00001000L, 0x00001001L, 0x00401081L, +0x00000000L, 0x00400080L, 0x00400001L, 0x00001080L, +0x00401001L, 0x00001081L, 0x00401080L, 0x00000001L, +0x00001081L, 0x00401001L, 0x00000080L, 0x00400000L, +0x00001081L, 0x00401000L, 0x00401001L, 0x00000081L, +0x00001000L, 0x00000080L, 0x00400000L, 0x00401001L, +0x00400081L, 0x00001081L, 0x00001080L, 0x00000000L, +0x00000080L, 0x00400001L, 0x00000001L, 0x00400080L, +0x00000000L, 0x00400081L, 0x00400080L, 0x00001080L, +0x00000081L, 0x00001000L, 0x00401081L, 0x00400000L, +0x00401080L, 0x00000001L, 0x00001001L, 0x00401081L, +0x00400001L, 0x00401080L, 0x00401000L, 0x00001001L, + +/* nibble 7 */ +0x08200020L, 0x08208000L, 0x00008020L, 0x00000000L, +0x08008000L, 0x00200020L, 0x08200000L, 0x08208020L, +0x00000020L, 0x08000000L, 0x00208000L, 0x00008020L, +0x00208020L, 0x08008020L, 0x08000020L, 0x08200000L, +0x00008000L, 0x00208020L, 0x00200020L, 0x08008000L, +0x08208020L, 0x08000020L, 0x00000000L, 0x00208000L, +0x08000000L, 0x00200000L, 0x08008020L, 0x08200020L, +0x00200000L, 0x00008000L, 0x08208000L, 0x00000020L, +0x00200000L, 0x00008000L, 0x08000020L, 0x08208020L, +0x00008020L, 0x08000000L, 0x00000000L, 0x00208000L, +0x08200020L, 0x08008020L, 0x08008000L, 0x00200020L, +0x08208000L, 0x00000020L, 0x00200020L, 0x08008000L, +0x08208020L, 0x00200000L, 0x08200000L, 0x08000020L, +0x00208000L, 0x00008020L, 0x08008020L, 0x08200000L, +0x00000020L, 0x08208000L, 0x00208020L, 0x00000000L, +0x08000000L, 0x08200020L, 0x00008000L, 0x00208020L}; diff --git a/third_party/cryptlib-0.99/libdes/version.h b/third_party/cryptlib-0.99/libdes/version.h new file mode 100644 index 0000000..b823f85 --- /dev/null +++ b/third_party/cryptlib-0.99/libdes/version.h @@ -0,0 +1,9 @@ +/* version.h */ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). + * All rights reserved. + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * See the COPYRIGHT file in the libdes distribution for more details. + */ + +static const char *version="libdes v 3.14 - eay"; diff --git a/third_party/cryptlib-0.99/makefile b/third_party/cryptlib-0.99/makefile new file mode 100644 index 0000000..dcde21b --- /dev/null +++ b/third_party/cryptlib-0.99/makefile @@ -0,0 +1,271 @@ +#**************************************************************************** +#* * +#* Makefile for the encryption library * +#* * +#**************************************************************************** + +PROJ = crypt +LIBNAME = lib$(PROJ).a + +CFLAGS = -c -D__UNIX__ -O -I. $(CMDC) # Flags for compiler + +LFLAGS = $(CMDL) # Flags for linker + +OUTPATH = # Where object files go (/tmp is a good place) +OBJ = .o # Extension for object files + +LD = $(CC) # Linker (just use the C compiler) +ECHO = echo # Echo to screen command +MAKE = make # The make command + +# The object files which make up the library + +OBJS = $(OUTPATH)crypt$(OBJ) $(OUTPATH)lib_3des$(OBJ) \ + $(OUTPATH)lib_des$(OBJ) $(OUTPATH)lib_idea$(OBJ) \ + $(OUTPATH)lib_mdc$(OBJ) $(OUTPATH)lib_null$(OBJ) \ + $(OUTPATH)lib_rc4$(OBJ) $(OUTPATH)lib_safr$(OBJ) \ + $(OUTPATH)idea$(OBJ) $(OUTPATH)3ecb_enc$(OBJ) \ + $(OUTPATH)ecb_enc$(OBJ) $(OUTPATH)pcbc_enc$(OBJ) \ + $(OUTPATH)set_key$(OBJ) $(OUTPATH)rc4$(OBJ) \ + $(OUTPATH)safer$(OBJ) $(OUTPATH)shs$(OBJ) + +#**************************************************************************** +#* * +#* If no args are given, print a usage message and exit * +#* * +#**************************************************************************** + +default: + @$(ECHO) + @$(ECHO) "Usage: make " + @$(ECHO) + @$(ECHO) "To create the encryption library, you have to enter the Unix system type" + @$(ECHO) "you want to build it for. Possible options are: aix, aix370, aix386," + @$(ECHO) "bsd386, convex, irix, hpux, hpux-gcc, isc, linux, mint, mipsbsd, next, osf1," + @$(ECHO) "qnx, sco, sun, svr4, ultrix, and uts4. If none of the above fit, try 'make " + @$(ECHO) "generic', and send a copy of any changes necessary to the author, " + @$(ECHO) "pgut01@cs.auckland.ac.nz" + @$(ECHO) + @$(ECHO) "After the library has been created, use 'make test' to build a test program" + @$(ECHO) "with it." + +# Frohe Ostern. + +babies: + @$(ECHO) "Good grief, what do you think I am? The Unix environment is capable, but" + @$(ECHO) "not that capable." + +cookies: + @$(ECHO) "Mix 250g flour, 150g sugar, 125g butter, an egg, a few drops of vanilla" + @$(ECHO) "essence, and 1 tsp baking powder into a dough, cut cookies from rolls of" + @$(ECHO) "dough, bake for about 15 minutes at 180C until they turn very light brown" + @$(ECHO) "at the edges." + +love: + @$(ECHO) "Nicht wahr?" + @$(ECHO) + +#**************************************************************************** +#* * +#* Rules to build the encryption library * +#* * +#**************************************************************************** + +# Main directory + +$(OUTPATH)crypt$(OBJ): crypt.h crypt.c + $(CC) $(CFLAGS) crypt.c + +$(OUTPATH)lib_3des$(OBJ): crypt.h libdes/des.h lib_3des.c + $(CC) $(CFLAGS) lib_3des.c + +$(OUTPATH)lib_des$(OBJ): crypt.h testdes.h libdes/des.h lib_des.c + $(CC) $(CFLAGS) lib_des.c + +$(OUTPATH)lib_idea$(OBJ): crypt.h idea/idea.h testidea.h lib_idea.c + $(CC) $(CFLAGS) lib_idea.c + +$(OUTPATH)lib_mdc$(OBJ): crypt.h mdc/shs.h lib_mdc.c + $(CC) $(CFLAGS) lib_mdc.c + +$(OUTPATH)lib_null$(OBJ): crypt.h lib_null.c + $(CC) $(CFLAGS) lib_null.c + +$(OUTPATH)lib_rc4$(OBJ): crypt.h testrc4.h rc4/rc4.h lib_rc4.c + $(CC) $(CFLAGS) lib_rc4.c + +$(OUTPATH)lib_safr$(OBJ): crypt.h testsafr.h safer/safer.h lib_safr.c + $(CC) $(CFLAGS) lib_safr.c + +$(OUTPATH)test$(OBJ): crypt.h test.c + $(CC) $(CFLAGS) test.c + +# idea subdirectory + +$(OUTPATH)idea$(OBJ): idea/idea.h idea/idea.c + $(CC) $(CFLAGS) idea/idea.c + +# libdes subdirectory + +$(OUTPATH)3ecb_enc$(OBJ): libdes/des.h libdes/des_locl.h libdes/3ecb_enc.c + $(CC) $(CFLAGS) libdes/3ecb_enc.c + +$(OUTPATH)ecb_enc$(OBJ): libdes/des.h libdes/des_locl.h libdes/spr.h \ + libdes/version.h libdes/ecb_enc.c + $(CC) $(CFLAGS) libdes/ecb_enc.c + +$(OUTPATH)pcbc_enc$(OBJ): libdes/des.h libdes/des_locl.h libdes/pcbc_enc.c + $(CC) $(CFLAGS) libdes/pcbc_enc.c + +$(OUTPATH)set_key$(OBJ): libdes/des.h libdes/des_locl.h libdes/podd.h \ + libdes/sk.h libdes/set_key.c + $(CC) $(CFLAGS) libdes/set_key.c + +# rc4 subdirectory + +$(OUTPATH)rc4$(OBJ): rc4/rc4.h rc4/rc4.c + $(CC) $(CFLAGS) rc4/rc4.c + +# safer subdirectory + +$(OUTPATH)safer$(OBJ): safer/safer.h safer/safer.c + $(CC) $(CFLAGS) safer/safer.c + +# mdc subdirectory + +$(OUTPATH)shs$(OBJ): mdc/shs.h mdc/shs.c + $(CC) $(CFLAGS) mdc/shs.c + +# Create the library. The test program is also listed as a dependancy +# since we need to use OS-specific compiler options for it which a +# simple 'make test' won't give us (yuck). + +$(LIBNAME): $(OBJS) $(OUTPATH)test$(OBJ) + ar rc $(LIBNAME) $(OBJS) + +# Link everything into a test program + +test: $(LIBNAME) $(OUTPATH)test$(OBJ) + @$(LD) -o testcrypt $(LFLAGS) $(OUTPATH)test$(OBJ) -L. -l$(PROJ) + +#**************************************************************************** +#* * +#* Defines for each variation of Unix * +#* * +#**************************************************************************** + +# AIX for the RS6000: Use cc. Differs from AIX370/386 in endianness + +aix: + @$(MAKE) $(LIBNAME) CC="cc" + +# AIX370, AIX386: Use cc + +aix370: + @$(MAKE) $(LIBNAME) CC="cc" +aix386: + @$(MAKE) $(LIBNAME) CC="cc" + +# AUX: The only Unix so bloated it has /etc.etc.etc + +# BSD 386: Use cc + +bsd386: + @$(MAKE) $(LIBNAME) CC="cc" + +# Convex: Use cc (cc has some bugs) + +convex: + @$(MAKE) $(LIBNAME) CC="cc" + +# Esix: Run away!! Run away!! + +# Generic: Generic BSD-ish system running gcc + +generic: + @$(MAKE) $(LIBNAME) CC="gcc" + +# HPUX: Use cc if you have the ANSI C compiler, otherwise use gcc +# Need to use '-Aa -D_HPUX_SOURCE' as compiler options to get +# C compiler into ANSI C mode with UNIX symbols. + +hpux: + @$(MAKE) $(LIBNAME) CMDC="-Aa -D_HPUX_SOURCE +O3" CC="cc" + +hpux-gcc: + @$(MAKE) $(LIBNAME) CC="gcc" + +# Irix: Use cc with the -acpp flag for maximum ANSI-ness + +irix: + @$(MAKE) $(LIBNAME) CMDC="-acpp" CC="cc" + +# ISC Unix: Use gcc + +isc: + @$(MAKE) $(LIBNAME) CC="gcc" + +# Linux: Use gcc + +linux: + @$(MAKE) $(LIBNAME) CC="gcc" + +# MiNT: Use gcc + +mint: + @$(MAKE) $(LIBNAME) CC="gcc" + +# Risc/OS 4: Use gcc + +mipsbsd: + @$(MAKE) $(LIBNAME) CC="gcc" + +# NeXT 3.0: Use cc + +next: + @$(MAKE) $(LIBNAME) CMDC="-O2" CMDL="-object -s" CC="cc" + +# OSF 1: Use gcc + +osf1: + @$(MAKE) $(LIBNAME) CC="gcc" + +# QNX 4.x: Use cc -ml, ld -N32768 -ml + +qnx: + @$(MAKE) $(LIBNAME) CMDC="-ml" CMDL="-N32768 -ml" CC="cc" + +# SCO: Use cc. + +sco: + @$(MAKE) $(LIBNAME) CC="cc" + +# Sun/Slowaris: Use gcc + +sun: + @$(MAKE) $(LIBNAME) CC="gcc" + +# SVR4: Use cc. Better results can be obtained by upgrading your OS to +# 4.4 BSD. + +svr4: + @$(MAKE) $(LIBNAME) CC="cc" + +# Ultrix: Use vcc or gcc + +ultrix: + @$(MAKE) $(LIBNAME) CC="gcc" + +# Amdahl UTS 4: Use cc + +uts4: + @$(MAKE) $(LIBNAME) CMDC="-Xc", CC="cc" + +#**************************************************************************** +#* * +#* Cleanup after make has finished * +#* * +#**************************************************************************** + +clean: + rm -f *.o core testcrypt $(LIBNAME) diff --git a/third_party/cryptlib-0.99/mdc/shs.c b/third_party/cryptlib-0.99/mdc/shs.c new file mode 100644 index 0000000..5d346a5 --- /dev/null +++ b/third_party/cryptlib-0.99/mdc/shs.c @@ -0,0 +1,540 @@ +#include +#ifdef _MSC_VER + #include "../crypt.h" + #include "shs.h" +#else + #include "crypt.h" + #include "mdc/shs.h" +#endif /* _MSC_VER */ + +/* The SHS f()-functions. The f1 and f3 functions can be optimized to + save one boolean operation each - thanks to Rich Schroeppel, + rcs@cs.arizona.edu for discovering this */ + +/*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) // Rounds 0-19 */ +#define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +/*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) // Rounds 40-59 */ +#define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + +/* The SHS Mysterious Constants */ + +#define K1 0x5A827999UL /* Rounds 0-19 */ +#define K2 0x6ED9EBA1UL /* Rounds 20-39 */ +#define K3 0x8F1BBCDCUL /* Rounds 40-59 */ +#define K4 0xCA62C1D6UL /* Rounds 60-79 */ + +/* SHS initial values */ + +#define h0init 0x67452301UL +#define h1init 0xEFCDAB89UL +#define h2init 0x98BADCFEUL +#define h3init 0x10325476UL +#define h4init 0xC3D2E1F0UL + +/* Note that it may be necessary to add parentheses to these macros if they + are to be called with expressions as arguments */ + +/* 32-bit rotate left - kludged with shifts */ + +#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) ) + +/* The initial expanding function. The hash function is defined over an + 80-word expanded input array W, where the first 16 are copies of the input + data, and the remaining 64 are defined by + + W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ] + + This implementation generates these values on the fly in a circular + buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this + optimization. + + The updated SHS changes the expanding function by adding a rotate of 1 + bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor + for this information */ + +#ifdef NEW_SHS + #define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ i - 14 & 15 ] ^ \ + W[ i - 8 & 15 ] ^ W[ i - 3 & 15 ] ) ) ) +#else + #define expand(W,i) ( W[ i & 15 ] ^= W[ i - 14 & 15 ] ^ W[ i - 8 & 15 ] ^ W[ i - 3 & 15 ] ) +#endif /* NEW_SHS */ + +/* The prototype SHS sub-round. The fundamental sub-round is: + + a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; + b' = a; + c' = ROTL( 30, b ); + d' = c; + e' = d; + + but this is implemented by unrolling the loop 5 times and renaming the + variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. + This code is then replicated 20 times for each of the 4 functions, using + the next 20 values from the W[] array each time */ + +#ifdef _BIG_WORDS + #define subRound(a, b, c, d, e, f, k, data) \ + e += ROTL( 5, a ) + f( b, c, d ) + k + data; \ + e &= 0xFFFFFFFFUL; \ + b = ROTL( 30, b ) & 0xFFFFFFFFUL +#else + #define subRound(a, b, c, d, e, f, k, data) \ + ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) +#endif /* _BIG_WORDS */ + +/* Initialize the SHS values */ + +void shsInit( SHS_INFO *shsInfo ) + { + /* Set the h-vars to their initial values */ + shsInfo->digest[ 0 ] = h0init; + shsInfo->digest[ 1 ] = h1init; + shsInfo->digest[ 2 ] = h2init; + shsInfo->digest[ 3 ] = h3init; + shsInfo->digest[ 4 ] = h4init; + + /* Initialise bit count */ + shsInfo->countLo = shsInfo->countHi = 0; + } + +#ifndef ASM_SHS + +/* Perform the SHS transformation. Note that this code, like MD5, seems to + break some optimizing compilers due to the complexity of the expressions + and the size of the basic block. It may be necessary to split it into + sections, e.g. based on the four subrounds */ + +void SHSTransform( LONG *digest, LONG *data ) + { + LONG A, B, C, D, E; /* Local vars */ + LONG eData[ 16 ]; /* Expanded data */ + int i; + + /* Set up first buffer and local data buffer */ + A = digest[ 0 ]; + B = digest[ 1 ]; + C = digest[ 2 ]; + D = digest[ 3 ]; + E = digest[ 4 ]; + for( i = 0; i < 16; i++ ) + eData[ i ] = data[ i ]; + + /* Heavy mangling, in 4 sub-rounds of 20 interations each. */ + subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 2 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 3 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 4 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 5 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 6 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 7 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 8 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 9 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 10 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 11 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 12 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 13 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 14 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 15 ] ); + subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) ); + subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) ); + subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) ); + subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) ); + + subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) ); + + subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) ); + + subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) ); + + /* Build message digest */ +#ifdef _BIG_WORDS + digest[ 0 ] = ( digest[ 0 ] + A ) & 0xFFFFFFFFUL; + digest[ 1 ] = ( digest[ 1 ] + B ) & 0xFFFFFFFFUL; + digest[ 2 ] = ( digest[ 2 ] + C ) & 0xFFFFFFFFUL; + digest[ 3 ] = ( digest[ 3 ] + D ) & 0xFFFFFFFFUL; + digest[ 4 ] = ( digest[ 4 ] + E ) & 0xFFFFFFFFUL; +#else + digest[ 0 ] += A; + digest[ 1 ] += B; + digest[ 2 ] += C; + digest[ 3 ] += D; + digest[ 4 ] += E; +#endif /* _BIG_WORDS */ + } +#else + void SHSTransform( LONG *digest, LONG *data ); +#endif /* !ASM_SHS */ + +#ifdef TEST_SHS + +/* When run on a little-endian CPU we need to perform byte reversal on an + array of longwords. It is possible to make the code endianness- + independant by fiddling around with data at the byte level, but this + makes for very slow code, so we rely on the user to sort out endianness + at compile time */ + +#if defined( LITTLE_ENDIAN ) + +void longReverse( LONG *buffer, int byteCount ) + { + LONG value; + + byteCount /= sizeof( LONG ); + while( byteCount-- ) + { + value = *buffer; + value = ( ( value & 0xFF00FF00L ) >> 8 ) | \ + ( ( value & 0x00FF00FFL ) << 8 ); + *buffer++ = ( value << 16 ) | ( value >> 16 ); + } + } +#else + #define longReverse(buf, count) +#endif /* LITTLE_ENDIAN */ + +#endif /* TEST_SHS */ + +#ifdef _BIG_WORDS + +/* When run on a CPU with > 32 bit word size, we need to move the data from + the byte-aligned buffer to the final word-aligned data buffer. We perform + the endianness-reversal at the same time */ + +static void extractData( SHS_INFO *shsInfo ) + { + BYTE *bufferPtr = shsInfo->dataBuffer; + int i; + + for( i = 0; i < 16; i++ ) + { + shsInfo->data[ i ] = ( ( LONG ) bufferPtr[ 0 ] << 24 ) | \ + ( ( LONG ) bufferPtr[ 1 ] << 16 ) | \ + ( ( LONG ) bufferPtr[ 2 ] << 8 ) | \ + ( ( LONG ) bufferPtr[ 3 ] ); + bufferPtr += 4; + } + } + +#endif /* _BIG_WORDS */ + +/* Update SHS for a block of data */ + +void shsUpdate( SHS_INFO *shsInfo, BYTE *buffer, int count ) + { + LONG tmp; + int dataCount; + + /* Update bitcount */ + tmp = shsInfo->countLo; + if ( ( shsInfo->countLo = tmp + ( ( LONG ) count << 3 ) ) < tmp ) + shsInfo->countHi++; /* Carry from low to high */ + shsInfo->countHi += count >> 29; + + /* Get count of bytes already in data */ + dataCount = ( int ) ( tmp >> 3 ) & 0x3F; + + /* Handle any leading odd-sized chunks */ + if( dataCount ) + { +#ifdef _BIG_WORDS + BYTE *p = shsInfo->dataBuffer + dataCount; +#else + BYTE *p = ( BYTE * ) shsInfo->data + dataCount; +#endif /* _BIG_WORDS */ + + dataCount = SHS_DATASIZE - dataCount; + if( count < dataCount ) + { + memcpy( p, buffer, count ); + return; + } + memcpy( p, buffer, dataCount ); +#ifdef _BIG_WORDS + extractData( shsInfo ); +#else + longReverse( shsInfo->data, SHS_DATASIZE ); +#endif /* _BIG_WORDS */ + SHSTransform( shsInfo->digest, shsInfo->data ); + buffer += dataCount; + count -= dataCount; + } + + /* Process data in SHS_DATASIZE chunks */ + while( count >= SHS_DATASIZE ) + { +#ifdef _BIG_WORDS + memcpy( shsInfo->dataBuffer, buffer, SHS_DATASIZE ); + extractData( shsInfo ); +#else + memcpy( shsInfo->data, buffer, SHS_DATASIZE ); + longReverse( shsInfo->data, SHS_DATASIZE ); +#endif /* _BIG_WORDS */ + SHSTransform( shsInfo->digest, shsInfo->data ); + buffer += SHS_DATASIZE; + count -= SHS_DATASIZE; + } + + /* Handle any remaining bytes of data. */ +#ifdef _BIG_WORDS + memcpy( shsInfo->dataBuffer, buffer, count ); +#else + memcpy( shsInfo->data, buffer, count ); +#endif /* _BIG_WORDS */ + } + +/* Final wrapup - pad to SHS_DATASIZE-byte boundary with the bit pattern + 1 0* (64-bit count of bits processed, MSB-first) */ + +void shsFinal( SHS_INFO *shsInfo ) + { + int count; + BYTE *dataPtr; + + /* Compute number of bytes mod 64 */ + count = ( int ) shsInfo->countLo; + count = ( count >> 3 ) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ +#ifdef _BIG_WORDS + dataPtr = shsInfo->dataBuffer + count; +#else + dataPtr = ( BYTE * ) shsInfo->data + count; +#endif /* _BIG_WORDS */ + *dataPtr++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = SHS_DATASIZE - 1 - count; + + /* Pad out to 56 mod 64 */ + if( count < 8 ) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset( dataPtr, 0, count ); +#ifdef _BIG_WORDS + extractData( shsInfo ); +#else + longReverse( shsInfo->data, SHS_DATASIZE ); +#endif /* _BIG_WORDS */ + SHSTransform( shsInfo->digest, shsInfo->data ); + + /* Now fill the next block with 56 bytes */ +#ifdef _BIG_WORDS + memset( shsInfo->dataBuffer, 0, SHS_DATASIZE - 8 ); +#else + memset( shsInfo->data, 0, SHS_DATASIZE - 8 ); +#endif /* _BIG_WORDS */ + } + else + /* Pad block to 56 bytes */ + memset( dataPtr, 0, count - 8 ); +#ifdef _BIG_WORDS + extractData( shsInfo ); +#endif /* _BIG_WORDS */ + + /* Append length in bits and transform */ + shsInfo->data[ 14 ] = shsInfo->countHi; + shsInfo->data[ 15 ] = shsInfo->countLo; + +#ifndef _BIG_WORDS + longReverse( shsInfo->data, SHS_DATASIZE - 8 ); +#endif /* _BIG_WORDS */ + SHSTransform( shsInfo->digest, shsInfo->data ); + } + +/**************************************************************************** +* * +* SHS Test Code * +* * +****************************************************************************/ + +#ifdef TEST_SHS + +#include +#include +#include + +/* Defines for the standalone test version */ + +#define ERROR -1 +#define OK 0 + +/* Test the SHS implementation */ + +#ifdef NEW_SHS + +static LONG shsTestResults[][ 5 ] = { + { 0xA9993E36L, 0x4706816AL, 0xBA3E2571L, 0x7850C26CL, 0x9CD0D89DL, }, + { 0x84983E44L, 0x1C3BD26EL, 0xBAAE4AA1L, 0xF95129E5L, 0xE54670F1L, }, + { 0x34AA973CL, 0xD4C4DAA4L, 0xF61EEB2BL, 0xDBAD2731L, 0x6534016FL, } + }; + +#else + +static LONG shsTestResults[][ 5 ] = { + { 0x0164B8A9L, 0x14CD2A5EL, 0x74C4F7FFL, 0x082C4D97L, 0xF1EDF880L }, + { 0xD2516EE1L, 0xACFA5BAFL, 0x33DFC1C4L, 0x71E43844L, 0x9EF134C8L }, + { 0x3232AFFAL, 0x48628A26L, 0x653B5AAAL, 0x44541FD9L, 0x0D690603L } + }; +#endif /* NEW_SHS */ + +static int compareSHSresults( SHS_INFO *shsInfo, int shsTestLevel ) + { + int i; + + /* Compare the returned digest and required values */ + for( i = 0; i < 5; i++ ) + if( shsInfo->digest[ i ] != shsTestResults[ shsTestLevel ][ i ] ) + return( ERROR ); + return( OK ); + } + +void main( void ) + { + SHS_INFO shsInfo; + unsigned int i; + time_t secondCount; + BYTE data[ 200 ]; + + /* Make sure we've got the endianness set right. If the machine is + big-endian (up to 64 bits) the following value will be signed, + otherwise it will be unsigned. Unfortunately we can't test for odd + things like middle-endianness without knowing the size of the data + types */ +#ifdef LITTLE_ENDIAN + if( *( long * ) "\x80\x00\x00\x00\x00\x00\x00\x00" < 0 ) + { + puts( "Error: Comment out the LITTLE_ENDIAN define in SHS.H and recompile" ); + exit( ERROR ); + } +#else + if( *( long * ) "\x80\x00\x00\x00\x00\x00\x00\x00" >= 0 ) + { + puts( "Error: Uncomment the LITTLE_ENDIAN define in SHS.H and recompile" ); + exit( ERROR ); + } +#endif /* LITTLE_ENDIAN */ + + /* Test SHS against values given in SHS standards document */ + printf( "Running SHS test 1 ... " ); + shsInit( &shsInfo ); + shsUpdate( &shsInfo, ( BYTE * ) "abc", 3 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 0 ) == ERROR ) + { + putchar( '\n' ); + puts( "SHS test 1 failed" ); + exit( ERROR ); + } +#ifdef NEW_SHS + puts( "passed, result= A9993E364706816ABA3E25717850C26C9CD0D89D" ); +#else + puts( "passed, result= 0164B8A914CD2A5E74C4F7FF082C4D97F1EDF880" ); +#endif /* NEW_SHS */ + + printf( "Running SHS test 2 ... " ); + shsInit( &shsInfo ); + shsUpdate( &shsInfo, ( BYTE * ) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 1 ) == ERROR ) + { + putchar( '\n' ); + puts( "SHS test 2 failed" ); + exit( ERROR ); + } +#ifdef NEW_SHS + puts( "passed, result= 84983E441C3BD26EBAAE4AA1F95129E5E54670F1" ); +#else + puts( "passed, result= D2516EE1ACFA5BAF33DFC1C471E438449EF134C8" ); +#endif /* NEW_SHS */ + + printf( "Running SHS test 3 ... " ); + shsInit( &shsInfo ); + for( i = 0; i < 15625; i++ ) + shsUpdate( &shsInfo, ( BYTE * ) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 2 ) == ERROR ) + { + putchar( '\n' ); + puts( "SHS test 3 failed" ); + exit( ERROR ); + } +#ifdef NEW_SHS + puts( "passed, result= 34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" ); +#else + puts( "passed, result= 3232AFFA48628A26653B5AAA44541FD90D690603" ); +#endif /* NEW_SHS */ + + printf( "\nTesting speed for 10MB data... " ); + shsInit( &shsInfo ); + secondCount = time( NULL ); + for( i = 0; i < 50000U; i++ ) + shsUpdate( &shsInfo, data, 200 ); + secondCount = time( NULL ) - secondCount; + printf( "done. Time = %ld seconds, %ld kbytes/second\n", \ + secondCount, 10050L / secondCount ); + + puts( "\nAll SHS tests passed" ); + exit( OK ); + } +#endif /* TEST_SHS */ diff --git a/third_party/cryptlib-0.99/mdc/shs.h b/third_party/cryptlib-0.99/mdc/shs.h new file mode 100644 index 0000000..cb7c6db --- /dev/null +++ b/third_party/cryptlib-0.99/mdc/shs.h @@ -0,0 +1,35 @@ +#ifndef _SHS_DEFINED + +#define _SHS_DEFINED + +/* Define the following to compile the SHS test code */ + +/*#define TEST_SHS*/ + +/* Define the following to use the updated SHS implementation */ + +/*#define NEW_SHS*/ + +/* The SHS block size and message digest sizes, in bytes */ + +#define SHS_DATASIZE 64 +#define SHS_DIGESTSIZE 20 + +/* The structure for storing SHS info */ + +typedef struct { + LONG digest[ 5 ]; /* Message digest */ + LONG countLo, countHi; /* 64-bit bit count */ + LONG data[ 16 ]; /* SHS data buffer */ +#ifdef _BIG_WORDS + BYTE dataBuffer[ SHS_DATASIZE ]; /* Byte buffer for data */ +#endif /* _BIG_WORDS */ + } SHS_INFO; + +/* Message digest functions */ + +void shsInit( SHS_INFO *shsInfo ); +void shsUpdate( SHS_INFO *shsInfo, BYTE *buffer, int count ); +void shsFinal( SHS_INFO *shsInfo ); + +#endif /* _SHS_DEFINED */ diff --git a/third_party/cryptlib-0.99/rc4/rc4.asm b/third_party/cryptlib-0.99/rc4/rc4.asm new file mode 100644 index 0000000..96ee9a1 --- /dev/null +++ b/third_party/cryptlib-0.99/rc4/rc4.asm @@ -0,0 +1,137 @@ +; Simple RC4 implementation, Peter Gutmann, 21 September 1995. +; This code was written in about 30 minutes as a testbed for an asm.RC4. It +; uses a static data area as the key so it's not terribly practical as it +; stands. In addition, the RC4 algorithm leads to an almost solid block of +; pipeline stalls on anything >= '486, so I wouldn't recommend using it on +; anything except perhaps 8-bit microcontrollers and smart cards. + + INCLUDE MISC.INC + MODULE RC4 + + PUBLIC _rc4expandKey, _rc4crypt + + DATA + +; The RC4 keying information + +rc4key DB 256 DUP (?) +rc4x DB 0 +rc4y DB 0 + + CODE + +; void rc4ExpandKey( unsigned char const *key, int keylen ) + +_rc4expandKey PROCEDURE + push bp + mov bp, sp + push si + push di ; Save register vars + les si, [bp+4] ; ES:SI = key + mov dx, [bp+8] ; DX = keylen + mov dh, dl ; keylenTmp = keylen + + ; rc4word y = 0; + xor ax, ax ; y = 0 + sub di, di ; DI = AX as an index register + + ; for( x = 0; x < 256; x++ ) + ; rc4key[ x ] = x; + xor bx, bx ; x = 0 +@@initLoop: + mov rc4key[bx], bl ; rc4key[ x ] = x + inc bl ; x++ + jnz SHORT @@initLoop + + ; for( x = 0; x < 256; x++ ) + ; { + ; sx = rc4key[ x ]; + ; y += sx + key[ keypos ]; + ; rc4key[ x ] = rc4key[ y ]; + ; rc4key[ y ] = sx; + ; + ; if( ++keypos == keylen ) + ; keypos = 0; + ; } +@@keyLoop: + mov cl, rc4key[bx] ; sx = rc4key[ x ] + add al, es:[si] ; y += key[ keypos ] + add al, cl ; y += sx + mov di, ax + mov ch, rc4key[di] ; temp = rc4key[ y ] + mov rc4key[bx], ch ; rc4key[ x ] = temp + mov rc4key[di], cl ; rc4key[ y ] = sx + inc si ; ++keypos + dec dh ; keylenTmp-- + jnz SHORT @@noResetKeypos ; if( !keylenTmp ) + sub si, dx ; keypos = 0 + mov dh, dl ; keylenTmp = keylen +@@noResetKeypos: + inc bl ; x++ + jnz SHORT @@keyLoop + + ; rc4->x = rc4->y = 0; + mov rc4x, bl ; rc4->x = 0 + mov rc4y, bl ; rc4->y = 0 + + pop di + pop si ; Restore register vars + pop bp + ret +_rc4expandKey ENDP + +; void rc4Crypt( unsigned char *data, int len ) + +_rc4crypt PROCEDURE + push bp + mov bp, sp + push si + push di ; Save register vars + les si, [bp+4] ; ES:SI = data + mov dx, [bp+8] ; DX = len + test dx, dx ; Check that len != 0 + jz SHORT @@exit ; Yes, exit now + + xor bx, bx + mov bl, rc4x ; BX = rc4x + xor ax, ax + mov al, rc4y ; AX = rc4y + xor di, di ; DI = AX as an index register + + ; while( len-- ) + ; { + ; x++; + ; sx = rc4key[ x ]; + ; y += sx; + ; sy = rc4key[ y ]; + ; rc4key[ y ] = sx; + ; rc4key[ x ] = sy; + ; *data++ ^= rc4key[ ( sx + sy ) & 0xFF ]; + ; } +@@rc4loop: + inc bl ; x++ + mov cl, rc4key[bx] ; sx = rc4key[ x ] + add al, cl ; y += sx + mov di, ax + mov ch, rc4key[di] ; sy = rc4key[ y ] + mov rc4key[di], cl ; rc4key[ y ] = sx + mov rc4key[bx], ch ; rc4key[ x ] = sy + add cl, ch + xor ch, ch + mov di, cx ; temp = ( sx + sy ) & 0xFF + mov cl, rc4key[di] + xor es:[si], cl ; *data ^= rc4key[ temp ] + inc si ; data++ + dec dx ; len-- + jnz SHORT @@rc4loop + + mov rc4x, bl + mov rc4y, al ; Remember x and y values + +@@exit: + pop di + pop si ; Restore register vars + pop bp + ret +_rc4crypt ENDP +ENDMODULE diff --git a/third_party/cryptlib-0.99/rc4/rc4.c b/third_party/cryptlib-0.99/rc4/rc4.c new file mode 100644 index 0000000..c38cd81 --- /dev/null +++ b/third_party/cryptlib-0.99/rc4/rc4.c @@ -0,0 +1,65 @@ +/* Optimized RC4 code, from an unknown source ("and they knew not from whence + it had come...") */ + +#ifdef _MSC_VER + #include "rc4.h" +#else + #include "rc4/rc4.h" +#endif /* _MSC_VER */ + +void rc4ExpandKey( RC4KEY *rc4, unsigned char const *key, int keylen ) + { + int x, keypos = 0; + rc4word sx, y = 0; + rc4word *state = &rc4->state[ 0 ]; + + rc4->x = rc4->y = 0; + + for( x = 0; x < 256; x++ ) + state[ x ] = x; + + for( x = 0; x < 256; x++ ) + { + sx = state[ x ]; + y += sx + key[ keypos ]; +#ifdef USE_LONG_RC4 + y &= 0xFF; +#endif /* USE_LONG_RC4 */ + state[ x ] = state[ y ]; + state[ y ] = sx; + + if( ++keypos == keylen ) + keypos = 0; + } + } + +void rc4Crypt( RC4KEY *rc4, unsigned char *data, int len ) +{ + rc4word x = rc4->x, y = rc4->y; + rc4word sx, sy; + rc4word *state = &rc4->state[ 0 ]; + + while (len--) { + x++; +#ifdef USE_LONG_RC4 + x &= 0xFF; +#endif /* USE_LONG_RC4 */ + sx = state[ x ]; + y += sx; +#ifdef USE_LONG_RC4 + y &= 0xFF; +#endif /* USE_LONG_RC4 */ + sy = state[ y ]; + state[ y ] = sx; + state[ x ] = sy; + +#ifdef USE_LONG_RC4 + *data++ ^= state[ ( unsigned char ) ( sx+sy ) ]; +#else + *data++ ^= state[ ( sx+sy ) & 0xFF ]; +#endif /* USE_LONG_RC4 */ + } + + rc4->x = x; + rc4->y = y; +} diff --git a/third_party/cryptlib-0.99/rc4/rc4.h b/third_party/cryptlib-0.99/rc4/rc4.h new file mode 100644 index 0000000..1e54565 --- /dev/null +++ b/third_party/cryptlib-0.99/rc4/rc4.h @@ -0,0 +1,23 @@ +#include + +/* If the system can handle byte ops, we use those so we don't have to do a + lot of masking. Otherwise, we use machine-word-size ops which will be + faster on RISC machines */ + +#if UINT_MAX > 0xFFFFL /* System has 32-bit ints */ + #define USE_LONG_RC4 + + typedef unsigned int rc4word; +#else + typedef unsigned char rc4word; +#endif /* UINT_MAX > 0xFFFFL */ + +/* The scheduled RC4 key */ + +typedef struct { + rc4word state[ 256 ]; + rc4word x, y; + } RC4KEY ; + +void rc4ExpandKey( RC4KEY *rc4, unsigned char const *key, int keylen ); +void rc4Crypt( RC4KEY *rc4, unsigned char *data, int len ); diff --git a/third_party/cryptlib-0.99/safer/safer.c b/third_party/cryptlib-0.99/safer/safer.c new file mode 100644 index 0000000..a275b66 --- /dev/null +++ b/third_party/cryptlib-0.99/safer/safer.c @@ -0,0 +1,203 @@ +/******************************************************************************* +* +* FILE: safer.c +* +* DESCRIPTION: block-cipher algorithm SAFER (Secure And Fast Encryption +* Routine) in its four versions: SAFER K-64, SAFER K-128, +* SAFER SK-64 and SAFER SK-128. +* +* AUTHOR: Richard De Moliner (demoliner@isi.ee.ethz.ch) +* Signal and Information Processing Laboratory +* Swiss Federal Institute of Technology +* CH-8092 Zuerich, Switzerland +* +* DATE: September 9, 1995 +* +* CHANGE HISTORY: +* +*******************************************************************************/ + +/******************* External Headers *****************************************/ + +/******************* Local Headers ********************************************/ +#ifdef _MSC_VER + #include "safer.h" +#else + #include "safer/safer.h" +#endif /* _MSC_VER */ + +/******************* Constants ************************************************/ +#define TAB_LEN 256 + +/******************* Assertions ***********************************************/ + +/******************* Macros ***************************************************/ +#define ROL(x, n) ((unsigned char)(((unsigned int)(x) << (n))\ + |((unsigned int)((x) & 0xFF) >> (8 - (n))))) +#define EXP(x) exp_tab[(x) & 0xFF] +#define LOG(x) log_tab[(x) & 0xFF] +#define PHT(x, y) { y += x; x += y; } +#define IPHT(x, y) { x -= y; y -= x; } + +/******************* Types ****************************************************/ +static unsigned char exp_tab[TAB_LEN]; +static unsigned char log_tab[TAB_LEN]; + +/******************* Module Data **********************************************/ +static int init_called = 0; +/******************* Functions ************************************************/ + +/******************************************************************************/ +#ifndef NOT_ANSI_C + void Safer_Init_Module(void) +#else + Safer_Init_Module() +#endif + +{ unsigned int i, exp; + + if (init_called) return; + + exp = 1; + for (i = 0; i < TAB_LEN; i++) + { + exp_tab[i] = (unsigned char)(exp & 0xFF); + log_tab[exp_tab[i]] = (unsigned char)i; + exp = exp * 45 % 257; + } + + init_called = 1; +} /* Safer_Init_Module */ + +/******************************************************************************/ +#ifndef NOT_ANSI_C + void Safer_Expand_Userkey(safer_block_t userkey_1, + safer_block_t userkey_2, + unsigned int nof_rounds, + int strengthened, + safer_key_t key) +#else + Safer_Expand_Userkey(userkey_1, userkey_2, nof_rounds, strengthened, key) + safer_block_t userkey_1; + safer_block_t userkey_2; + unsigned int nof_rounds; + int strengthened; + safer_key_t key; +#endif + +{ unsigned int i, j; + unsigned char ka[SAFER_BLOCK_LEN + 1]; + unsigned char kb[SAFER_BLOCK_LEN + 1]; + + if (SAFER_MAX_NOF_ROUNDS < nof_rounds) + nof_rounds = SAFER_MAX_NOF_ROUNDS; + *key++ = (unsigned char)nof_rounds; + ka[SAFER_BLOCK_LEN] = 0; + kb[SAFER_BLOCK_LEN] = 0; + for (j = 0; j < SAFER_BLOCK_LEN; j++) + { + ka[SAFER_BLOCK_LEN] ^= ka[j] = ROL(userkey_1[j], 5); + kb[SAFER_BLOCK_LEN] ^= kb[j] = *key++ = userkey_2[j]; + } + for (i = 1; i <= nof_rounds; i++) + { + for (j = 0; j < SAFER_BLOCK_LEN + 1; j++) + { + ka[j] = ROL(ka[j], 6); + kb[j] = ROL(kb[j], 6); + } + for (j = 0; j < SAFER_BLOCK_LEN; j++) + if (strengthened) + *key++ = (ka[(j + 2 * i - 1) % (SAFER_BLOCK_LEN + 1)] + + exp_tab[exp_tab[18 * i + j + 1]]) & 0xFF; + else + *key++ = (ka[j] + exp_tab[exp_tab[18 * i + j + 1]]) & 0xFF; + for (j = 0; j < SAFER_BLOCK_LEN; j++) + if (strengthened) + *key++ = (kb[(j + 2 * i) % (SAFER_BLOCK_LEN + 1)] + + exp_tab[exp_tab[18 * i + j + 10]]) & 0xFF; + else + *key++ = (kb[j] + exp_tab[exp_tab[18 * i + j + 10]]) & 0xFF; + } + for (j = 0; j < SAFER_BLOCK_LEN + 1; j++) + ka[j] = kb[j] = 0; +} /* Safer_Expand_Userkey */ + +/******************************************************************************/ +#ifndef NOT_ANSI_C + void Safer_Encrypt_Block(safer_block_t block_in, safer_key_t key, + safer_block_t block_out) +#else + Safer_Encrypt_Block(block_in, key, block_out) + safer_block_t block_in; + safer_key_t key; + safer_block_t block_out; +#endif + +{ unsigned char a, b, c, d, e, f, g, h, t; + unsigned int round; + + a = block_in[0]; b = block_in[1]; c = block_in[2]; d = block_in[3]; + e = block_in[4]; f = block_in[5]; g = block_in[6]; h = block_in[7]; + if (SAFER_MAX_NOF_ROUNDS < (round = *key)) round = SAFER_MAX_NOF_ROUNDS; + while(round--) + { + a ^= *++key; b += *++key; c += *++key; d ^= *++key; + e ^= *++key; f += *++key; g += *++key; h ^= *++key; + a = EXP(a) + *++key; b = LOG(b) ^ *++key; + c = LOG(c) ^ *++key; d = EXP(d) + *++key; + e = EXP(e) + *++key; f = LOG(f) ^ *++key; + g = LOG(g) ^ *++key; h = EXP(h) + *++key; + PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h); + PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h); + PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h); + t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t; + } + a ^= *++key; b += *++key; c += *++key; d ^= *++key; + e ^= *++key; f += *++key; g += *++key; h ^= *++key; + block_out[0] = a & 0xFF; block_out[1] = b & 0xFF; + block_out[2] = c & 0xFF; block_out[3] = d & 0xFF; + block_out[4] = e & 0xFF; block_out[5] = f & 0xFF; + block_out[6] = g & 0xFF; block_out[7] = h & 0xFF; +} /* Safer_Encrypt_Block */ + +/******************************************************************************/ +#ifndef NOT_ANSI_C + void Safer_Decrypt_Block(safer_block_t block_in, safer_key_t key, + safer_block_t block_out) +#else + Safer_Decrypt_Block(block_in, key, block_out) + safer_block_t block_in; + safer_key_t key; + safer_block_t block_out; +#endif + +{ unsigned char a, b, c, d, e, f, g, h, t; + unsigned int round; + + a = block_in[0]; b = block_in[1]; c = block_in[2]; d = block_in[3]; + e = block_in[4]; f = block_in[5]; g = block_in[6]; h = block_in[7]; + if (SAFER_MAX_NOF_ROUNDS < (round = *key)) round = SAFER_MAX_NOF_ROUNDS; + key += SAFER_BLOCK_LEN * (1 + 2 * round); + h ^= *key; g -= *--key; f -= *--key; e ^= *--key; + d ^= *--key; c -= *--key; b -= *--key; a ^= *--key; + while (round--) + { + t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t; + IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h); + IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h); + IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h); + h -= *--key; g ^= *--key; f ^= *--key; e -= *--key; + d -= *--key; c ^= *--key; b ^= *--key; a -= *--key; + h = LOG(h) ^ *--key; g = EXP(g) - *--key; + f = EXP(f) - *--key; e = LOG(e) ^ *--key; + d = LOG(d) ^ *--key; c = EXP(c) - *--key; + b = EXP(b) - *--key; a = LOG(a) ^ *--key; + } + block_out[0] = a & 0xFF; block_out[1] = b & 0xFF; + block_out[2] = c & 0xFF; block_out[3] = d & 0xFF; + block_out[4] = e & 0xFF; block_out[5] = f & 0xFF; + block_out[6] = g & 0xFF; block_out[7] = h & 0xFF; +} /* Safer_Decrypt_Block */ + +/******************************************************************************/ diff --git a/third_party/cryptlib-0.99/safer/safer.h b/third_party/cryptlib-0.99/safer/safer.h new file mode 100644 index 0000000..0474a5f --- /dev/null +++ b/third_party/cryptlib-0.99/safer/safer.h @@ -0,0 +1,114 @@ +/******************************************************************************* +* +* FILE: safer.h +* +* DESCRIPTION: block-cipher algorithm SAFER (Secure And Fast Encryption +* Routine) in its four versions: SAFER K-64, SAFER K-128, +* SAFER SK-64 and SAFER SK-128. +* +* AUTHOR: Richard De Moliner (demoliner@isi.ee.ethz.ch) +* Signal and Information Processing Laboratory +* Swiss Federal Institute of Technology +* CH-8092 Zuerich, Switzerland +* +* DATE: September 9, 1995 +* +* CHANGE HISTORY: +* +*******************************************************************************/ +#ifndef SAFER_H +#define SAFER_H + +/******************* External Headers *****************************************/ + +/******************* Local Headers ********************************************/ + +/******************* Constants ************************************************/ +#define SAFER_K64_DEFAULT_NOF_ROUNDS 6 +#define SAFER_K128_DEFAULT_NOF_ROUNDS 10 +#define SAFER_SK64_DEFAULT_NOF_ROUNDS 8 +#define SAFER_SK128_DEFAULT_NOF_ROUNDS 10 +#define SAFER_MAX_NOF_ROUNDS 13 +#define SAFER_BLOCK_LEN 8 +#define SAFER_KEY_LEN (1 + SAFER_BLOCK_LEN * (1 + 2 * SAFER_MAX_NOF_ROUNDS)) + +/******************* Assertions ***********************************************/ + +/******************* Macros ***************************************************/ + +/******************* Types ****************************************************/ +typedef unsigned char safer_block_t[SAFER_BLOCK_LEN]; +typedef unsigned char safer_key_t[SAFER_KEY_LEN]; + +/******************* Module Data **********************************************/ + +/******************* Prototypes ***********************************************/ + +/******************************************************************************* +* void Safer_Init_Module(void) +* +* initializes this module. +* +******************************************************************************** +* void Safer_Expand_Userkey(safer_block_t userkey_1, +* safer_block_t userkey_2, +* unsigned int nof_rounds, +* int strengthened, +* safer_key_t key) +* +* expands a user-selected key of length 64 bits or 128 bits to a encryption / +* decryption key. If your user-selected key is of length 64 bits, then give +* this key to both arguments 'userkey_1' and 'userkey_2', e.g. +* 'Safer_Expand_Userkey(z, z, key)'. Note: SAFER K-64 and SAFER SK-64 with a +* user-selected key 'z' of length 64 bits are identical to SAFER K-128 and +* SAFER SK-128 with a user-selected key 'z z' of length 128 bits, +* respectively. +* pre: 'userkey_1' contains the first 64 bits of user key. +* 'userkey_2' contains the second 64 bits of user key. +* 'nof_rounds' contains the number of encryption rounds +* 'nof_rounds' <= 'SAFER_MAX_NOF_ROUNDS' +* 'strengthened' is non-zero if the strengthened key schedule should be +* used and zero if the original key schedule should be +* used. +* post: 'key' contains the expanded key. +* +******************************************************************************** +* void Safer_Encrypt_Block(safer_block_t block_in, safer_key_t key, +* safer_block_t block_out) +* +* encryption algorithm. +* pre: 'block_in' contains the plain-text block. +* 'key' contains the expanded key. +* post: 'block_out' contains the cipher-text block. +* +******************************************************************************** +* void Safer_Decrypt_Block(safer_block_t block_in, safer_key_t key, +* safer_block_t block_out) +* +* decryption algorithm. +* pre: 'block_in' contains the cipher-text block. +* 'key' contains the expanded key. +* post: 'block_out' contains the plain-text block. +* +*******************************************************************************/ + +#ifndef NOT_ANSI_C + extern void Safer_Init_Module(void); + extern void Safer_Expand_Userkey(safer_block_t userkey_1, + safer_block_t userkey_2, + unsigned int nof_rounds, + int strengthened, + safer_key_t key); + extern void Safer_Encrypt_Block (safer_block_t block_in, safer_key_t key, + safer_block_t block_out); + extern void Safer_Decrypt_Block (safer_block_t block_in, safer_key_t key, + safer_block_t block_out); +#else + Safer_Init_Module(); + Safer_Expand_Userkey(); + Safer_Encrypt_Block(); + Safer_Decrypt_Block(); +#endif + +/******************************************************************************/ +#endif /* SAFER_H */ diff --git a/third_party/cryptlib-0.99/test.c b/third_party/cryptlib-0.99/test.c new file mode 100644 index 0000000..180dca9 --- /dev/null +++ b/third_party/cryptlib-0.99/test.c @@ -0,0 +1,519 @@ +#include +#include +#include +#include "crypt.h" + +/* The size of the test buffers */ + +#define TESTBUFFER_SIZE 256 + +/* Work routines: Set a pair of encrypt/decrypt buffers to a known state, + and make sure they're still in that known state */ + +static void initTestBuffers( BYTE *buffer1, BYTE *buffer2 ) + { + /* Set the buffers to a known state */ + memset( buffer1, '*', TESTBUFFER_SIZE ); + memcpy( buffer1, "12345678", 8 ); /* For endianness check */ + memcpy( buffer2, buffer1, TESTBUFFER_SIZE ); + } + +static void checkTestBuffers( BYTE *buffer1, BYTE *buffer2 ) + { + /* Make sure everything went OK */ + if( memcmp( buffer1, buffer2, TESTBUFFER_SIZE ) ) + { + puts( "Warning: Decrypted data != original plaintext." ); + + /* Try and guess at block chaining problems */ + if( !memcmp( buffer1, "12345678****", 12 ) ) + puts( "\t It looks like there's a problem with block chaining." ); + else + /* Try and guess at endianness problems - we want "1234" */ + if( !memcmp( buffer1, "4321", 4 ) ) + puts( "\t It looks like the 32-bit word endianness is " + "reversed." ); + else + if( !memcmp( buffer1, "2143", 4 ) ) + puts( "\t It looks like the 16-bit word endianness is " + "reversed." ); + else + if( buffer1[ 0 ] >= '1' && buffer1[ 0 ] <= '9' ) + puts( "\t It looks like there's some sort of endianness " + "problem which is\n\t more complex than just a " + "reversal." ); + else + puts( "\t It's probably more than just an endianness " + "problem." ); + } + } + +/* Report information on the encryption algorithm */ + +static void reportAlgorithmInformation( char *algorithmName, + CRYPT_QUERY_INFO *cryptQueryInfo ) + { + char speedFactor[ 50 ]; + + /* Determine the speed factor relative to a block copy */ + if( cryptQueryInfo->speed == CRYPT_ERROR ) + strcpy( speedFactor, "unknown speed factor" ); + else + sprintf( speedFactor, "0.%03d times the speed of a block copy", + cryptQueryInfo->speed ); + + printf( "%s algorithm is available with\n" + " name `%s', block size %d bits, %s,\n" + " min key size %d bits, recommended key size %d bits, " + "max key size %d bits,\n" + " min IV size %d bits, recommended IV size %d bits, " + "max IV size %d bits.\n", + algorithmName, cryptQueryInfo->algoName, + bytesToBits( cryptQueryInfo->blockSize ), speedFactor, + bytesToBits( cryptQueryInfo->minKeySize ), + bytesToBits( cryptQueryInfo->keySize ), + bytesToBits( cryptQueryInfo->maxKeySize ), + bytesToBits( cryptQueryInfo->minIVsize ), + bytesToBits( cryptQueryInfo->ivSize ), + bytesToBits( cryptQueryInfo->maxIVsize ) ); + } + +/* Check the library for an algorithm/mode */ + +static BOOLEAN checkLibraryInfo( char *name, char *longName, + CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode ) + { + CRYPT_QUERY_INFO cryptQueryInfo; + int status; + + status = queryAlgoAvailability( cryptAlgo ); + if( isStatusError( status ) ) + { + printf( "queryAlgoAvailability() reports %s is not available: " + "Code %d.\n", name, status ); + return( FALSE ); + } + status = queryModeAvailability( cryptAlgo, cryptMode ); + if( isStatusError( status ) ) + { + printf( "queryModeAvailability() reports %s is not available: " + "Code %d.\n", longName, status ); + return( FALSE ); + } + status = queryAlgoModeInformation( cryptAlgo, cryptMode, &cryptQueryInfo ); + printf( "queryModeAvailability() reports " ); + if( isStatusOK( status ) ) + reportAlgorithmInformation( longName, &cryptQueryInfo ); + else + { + printf( "no information available on %s algorithm: Code %d.\n", + name, status ); + return( FALSE ); + } + + return( TRUE ); + } + +/* Load the encryption contexts */ + +static BOOLEAN loadContexts( CRYPT_INFO *cryptInfo, CRYPT_INFO *decryptInfo, + CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, + BYTE *key, int length ) + { + int status; + + /* Create the encryption context */ + status = initCryptContext( cryptInfo, cryptAlgo, cryptMode ); + if( isStatusError( status ) ) + { + printf( "initCryptContext(): Failed with error code %d.\n", status ); + return( FALSE ); + } + status = loadCryptContext( cryptInfo, key, length ); + if( isStatusError( status ) ) + { + printf( "loadCryptContext(): Failed with error code %d.\n", status ); + return( FALSE ); + } + + /* Create the decryption context */ + status = initCryptContext( decryptInfo, cryptAlgo, cryptMode ); + if( isStatusError( status ) ) + { + printf( "initCryptContext(): Failed with error code %d.\n", status ); + return( FALSE ); + } + status = loadCryptContext( decryptInfo, key, length ); + if( isStatusError( status ) ) + { + printf( "loadCryptContext(): Failed with error code %d.\n", status ); + return( FALSE ); + } + + return( TRUE ); + } + +/* Perform a test en/decryption */ + +static void testCrypt( CRYPT_INFO *cryptInfo, CRYPT_INFO *decryptInfo, + BYTE *buffer ) + { + CRYPT_QUERY_INFO cryptQueryInfo; + BYTE iv[ 100 ]; + int status; + + /* Find out about the algorithm we're using */ + queryContextInformation( cryptInfo, &cryptQueryInfo ); + if( cryptQueryInfo.cryptMode == CRYPT_MODE_CFB || + cryptQueryInfo.cryptMode == CRYPT_MODE_OFB || + cryptQueryInfo.cryptMode == CRYPT_MODE_STREAM ) + { + /* Encrypt the buffer in two odd-sized chunks */ + status = encryptBuffer( cryptInfo, buffer, 79 ); + if( isStatusError( status ) ) + printf( "Couldn't encrypt data: Code %d.\n", status ); + status = encryptBuffer( cryptInfo, buffer + 79, TESTBUFFER_SIZE - 79 ); + if( isStatusError( status ) ) + printf( "Couldn't encrypt data: Code %d.\n", status ); + status = encryptBuffer( cryptInfo, buffer + TESTBUFFER_SIZE, 0 ); + + /* Copy the IV from the encryption to the decryption context */ + status = retrieveIV( cryptInfo, iv ); + if( isStatusError( status ) ) + printf( "Couldn't retrieve IV after encryption: Code %d.\n", + status ); + status = loadIV( decryptInfo, iv, cryptQueryInfo.ivSize ); + if( isStatusError( status ) ) + printf( "Couldn't load IV for decryption: Code %d.\n", status ); + + /* Decrypt the buffer in different odd-size chunks */ + status = decryptBuffer( decryptInfo, buffer, 125 ); + if( isStatusError( status ) ) + printf( "Couldn't decrypt data: Code %d.\n", status ); + status = decryptBuffer( decryptInfo, buffer + 125, TESTBUFFER_SIZE - 125 ); + if( isStatusError( status ) ) + printf( "Couldn't decrypt data: Code %d.\n", status ); + + return; + } + if( cryptQueryInfo.cryptMode == CRYPT_MODE_ECB || + cryptQueryInfo.cryptMode == CRYPT_MODE_CBC || + cryptQueryInfo.cryptMode == CRYPT_MODE_PCBC ) + { + /* Encrypt the buffer in two odd-sized chunks */ + status = encryptBuffer( cryptInfo, buffer, 80 ); + if( isStatusError( status ) ) + printf( "Couldn't encrypt data: Code %d.\n", status ); + status = encryptBuffer( cryptInfo, buffer + 80, TESTBUFFER_SIZE - 80 ); + if( isStatusError( status ) ) + printf( "Couldn't encrypt data: Code %d.\n", status ); + status = encryptBuffer( cryptInfo, buffer + TESTBUFFER_SIZE, 0 ); + + /* Copy the IV from the encryption to the decryption context */ + status = retrieveIV( cryptInfo, iv ); + if( isStatusError( status ) ) + printf( "Couldn't retrieve IV after encryption: Code %d.\n", + status ); + status = loadIV( decryptInfo, iv, cryptQueryInfo.ivSize ); + if( isStatusError( status ) ) + printf( "Couldn't load IV for decryption: Code %d.\n", status ); + + /* Decrypt the buffer in different odd-size chunks */ + status = decryptBuffer( decryptInfo, buffer, 128 ); + if( isStatusError( status ) ) + printf( "Couldn't decrypt data: Code %d.\n", status ); + status = decryptBuffer( decryptInfo, buffer + 128, TESTBUFFER_SIZE - 128 ); + if( isStatusError( status ) ) + printf( "Couldn't decrypt data: Code %d.\n", status ); + + return; + } + + puts( "Unknown encryption mode found in test code." ); + } + +/* Destroy the encryption contexts */ + +static void destroyContexts( CRYPT_INFO *cryptInfo, CRYPT_INFO *decryptInfo ) + { + int status; + + status = destroyCryptContext( cryptInfo ); + if( isStatusError( status ) ) + printf( "destroyCryptContext(): Failed with error code %d.\n", status ); + status = destroyCryptContext( decryptInfo ); + if( isStatusError( status ) ) + printf( "destroyCryptContext(): Failed with error code %d.\n", status ); + } + +/* Sample code to test an algorithm/mode implementation */ + +static int testLibrary( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, + char *name, char *longName ) + { + BYTE buffer[ TESTBUFFER_SIZE ], testBuffer[ TESTBUFFER_SIZE ]; + CRYPT_INFO cryptInfo, decryptInfo; + CRYPT_INFO_MDCSHS cryptInfoEx; + int status; + + /* Initialise the test buffers */ + initTestBuffers( buffer, testBuffer ); + + /* Check the capabilities of the library */ + putchar( '\n' ); + if( !checkLibraryInfo( name, longName, cryptAlgo, cryptMode ) ) + return( FALSE ); + + /* Set up an encryption context, load a user key into it, and perform a + key setup */ + switch( cryptAlgo ) + { + case CRYPT_ALGO_MDCSHS: + /* We use an extended setup with reduced iteration count for + people who have to run this thing 2000 times while debugging */ + cryptInfoEx.keySetupIterations = 10; + status = initCryptContextEx( &cryptInfo, cryptAlgo, cryptMode, + &cryptInfoEx ); + if( isStatusError( status ) ) + { + printf( "initCryptContext(): Failed with error code %d.\n", + status ); + return( FALSE ); + } + status = loadCryptContext( &cryptInfo, "Test key", 8 ); + if( isStatusError( status ) ) + { + printf( "loadCryptContext(): Failed with error code %d.\n", + status ); + return( FALSE ); + } + + /* Create another crypt context for decryption. The error + checking here is a bit less picky to save space */ + cryptInfoEx.keySetupIterations = 10; + initCryptContextEx( &decryptInfo, cryptAlgo, cryptMode, + &cryptInfoEx ); + status = loadCryptContext( &decryptInfo, "Test key", 8 ); + if( isStatusError( status ) ) + { + printf( "loadCryptContext(): Failed with error code %d.\n", + status ); + return( FALSE ); + } + break; + + case CRYPT_ALGO_DES: + if( !loadContexts( &cryptInfo, &decryptInfo, cryptAlgo, cryptMode, + ( BYTE * ) "1234567", 7 ) ) + return( FALSE ); + break; + + case CRYPT_ALGO_3DES: + if( !loadContexts( &cryptInfo, &decryptInfo, cryptAlgo, cryptMode, + ( BYTE * ) "12345677654321", 14 ) ) + return( FALSE ); + break; + + case CRYPT_ALGO_IDEA: + if( !loadContexts( &cryptInfo, &decryptInfo, cryptAlgo, cryptMode, + ( BYTE * ) "1234567887654321", 16 ) ) + return( FALSE ); + break; + + case CRYPT_ALGO_RC4: + if( !loadContexts( &cryptInfo, &decryptInfo, cryptAlgo, cryptMode, + ( BYTE * ) "12345678900987654321", 20 ) ) + return( FALSE ); + break; + + case CRYPT_ALGO_SAFER: + if( !loadContexts( &cryptInfo, &decryptInfo, cryptAlgo, cryptMode, + ( BYTE * ) "1234567887654321", 16 ) ) + return( FALSE ); + break; + + default: + printf( "Unknown encryption algorithm = ID %d, cannot perform " + "encryption test\n", cryptAlgo ); + return( FALSE ); + } + + /* Perform a test en/decryption */ + testCrypt( &cryptInfo, &decryptInfo, buffer ); + + /* Make sure everything went OK */ + checkTestBuffers( buffer, testBuffer ); + + /* Destroy the encryption contexts */ + destroyContexts( &cryptInfo, &decryptInfo ); + + return( TRUE ); + } + +/* Exercise various aspects of the encryption library */ + +int main( int argc, char **argv ) + { + int status, bigEndian; + + /* Get rid of compiler warning */ + if( argc || argv ); + + /* Make sure we've got the endianness set right. If the machine is + big-endian (up to 64 bits) the following value will be signed, + otherwise it will be unsigned. Unfortunately we can't test for + things like middle-endianness without knowing the size of the data + types */ + bigEndian = ( *( long * ) "\x80\x00\x00\x00\x00\x00\x00\x00" < 0 ); +#ifdef LITTLE_ENDIAN + if( bigEndian ) + { + puts( "The CPU endianness define is set wrong in crypt.h, this " + "machine appears to be\nbig-endian, not little-endian. Edit " + "the file and rebuild the library." ); + exit( EXIT_FAILURE ); + } +#else + if( !bigEndian ) + { + puts( "The CPU endianness define is set wrong in crypt.h, this " + "machine appears to be\nlittle-endian, not big-endian. Edit " + "the file and rebuild the library." ); + exit( EXIT_FAILURE ); + } +#endif /* LITTLE_ENDIAN */ + + /* If we're compiling under Windoze, make sure that this weeks version + of Visual C gets the LONG type right */ +#ifdef __WINDOWS__ + { + LONG test = 0x80000000L; + + if( test < 0 ) + { + puts( "typeof( LONG ) is incorrect. It evaluates to a signed 32-bit " + "value rather\nthan an unsigned 32-bit value. You need to edit " + "crypt.h and recompile the\nencryption library" ); + exit( EXIT_FAILURE ); + } + } +#endif /* __WINDOWS__ */ + + /* Initialise the library */ + status = initLibrary(); + if( isStatusError( status ) ) + { + printf( "Couldn't init library, code %d.\n", status ); + exit( EXIT_FAILURE ); + } + + /* Test the encryption routines contained in the library */ +#if 1 + if( !testLibrary( CRYPT_ALGO_MDCSHS, CRYPT_MODE_CFB, "MDC/SHS", + "MDC/SHS-CFB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_DES, CRYPT_MODE_ECB, "DES", "DES-ECB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_DES, CRYPT_MODE_CBC, "DES", "DES-CBC" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_DES, CRYPT_MODE_CFB, "DES", "DES-CFB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_DES, CRYPT_MODE_OFB, "DES", "DES-OFB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_DES, CRYPT_MODE_PCBC, "DES", "DES-PCBC" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_3DES, CRYPT_MODE_ECB, "3DES", "3DES-ECB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_3DES, CRYPT_MODE_CBC, "3DES", "3DES-CBC" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_3DES, CRYPT_MODE_CFB, "3DES", "3DES-CFB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_3DES, CRYPT_MODE_OFB, "3DES", "3DES-OFB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_IDEA, CRYPT_MODE_ECB, "IDEA", "IDEA-ECB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_IDEA, CRYPT_MODE_CBC, "IDEA", "IDEA-CBC" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_IDEA, CRYPT_MODE_CFB, "IDEA", "IDEA-CFB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_IDEA, CRYPT_MODE_OFB, "IDEA", "IDEA-OFB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_RC4, CRYPT_MODE_STREAM, "RC4", "RC4" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_SAFER, CRYPT_MODE_ECB, "SAFER", "SAFER-ECB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_SAFER, CRYPT_MODE_CBC, "SAFER", "SAFER-CBC" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_SAFER, CRYPT_MODE_CFB, "SAFER", "SAFER-CFB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } + if( !testLibrary( CRYPT_ALGO_SAFER, CRYPT_MODE_OFB, "SAFER", "SAFER-OFB" ) ) + { + puts( "Tests aborted due to encryption library error." ); + exit( EXIT_FAILURE ); + } +#endif /* 0 or 1 */ + + /* Shut down the library */ + status = endLibrary(); + if( isStatusError( status ) ) + { + printf( "endLibrary(): Failed with error code %d.\n", status ); + exit( EXIT_FAILURE ); + } + + return( EXIT_SUCCESS ); + } diff --git a/third_party/cryptlib-0.99/testdes.h b/third_party/cryptlib-0.99/testdes.h new file mode 100644 index 0000000..39386b0 --- /dev/null +++ b/third_party/cryptlib-0.99/testdes.h @@ -0,0 +1,928 @@ +/* DES test vectors, derived from "Validating the Correctness of Hardware + Implementations of the NBS Data Encryption Standard", NBS Special + Publication 500-20, 1980 */ + +/* The data structure for the ( key, plaintext, ciphertext ) triplets. Each + set of tests also includes a string describing the test, suitable for + printing as "Testing " during the testing process */ + +typedef struct { + BYTE key[ DES_BLOCKSIZE ]; + BYTE plaintext[ DES_BLOCKSIZE ]; + BYTE ciphertext[ DES_BLOCKSIZE ]; + } DES_TEST; + +/* Initial Permutation and Expansion test: Encrypt */ + +static char *testIPname = "Initial Permutation and Expansion"; + +static DES_TEST testIP[] = { + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA }, + { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F }, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 }, + { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF }, + { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A }, + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x42, 0x42, 0x50, 0xB3, 0x7C, 0x3D, 0xD9, 0x51 }, + { 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xB8, 0x06, 0x1B, 0x7E, 0xCD, 0x9A, 0x21, 0xE5 }, + { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xF1, 0x5D, 0x0F, 0x28, 0x6B, 0x65, 0xBD, 0x28 }, + { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xAD, 0xD0, 0xCC, 0x8D, 0x6E, 0x5D, 0xEB, 0xA1 }, + { 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xE6, 0xD5, 0xF8, 0x27, 0x52, 0xAD, 0x63, 0xD1 }, + { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xEC, 0xBF, 0xE3, 0xBD, 0x3F, 0x59, 0x1A, 0x5E }, + { 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xF3, 0x56, 0x83, 0x43, 0x79, 0xD1, 0x65, 0xCD }, + { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x2B, 0x9F, 0x98, 0x2F, 0x20, 0x03, 0x7F, 0xA9 }, + { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x88, 0x9D, 0xE0, 0x68, 0xA1, 0x6F, 0x0B, 0xE6 }, + { 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xE1, 0x9E, 0x27, 0x5D, 0x84, 0x6A, 0x12, 0x98 }, + { 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x32, 0x9A, 0x8E, 0xD5, 0x23, 0xD7, 0x1A, 0xEC }, + { 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xE7, 0xFC, 0xE2, 0x25, 0x57, 0xD2, 0x3C, 0x97 }, + { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x12, 0xA9, 0xF5, 0x81, 0x7F, 0xF2, 0xD6, 0x5D }, + { 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xA4, 0x84, 0xC3, 0xAD, 0x38, 0xDC, 0x9C, 0x19 }, + { 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFB, 0xE0, 0x0A, 0x8A, 0x1E, 0xF8, 0xAD, 0x72 }, + { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x75, 0x0D, 0x07, 0x94, 0x07, 0x52, 0x13, 0x63 }, + { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x64, 0xFE, 0xED, 0x9C, 0x72, 0x4C, 0x2F, 0xAF }, + { 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xF0, 0x2B, 0x26, 0x3B, 0x32, 0x8E, 0x2B, 0x60 }, + { 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x9D, 0x64, 0x55, 0x5A, 0x9A, 0x10, 0xB8, 0x52 }, + { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xD1, 0x06, 0xFF, 0x0B, 0xED, 0x52, 0x55, 0xD7 }, + { 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xE1, 0x65, 0x2C, 0x6B, 0x13, 0x8C, 0x64, 0xA5 }, + { 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xE4, 0x28, 0x58, 0x11, 0x86, 0xEC, 0x8F, 0x46 }, + { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xAE, 0xB5, 0xF5, 0xED, 0xE2, 0x2D, 0x1A, 0x36 }, + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xE9, 0x43, 0xD7, 0x56, 0x8A, 0xEC, 0x0C, 0x5C }, + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xDF, 0x98, 0xC8, 0x27, 0x6F, 0x54, 0xB0, 0x4B }, + { 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xB1, 0x60, 0xE4, 0x68, 0x0F, 0x6C, 0x69, 0x6F }, + { 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFA, 0x07, 0x52, 0xB0, 0x7D, 0x9C, 0x4A, 0xB8 }, + { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xCA, 0x3A, 0x2B, 0x03, 0x6D, 0xBC, 0x85, 0x02 }, + { 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x5E, 0x09, 0x05, 0x51, 0x7B, 0xB5, 0x9B, 0xCF }, + { 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x81, 0x4E, 0xEB, 0x3B, 0x91, 0xD9, 0x07, 0x26 }, + { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x4D, 0x49, 0xDB, 0x15, 0x32, 0x91, 0x9C, 0x9F }, + { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x25, 0xEB, 0x5F, 0xC3, 0xF8, 0xCF, 0x06, 0x21 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xAB, 0x6A, 0x20, 0xC0, 0x62, 0x0D, 0x1C, 0x6F }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x79, 0xE9, 0x0D, 0xBC, 0x98, 0xF9, 0x2C, 0xCA }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x86, 0x6E, 0xCE, 0xDD, 0x80, 0x72, 0xBB, 0x0E }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x8B, 0x54, 0x53, 0x6F, 0x2F, 0x3E, 0x64, 0xA8 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xEA, 0x51, 0xD3, 0x97, 0x55, 0x95, 0xB8, 0x6B }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xCA, 0xFF, 0xC6, 0xAC, 0x45, 0x42, 0xDE, 0x31 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x8D, 0xD4, 0x5A, 0x2D, 0xDF, 0x90, 0x79, 0x6C }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x10, 0x29, 0xD5, 0x5E, 0x88, 0x0E, 0xC2, 0xD0 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x5D, 0x86, 0xCB, 0x23, 0x63, 0x9D, 0xBE, 0xA9 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x1D, 0x1C, 0xA8, 0x53, 0xAE, 0x7C, 0x0C, 0x5F }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xCE, 0x33, 0x23, 0x29, 0x24, 0x8F, 0x32, 0x28 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x84, 0x05, 0xD1, 0xAB, 0xE2, 0x4F, 0xB9, 0x42 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xE6, 0x43, 0xD7, 0x80, 0x90, 0xCA, 0x42, 0x07 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x48, 0x22, 0x1B, 0x99, 0x37, 0x74, 0x8A, 0x23 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xDD, 0x7C, 0x0B, 0xBD, 0x61, 0xFA, 0xFD, 0x54 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x2F, 0xBC, 0x29, 0x1A, 0x57, 0x0D, 0xB5, 0xC4 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xE0, 0x7C, 0x30, 0xD7, 0xE4, 0xE2, 0x6E, 0x12 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x09, 0x53, 0xE2, 0x25, 0x8E, 0x8E, 0x90, 0xA1 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x5B, 0x71, 0x1B, 0xC4, 0xCE, 0xEB, 0xF2, 0xEE }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xCC, 0x08, 0x3F, 0x1E, 0x6D, 0x9E, 0x85, 0xF6 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xD2, 0xFD, 0x88, 0x67, 0xD5, 0x0D, 0x2D, 0xFE }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x06, 0xE7, 0xEA, 0x22, 0xCE, 0x92, 0x70, 0x8F }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x16, 0x6B, 0x40, 0xB4, 0x4A, 0xBA, 0x4B, 0xD6 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } + }; + +/* Inverse Permutation and Expansion test: Encrypt */ + +static char *testVPname = "Inverse Permutation and Expansion"; + +static DES_TEST testVP[] = { + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x42, 0x42, 0x50, 0xB3, 0x7C, 0x3D, 0xD9, 0x51 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB8, 0x06, 0x1B, 0x7E, 0xCD, 0x9A, 0x21, 0xE5 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xF1, 0x5D, 0x0F, 0x28, 0x6B, 0x65, 0xBD, 0x28 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAD, 0xD0, 0xCC, 0x8D, 0x6E, 0x5D, 0xEB, 0xA1 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE6, 0xD5, 0xF8, 0x27, 0x52, 0xAD, 0x63, 0xD1 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xEC, 0xBF, 0xE3, 0xBD, 0x3F, 0x59, 0x1A, 0x5E } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xF3, 0x56, 0x83, 0x43, 0x79, 0xD1, 0x65, 0xCD } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2B, 0x9F, 0x98, 0x2F, 0x20, 0x03, 0x7F, 0xA9 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x88, 0x9D, 0xE0, 0x68, 0xA1, 0x6F, 0x0B, 0xE6 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE1, 0x9E, 0x27, 0x5D, 0x84, 0x6A, 0x12, 0x98 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x32, 0x9A, 0x8E, 0xD5, 0x23, 0xD7, 0x1A, 0xEC } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE7, 0xFC, 0xE2, 0x25, 0x57, 0xD2, 0x3C, 0x97 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x12, 0xA9, 0xF5, 0x81, 0x7F, 0xF2, 0xD6, 0x5D } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA4, 0x84, 0xC3, 0xAD, 0x38, 0xDC, 0x9C, 0x19 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFB, 0xE0, 0x0A, 0x8A, 0x1E, 0xF8, 0xAD, 0x72 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00 }, + { 0x75, 0x0D, 0x07, 0x94, 0x07, 0x52, 0x13, 0x63 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00 }, + { 0x64, 0xFE, 0xED, 0x9C, 0x72, 0x4C, 0x2F, 0xAF } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00 }, + { 0xF0, 0x2B, 0x26, 0x3B, 0x32, 0x8E, 0x2B, 0x60 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 }, + { 0x9D, 0x64, 0x55, 0x5A, 0x9A, 0x10, 0xB8, 0x52 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 }, + { 0xD1, 0x06, 0xFF, 0x0B, 0xED, 0x52, 0x55, 0xD7 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 }, + { 0xE1, 0x65, 0x2C, 0x6B, 0x13, 0x8C, 0x64, 0xA5 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, + { 0xE4, 0x28, 0x58, 0x11, 0x86, 0xEC, 0x8F, 0x46 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0xAE, 0xB5, 0xF5, 0xED, 0xE2, 0x2D, 0x1A, 0x36 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 }, + { 0xE9, 0x43, 0xD7, 0x56, 0x8A, 0xEC, 0x0C, 0x5C } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 }, + { 0xDF, 0x98, 0xC8, 0x27, 0x6F, 0x54, 0xB0, 0x4B } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 }, + { 0xB1, 0x60, 0xE4, 0x68, 0x0F, 0x6C, 0x69, 0x6F } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 }, + { 0xFA, 0x07, 0x52, 0xB0, 0x7D, 0x9C, 0x4A, 0xB8 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, + { 0xCA, 0x3A, 0x2B, 0x03, 0x6D, 0xBC, 0x85, 0x02 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 }, + { 0x5E, 0x09, 0x05, 0x51, 0x7B, 0xB5, 0x9B, 0xCF } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }, + { 0x81, 0x4E, 0xEB, 0x3B, 0x91, 0xD9, 0x07, 0x26 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }, + { 0x4D, 0x49, 0xDB, 0x15, 0x32, 0x91, 0x9C, 0x9F } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 }, + { 0x25, 0xEB, 0x5F, 0xC3, 0xF8, 0xCF, 0x06, 0x21 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00 }, + { 0xAB, 0x6A, 0x20, 0xC0, 0x62, 0x0D, 0x1C, 0x6F } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00 }, + { 0x79, 0xE9, 0x0D, 0xBC, 0x98, 0xF9, 0x2C, 0xCA } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00 }, + { 0x86, 0x6E, 0xCE, 0xDD, 0x80, 0x72, 0xBB, 0x0E } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00 }, + { 0x8B, 0x54, 0x53, 0x6F, 0x2F, 0x3E, 0x64, 0xA8 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 }, + { 0xEA, 0x51, 0xD3, 0x97, 0x55, 0x95, 0xB8, 0x6B } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 }, + { 0xCA, 0xFF, 0xC6, 0xAC, 0x45, 0x42, 0xDE, 0x31 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }, + { 0x8D, 0xD4, 0x5A, 0x2D, 0xDF, 0x90, 0x79, 0x6C } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 }, + { 0x10, 0x29, 0xD5, 0x5E, 0x88, 0x0E, 0xC2, 0xD0 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00 }, + { 0x5D, 0x86, 0xCB, 0x23, 0x63, 0x9D, 0xBE, 0xA9 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00 }, + { 0x1D, 0x1C, 0xA8, 0x53, 0xAE, 0x7C, 0x0C, 0x5F } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 }, + { 0xCE, 0x33, 0x23, 0x29, 0x24, 0x8F, 0x32, 0x28 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 }, + { 0x84, 0x05, 0xD1, 0xAB, 0xE2, 0x4F, 0xB9, 0x42 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00 }, + { 0xE6, 0x43, 0xD7, 0x80, 0x90, 0xCA, 0x42, 0x07 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00 }, + { 0x48, 0x22, 0x1B, 0x99, 0x37, 0x74, 0x8A, 0x23 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }, + { 0xDD, 0x7C, 0x0B, 0xBD, 0x61, 0xFA, 0xFD, 0x54 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, + { 0x2F, 0xBC, 0x29, 0x1A, 0x57, 0x0D, 0xB5, 0xC4 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 }, + { 0xE0, 0x7C, 0x30, 0xD7, 0xE4, 0xE2, 0x6E, 0x12 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20 }, + { 0x09, 0x53, 0xE2, 0x25, 0x8E, 0x8E, 0x90, 0xA1 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }, + { 0x5B, 0x71, 0x1B, 0xC4, 0xCE, 0xEB, 0xF2, 0xEE } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 }, + { 0xCC, 0x08, 0x3F, 0x1E, 0x6D, 0x9E, 0x85, 0xF6 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 }, + { 0xD2, 0xFD, 0x88, 0x67, 0xD5, 0x0D, 0x2D, 0xFE } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }, + { 0x06, 0xE7, 0xEA, 0x22, 0xCE, 0x92, 0x70, 0x8F } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x16, 0x6B, 0x40, 0xB4, 0x4A, 0xBA, 0x4B, 0xD6 } } + }; + +/* Key Permutation tests: Encrypt */ + +static char *testKPname = "Key Permutation"; + +static DES_TEST testKP[] = { + { { 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x95, 0xA8, 0xD7, 0x28, 0x13, 0xDA, 0xA9, 0x4D } }, + { { 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0E, 0xEC, 0x14, 0x87, 0xDD, 0x8C, 0x26, 0xD5 } }, + { { 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7A, 0xD1, 0x6F, 0xFB, 0x79, 0xC4, 0x59, 0x26 } }, + { { 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD3, 0x74, 0x62, 0x94, 0xCA, 0x6A, 0x6C, 0xF3 } }, + { { 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x80, 0x9F, 0x5F, 0x87, 0x3C, 0x1F, 0xD7, 0x61 } }, + { { 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xC0, 0x2F, 0xAF, 0xFE, 0xC9, 0x89, 0xD1, 0xFC } }, + { { 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x46, 0x15, 0xAA, 0x1D, 0x33, 0xE7, 0x2F, 0x10 } }, + { { 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x20, 0x55, 0x12, 0x33, 0x50, 0xC0, 0x08, 0x58 } }, + { { 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDF, 0x3B, 0x99, 0xD6, 0x57, 0x73, 0x97, 0xC8 } }, + { { 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x31, 0xFE, 0x17, 0x36, 0x9B, 0x52, 0x88, 0xC9 } }, + { { 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDF, 0xDD, 0x3C, 0xC6, 0x4D, 0xAE, 0x16, 0x42 } }, + { { 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x17, 0x8C, 0x83, 0xCE, 0x2B, 0x39, 0x9D, 0x94 } }, + { { 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x50, 0xF6, 0x36, 0x32, 0x4A, 0x9B, 0x7F, 0x80 } }, + { { 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA8, 0x46, 0x8E, 0xE3, 0xBC, 0x18, 0xF0, 0x6D } }, + { { 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA2, 0xDC, 0x9E, 0x92, 0xFD, 0x3C, 0xDE, 0x92 } }, + { { 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xCA, 0xC0, 0x9F, 0x79, 0x7D, 0x03, 0x12, 0x87 } }, + { { 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x90, 0xBA, 0x68, 0x0B, 0x22, 0xAE, 0xB5, 0x25 } }, + { { 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xCE, 0x7A, 0x24, 0xF3, 0x50, 0xE2, 0x80, 0xB6 } }, + { { 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x88, 0x2B, 0xFF, 0x0A, 0xA0, 0x1A, 0x0B, 0x87 } }, + { { 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xC2 } }, + { { 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xC7, 0x15, 0x16, 0xC2, 0x9C, 0x75, 0xD1, 0x70 } }, + { { 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x51, 0x99, 0xC2, 0x9A, 0x52, 0xC9, 0xF0, 0x59 } }, + { { 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xC2, 0x2F, 0x0A, 0x29, 0x4A, 0x71, 0xF2, 0x9F } }, + { { 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xEE, 0x37, 0x14, 0x83, 0x71, 0x4C, 0x02, 0xEA } }, + { { 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA8, 0x1F, 0xBD, 0x44, 0x8F, 0x9E, 0x52, 0x2F } }, + { { 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4F, 0x64, 0x4C, 0x92, 0xE1, 0x92, 0xDF, 0xED } }, + { { 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x1A, 0xFA, 0x9A, 0x66, 0xA6, 0xDF, 0x92, 0xAE } }, + { { 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB3, 0xC1, 0xCC, 0x71, 0x5C, 0xB8, 0x79, 0xD8 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x19, 0xD0, 0x32, 0xE6, 0x4A, 0xB0, 0xBD, 0x8B } }, + { { 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x3C, 0xFA, 0xA7, 0xA7, 0xDC, 0x87, 0x20, 0xDC } }, + { { 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB7, 0x26, 0x5F, 0x7F, 0x44, 0x7A, 0xC6, 0xF3 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9D, 0xB7, 0x3B, 0x3C, 0x0D, 0x16, 0x3F, 0x54 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x81, 0x81, 0xB6, 0x5B, 0xAB, 0xF4, 0xA9, 0x75 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x93, 0xC9, 0xB6, 0x40, 0x42, 0xEA, 0xA2, 0x40 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x86, 0x38, 0x80, 0x9E, 0x87, 0x87, 0x87, 0xA0 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x41, 0xB9, 0xA7, 0x9A, 0xF7, 0x9A, 0xC2, 0x08 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7A, 0x9B, 0xE4, 0x2F, 0x20, 0x09, 0xA8, 0x92 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x29, 0x03, 0x8D, 0x56, 0xBA, 0x6D, 0x27, 0x45 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x54, 0x95, 0xC6, 0xAB, 0xF1, 0xE5, 0xDF, 0x51 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAE, 0x13, 0xDB, 0xD5, 0x61, 0x48, 0x89, 0x33 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x4D, 0x1F, 0xFA, 0x89, 0x04, 0xE3, 0x89 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD1, 0x39, 0x97, 0x12, 0xF9, 0x9B, 0xF0, 0x2E } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x14, 0xC1, 0xD7, 0xC1, 0xCF, 0xFE, 0xC7, 0x9E } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x1D, 0xE5, 0x27, 0x9D, 0xAE, 0x3B, 0xED, 0x6F } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE9, 0x41, 0xA3, 0x3F, 0x85, 0x50, 0x13, 0x03 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDA, 0x99, 0xDB, 0xBC, 0x9A, 0x03, 0xF3, 0x79 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB7, 0xFC, 0x92, 0xF9, 0x1D, 0x8E, 0x92, 0xE9 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAE, 0x8E, 0x5C, 0xAA, 0x3C, 0xA0, 0x4E, 0x85 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9C, 0xC6, 0x2D, 0xF4, 0x3B, 0x6E, 0xED, 0x74 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD8, 0x63, 0xDB, 0xB5, 0xC5, 0x9A, 0x91, 0xA0 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA1, 0xAB, 0x21, 0x90, 0x54, 0x5B, 0x91, 0xD7 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x08, 0x75, 0x04, 0x1E, 0x64, 0xC5, 0x70, 0xF7 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x5A, 0x59, 0x45, 0x28, 0xBE, 0xBE, 0xF1, 0xCC } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFC, 0xDB, 0x32, 0x91, 0xDE, 0x21, 0xF0, 0xC0 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x86, 0x9E, 0xFD, 0x7F, 0x9F, 0x26, 0x5A, 0x09 } } + }; + +/* Test of right-shifts in Decryption: Decrypt */ + +static char *testRSname = "Right-shifts in Decryption"; + +static DES_TEST testRS[] = { + { { 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x95, 0xA8, 0xD7, 0x28, 0x13, 0xDA, 0xA9, 0x4D }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x0E, 0xEC, 0x14, 0x87, 0xDD, 0x8C, 0x26, 0xD5 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x7A, 0xD1, 0x6F, 0xFB, 0x79, 0xC4, 0x59, 0x26 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xD3, 0x74, 0x62, 0x94, 0xCA, 0x6A, 0x6C, 0xF3 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x80, 0x9F, 0x5F, 0x87, 0x3C, 0x1F, 0xD7, 0x61 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xC0, 0x2F, 0xAF, 0xFE, 0xC9, 0x89, 0xD1, 0xFC }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x46, 0x15, 0xAA, 0x1D, 0x33, 0xE7, 0x2F, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x20, 0x55, 0x12, 0x33, 0x50, 0xC0, 0x08, 0x58 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xDF, 0x3B, 0x99, 0xD6, 0x57, 0x73, 0x97, 0xC8 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x31, 0xFE, 0x17, 0x36, 0x9B, 0x52, 0x88, 0xC9 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xDF, 0xDD, 0x3C, 0xC6, 0x4D, 0xAE, 0x16, 0x42 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x17, 0x8C, 0x83, 0xCE, 0x2B, 0x39, 0x9D, 0x94 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x50, 0xF6, 0x36, 0x32, 0x4A, 0x9B, 0x7F, 0x80 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xA8, 0x46, 0x8E, 0xE3, 0xBC, 0x18, 0xF0, 0x6D }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xA2, 0xDC, 0x9E, 0x92, 0xFD, 0x3C, 0xDE, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xCA, 0xC0, 0x9F, 0x79, 0x7D, 0x03, 0x12, 0x87 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x90, 0xBA, 0x68, 0x0B, 0x22, 0xAE, 0xB5, 0x25 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xCE, 0x7A, 0x24, 0xF3, 0x50, 0xE2, 0x80, 0xB6 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x88, 0x2B, 0xFF, 0x0A, 0xA0, 0x1A, 0x0B, 0x87 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xC2 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xC7, 0x15, 0x16, 0xC2, 0x9C, 0x75, 0xD1, 0x70 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01 }, + { 0x51, 0x99, 0xC2, 0x9A, 0x52, 0xC9, 0xF0, 0x59 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01 }, + { 0xC2, 0x2F, 0x0A, 0x29, 0x4A, 0x71, 0xF2, 0x9F }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01 }, + { 0xEE, 0x37, 0x14, 0x83, 0x71, 0x4C, 0x02, 0xEA }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01 }, + { 0xA8, 0x1F, 0xBD, 0x44, 0x8F, 0x9E, 0x52, 0x2F }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01 }, + { 0x4F, 0x64, 0x4C, 0x92, 0xE1, 0x92, 0xDF, 0xED }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01 }, + { 0x1A, 0xFA, 0x9A, 0x66, 0xA6, 0xDF, 0x92, 0xAE }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01 }, + { 0xB3, 0xC1, 0xCC, 0x71, 0x5C, 0xB8, 0x79, 0xD8 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01 }, + { 0x19, 0xD0, 0x32, 0xE6, 0x4A, 0xB0, 0xBD, 0x8B }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01 }, + { 0x3C, 0xFA, 0xA7, 0xA7, 0xDC, 0x87, 0x20, 0xDC }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01 }, + { 0xB7, 0x26, 0x5F, 0x7F, 0x44, 0x7A, 0xC6, 0xF3 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01 }, + { 0x9D, 0xB7, 0x3B, 0x3C, 0x0D, 0x16, 0x3F, 0x54 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01 }, + { 0x81, 0x81, 0xB6, 0x5B, 0xAB, 0xF4, 0xA9, 0x75 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01 }, + { 0x93, 0xC9, 0xB6, 0x40, 0x42, 0xEA, 0xA2, 0x40 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01 }, + { 0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01 }, + { 0x86, 0x38, 0x80, 0x9E, 0x87, 0x87, 0x87, 0xA0 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01 }, + { 0x41, 0xB9, 0xA7, 0x9A, 0xF7, 0x9A, 0xC2, 0x08 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01 }, + { 0x7A, 0x9B, 0xE4, 0x2F, 0x20, 0x09, 0xA8, 0x92 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01 }, + { 0x29, 0x03, 0x8D, 0x56, 0xBA, 0x6D, 0x27, 0x45 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01 }, + { 0x54, 0x95, 0xC6, 0xAB, 0xF1, 0xE5, 0xDF, 0x51 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01 }, + { 0xAE, 0x13, 0xDB, 0xD5, 0x61, 0x48, 0x89, 0x33 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01 }, + { 0x02, 0x4D, 0x1F, 0xFA, 0x89, 0x04, 0xE3, 0x89 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01 }, + { 0xD1, 0x39, 0x97, 0x12, 0xF9, 0x9B, 0xF0, 0x2E }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01 }, + { 0x14, 0xC1, 0xD7, 0xC1, 0xCF, 0xFE, 0xC7, 0x9E }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01 }, + { 0x1D, 0xE5, 0x27, 0x9D, 0xAE, 0x3B, 0xED, 0x6F }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01 }, + { 0xE9, 0x41, 0xA3, 0x3F, 0x85, 0x50, 0x13, 0x03 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01 }, + { 0xDA, 0x99, 0xDB, 0xBC, 0x9A, 0x03, 0xF3, 0x79 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01 }, + { 0xB7, 0xFC, 0x92, 0xF9, 0x1D, 0x8E, 0x92, 0xE9 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01 }, + { 0xAE, 0x8E, 0x5C, 0xAA, 0x3C, 0xA0, 0x4E, 0x85 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80 }, + { 0x9C, 0xC6, 0x2D, 0xF4, 0x3B, 0x6E, 0xED, 0x74 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40 }, + { 0xD8, 0x63, 0xDB, 0xB5, 0xC5, 0x9A, 0x91, 0xA0 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20 }, + { 0xA1, 0xAB, 0x21, 0x90, 0x54, 0x5B, 0x91, 0xD7 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10 }, + { 0x08, 0x75, 0x04, 0x1E, 0x64, 0xC5, 0x70, 0xF7 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08 }, + { 0x5A, 0x59, 0x45, 0x28, 0xBE, 0xBE, 0xF1, 0xCC }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04 }, + { 0xFC, 0xDB, 0x32, 0x91, 0xDE, 0x21, 0xF0, 0xC0 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 }, + { 0x86, 0x9E, 0xFD, 0x7F, 0x9F, 0x26, 0x5A, 0x09 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } + }; + +/* Data Permutation test: Encrypt */ + +static char *testDPname = "Data Permutation"; + +static DES_TEST testDP[] = { + { { 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x88, 0xD5, 0x5E, 0x54, 0xF5, 0x4C, 0x97, 0xB4 } }, + { { 0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0C, 0x0C, 0xC0, 0x0C, 0x83, 0xEA, 0x48, 0xFD } }, + { { 0x10, 0x07, 0x10, 0x34, 0xC8, 0x98, 0x01, 0x20 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x83, 0xBC, 0x8E, 0xF3, 0xA6, 0x57, 0x01, 0x83 } }, + { { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDF, 0x72, 0x5D, 0xCA, 0xD9, 0x4E, 0xA2, 0xE9 } }, + { { 0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE6, 0x52, 0xB5, 0x3B, 0x55, 0x0B, 0xE8, 0xB0 } }, + { { 0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAF, 0x52, 0x71, 0x20, 0xC4, 0x85, 0xCB, 0xB0 } }, + { { 0x51, 0x07, 0xB0, 0x15, 0x19, 0x58, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0F, 0x04, 0xCE, 0x39, 0x3D, 0xB9, 0x26, 0xD5 } }, + { { 0x10, 0x07, 0xB0, 0x15, 0x19, 0x19, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xC9, 0xF0, 0x0F, 0xFC, 0x74, 0x07, 0x90, 0x67 } }, + { { 0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7C, 0xFD, 0x82, 0xA5, 0x93, 0x25, 0x2B, 0x4E } }, + { { 0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xCB, 0x49, 0xA2, 0xF9, 0xE9, 0x13, 0x63, 0xE3 } }, + { { 0x10, 0x07, 0x91, 0x15, 0xB9, 0x08, 0x01, 0x40 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0xB5, 0x88, 0xBE, 0x70, 0xD2, 0x3F, 0x56 } }, + { { 0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x40, 0x6A, 0x9A, 0x6A, 0xB4, 0x33, 0x99, 0xAE } }, + { { 0x10, 0x07, 0xD0, 0x15, 0x89, 0x98, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x6C, 0xB7, 0x73, 0x61, 0x1D, 0xCA, 0x9A, 0xDA } }, + { { 0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x67, 0xFD, 0x21, 0xC1, 0x7D, 0xBB, 0x5D, 0x70 } }, + { { 0x91, 0x07, 0xD0, 0x15, 0x89, 0x19, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x95, 0x92, 0xCB, 0x41, 0x10, 0x43, 0x07, 0x87 } }, + { { 0x10, 0x07, 0xD0, 0x15, 0x98, 0x98, 0x01, 0x20 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA6, 0xB7, 0xFF, 0x68, 0xA3, 0x18, 0xDD, 0xD3 } }, + { { 0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4D, 0x10, 0x21, 0x96, 0xC9, 0x14, 0xCA, 0x16 } }, + { { 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2D, 0xFA, 0x9F, 0x45, 0x73, 0x59, 0x49, 0x65 } }, + { { 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB4, 0x66, 0x04, 0x81, 0x6C, 0x0E, 0x07, 0x74 } }, + { { 0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x6E, 0x7E, 0x62, 0x21, 0xA4, 0xF3, 0x4E, 0x87 } }, + { { 0x19, 0x07, 0x92, 0x10, 0x98, 0x1A, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAA, 0x85, 0xE7, 0x46, 0x43, 0x23, 0x31, 0x99 } }, + { { 0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2E, 0x5A, 0x19, 0xDB, 0x4D, 0x19, 0x62, 0xD6 } }, + { { 0x10, 0x07, 0x91, 0x19, 0x98, 0x1A, 0x08, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x23, 0xA8, 0x66, 0xA8, 0x09, 0xD3, 0x08, 0x94 } }, + { { 0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD8, 0x12, 0xD9, 0x61, 0xF0, 0x17, 0xD3, 0x20 } }, + { { 0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0B }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x05, 0x56, 0x05, 0x81, 0x6E, 0x58, 0x60, 0x8F } }, + { { 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAB, 0xD8, 0x8E, 0x8B, 0x1B, 0x77, 0x16, 0xF1 } }, + { { 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x53, 0x7A, 0xC9, 0x5B, 0xE6, 0x9D, 0xA1, 0xE1 } }, + { { 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAE, 0xD0, 0xF6, 0xAE, 0x3C, 0x25, 0xCD, 0xD8 } }, + { { 0x10, 0x02, 0x91, 0x14, 0x98, 0x10, 0x01, 0x04 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB3, 0xE3, 0x5A, 0x5E, 0xE5, 0x3E, 0x7B, 0x8D } }, + { { 0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x61, 0xC7, 0x9C, 0x71, 0x92, 0x1A, 0x2E, 0xF8 } }, + { { 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE2, 0xF5, 0x72, 0x8F, 0x09, 0x95, 0x01, 0x3C } }, + { { 0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x1A, 0xEA, 0xC3, 0x9A, 0x61, 0xF0, 0xA4, 0x64 } } + }; + +/* S-Box test: Encrypt */ + +static char *testSBname = "S-Boxes"; + +static DES_TEST testSB[] = { + { { 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 }, + { 0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42 }, + { 0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B } }, + { { 0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E }, + { 0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA }, + { 0x7A, 0x38, 0x9D, 0x10, 0x35, 0x4B, 0xD2, 0x71 } }, + { { 0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86 }, + { 0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72 }, + { 0x86, 0x8E, 0xBB, 0x51, 0xCA, 0xB4, 0x59, 0x9A } }, + { { 0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E }, + { 0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A }, + { 0x71, 0x78, 0x87, 0x6E, 0x01, 0xF1, 0x9B, 0x2A } }, + { { 0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6 }, + { 0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2 }, + { 0xAF, 0x37, 0xFB, 0x42, 0x1F, 0x8C, 0x40, 0x95 } }, + { { 0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE }, + { 0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A }, + { 0x86, 0xA5, 0x60, 0xF1, 0x0E, 0xC6, 0xD8, 0x5B } }, + { { 0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6 }, + { 0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2 }, + { 0x0C, 0xD3, 0xDA, 0x02, 0x00, 0x21, 0xDC, 0x09 } }, + { { 0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE }, + { 0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A }, + { 0xEA, 0x67, 0x6B, 0x2C, 0xB7, 0xDB, 0x2B, 0x7A } }, + { { 0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16 }, + { 0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02 }, + { 0xDF, 0xD6, 0x4A, 0x81, 0x5C, 0xAF, 0x1A, 0x0F } }, + { { 0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F }, + { 0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A }, + { 0x5C, 0x51, 0x3C, 0x9C, 0x48, 0x86, 0xC0, 0x88 } }, + { { 0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46 }, + { 0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32 }, + { 0x0A, 0x2A, 0xEE, 0xAE, 0x3F, 0xF4, 0xAB, 0x77 } }, + { { 0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E }, + { 0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA }, + { 0xEF, 0x1B, 0xF0, 0x3E, 0x5D, 0xFA, 0x57, 0x5A } }, + { { 0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76 }, + { 0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62 }, + { 0x88, 0xBF, 0x0D, 0xB6, 0xD7, 0x0D, 0xEE, 0x56 } }, + { { 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07 }, + { 0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2 }, + { 0xA1, 0xF9, 0x91, 0x55, 0x41, 0x02, 0x0B, 0x56 } }, + { { 0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F }, + { 0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA }, + { 0x6F, 0xBF, 0x1C, 0xAF, 0xCF, 0xFD, 0x05, 0x56 } }, + { { 0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7 }, + { 0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92 }, + { 0x2F, 0x22, 0xE4, 0x9B, 0xAB, 0x7C, 0xA1, 0xAC } }, + { { 0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF }, + { 0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A }, + { 0x5A, 0x6B, 0x61, 0x2C, 0xC2, 0x6C, 0xCE, 0x4A } }, + { { 0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6 }, + { 0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2 }, + { 0x5F, 0x4C, 0x03, 0x8E, 0xD1, 0x2B, 0x2E, 0x41 } }, + { { 0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF }, + { 0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A }, + { 0x63, 0xFA, 0xC0, 0xD0, 0x34, 0xD9, 0xF7, 0x93 } } + }; diff --git a/third_party/cryptlib-0.99/testidea.h b/third_party/cryptlib-0.99/testidea.h new file mode 100644 index 0000000..42d5991 --- /dev/null +++ b/third_party/cryptlib-0.99/testidea.h @@ -0,0 +1,56 @@ +/* IDEA test vectors, from the ETH reference implementation */ + +/* The data structure for the ( key, plaintext, ciphertext ) triplets */ + +typedef struct { + BYTE key[ IDEA_KEYSIZE ]; + BYTE plaintext[ IDEA_BLOCKSIZE ]; + BYTE ciphertext[ IDEA_BLOCKSIZE ]; + } IDEA_TEST; + +static IDEA_TEST testIdea[] = { + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 }, + { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x54, 0x0E, 0x5F, 0xEA, 0x18, 0xC2, 0xF8, 0xB1 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x00, 0x19, 0x32, 0x4B, 0x64, 0x7D, 0x96, 0xAF }, + { 0x9F, 0x0A, 0x0A, 0xB6, 0xE1, 0x0C, 0xED, 0x78 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0xF5, 0x20, 0x2D, 0x5B, 0x9C, 0x67, 0x1B, 0x08 }, + { 0xCF, 0x18, 0xFD, 0x73, 0x55, 0xE2, 0xC5, 0xC5 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0xFA, 0xE6, 0xD2, 0xBE, 0xAA, 0x96, 0x82, 0x6E }, + { 0x85, 0xDF, 0x52, 0x00, 0x56, 0x08, 0x19, 0x3D } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x46, 0x50 }, + { 0x2F, 0x7D, 0xE7, 0x50, 0x21, 0x2F, 0xB7, 0x34 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x05, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x23, 0x28 }, + { 0x7B, 0x73, 0x14, 0x92, 0x5D, 0xE5, 0x9C, 0x09 } }, + { { 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14, + 0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x3E, 0xC0, 0x47, 0x80, 0xBE, 0xFF, 0x6E, 0x20 } }, + { { 0x3A, 0x98, 0x4E, 0x20, 0x00, 0x19, 0x5D, 0xB3, + 0x2E, 0xE5, 0x01, 0xC8, 0xC4, 0x7C, 0xEA, 0x60 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x97, 0xBC, 0xD8, 0x20, 0x07, 0x80, 0xDA, 0x86 } }, + { { 0x00, 0x64, 0x00, 0xC8, 0x01, 0x2C, 0x01, 0x90, + 0x01, 0xF4, 0x02, 0x58, 0x02, 0xBC, 0x03, 0x20 }, + { 0x05, 0x32, 0x0A, 0x64, 0x14, 0xC8, 0x19, 0xFA }, + { 0x65, 0xBE, 0x87, 0xE7, 0xA2, 0x53, 0x8A, 0xED } }, + { { 0x9D, 0x40, 0x75, 0xC1, 0x03, 0xBC, 0x32, 0x2A, + 0xFB, 0x03, 0xE7, 0xBE, 0x6A, 0xB3, 0x00, 0x06 }, + { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, + { 0xF5, 0xDB, 0x1A, 0xC4, 0x5E, 0x5E, 0xF9, 0xF9 } } + }; diff --git a/third_party/cryptlib-0.99/testrc4.h b/third_party/cryptlib-0.99/testrc4.h new file mode 100644 index 0000000..4ab5aaf --- /dev/null +++ b/third_party/cryptlib-0.99/testrc4.h @@ -0,0 +1,162 @@ +/* RC4 test vectors from the BSAFE2 implementation */ + +BYTE testRC4key1[] = + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; +BYTE testRC4plaintext1[] = + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; +BYTE testRC4ciphertext1[] = + { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }; + +BYTE testRC4key2[] = + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; +BYTE testRC4plaintext2[] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +BYTE testRC4ciphertext2[] = + { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }; + +BYTE testRC4key3[] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +BYTE testRC4plaintext3[] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +BYTE testRC4ciphertext3[] = + { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }; + +BYTE testRC4key4[] = + { 0xEF, 0x01, 0x23, 0x45 }; +BYTE testRC4plaintext4[] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +BYTE testRC4ciphertext4[] = + { 0xD6, 0xA1, 0x41, 0xA7, 0xEC, 0x3C, 0x38, 0xDF, 0xBD, 0x61 }; + +BYTE testRC4key5[] = + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; +BYTE testRC4plaintext5[] = + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; +BYTE testRC4ciphertext5[] = + { 0x75, 0x95, 0xC3, 0xE6, 0x11, 0x4A, 0x09, 0x78, + 0x0C, 0x4A, 0xD4, 0x52, 0x33, 0x8E, 0x1F, 0xFD, + 0x9A, 0x1B, 0xE9, 0x49, 0x8F, 0x81, 0x3D, 0x76, + 0x53, 0x34, 0x49, 0xB6, 0x77, 0x8D, 0xCA, 0xD8, + 0xC7, 0x8A, 0x8D, 0x2B, 0xA9, 0xAC, 0x66, 0x08, + 0x5D, 0x0E, 0x53, 0xD5, 0x9C, 0x26, 0xC2, 0xD1, + 0xC4, 0x90, 0xC1, 0xEB, 0xBE, 0x0C, 0xE6, 0x6D, + 0x1B, 0x6B, 0x1B, 0x13, 0xB6, 0xB9, 0x19, 0xB8, + 0x47, 0xC2, 0x5A, 0x91, 0x44, 0x7A, 0x95, 0xE7, + 0x5E, 0x4E, 0xF1, 0x67, 0x79, 0xCD, 0xE8, 0xBF, + 0x0A, 0x95, 0x85, 0x0E, 0x32, 0xAF, 0x96, 0x89, + 0x44, 0x4F, 0xD3, 0x77, 0x10, 0x8F, 0x98, 0xFD, + 0xCB, 0xD4, 0xE7, 0x26, 0x56, 0x75, 0x00, 0x99, + 0x0B, 0xCC, 0x7E, 0x0C, 0xA3, 0xC4, 0xAA, 0xA3, + 0x04, 0xA3, 0x87, 0xD2, 0x0F, 0x3B, 0x8F, 0xBB, + 0xCD, 0x42, 0xA1, 0xBD, 0x31, 0x1D, 0x7A, 0x43, + 0x03, 0xDD, 0xA5, 0xAB, 0x07, 0x88, 0x96, 0xAE, + 0x80, 0xC1, 0x8B, 0x0A, 0xF6, 0x6D, 0xFF, 0x31, + 0x96, 0x16, 0xEB, 0x78, 0x4E, 0x49, 0x5A, 0xD2, + 0xCE, 0x90, 0xD7, 0xF7, 0x72, 0xA8, 0x17, 0x47, + 0xB6, 0x5F, 0x62, 0x09, 0x3B, 0x1E, 0x0D, 0xB9, + 0xE5, 0xBA, 0x53, 0x2F, 0xAF, 0xEC, 0x47, 0x50, + 0x83, 0x23, 0xE6, 0x71, 0x32, 0x7D, 0xF9, 0x44, + 0x44, 0x32, 0xCB, 0x73, 0x67, 0xCE, 0xC8, 0x2F, + 0x5D, 0x44, 0xC0, 0xD0, 0x0B, 0x67, 0xD6, 0x50, + 0xA0, 0x75, 0xCD, 0x4B, 0x70, 0xDE, 0xDD, 0x77, + 0xEB, 0x9B, 0x10, 0x23, 0x1B, 0x6B, 0x5B, 0x74, + 0x13, 0x47, 0x39, 0x6D, 0x62, 0x89, 0x74, 0x21, + 0xD4, 0x3D, 0xF9, 0xB4, 0x2E, 0x44, 0x6E, 0x35, + 0x8E, 0x9C, 0x11, 0xA9, 0xB2, 0x18, 0x4E, 0xCB, + 0xEF, 0x0C, 0xD8, 0xE7, 0xA8, 0x77, 0xEF, 0x96, + 0x8F, 0x13, 0x90, 0xEC, 0x9B, 0x3D, 0x35, 0xA5, + 0x58, 0x5C, 0xB0, 0x09, 0x29, 0x0E, 0x2F, 0xCD, + 0xE7, 0xB5, 0xEC, 0x66, 0xD9, 0x08, 0x4B, 0xE4, + 0x40, 0x55, 0xA6, 0x19, 0xD9, 0xDD, 0x7F, 0xC3, + 0x16, 0x6F, 0x94, 0x87, 0xF7, 0xCB, 0x27, 0x29, + 0x12, 0x42, 0x64, 0x45, 0x99, 0x85, 0x14, 0xC1, + 0x5D, 0x53, 0xA1, 0x8C, 0x86, 0x4C, 0xE3, 0xA2, + 0xB7, 0x55, 0x57, 0x93, 0x98, 0x81, 0x26, 0x52, + 0x0E, 0xAC, 0xF2, 0xE3, 0x06, 0x6E, 0x23, 0x0C, + 0x91, 0xBE, 0xE4, 0xDD, 0x53, 0x04, 0xF5, 0xFD, + 0x04, 0x05, 0xB3, 0x5B, 0xD9, 0x9C, 0x73, 0x13, + 0x5D, 0x3D, 0x9B, 0xC3, 0x35, 0xEE, 0x04, 0x9E, + 0xF6, 0x9B, 0x38, 0x67, 0xBF, 0x2D, 0x7B, 0xD1, + 0xEA, 0xA5, 0x95, 0xD8, 0xBF, 0xC0, 0x06, 0x6F, + 0xF8, 0xD3, 0x15, 0x09, 0xEB, 0x0C, 0x6C, 0xAA, + 0x00, 0x6C, 0x80, 0x7A, 0x62, 0x3E, 0xF8, 0x4C, + 0x3D, 0x33, 0xC1, 0x95, 0xD2, 0x3E, 0xE3, 0x20, + 0xC4, 0x0D, 0xE0, 0x55, 0x81, 0x57, 0xC8, 0x22, + 0xD4, 0xB8, 0xC5, 0x69, 0xD8, 0x49, 0xAE, 0xD5, + 0x9D, 0x4E, 0x0F, 0xD7, 0xF3, 0x79, 0x58, 0x6B, + 0x4B, 0x7F, 0xF6, 0x84, 0xED, 0x6A, 0x18, 0x9F, + 0x74, 0x86, 0xD4, 0x9B, 0x9C, 0x4B, 0xAD, 0x9B, + 0xA2, 0x4B, 0x96, 0xAB, 0xF9, 0x24, 0x37, 0x2C, + 0x8A, 0x8F, 0xFF, 0xB1, 0x0D, 0x55, 0x35, 0x49, + 0x00, 0xA7, 0x7A, 0x3D, 0xB5, 0xF2, 0x05, 0xE1, + 0xB9, 0x9F, 0xCD, 0x86, 0x60, 0x86, 0x3A, 0x15, + 0x9A, 0xD4, 0xAB, 0xE4, 0x0F, 0xA4, 0x89, 0x34, + 0x16, 0x3D, 0xDD, 0xE5, 0x42, 0xA6, 0x58, 0x55, + 0x40, 0xFD, 0x68, 0x3C, 0xBF, 0xD8, 0xC0, 0x0F, + 0x12, 0x12, 0x9A, 0x28, 0x4D, 0xEA, 0xCC, 0x4C, + 0xDE, 0xFE, 0x58, 0xBE, 0x71, 0x37, 0x54, 0x1C, + 0x04, 0x71, 0x26, 0xC8, 0xD4, 0x9E, 0x27, 0x55, + 0xAB, 0x18, 0x1A, 0xB7, 0xE9, 0x40, 0xB0, 0xC0 }; diff --git a/third_party/cryptlib-0.99/testsafr.h b/third_party/cryptlib-0.99/testsafr.h new file mode 100644 index 0000000..f2449d4 --- /dev/null +++ b/third_party/cryptlib-0.99/testsafr.h @@ -0,0 +1,36 @@ +/* SAFER-SK64 test vectors, from the ETH reference implementation */ + +/* The data structure for the ( key, plaintext, ciphertext ) triplets */ + +typedef struct { + int rounds; + BYTE key[ SAFER_KEYSIZE ]; + BYTE plaintext[ SAFER_BLOCKSIZE ]; + BYTE ciphertext[ SAFER_BLOCKSIZE ]; + } SAFER_TEST; + +static SAFER_TEST testSafer[] = { + { SAFER_K64_DEFAULT_NOF_ROUNDS, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x15, 0x1B, 0xFF, 0x02, 0xAD, 0x11, 0xBF, 0x2D } }, + { SAFER_K64_DEFAULT_NOF_ROUNDS, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x5F, 0xCE, 0x9B, 0xA2, 0x05, 0x84, 0x38, 0xC7 } }, + { SAFER_K128_DEFAULT_NOF_ROUNDS, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x41, 0x4C, 0x54, 0x5A, 0xB6, 0x99, 0x4A, 0xF7 } }, + { SAFER_K128_DEFAULT_NOF_ROUNDS, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0xFF, 0x78, 0x11, 0xE4, 0xB3, 0xA7, 0x2E, 0x71 } }, + { SAFER_K128_DEFAULT_NOF_ROUNDS, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x49, 0xC9, 0x9D, 0x98, 0xA5, 0xBC, 0x59, 0x08 } }, + }; diff --git a/undes.c b/undes.c new file mode 100644 index 0000000..33937c5 --- /dev/null +++ b/undes.c @@ -0,0 +1,193 @@ +/* + * UNDES V1.1.0 - reconstructed from undes.exe + * Original executable: (C) 1998 H.N.M. Dijkema, GPL + * + * IMPORTANT: despite the program name, the executable selects + * CRYPT_ALGO_3DES + CRYPT_MODE_CBC, i.e. two-key triple DES in CBC mode. + * + * This is reconstructed source, not the original source text. Control flow, + * constants, CRYPTLIB calls and file-format behaviour are derived from the + * 16-bit Turbo C executable and verified against CRYPTLIB 0.99 source. + */ + +#include +#include +#include +#include +#include "crypt.h" +#include "des_common.h" + +int main( int argc, char **argv ) +{ + char *password; + char *inputName; + char *outputName; + FILE *input; + FILE *output; + unsigned char *buffer; + unsigned char *payload; + BYTE key[ CRYPT_MAX_KEYSIZE ]; + BYTE iv[ CRYPT_MAX_IVSIZE ]; + BYTE passwordBlock[ CRYPT_MAX_KEYSIZE ]; + CRYPT_INFO cryptInfo; + CRYPT_QUERY_INFO queryInfo; + CRYPT_ALGO algorithm = CRYPT_ALGO_3DES; + CRYPT_MODE mode = CRYPT_MODE_CBC; + DES_INT32 fileVersion; + DES_INT32 plainLength; + int keySize; + int ivSize; + int bytesRead; + int firstTime; + int inputFd; + int i; + + if( argc == 2 ) + { + if( strcmp( argv[ 1 ], "--copyright" ) == 0 ) + { + printf( "%s\n\n", desProgramVersion ); + printf( "%s", desCopyrightText ); + exit( 0 ); + } + + if( strcmp( argv[ 1 ], "--version" ) == 0 ) + { + printf( "%s\n", desProgramVersion ); + exit( 0 ); + } + } + + if( argc != 4 ) + { + fprintf( stderr, + "usage: undes \n" + " undes --copyright\n" + " undes --version\n" + " '-' for file --> stdin/stdout\n" ); + exit( argc == 1 ? 0 : 2 ); + } + + password = argv[ 1 ]; + inputName = argv[ 2 ]; + outputName = argv[ 3 ]; + + if( strcmp( inputName, "-" ) != 0 && + strcmp( inputName, outputName ) == 0 ) + { + fprintf( stderr, " and cannot be the same\n" ); + exit( 1 ); + } + + input = ( strcmp( inputName, "-" ) == 0 ) ? + stdin : fopen( inputName, "rb" ); + output = ( strcmp( outputName, "-" ) == 0 ) ? + stdout : fopen( outputName, "wb" ); + + checkOpen( input, inputName ); + checkOpen( output, outputName ); + + algorithm = CRYPT_ALGO_3DES; + mode = CRYPT_MODE_CBC; + firstTime = TRUE; + + buffer = (unsigned char *) malloc( DES_BUFFER_SIZE ); + if( buffer == NULL ) + { + fprintf( stderr, "Can't allocate buffer\n" ); + exit( 1 ); + } + + payload = buffer + DES_PREFIX_SIZE; + + initLibrary(); + + queryAlgoModeInformation( algorithm, mode, &queryInfo ); + keySize = queryInfo.keySize; /* 14 bytes */ + ivSize = queryInfo.ivSize; /* 4 bytes */ + + i = 0; + while( i < keySize && password[ i ] != '\0' ) + { + key[ i ] = (BYTE) password[ i ]; + i++; + } + while( i < keySize ) + key[ i++ ] = 0; + + fileVersion = (DES_INT32) -1; + inputFd = fileno( input ); + + bytesRead = read( inputFd, &fileVersion, 4 ); + checkRead( bytesRead ); + checkVersion( fileVersion ); + + initCryptContext( &cryptInfo, algorithm, mode ); + loadCryptContext( &cryptInfo, key, keySize ); + + queryContextInformation( &cryptInfo, &queryInfo ); + ivSize = queryInfo.ivSize; + + bytesRead = read( inputFd, iv, ivSize ); + checkRead( bytesRead ); + loadIV( &cryptInfo, iv, ivSize ); + + bytesRead = read( inputFd, passwordBlock, CRYPT_MAX_KEYSIZE ); + checkRead( bytesRead ); + + bytesRead = read( inputFd, buffer, DES_BUFFER_SIZE ); + checkRead( bytesRead ); + + while( bytesRead != 0 ) + { + /* + * This ordering is intentional. DES encrypts the first data block + * before passwordBlock, although passwordBlock is stored first in the + * file. Decrypting in the same crypto order preserves CBC state. + */ + decryptBuffer( &cryptInfo, buffer, DES_BUFFER_SIZE ); + + memcpy( &plainLength, buffer, 4 ); + if( plainLength < 0 ) + plainLength = DES_PAYLOAD_SIZE; + + if( firstTime ) + { + decryptBuffer( &cryptInfo, passwordBlock, CRYPT_MAX_KEYSIZE ); + + i = 0; + while( i < keySize && passwordBlock[ i ] == key[ i ] ) + i++; + + if( i != keySize ) + { + fprintf( stderr, + "Password is not correct, no decryption possible\n" ); + exit( 1 ); + } + + firstTime = FALSE; + } + + fwrite( payload, (DES_UINT16) plainLength, 1, output ); + checkWrite( output ); + fflush( output ); + + bytesRead = read( inputFd, buffer, DES_BUFFER_SIZE ); + checkRead( bytesRead ); + } + + decryptBuffer( &cryptInfo, buffer, 0 ); + + destroyCryptContext( &cryptInfo ); + endLibrary(); + + free( buffer ); + + if( input != stdin ) + fclose( input ); + if( output != stdout ) + fclose( output ); + + return( 0 ); +} diff --git a/validation.md b/validation.md new file mode 100644 index 0000000..8f096b2 --- /dev/null +++ b/validation.md @@ -0,0 +1,50 @@ +# Validation + +The reconstructed sources were checked in two ways. + +## 1. Header/API syntax check + +`des.c`, `undes.c` and the common support compile syntactically against the +actual `crypt.h` from the supplied `cryptl99.zip`. There are no remaining +placeholder CRYPTLIB declarations. + +## 2. Full CRYPTLIB round-trip on a modern compiler + +For a behavioural sanity check, the supplied CRYPTLIB 0.99 source and libdes +3.14 source were compiled with GCC 14.2 together with the reconstruction. + +A binary test file was then processed as: + +```text +plain.bin -> des_v2 -> encrypted.bin -> undes_v2 -> roundtrip.bin +``` + +`plain.bin` and `roundtrip.bin` compare byte-for-byte equal. + +The generated single-block encrypted file has the expected size: + +```text +4 version +4 IV +256 password-check block +16384 encrypted data block +----- +16648 bytes total +``` + +The prefix begins with `75 27 00 00`, i.e. file version `0x00002775` in the +little-endian format used by the DOS executable. + +A second test with an incorrect password exits with status 1 and prints the +same executable string: + +`Password is not correct, no decryption possible` + +## Scope of this validation + +This confirms that the reconstructed control flow is internally consistent +with the supplied CRYPTLIB source. It does **not** prove that a modern GCC +build produces ciphertext byte-for-byte identical to the original Turbo C +build. The strongest compatibility test would be to decrypt an actual file +created by the 1998 `des.exe`, or run the original executable in a DOS +environment and compare outputs.