kpmpgsmkii/shared/thirdparty/blowfish-api/blowfish.c

1596 lines
52 KiB
C

/**
@file blowfish.c
@brief Portable, optimised implementation of Bruce Schneier's 64-bit
symmetric block cipher, Blowfish. Includes support for multiple
block cipher modes, including electronic codebook (ECB), cipher
block chaining (CBC), cipher feedback (CFB), output feedback
(OFB) and counter (CTR), as well as support for weak key
detection and parallelisation using OpenMP.
For more information on the Blowfish block cipher algorithm see
http://www.schneier.com/blowfish.html
@author Tom Bonner (tom.bonner@gmail.com)
@date 15-June-2008
Copyright (c) 2008, Tom Bonner.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright
holders shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written authorisation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "blowfish.h"
/**
@ingroup blowfish
@defgroup blowfish_api Blowfish API
@{
@details See description for @ref blowfish.c
@todo Include support for little-endian systems.
@todo Remove restrictions on buffer lengths being a multiple of 8 by either padding input buffers, or truncating enciphered data, depending on the selected block cipher mode.
*/
/**
@internal
@page glossary Glossary of symbols
@param Iv 8-byte initialisation vector.
@param xL High 4-bytes of block to encipher/decipher.
@param xR Low 4-bytes of block to encipher/decipher.
@param C 8-byte block of ciphertext.
@param P PArray or 8-byte block of plaintext.
@param S Sbox.
@param k Key.
@param E Blowfish encipher.
@param D Blowfish decipher.
@param n Round number.
*/
/* Internal function prototypes (Encipher/Decipher stream callbacks) */
static void _BLOWFISH_EncipherStream_ECB ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG PlainTextStream, BLOWFISH_PULONG CipherTextStream, BLOWFISH_SIZE_T StreamLength );
static void _BLOWFISH_DecipherStream_ECB ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG CipherTextStream, BLOWFISH_PULONG PlainTextStream, BLOWFISH_SIZE_T StreamLength );
static void _BLOWFISH_EncipherStream_CBC ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG PlainTextStream, BLOWFISH_PULONG CipherTextStream, BLOWFISH_SIZE_T StreamLength );
static void _BLOWFISH_DecipherStream_CBC ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG CipherTextStream, BLOWFISH_PULONG PlainTextStream, BLOWFISH_SIZE_T StreamLength );
static void _BLOWFISH_EncipherStream_CFB ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG PlainTextStream, BLOWFISH_PULONG CipherTextStream, BLOWFISH_SIZE_T StreamLength );
static void _BLOWFISH_DecipherStream_CFB ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG CipherTextStream, BLOWFISH_PULONG PlainTextStream, BLOWFISH_SIZE_T StreamLength );
static void _BLOWFISH_EncipherDecipherStream_OFB ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG InStream, BLOWFISH_PULONG OutStream, BLOWFISH_SIZE_T StreamLength );
static void _BLOWFISH_EncipherDecipherStream_CTR ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG InStream, BLOWFISH_PULONG OutStream, BLOWFISH_SIZE_T StreamLength );
/** @internal Original S-Boxes (hexdigits of pi). */
static const BLOWFISH_ULONG _BLOWFISH_SBox [ BLOWFISH_SBOXES ] [ BLOWFISH_SBOX_ENTRIES ] =
{
{
0xd1310ba6l, 0x98dfb5acl, 0x2ffd72dbl, 0xd01adfb7l,
0xb8e1afedl, 0x6a267e96l, 0xba7c9045l, 0xf12c7f99l,
0x24a19947l, 0xb3916cf7l, 0x0801f2e2l, 0x858efc16l,
0x636920d8l, 0x71574e69l, 0xa458fea3l, 0xf4933d7el,
0x0d95748fl, 0x728eb658l, 0x718bcd58l, 0x82154aeel,
0x7b54a41dl, 0xc25a59b5l, 0x9c30d539l, 0x2af26013l,
0xc5d1b023l, 0x286085f0l, 0xca417918l, 0xb8db38efl,
0x8e79dcb0l, 0x603a180el, 0x6c9e0e8bl, 0xb01e8a3el,
0xd71577c1l, 0xbd314b27l, 0x78af2fdal, 0x55605c60l,
0xe65525f3l, 0xaa55ab94l, 0x57489862l, 0x63e81440l,
0x55ca396al, 0x2aab10b6l, 0xb4cc5c34l, 0x1141e8cel,
0xa15486afl, 0x7c72e993l, 0xb3ee1411l, 0x636fbc2al,
0x2ba9c55dl, 0x741831f6l, 0xce5c3e16l, 0x9b87931el,
0xafd6ba33l, 0x6c24cf5cl, 0x7a325381l, 0x28958677l,
0x3b8f4898l, 0x6b4bb9afl, 0xc4bfe81bl, 0x66282193l,
0x61d809ccl, 0xfb21a991l, 0x487cac60l, 0x5dec8032l,
0xef845d5dl, 0xe98575b1l, 0xdc262302l, 0xeb651b88l,
0x23893e81l, 0xd396acc5l, 0x0f6d6ff3l, 0x83f44239l,
0x2e0b4482l, 0xa4842004l, 0x69c8f04al, 0x9e1f9b5el,
0x21c66842l, 0xf6e96c9al, 0x670c9c61l, 0xabd388f0l,
0x6a51a0d2l, 0xd8542f68l, 0x960fa728l, 0xab5133a3l,
0x6eef0b6cl, 0x137a3be4l, 0xba3bf050l, 0x7efb2a98l,
0xa1f1651dl, 0x39af0176l, 0x66ca593el, 0x82430e88l,
0x8cee8619l, 0x456f9fb4l, 0x7d84a5c3l, 0x3b8b5ebel,
0xe06f75d8l, 0x85c12073l, 0x401a449fl, 0x56c16aa6l,
0x4ed3aa62l, 0x363f7706l, 0x1bfedf72l, 0x429b023dl,
0x37d0d724l, 0xd00a1248l, 0xdb0fead3l, 0x49f1c09bl,
0x075372c9l, 0x80991b7bl, 0x25d479d8l, 0xf6e8def7l,
0xe3fe501al, 0xb6794c3bl, 0x976ce0bdl, 0x04c006bal,
0xc1a94fb6l, 0x409f60c4l, 0x5e5c9ec2l, 0x196a2463l,
0x68fb6fafl, 0x3e6c53b5l, 0x1339b2ebl, 0x3b52ec6fl,
0x6dfc511fl, 0x9b30952cl, 0xcc814544l, 0xaf5ebd09l,
0xbee3d004l, 0xde334afdl, 0x660f2807l, 0x192e4bb3l,
0xc0cba857l, 0x45c8740fl, 0xd20b5f39l, 0xb9d3fbdbl,
0x5579c0bdl, 0x1a60320al, 0xd6a100c6l, 0x402c7279l,
0x679f25fel, 0xfb1fa3ccl, 0x8ea5e9f8l, 0xdb3222f8l,
0x3c7516dfl, 0xfd616b15l, 0x2f501ec8l, 0xad0552abl,
0x323db5fal, 0xfd238760l, 0x53317b48l, 0x3e00df82l,
0x9e5c57bbl, 0xca6f8ca0l, 0x1a87562el, 0xdf1769dbl,
0xd542a8f6l, 0x287effc3l, 0xac6732c6l, 0x8c4f5573l,
0x695b27b0l, 0xbbca58c8l, 0xe1ffa35dl, 0xb8f011a0l,
0x10fa3d98l, 0xfd2183b8l, 0x4afcb56cl, 0x2dd1d35bl,
0x9a53e479l, 0xb6f84565l, 0xd28e49bcl, 0x4bfb9790l,
0xe1ddf2dal, 0xa4cb7e33l, 0x62fb1341l, 0xcee4c6e8l,
0xef20cadal, 0x36774c01l, 0xd07e9efel, 0x2bf11fb4l,
0x95dbda4dl, 0xae909198l, 0xeaad8e71l, 0x6b93d5a0l,
0xd08ed1d0l, 0xafc725e0l, 0x8e3c5b2fl, 0x8e7594b7l,
0x8ff6e2fbl, 0xf2122b64l, 0x8888b812l, 0x900df01cl,
0x4fad5ea0l, 0x688fc31cl, 0xd1cff191l, 0xb3a8c1adl,
0x2f2f2218l, 0xbe0e1777l, 0xea752dfel, 0x8b021fa1l,
0xe5a0cc0fl, 0xb56f74e8l, 0x18acf3d6l, 0xce89e299l,
0xb4a84fe0l, 0xfd13e0b7l, 0x7cc43b81l, 0xd2ada8d9l,
0x165fa266l, 0x80957705l, 0x93cc7314l, 0x211a1477l,
0xe6ad2065l, 0x77b5fa86l, 0xc75442f5l, 0xfb9d35cfl,
0xebcdaf0cl, 0x7b3e89a0l, 0xd6411bd3l, 0xae1e7e49l,
0x00250e2dl, 0x2071b35el, 0x226800bbl, 0x57b8e0afl,
0x2464369bl, 0xf009b91el, 0x5563911dl, 0x59dfa6aal,
0x78c14389l, 0xd95a537fl, 0x207d5ba2l, 0x02e5b9c5l,
0x83260376l, 0x6295cfa9l, 0x11c81968l, 0x4e734a41l,
0xb3472dcal, 0x7b14a94al, 0x1b510052l, 0x9a532915l,
0xd60f573fl, 0xbc9bc6e4l, 0x2b60a476l, 0x81e67400l,
0x08ba6fb5l, 0x571be91fl, 0xf296ec6bl, 0x2a0dd915l,
0xb6636521l, 0xe7b9f9b6l, 0xff34052el, 0xc5855664l,
0x53b02d5dl, 0xa99f8fa1l, 0x08ba4799l, 0x6e85076al
},
{
0x4b7a70e9l, 0xb5b32944l, 0xdb75092el, 0xc4192623l,
0xad6ea6b0l, 0x49a7df7dl, 0x9cee60b8l, 0x8fedb266l,
0xecaa8c71l, 0x699a17ffl, 0x5664526cl, 0xc2b19ee1l,
0x193602a5l, 0x75094c29l, 0xa0591340l, 0xe4183a3el,
0x3f54989al, 0x5b429d65l, 0x6b8fe4d6l, 0x99f73fd6l,
0xa1d29c07l, 0xefe830f5l, 0x4d2d38e6l, 0xf0255dc1l,
0x4cdd2086l, 0x8470eb26l, 0x6382e9c6l, 0x021ecc5el,
0x09686b3fl, 0x3ebaefc9l, 0x3c971814l, 0x6b6a70a1l,
0x687f3584l, 0x52a0e286l, 0xb79c5305l, 0xaa500737l,
0x3e07841cl, 0x7fdeae5cl, 0x8e7d44ecl, 0x5716f2b8l,
0xb03ada37l, 0xf0500c0dl, 0xf01c1f04l, 0x0200b3ffl,
0xae0cf51al, 0x3cb574b2l, 0x25837a58l, 0xdc0921bdl,
0xd19113f9l, 0x7ca92ff6l, 0x94324773l, 0x22f54701l,
0x3ae5e581l, 0x37c2dadcl, 0xc8b57634l, 0x9af3dda7l,
0xa9446146l, 0x0fd0030el, 0xecc8c73el, 0xa4751e41l,
0xe238cd99l, 0x3bea0e2fl, 0x3280bba1l, 0x183eb331l,
0x4e548b38l, 0x4f6db908l, 0x6f420d03l, 0xf60a04bfl,
0x2cb81290l, 0x24977c79l, 0x5679b072l, 0xbcaf89afl,
0xde9a771fl, 0xd9930810l, 0xb38bae12l, 0xdccf3f2el,
0x5512721fl, 0x2e6b7124l, 0x501adde6l, 0x9f84cd87l,
0x7a584718l, 0x7408da17l, 0xbc9f9abcl, 0xe94b7d8cl,
0xec7aec3al, 0xdb851dfal, 0x63094366l, 0xc464c3d2l,
0xef1c1847l, 0x3215d908l, 0xdd433b37l, 0x24c2ba16l,
0x12a14d43l, 0x2a65c451l, 0x50940002l, 0x133ae4ddl,
0x71dff89el, 0x10314e55l, 0x81ac77d6l, 0x5f11199bl,
0x043556f1l, 0xd7a3c76bl, 0x3c11183bl, 0x5924a509l,
0xf28fe6edl, 0x97f1fbfal, 0x9ebabf2cl, 0x1e153c6el,
0x86e34570l, 0xeae96fb1l, 0x860e5e0al, 0x5a3e2ab3l,
0x771fe71cl, 0x4e3d06fal, 0x2965dcb9l, 0x99e71d0fl,
0x803e89d6l, 0x5266c825l, 0x2e4cc978l, 0x9c10b36al,
0xc6150ebal, 0x94e2ea78l, 0xa5fc3c53l, 0x1e0a2df4l,
0xf2f74ea7l, 0x361d2b3dl, 0x1939260fl, 0x19c27960l,
0x5223a708l, 0xf71312b6l, 0xebadfe6el, 0xeac31f66l,
0xe3bc4595l, 0xa67bc883l, 0xb17f37d1l, 0x018cff28l,
0xc332ddefl, 0xbe6c5aa5l, 0x65582185l, 0x68ab9802l,
0xeecea50fl, 0xdb2f953bl, 0x2aef7dadl, 0x5b6e2f84l,
0x1521b628l, 0x29076170l, 0xecdd4775l, 0x619f1510l,
0x13cca830l, 0xeb61bd96l, 0x0334fe1el, 0xaa0363cfl,
0xb5735c90l, 0x4c70a239l, 0xd59e9e0bl, 0xcbaade14l,
0xeecc86bcl, 0x60622ca7l, 0x9cab5cabl, 0xb2f3846el,
0x648b1eafl, 0x19bdf0cal, 0xa02369b9l, 0x655abb50l,
0x40685a32l, 0x3c2ab4b3l, 0x319ee9d5l, 0xc021b8f7l,
0x9b540b19l, 0x875fa099l, 0x95f7997el, 0x623d7da8l,
0xf837889al, 0x97e32d77l, 0x11ed935fl, 0x16681281l,
0x0e358829l, 0xc7e61fd6l, 0x96dedfa1l, 0x7858ba99l,
0x57f584a5l, 0x1b227263l, 0x9b83c3ffl, 0x1ac24696l,
0xcdb30aebl, 0x532e3054l, 0x8fd948e4l, 0x6dbc3128l,
0x58ebf2efl, 0x34c6ffeal, 0xfe28ed61l, 0xee7c3c73l,
0x5d4a14d9l, 0xe864b7e3l, 0x42105d14l, 0x203e13e0l,
0x45eee2b6l, 0xa3aaabeal, 0xdb6c4f15l, 0xfacb4fd0l,
0xc742f442l, 0xef6abbb5l, 0x654f3b1dl, 0x41cd2105l,
0xd81e799el, 0x86854dc7l, 0xe44b476al, 0x3d816250l,
0xcf62a1f2l, 0x5b8d2646l, 0xfc8883a0l, 0xc1c7b6a3l,
0x7f1524c3l, 0x69cb7492l, 0x47848a0bl, 0x5692b285l,
0x095bbf00l, 0xad19489dl, 0x1462b174l, 0x23820e00l,
0x58428d2al, 0x0c55f5eal, 0x1dadf43el, 0x233f7061l,
0x3372f092l, 0x8d937e41l, 0xd65fecf1l, 0x6c223bdbl,
0x7cde3759l, 0xcbee7460l, 0x4085f2a7l, 0xce77326el,
0xa6078084l, 0x19f8509el, 0xe8efd855l, 0x61d99735l,
0xa969a7aal, 0xc50c06c2l, 0x5a04abfcl, 0x800bcadcl,
0x9e447a2el, 0xc3453484l, 0xfdd56705l, 0x0e1e9ec9l,
0xdb73dbd3l, 0x105588cdl, 0x675fda79l, 0xe3674340l,
0xc5c43465l, 0x713e38d8l, 0x3d28f89el, 0xf16dff20l,
0x153e21e7l, 0x8fb03d4al, 0xe6e39f2bl, 0xdb83adf7l
},
{
0xe93d5a68l, 0x948140f7l, 0xf64c261cl, 0x94692934l,
0x411520f7l, 0x7602d4f7l, 0xbcf46b2el, 0xd4a20068l,
0xd4082471l, 0x3320f46al, 0x43b7d4b7l, 0x500061afl,
0x1e39f62el, 0x97244546l, 0x14214f74l, 0xbf8b8840l,
0x4d95fc1dl, 0x96b591afl, 0x70f4ddd3l, 0x66a02f45l,
0xbfbc09ecl, 0x03bd9785l, 0x7fac6dd0l, 0x31cb8504l,
0x96eb27b3l, 0x55fd3941l, 0xda2547e6l, 0xabca0a9al,
0x28507825l, 0x530429f4l, 0x0a2c86dal, 0xe9b66dfbl,
0x68dc1462l, 0xd7486900l, 0x680ec0a4l, 0x27a18deel,
0x4f3ffea2l, 0xe887ad8cl, 0xb58ce006l, 0x7af4d6b6l,
0xaace1e7cl, 0xd3375fecl, 0xce78a399l, 0x406b2a42l,
0x20fe9e35l, 0xd9f385b9l, 0xee39d7abl, 0x3b124e8bl,
0x1dc9faf7l, 0x4b6d1856l, 0x26a36631l, 0xeae397b2l,
0x3a6efa74l, 0xdd5b4332l, 0x6841e7f7l, 0xca7820fbl,
0xfb0af54el, 0xd8feb397l, 0x454056acl, 0xba489527l,
0x55533a3al, 0x20838d87l, 0xfe6ba9b7l, 0xd096954bl,
0x55a867bcl, 0xa1159a58l, 0xcca92963l, 0x99e1db33l,
0xa62a4a56l, 0x3f3125f9l, 0x5ef47e1cl, 0x9029317cl,
0xfdf8e802l, 0x04272f70l, 0x80bb155cl, 0x05282ce3l,
0x95c11548l, 0xe4c66d22l, 0x48c1133fl, 0xc70f86dcl,
0x07f9c9eel, 0x41041f0fl, 0x404779a4l, 0x5d886e17l,
0x325f51ebl, 0xd59bc0d1l, 0xf2bcc18fl, 0x41113564l,
0x257b7834l, 0x602a9c60l, 0xdff8e8a3l, 0x1f636c1bl,
0x0e12b4c2l, 0x02e1329el, 0xaf664fd1l, 0xcad18115l,
0x6b2395e0l, 0x333e92e1l, 0x3b240b62l, 0xeebeb922l,
0x85b2a20el, 0xe6ba0d99l, 0xde720c8cl, 0x2da2f728l,
0xd0127845l, 0x95b794fdl, 0x647d0862l, 0xe7ccf5f0l,
0x5449a36fl, 0x877d48fal, 0xc39dfd27l, 0xf33e8d1el,
0x0a476341l, 0x992eff74l, 0x3a6f6eabl, 0xf4f8fd37l,
0xa812dc60l, 0xa1ebddf8l, 0x991be14cl, 0xdb6e6b0dl,
0xc67b5510l, 0x6d672c37l, 0x2765d43bl, 0xdcd0e804l,
0xf1290dc7l, 0xcc00ffa3l, 0xb5390f92l, 0x690fed0bl,
0x667b9ffbl, 0xcedb7d9cl, 0xa091cf0bl, 0xd9155ea3l,
0xbb132f88l, 0x515bad24l, 0x7b9479bfl, 0x763bd6ebl,
0x37392eb3l, 0xcc115979l, 0x8026e297l, 0xf42e312dl,
0x6842ada7l, 0xc66a2b3bl, 0x12754cccl, 0x782ef11cl,
0x6a124237l, 0xb79251e7l, 0x06a1bbe6l, 0x4bfb6350l,
0x1a6b1018l, 0x11caedfal, 0x3d25bdd8l, 0xe2e1c3c9l,
0x44421659l, 0x0a121386l, 0xd90cec6el, 0xd5abea2al,
0x64af674el, 0xda86a85fl, 0xbebfe988l, 0x64e4c3fel,
0x9dbc8057l, 0xf0f7c086l, 0x60787bf8l, 0x6003604dl,
0xd1fd8346l, 0xf6381fb0l, 0x7745ae04l, 0xd736fcccl,
0x83426b33l, 0xf01eab71l, 0xb0804187l, 0x3c005e5fl,
0x77a057bel, 0xbde8ae24l, 0x55464299l, 0xbf582e61l,
0x4e58f48fl, 0xf2ddfda2l, 0xf474ef38l, 0x8789bdc2l,
0x5366f9c3l, 0xc8b38e74l, 0xb475f255l, 0x46fcd9b9l,
0x7aeb2661l, 0x8b1ddf84l, 0x846a0e79l, 0x915f95e2l,
0x466e598el, 0x20b45770l, 0x8cd55591l, 0xc902de4cl,
0xb90bace1l, 0xbb8205d0l, 0x11a86248l, 0x7574a99el,
0xb77f19b6l, 0xe0a9dc09l, 0x662d09a1l, 0xc4324633l,
0xe85a1f02l, 0x09f0be8cl, 0x4a99a025l, 0x1d6efe10l,
0x1ab93d1dl, 0x0ba5a4dfl, 0xa186f20fl, 0x2868f169l,
0xdcb7da83l, 0x573906fel, 0xa1e2ce9bl, 0x4fcd7f52l,
0x50115e01l, 0xa70683fal, 0xa002b5c4l, 0x0de6d027l,
0x9af88c27l, 0x773f8641l, 0xc3604c06l, 0x61a806b5l,
0xf0177a28l, 0xc0f586e0l, 0x006058aal, 0x30dc7d62l,
0x11e69ed7l, 0x2338ea63l, 0x53c2dd94l, 0xc2c21634l,
0xbbcbee56l, 0x90bcb6del, 0xebfc7da1l, 0xce591d76l,
0x6f05e409l, 0x4b7c0188l, 0x39720a3dl, 0x7c927c24l,
0x86e3725fl, 0x724d9db9l, 0x1ac15bb4l, 0xd39eb8fcl,
0xed545578l, 0x08fca5b5l, 0xd83d7cd3l, 0x4dad0fc4l,
0x1e50ef5el, 0xb161e6f8l, 0xa28514d9l, 0x6c51133cl,
0x6fd5c7e7l, 0x56e14ec4l, 0x362abfcel, 0xddc6c837l,
0xd79a3234l, 0x92638212l, 0x670efa8el, 0x406000e0l
},
{
0x3a39ce37l, 0xd3faf5cfl, 0xabc27737l, 0x5ac52d1bl,
0x5cb0679el, 0x4fa33742l, 0xd3822740l, 0x99bc9bbel,
0xd5118e9dl, 0xbf0f7315l, 0xd62d1c7el, 0xc700c47bl,
0xb78c1b6bl, 0x21a19045l, 0xb26eb1bel, 0x6a366eb4l,
0x5748ab2fl, 0xbc946e79l, 0xc6a376d2l, 0x6549c2c8l,
0x530ff8eel, 0x468dde7dl, 0xd5730a1dl, 0x4cd04dc6l,
0x2939bbdbl, 0xa9ba4650l, 0xac9526e8l, 0xbe5ee304l,
0xa1fad5f0l, 0x6a2d519al, 0x63ef8ce2l, 0x9a86ee22l,
0xc089c2b8l, 0x43242ef6l, 0xa51e03aal, 0x9cf2d0a4l,
0x83c061bal, 0x9be96a4dl, 0x8fe51550l, 0xba645bd6l,
0x2826a2f9l, 0xa73a3ae1l, 0x4ba99586l, 0xef5562e9l,
0xc72fefd3l, 0xf752f7dal, 0x3f046f69l, 0x77fa0a59l,
0x80e4a915l, 0x87b08601l, 0x9b09e6adl, 0x3b3ee593l,
0xe990fd5al, 0x9e34d797l, 0x2cf0b7d9l, 0x022b8b51l,
0x96d5ac3al, 0x017da67dl, 0xd1cf3ed6l, 0x7c7d2d28l,
0x1f9f25cfl, 0xadf2b89bl, 0x5ad6b472l, 0x5a88f54cl,
0xe029ac71l, 0xe019a5e6l, 0x47b0acfdl, 0xed93fa9bl,
0xe8d3c48dl, 0x283b57ccl, 0xf8d56629l, 0x79132e28l,
0x785f0191l, 0xed756055l, 0xf7960e44l, 0xe3d35e8cl,
0x15056dd4l, 0x88f46dbal, 0x03a16125l, 0x0564f0bdl,
0xc3eb9e15l, 0x3c9057a2l, 0x97271aecl, 0xa93a072al,
0x1b3f6d9bl, 0x1e6321f5l, 0xf59c66fbl, 0x26dcf319l,
0x7533d928l, 0xb155fdf5l, 0x03563482l, 0x8aba3cbbl,
0x28517711l, 0xc20ad9f8l, 0xabcc5167l, 0xccad925fl,
0x4de81751l, 0x3830dc8el, 0x379d5862l, 0x9320f991l,
0xea7a90c2l, 0xfb3e7bcel, 0x5121ce64l, 0x774fbe32l,
0xa8b6e37el, 0xc3293d46l, 0x48de5369l, 0x6413e680l,
0xa2ae0810l, 0xdd6db224l, 0x69852dfdl, 0x09072166l,
0xb39a460al, 0x6445c0ddl, 0x586cdecfl, 0x1c20c8ael,
0x5bbef7ddl, 0x1b588d40l, 0xccd2017fl, 0x6bb4e3bbl,
0xdda26a7el, 0x3a59ff45l, 0x3e350a44l, 0xbcb4cdd5l,
0x72eacea8l, 0xfa6484bbl, 0x8d6612ael, 0xbf3c6f47l,
0xd29be463l, 0x542f5d9el, 0xaec2771bl, 0xf64e6370l,
0x740e0d8dl, 0xe75b1357l, 0xf8721671l, 0xaf537d5dl,
0x4040cb08l, 0x4eb4e2ccl, 0x34d2466al, 0x0115af84l,
0xe1b00428l, 0x95983a1dl, 0x06b89fb4l, 0xce6ea048l,
0x6f3f3b82l, 0x3520ab82l, 0x011a1d4bl, 0x277227f8l,
0x611560b1l, 0xe7933fdcl, 0xbb3a792bl, 0x344525bdl,
0xa08839e1l, 0x51ce794bl, 0x2f32c9b7l, 0xa01fbac9l,
0xe01cc87el, 0xbcc7d1f6l, 0xcf0111c3l, 0xa1e8aac7l,
0x1a908749l, 0xd44fbd9al, 0xd0dadecbl, 0xd50ada38l,
0x0339c32al, 0xc6913667l, 0x8df9317cl, 0xe0b12b4fl,
0xf79e59b7l, 0x43f5bb3al, 0xf2d519ffl, 0x27d9459cl,
0xbf97222cl, 0x15e6fc2al, 0x0f91fc71l, 0x9b941525l,
0xfae59361l, 0xceb69cebl, 0xc2a86459l, 0x12baa8d1l,
0xb6c1075el, 0xe3056a0cl, 0x10d25065l, 0xcb03a442l,
0xe0ec6e0el, 0x1698db3bl, 0x4c98a0bel, 0x3278e964l,
0x9f1f9532l, 0xe0d392dfl, 0xd3a0342bl, 0x8971f21el,
0x1b0a7441l, 0x4ba3348cl, 0xc5be7120l, 0xc37632d8l,
0xdf359f8dl, 0x9b992f2el, 0xe60b6f47l, 0x0fe3f11dl,
0xe54cda54l, 0x1edad891l, 0xce6279cfl, 0xcd3e7e6fl,
0x1618b166l, 0xfd2c1d05l, 0x848fd2c5l, 0xf6fb2299l,
0xf523f357l, 0xa6327623l, 0x93a83531l, 0x56cccd02l,
0xacf08162l, 0x5a75ebb5l, 0x6e163697l, 0x88d273ccl,
0xde966292l, 0x81b949d0l, 0x4c50901bl, 0x71c65614l,
0xe6c6c7bdl, 0x327a140al, 0x45e1d006l, 0xc3f27b9al,
0xc9aa53fdl, 0x62a80f00l, 0xbb25bfe2l, 0x35bdd2f6l,
0x71126905l, 0xb2040222l, 0xb6cbcf7cl, 0xcd769c2bl,
0x53113ec0l, 0x1640e3d3l, 0x38abbd60l, 0x2547adf0l,
0xba38209cl, 0xf746ce76l, 0x77afa1c5l, 0x20756060l,
0x85cbfe4el, 0x8ae88dd8l, 0x7aaaf9b0l, 0x4cf9aa7el,
0x1948c25cl, 0x02fb8a8cl, 0x01c36ae4l, 0xd6ebe1f9l,
0x90d4f869l, 0xa65cdea0l, 0x3f09252dl, 0xc208e69fl,
0xb74e6132l, 0xce77e25bl, 0x578fdfe3l, 0x3ac372e6l
}
};
/** @internal Original P-Array (hexdigits of pi) */
static const BLOWFISH_ULONG _BLOWFISH_PArray [ BLOWFISH_SUBKEYS ] =
{
0x243f6a88l, 0x85a308d3l, 0x13198a2el,
0x03707344l, 0xa4093822l, 0x299f31d0l,
0x082efa98l, 0xec4e6c89l, 0x452821e6l,
0x38d01377l, 0xbe5466cfl, 0x34e90c6cl,
0xc0ac29b7l, 0xc97c50ddl, 0x3f84d5b5l,
0xb5470917l, 0x9216d5d9l, 0x8979fb1bl
};
/**
@internal
Set the mode and original initialisation vector in a context record.
@param Context Pointer to a context record to set the mode and initialisation vector.
@param Mode Mode to use when enciphering/decipering blocks. For supported modes see #BLOWFISH_MODE.
@param IvHigh32 High 32-bits of the initialisation vector. Required if the Mode parameter is not #BLOWFISH_MODE_ECB.
@param IvLow32 Low 32-bits of the initialisation vector. Required if the Mode parameter is not #BLOWFISH_MODE_ECB.
@remarks It is an unchecked runtime error to supply a null pointer to this function.
@return #BLOWFISH_RC_SUCCESS The mode and original initialisation vector were set successfully.
@return #BLOWFISH_RC_INVALID_MODE The mode supplied was invalid.
*/
static BLOWFISH_RC _BLOWFISH_SetMode ( BLOWFISH_PCONTEXT Context, BLOWFISH_MODE Mode, BLOWFISH_ULONG IvHigh32, BLOWFISH_ULONG IvLow32 )
{
/* Validate the block cipher mode, and set pointers to the encipher/decipher stream callbacks */
switch ( Mode )
{
case BLOWFISH_MODE_ECB:
{
Context->EncipherStream = &_BLOWFISH_EncipherStream_ECB;
Context->DecipherStream = &_BLOWFISH_DecipherStream_ECB;
break;
}
case BLOWFISH_MODE_CBC:
{
Context->EncipherStream = &_BLOWFISH_EncipherStream_CBC;
Context->DecipherStream = &_BLOWFISH_DecipherStream_CBC;
break;
}
case BLOWFISH_MODE_CFB:
{
Context->EncipherStream = &_BLOWFISH_EncipherStream_CFB;
Context->DecipherStream = &_BLOWFISH_DecipherStream_CFB;
break;
}
case BLOWFISH_MODE_OFB:
{
Context->EncipherStream = &_BLOWFISH_EncipherDecipherStream_OFB;
Context->DecipherStream = &_BLOWFISH_EncipherDecipherStream_OFB;
break;
}
case BLOWFISH_MODE_CTR:
{
Context->EncipherStream = &_BLOWFISH_EncipherDecipherStream_CTR;
Context->DecipherStream = &_BLOWFISH_EncipherDecipherStream_CTR;
break;
}
default:
{
return BLOWFISH_RC_INVALID_MODE;
}
}
/* Save the initialisation vector */
Context->OriginalIvHigh32 = IvHigh32;
Context->OriginalIvLow32 = IvLow32;
return BLOWFISH_RC_SUCCESS;
}
/**
@internal
Initialise the P-Array and S-Boxes in a context record based on the key.
@param Context Pointer to a context record to initialise.
@param Key Pointer to the key.
@param KeyLength Length of the Key buffer.
@remarks It is an unchecked runtime error to supply a null pointer to this function.
@return #BLOWFISH_RC_SUCCESS Successfully initialised the context record.
@return #BLOWFISH_RC_INVALID_KEY The length of the key is invalid.
@return #BLOWFISH_RC_WEAK_KEY The key has been deemed to be weak.
*/
static BLOWFISH_RC _BLOWFISH_SetKey ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCUCHAR Key, BLOWFISH_SIZE_T KeyLength )
{
BLOWFISH_SIZE_T i;
BLOWFISH_SIZE_T j;
BLOWFISH_SIZE_T k;
BLOWFISH_ULONG Data = 0;
BLOWFISH_ULONG XLeft = 0;
BLOWFISH_ULONG XRight = 0;
/* Ensure the key length is valid, ( between 4 and 56 bytes ) */
if ( KeyLength < BLOWFISH_MIN_KEY_LENGTH || KeyLength > BLOWFISH_MAX_KEY_LENGTH )
{
return BLOWFISH_RC_INVALID_KEY;
}
/* Copy the original S-Boxes to the context */
for ( i = 0; i < BLOWFISH_SBOXES; i++ )
{
for ( j = 0; j < BLOWFISH_SBOX_ENTRIES; j++ )
{
Context->SBox [ i ] [ j ] = _BLOWFISH_SBox [ i ] [ j ];
}
}
/* XOR the original P-Array and key into the context P-Array */
for ( i = 0, j = 0; i < BLOWFISH_SUBKEYS; i++ )
{
for ( k = 0; k < 4; k++ )
{
Data = ( Data << 8 ) | Key [ j ];
/* Have we reached the end of the key? */
j++;
if ( j >= KeyLength )
{
/* Resume from the begining of the key */
j = 0;
}
}
Context->PArray [ i ] = _BLOWFISH_PArray [ i ] ^ Data;
}
/* Update all entries in the context P-Array with output from the continuously changing blowfish algorithm */
for ( i = 0; i < BLOWFISH_SUBKEYS; i += 2 )
{
BLOWFISH_Encipher ( Context, &XLeft, &XRight );
Context->PArray [ i ] = XLeft;
Context->PArray [ i + 1 ] = XRight;
}
/* Update all entries in the context S-Boxes with output from the continuously changing blowfish algorithm */
for ( i = 0; i < BLOWFISH_SBOXES; i++ )
{
for ( j = 0; j < BLOWFISH_SBOX_ENTRIES; j += 2 )
{
BLOWFISH_Encipher ( Context, &XLeft, &XRight );
/* Test the strength of the key */
if ( XLeft == XRight )
{
return BLOWFISH_RC_WEAK_KEY;
}
Context->SBox [ i ] [ j ] = XLeft;
Context->SBox [ i ] [ j + 1 ] = XRight;
}
}
return BLOWFISH_RC_SUCCESS;
}
BLOWFISH_RC BLOWFISH_Init ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCUCHAR Key, BLOWFISH_SIZE_T KeyLength, BLOWFISH_MODE Mode, BLOWFISH_ULONG IvHigh32, BLOWFISH_ULONG IvLow32 )
{
BLOWFISH_RC ReturnCode;
/* Ensure pointers are valid */
if ( Context == 0 || Key == 0 )
{
return BLOWFISH_RC_INVALID_PARAMETER;
}
/* Set the mode and initialisation vector */
ReturnCode = _BLOWFISH_SetMode ( Context, Mode, IvHigh32, IvLow32 );
if ( ReturnCode == BLOWFISH_RC_SUCCESS )
{
/* Initialise the P-Array and S-Boxes based on the key */
ReturnCode = _BLOWFISH_SetKey ( Context, Key, KeyLength );
}
return ReturnCode;
}
BLOWFISH_RC BLOWFISH_Reset ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCUCHAR Key, BLOWFISH_SIZE_T KeyLength, BLOWFISH_MODE Mode, BLOWFISH_ULONG IvHigh32, BLOWFISH_ULONG IvLow32 )
{
BLOWFISH_RC ReturnCode = BLOWFISH_RC_SUCCESS;
/* Ensure the context pointer is valid */
if ( Context == 0 )
{
return BLOWFISH_RC_INVALID_PARAMETER;
}
/* Has a new mode been specified */
if ( Mode != BLOWFISH_MODE_CURRENT )
{
/* Reinitialise the mode and initialisation vector */
ReturnCode = _BLOWFISH_SetMode ( Context, Mode, IvHigh32, IvLow32 );
if ( ReturnCode != BLOWFISH_RC_SUCCESS )
{
return ReturnCode;
}
}
/* Has a new key been specified? */
if ( Key != 0 )
{
/* Reinitialise the P-Array and S-Boxes based on the new key */
ReturnCode = _BLOWFISH_SetKey ( Context, Key, KeyLength );
}
return ReturnCode;
}
BLOWFISH_RC BLOWFISH_CloneContext ( BLOWFISH_PCONTEXT InContext, BLOWFISH_PCONTEXT OutContext )
{
if ( InContext == 0 || OutContext == 0 )
{
return BLOWFISH_RC_INVALID_PARAMETER;
}
/* Copy the context record */
*OutContext = *InContext;
return BLOWFISH_RC_SUCCESS;
}
BLOWFISH_RC BLOWFISH_Exit ( BLOWFISH_PCONTEXT Context )
{
BLOWFISH_PUCHAR MemoryToWipe = (BLOWFISH_PUCHAR)Context;
BLOWFISH_SIZE_T i;
/* Ensure the context pointer is valid */
if ( Context == 0 )
{
return BLOWFISH_RC_INVALID_PARAMETER;
}
/* Overwrite the context record with null bytes (do not use memset!) */
for ( i = 0; i < (BLOWFISH_SIZE_T)sizeof ( *Context ); i++ )
{
MemoryToWipe [ i ] = 0x00;
}
return BLOWFISH_RC_SUCCESS;
}
/**
@internal
Restore the original initialisation vector in a context record.
@param Context Pointer to an initialised context record.
*/
#define _BLOWFISH_BEGINSTREAM( Context ) \
{ \
Context->IvHigh32 = Context->OriginalIvHigh32; \
Context->IvLow32 = Context->OriginalIvLow32; \
}
BLOWFISH_RC BLOWFISH_BeginStream ( BLOWFISH_PCONTEXT Context )
{
/* Ensure the context pointer is valid */
if ( Context == 0 )
{
return BLOWFISH_RC_INVALID_PARAMETER;
}
_BLOWFISH_BEGINSTREAM ( Context );
return BLOWFISH_RC_SUCCESS;
}
/**
@internal
Overwrite the final initialisation vector in a context record.
@param Context Pointer to an initialised context record.
*/
#define _BLOWFISH_ENDSTREAM( Context ) \
{ \
Context->IvHigh32 = 0; \
Context->IvLow32 = 0; \
}
BLOWFISH_RC BLOWFISH_EndStream ( BLOWFISH_PCONTEXT Context )
{
/* Ensure the context pointer is valid */
if ( Context == 0 )
{
return BLOWFISH_RC_INVALID_PARAMETER;
}
_BLOWFISH_ENDSTREAM ( Context );
return BLOWFISH_RC_SUCCESS;
}
/**
@internal
Perform a single round of the cipher.
xL = xL XOR Pn
xR = F(xL) XOR xR
Divide xL into four eight-bit quarters: a, b, c, and d.
Then, F(xL) = ((S0,a + S1,b mod 232) XOR S2,c) + S3,d mod 232.
See @link glossary @endlink for more information.
@remarks After each round the caller must swap xL and xR.
@param XLeft High 32-bits of the message to encipher.
@param XRight Low 32-bits of the message to encipher.
@param P Pointer to the P-Array.
@param S0, S1, S2, S3 Pointers to each element of the S-Box array.
@param Round Current round to perform (0-15 to encipher, 17-2 to decipher).
*/
#define _BLOWFISH_CIPHER( XLeft, XRight, P, S0, S1, S2, S3, Round ) \
{ \
XLeft ^= P [ Round ]; \
XRight ^= ( ( ( S0 [ XLeft >> 24 ] + \
S1 [ ( XLeft >> 16 ) & 0xff ] ) ^ \
S2 [ ( XLeft >> 8 ) & 0xff ] ) + \
S3 [ XLeft & 0xff ] ); \
}
/**
@internal
Perform 16-round encipher, finalise round and unswap xL and xR:
xR = xR XOR P18
xL = xL XOR P17
See @link glossary @endlink for more information.
@param BufferHigh Pointer to the high 32-bits of the output buffer.
@param BufferLow Pointer to the low 32-bits of the output buffer.
@param XLeft High 32-bits of the message to encipher.
@param XRight Low 32-bits of the message to encipher.
@param P Pointer to the P-Array.
@param S0, S1, S2, S3 Pointers to each element of the S-Box array.
@remarks If BufferHigh and BufferLow are the same variables as XLeft and XRight then the result will not be swapped!
*/
#define _BLOWFISH_ENCIPHER( BufferHigh, BufferLow, XLeft, XRight, P, S0, S1, S2, S3 ) \
{ \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 0 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 1 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 2 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 3 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 4 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 5 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 6 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 7 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 8 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 9 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 10 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 11 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 12 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 13 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 14 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 15 ); \
BufferLow = XLeft ^ P [ 16 ]; \
BufferHigh = XRight ^ P [ 17 ]; \
}
void BLOWFISH_Encipher ( BLOWFISH_PCONTEXT Context, BLOWFISH_PULONG High32, BLOWFISH_PULONG Low32 )
{
BLOWFISH_ULONG XLeft = *High32;
BLOWFISH_ULONG XRight = *Low32;
BLOWFISH_PULONG P = Context->PArray;
BLOWFISH_PULONG S0 = Context->SBox [ 0 ];
BLOWFISH_PULONG S1 = Context->SBox [ 1 ];
BLOWFISH_PULONG S2 = Context->SBox [ 2 ];
BLOWFISH_PULONG S3 = Context->SBox [ 3 ];
/* Encipher 8-byte plaintext block */
_BLOWFISH_ENCIPHER ( *High32, *Low32, XLeft, XRight, P, S0, S1, S2, S3 );
return;
}
/**
@internal
Encipher a stream of data in electronic codebook mode.
Cn = Ek ( Pn )
See @link glossary @endlink for more information.
@param Context Pointer to an initialised context record.
@param PlainTextStream Buffer of plaintext to encipher.
@param CipherTextStream Buffer to receive the ciphertext.
@param StreamLength Length of the plaintext and ciphertext stream buffers in 4-byte blocks.
@remarks It is an unchecked runtime error to supply either a null pointer, or a stream buffer length that is not a multiple of 4 to this function.
@remarks This function can be parallelised using OpenMP.
*/
static void _BLOWFISH_EncipherStream_ECB ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG PlainTextStream, BLOWFISH_PULONG CipherTextStream, BLOWFISH_SIZE_T StreamLength )
{
BLOWFISH_ULONG XLeft;
BLOWFISH_ULONG XRight;
BLOWFISH_PULONG P = Context->PArray;
BLOWFISH_PULONG S0 = Context->SBox [ 0 ];
BLOWFISH_PULONG S1 = Context->SBox [ 1 ];
BLOWFISH_PULONG S2 = Context->SBox [ 2 ];
BLOWFISH_PULONG S3 = Context->SBox [ 3 ];
BLOWFISH_SIZE_T i;
/* Encipher plaintext in 8-byte blocks */
#ifdef _OPENMP
#pragma omp parallel for default ( none ) private ( i, XLeft, XRight ) shared ( PlainTextStream, CipherTextStream, P, S0, S1, S2, S3, StreamLength ) schedule ( static )
#endif
for ( i = 0; i < StreamLength; i += 2 )
{
XLeft = PlainTextStream [ i ];
XRight = PlainTextStream [ i + 1 ];
_BLOWFISH_ENCIPHER ( CipherTextStream [ i ], CipherTextStream [ i + 1 ], XLeft, XRight, P, S0, S1, S2, S3 );
}
return;
}
/**
@internal
Encipher a stream of data in cipher block chaining mode.
Round 1:
C0 = Ek ( P0 XOR Iv )
Round n:
Cn = Ek ( Pn XOR ( Cn - 1 ) )
See @link glossary @endlink for more information.
@param Context Pointer to an initialised context record.
@param PlainTextStream Buffer of plaintext to encipher.
@param CipherTextStream Buffer to receive the ciphertext.
@param StreamLength Length of the plaintext and ciphertext stream buffers in 4-byte blocks.
@remarks It is an unchecked runtime error to supply either a null pointer, or a stream buffer length that is not a multiple of 4 to this function.
*/
static void _BLOWFISH_EncipherStream_CBC ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG PlainTextStream, BLOWFISH_PULONG CipherTextStream, BLOWFISH_SIZE_T StreamLength )
{
BLOWFISH_ULONG XLeft;
BLOWFISH_ULONG XRight;
BLOWFISH_PULONG P = Context->PArray;
BLOWFISH_PULONG S0 = Context->SBox [ 0 ];
BLOWFISH_PULONG S1 = Context->SBox [ 1 ];
BLOWFISH_PULONG S2 = Context->SBox [ 2 ];
BLOWFISH_PULONG S3 = Context->SBox [ 3 ];
BLOWFISH_SIZE_T i;
/* XOR the first block of plaintext with the initialisation vector */
XLeft = PlainTextStream [ 0 ] ^ Context->IvHigh32;
XRight = PlainTextStream [ 1 ] ^ Context->IvLow32;
/* Encipher the first block of plaintext */
_BLOWFISH_ENCIPHER ( CipherTextStream [ 0 ], CipherTextStream [ 1 ], XLeft, XRight, P, S0, S1, S2, S3 );
/* Encrypt any remaining blocks */
for ( i = 2; i < StreamLength; i += 2 )
{
/* XOR the block of plaintext with the previous block of ciphertext */
XLeft = PlainTextStream [ i ] ^ CipherTextStream [ i - 2 ];
XRight = PlainTextStream [ i + 1 ] ^ CipherTextStream [ i - 1 ];
/* Encipher the block of plaintext */
_BLOWFISH_ENCIPHER ( CipherTextStream [ i ], CipherTextStream [ i + 1 ], XLeft, XRight, P, S0, S1, S2, S3 );
}
/* Preserve the previous block of ciphertext as the new initialisation vector for stream based operations */
Context->IvHigh32 = CipherTextStream [ i - 2 ];
Context->IvLow32 = CipherTextStream [ i - 1 ];
return;
}
/**
@internal
Encipher a stream of data in cipher feedback mode.
Round 1:
C0 = P0 XOR Ek ( Iv )
Round n:
Cn = Pn XOR Ek ( ( Cn - 1 ) )
See @link glossary @endlink for more information.
@param Context Pointer to an initialised context record.
@param PlainTextStream Buffer of plaintext to encipher.
@param CipherTextStream Buffer to receive the ciphertext.
@param StreamLength Length of the plaintext and ciphertext stream buffers in 4-byte blocks.
@remarks It is an unchecked runtime error to supply either a null pointer, or a stream buffer length that is not a multiple of 4 to this function.
*/
static void _BLOWFISH_EncipherStream_CFB ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG PlainTextStream, BLOWFISH_PULONG CipherTextStream, BLOWFISH_SIZE_T StreamLength )
{
BLOWFISH_ULONG XLeft = Context->IvHigh32;
BLOWFISH_ULONG XRight = Context->IvLow32;
BLOWFISH_PULONG P = Context->PArray;
BLOWFISH_PULONG S0 = Context->SBox [ 0 ];
BLOWFISH_PULONG S1 = Context->SBox [ 1 ];
BLOWFISH_PULONG S2 = Context->SBox [ 2 ];
BLOWFISH_PULONG S3 = Context->SBox [ 3 ];
BLOWFISH_SIZE_T i;
/* Encipher the initialisation vector */
_BLOWFISH_ENCIPHER ( XRight, XLeft, XLeft, XRight, P, S0, S1, S2, S3 );
/* XOR the enciphered initialisation vector with the plaintext to yeild the ciphertext */
XRight ^= PlainTextStream [ 0 ];
XLeft ^= PlainTextStream [ 1 ];
CipherTextStream [ 0 ] = XRight;
CipherTextStream [ 1 ] = XLeft;
for ( i = 2; i < StreamLength; i += 2 )
{
/* Encipher the previous block of ciphertext */
XLeft = CipherTextStream [ i - 2 ];
XRight = CipherTextStream [ i - 1 ];
_BLOWFISH_ENCIPHER ( XRight, XLeft, XLeft, XRight, P, S0, S1, S2, S3 );
/* XOR the enciphered previous block of ciphertext with the plaintext to yeild the current block of ciphertext */
XRight ^= PlainTextStream [ i ];
XLeft ^= PlainTextStream [ i + 1 ];
CipherTextStream [ i ] = XRight;
CipherTextStream [ i + 1 ] = XLeft;
}
/* Preserve the previous block of ciphertext as the new initialisation vector for stream based operations */
Context->IvHigh32 = XRight;
Context->IvLow32 = XLeft;
return;
}
/**
@internal
Encipher/Decipher a stream of data in output feedback mode.
Iv = Ek ( Iv )
Cn = Pn XOR Iv
To decipher simply swap C and P.
See @link glossary @endlink for more information.
@param Context Pointer to an initialised context record.
@param InStream Pointer to either a buffer of plaintext to encipher, or a buffer of ciphertext to decipher.
@param OutStream Pointer to a buffer to receive either the ciphertext or plaintext output.
@param StreamLength Length of the plaintext and ciphertext stream buffers in 4-byte blocks.
@remarks It is an unchecked runtime error to supply either a null pointer, or a stream buffer length that is not a multiple of 4 to this function.
*/
static void _BLOWFISH_EncipherDecipherStream_OFB ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG InStream, BLOWFISH_PULONG OutStream, BLOWFISH_SIZE_T StreamLength )
{
BLOWFISH_ULONG XLeft = Context->IvHigh32;
BLOWFISH_ULONG XRight = Context->IvLow32;
BLOWFISH_PULONG P = Context->PArray;
BLOWFISH_PULONG S0 = Context->SBox [ 0 ];
BLOWFISH_PULONG S1 = Context->SBox [ 1 ];
BLOWFISH_PULONG S2 = Context->SBox [ 2 ];
BLOWFISH_PULONG S3 = Context->SBox [ 3 ];
BLOWFISH_SIZE_T i;
for ( i = 0; i < StreamLength; i += 2 )
{
/* Encipher the initialisation vector */
_BLOWFISH_ENCIPHER ( XRight, XLeft, XLeft, XRight, P, S0, S1, S2, S3 );
/* Store and swap the enciphered initialisation vector */
OutStream [ i ] = XRight;
OutStream [ i + 1 ] = XLeft;
XLeft = OutStream [ i ];
XRight = OutStream [ i + 1 ];
/* XOR the enciphered initialisation vector with the ciphertext or plaintext */
OutStream [ i ] ^= InStream [ i ];
OutStream [ i + 1 ] ^= InStream [ i + 1 ];
}
/* Preserve the enciphered initialisation vector as the new initialisation vector for stream based operations */
Context->IvHigh32 = XLeft;
Context->IvLow32 = XRight;
return;
}
/**
@internal
Encipher/Decipher a stream of data in counter (segmented integer counter) mode.
O = Ek ( Iv ADD ( n ) )
Cn = Pn XOR O
To decipher simply swap C and P.
See @link glossary @endlink for more information.
@param Context Pointer to an initialised context record.
@param InStream Pointer to either a buffer of plaintext to encipher, or a buffer of ciphertext to decipher.
@param OutStream Pointer to a buffer to receive either the ciphertext or plaintext output.
@param StreamLength Length of the plaintext and ciphertext stream buffers in 4-byte blocks.
@remarks It is an unchecked runtime error to supply either a null pointer, or a stream buffer length that is not a multiple of 4 to this function.
@remarks This function can be parallelised using OpenMP.
*/
static void _BLOWFISH_EncipherDecipherStream_CTR ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG InStream, BLOWFISH_PULONG OutStream, BLOWFISH_SIZE_T StreamLength )
{
BLOWFISH_ULONG XLeft;
BLOWFISH_ULONG XRight;
BLOWFISH_ULONG IvHigh32 = Context->IvHigh32;
BLOWFISH_ULONG IvLow32 = Context->IvLow32;
BLOWFISH_PULONG P = Context->PArray;
BLOWFISH_PULONG S0 = Context->SBox [ 0 ];
BLOWFISH_PULONG S1 = Context->SBox [ 1 ];
BLOWFISH_PULONG S2 = Context->SBox [ 2 ];
BLOWFISH_PULONG S3 = Context->SBox [ 3 ];
BLOWFISH_SIZE_T i;
#ifdef _OPENMP
#pragma omp parallel for default ( none ) private ( i, XLeft, XRight ) shared ( InStream, OutStream, IvHigh32, IvLow32, P, S0, S1, S2, S3, StreamLength ) schedule ( static )
#endif
for ( i = 0; i < StreamLength; i += 2 )
{
/* Encipher the initialisation vector added with the counter */
XLeft = IvHigh32 + (BLOWFISH_ULONG)i;
XRight = IvLow32 + (BLOWFISH_ULONG)( i + 1 );
_BLOWFISH_ENCIPHER ( XRight, XLeft, XLeft, XRight, P, S0, S1, S2, S3 );
/* XOR the enciphered initialisation vector with the plaintext or ciphertext */
OutStream [ i ] = InStream [ i ] ^ XRight;
OutStream [ i + 1 ] = InStream [ i + 1 ] ^ XLeft;
}
/* Preserve the initialisation vector added with the counter as the new initialisation vector for stream based operations */
Context->IvHigh32 += (BLOWFISH_ULONG)StreamLength;
Context->IvLow32 += (BLOWFISH_ULONG)( StreamLength + 1 );
return;
}
BLOWFISH_RC BLOWFISH_EncipherStream ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCUCHAR PlainTextStream, BLOWFISH_PUCHAR CipherTextStream, BLOWFISH_SIZE_T StreamLength )
{
/* Ensure the context and stream buffer pointers are non null */
if ( Context == 0 || PlainTextStream == 0 || CipherTextStream == 0 )
{
return BLOWFISH_RC_INVALID_PARAMETER;
}
/* Ensure the stream length is a multiple of 8 */
if ( ( StreamLength & ~0x07 ) == 0 )
{
return BLOWFISH_RC_BAD_BUFFER_LENGTH;
}
#ifdef _OPENMP
/* Ensure the stream length is not negative */
if ( StreamLength < 0 )
{
return BLOWFISH_RC_BAD_BUFFER_LENGTH;
}
#endif
/* Encipher stream based on block cipher mode */
Context->EncipherStream ( Context, (BLOWFISH_PCULONG)PlainTextStream, (BLOWFISH_PULONG)CipherTextStream, StreamLength >> 2 );
return BLOWFISH_RC_SUCCESS;
}
BLOWFISH_RC BLOWFISH_EncipherBuffer ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCUCHAR PlainTextBuffer, BLOWFISH_PUCHAR CipherTextBuffer, BLOWFISH_SIZE_T BufferLength )
{
/* Ensure the context and buffer pointers are non null */
if ( Context == 0 || CipherTextBuffer == 0 || PlainTextBuffer == 0 )
{
return BLOWFISH_RC_INVALID_PARAMETER;
}
/* Ensure the buffer length is a multiple of 8 */
if ( ( BufferLength & ~0x07 ) == 0 )
{
return BLOWFISH_RC_BAD_BUFFER_LENGTH;
}
#ifdef _OPENMP
/* Ensure the buffer length is not negative */
if ( BufferLength < 0 )
{
return BLOWFISH_RC_BAD_BUFFER_LENGTH;
}
#endif
/* Encipher buffer as a stream based on the block cipher mode */
_BLOWFISH_BEGINSTREAM ( Context );
Context->EncipherStream ( Context, (BLOWFISH_PCULONG)PlainTextBuffer, (BLOWFISH_PULONG)CipherTextBuffer, BufferLength >> 2 );
_BLOWFISH_ENDSTREAM ( Context );
return BLOWFISH_RC_SUCCESS;
}
/**
@internal
Perform 16-round decipher, finalise round and unswap xL and xR:
xR = xR XOR P0
xL = xL XOR P1
See @link glossary @endlink for more information.
@param BufferHigh Pointer to the high 32-bits of the output buffer.
@param BufferLow Pointer to the low 32-bits of the output buffer.
@param XLeft High 32-bits of the message to decipher.
@param XRight Low 32-bits of the message to decipher.
@param P Pointer to the P-Array.
@param S0, S1, S2, S3 Pointers to each element of the S-Box array.
@remarks If BufferHigh and BufferLow are the same variables as XLeft and XRight then the result will not be swapped!
*/
#define _BLOWFISH_DECIPHER( BufferHigh, BufferLow, XLeft, XRight, P, S0, S1, S2, S3 ) \
{ \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 17 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 16 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 15 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 14 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 13 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 12 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 11 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 10 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 9 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 8 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 7 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 6 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 5 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 4 ); \
_BLOWFISH_CIPHER ( XLeft, XRight, P, S0, S1, S2, S3, 3 ); \
_BLOWFISH_CIPHER ( XRight, XLeft, P, S0, S1, S2, S3, 2 ); \
BufferHigh = XRight ^ P [ 0 ]; \
BufferLow = XLeft ^ P [ 1 ]; \
}
void BLOWFISH_Decipher ( BLOWFISH_PCONTEXT Context, BLOWFISH_PULONG High32, BLOWFISH_PULONG Low32 )
{
BLOWFISH_ULONG XLeft = *High32;
BLOWFISH_ULONG XRight = *Low32;
BLOWFISH_PULONG P = Context->PArray;
BLOWFISH_PULONG S0 = Context->SBox [ 0 ];
BLOWFISH_PULONG S1 = Context->SBox [ 1 ];
BLOWFISH_PULONG S2 = Context->SBox [ 2 ];
BLOWFISH_PULONG S3 = Context->SBox [ 3 ];
/* Decipher 8-byte plaintext block */
_BLOWFISH_DECIPHER ( *High32, *Low32, XLeft, XRight, P, S0, S1, S2, S3 );
return;
}
/**
@internal
Decipher a stream of data in electronic codebook mode.
Pn = Ek ( Cn )
See @link glossary @endlink for more information.
@param Context Pointer to an initialised context record.
@param CipherTextStream Buffer of ciphertext to decipher.
@param CipherTextStream Buffer to receive the plaintext.
@param StreamLength Length of the plaintext and ciphertext stream buffers in 4-byte blocks.
@remarks It is an unchecked runtime error to supply either a null pointer, or a stream buffer length that is not a multiple of 4 to this function.
@remarks This function can be parallelised using OpenMP.
*/
static void _BLOWFISH_DecipherStream_ECB ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG CipherTextStream, BLOWFISH_PULONG PlainTextStream, BLOWFISH_SIZE_T StreamLength )
{
BLOWFISH_ULONG XLeft;
BLOWFISH_ULONG XRight;
BLOWFISH_PULONG P = Context->PArray;
BLOWFISH_PULONG S0 = Context->SBox [ 0 ];
BLOWFISH_PULONG S1 = Context->SBox [ 1 ];
BLOWFISH_PULONG S2 = Context->SBox [ 2 ];
BLOWFISH_PULONG S3 = Context->SBox [ 3 ];
BLOWFISH_SIZE_T i;
/* Decipher ciphertext in 8-byte blocks */
#ifdef _OPENMP
#pragma omp parallel for default ( none ) private ( i, XLeft, XRight ) shared ( PlainTextStream, CipherTextStream, P, S0, S1, S2, S3, StreamLength ) schedule ( static )
#endif
for ( i = 0; i < StreamLength; i += 2 )
{
XLeft = CipherTextStream [ i ];
XRight = CipherTextStream [ i + 1 ];
_BLOWFISH_DECIPHER ( PlainTextStream [ i ], PlainTextStream [ i + 1 ], XLeft, XRight, P, S0, S1, S2, S3 );
}
return;
}
/**
@internal
Decipher a stream of data in cipher block chaining mode.
Round 1:
P0 = Dk ( C0 ) XOR ( Iv )
Round n:
Pn = Dk ( Cn ) XOR ( Cn - 1 )
See @link glossary @endlink for more information.
@param Context Pointer to an initialised context record.
@param CipherTextStream Buffer of ciphertext to decipher.
@param CipherTextStream Buffer to receive the plaintext.
@param StreamLength Length of the plaintext and ciphertext stream buffers in 4-byte blocks.
@remarks It is an unchecked runtime error to supply either a null pointer, or a stream buffer length that is not a multiple of 4 to this function.
@remarks This function can be parallelised using OpenMP.
*/
static void _BLOWFISH_DecipherStream_CBC ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG CipherTextStream, BLOWFISH_PULONG PlainTextStream, BLOWFISH_SIZE_T StreamLength )
{
BLOWFISH_ULONG XLeft;
BLOWFISH_ULONG XRight;
BLOWFISH_PULONG P = Context->PArray;
BLOWFISH_PULONG S0 = Context->SBox [ 0 ];
BLOWFISH_PULONG S1 = Context->SBox [ 1 ];
BLOWFISH_PULONG S2 = Context->SBox [ 2 ];
BLOWFISH_PULONG S3 = Context->SBox [ 3 ];
BLOWFISH_SIZE_T i;
/* Decipher the first block of ciphertext */
XLeft = CipherTextStream [ 0 ];
XRight = CipherTextStream [ 1 ];
_BLOWFISH_DECIPHER ( PlainTextStream [ 0 ], PlainTextStream [ 1 ], XLeft, XRight, P, S0, S1, S2, S3 );
/* XOR the deciphered first block with the initialisation vector to yeild the plaintext */
PlainTextStream [ 0 ] ^= Context->IvHigh32;
PlainTextStream [ 1 ] ^= Context->IvLow32;
/* Decrypt any remaining blocks */
#ifdef _OPENMP
#pragma omp parallel for default ( none ) private ( i, XLeft, XRight ) shared ( PlainTextStream, CipherTextStream, P, S0, S1, S2, S3, StreamLength ) schedule ( static )
#endif
for ( i = 2; i < StreamLength; i += 2 )
{
/* Decipher block of ciphertext */
XLeft = CipherTextStream [ i ];
XRight = CipherTextStream [ i + 1 ];
_BLOWFISH_DECIPHER ( PlainTextStream [ i ], PlainTextStream [ i + 1 ], XLeft, XRight, P, S0, S1, S2, S3 );
/* XOR the deciphered block with the previous block of ciphertext to yeild the plaintext */
PlainTextStream [ i ] ^= CipherTextStream [ i - 2 ];
PlainTextStream [ i + 1 ] ^= CipherTextStream [ i - 1 ];
}
/* Preserve the previous block of ciphertext as the new initialisation vector for stream based operations */
Context->IvHigh32 = CipherTextStream [ StreamLength - 2 ];
Context->IvLow32 = CipherTextStream [ StreamLength - 1 ];
return;
}
/**
@internal
Decipher a stream of data in cipher feedback mode.
Round 1:
P0 = C0 XOR Ek ( Iv )
Round n:
Pn = Cn XOR Ek ( ( Cn - 1 ) )
See @link glossary @endlink for more information.
@param Context Pointer to an initialised context record.
@param CipherTextStream Buffer of ciphertext to decipher.
@param CipherTextStream Buffer to receive the plaintext.
@param StreamLength Length of the plaintext and ciphertext stream buffers in 4-byte blocks.
@remarks It is an unchecked runtime error to supply either a null pointer, or a stream buffer length that is not a multiple of 4 to this function.
@remarks This function can be parallelised using OpenMP.
*/
static void _BLOWFISH_DecipherStream_CFB ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCULONG CipherTextStream, BLOWFISH_PULONG PlainTextStream, BLOWFISH_SIZE_T StreamLength )
{
BLOWFISH_ULONG XLeft;
BLOWFISH_ULONG XRight;
BLOWFISH_PULONG P = Context->PArray;
BLOWFISH_PULONG S0 = Context->SBox [ 0 ];
BLOWFISH_PULONG S1 = Context->SBox [ 1 ];
BLOWFISH_PULONG S2 = Context->SBox [ 2 ];
BLOWFISH_PULONG S3 = Context->SBox [ 3 ];
BLOWFISH_SIZE_T i;
/* Encipher the initialisation vector */
XLeft = Context->IvHigh32;
XRight = Context->IvLow32;
_BLOWFISH_ENCIPHER ( XRight, XLeft, XLeft, XRight, P, S0, S1, S2, S3 );
/* XOR enciphered initialisation vector with the ciphertext to yeild the plaintext */
PlainTextStream [ 0 ] = XRight ^ CipherTextStream [ 0 ];
PlainTextStream [ 1 ] = XLeft ^ CipherTextStream [ 1 ];
/* Decrypt any remaining blocks */
#ifdef _OPENMP
#pragma omp parallel for default ( none ) private ( i, XLeft, XRight ) shared ( PlainTextStream, CipherTextStream, P, S0, S1, S2, S3, StreamLength ) schedule ( static )
#endif
for ( i = 2; i < StreamLength; i += 2 )
{
/* Encipher the previous block of ciphertext */
XLeft = CipherTextStream [ i - 2 ];
XRight = CipherTextStream [ i - 1 ];
_BLOWFISH_ENCIPHER ( XRight, XLeft, XLeft, XRight, P, S0, S1, S2, S3 );
/* XOR the enciphered previous block of ciphertext with the current block ciphertext to yeild the plaintext */
PlainTextStream [ i ] = XRight ^ CipherTextStream [ i ];
PlainTextStream [ i + 1 ] = XLeft ^ CipherTextStream [ i + 1 ];
}
/* Preserve the previous block of ciphertext as the new initialisation vector for stream based operations */
Context->IvHigh32 = CipherTextStream [ StreamLength - 2 ];
Context->IvLow32 = CipherTextStream [ StreamLength - 1 ];
return;
}
BLOWFISH_RC BLOWFISH_DecipherStream ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCUCHAR CipherTextStream, BLOWFISH_PUCHAR PlainTextStream, BLOWFISH_SIZE_T StreamLength )
{
/* Ensure the context and stream buffer pointers are non null */
if ( Context == 0 || CipherTextStream == 0 || PlainTextStream == 0 )
{
return BLOWFISH_RC_INVALID_PARAMETER;
}
/* Ensure the stream length is a multiple of 8 */
if ( ( StreamLength & ~0x07 ) == 0 )
{
return BLOWFISH_RC_BAD_BUFFER_LENGTH;
}
#ifdef _OPENMP
/* Ensure the stream length is not negative */
if ( StreamLength < 0 )
{
return BLOWFISH_RC_BAD_BUFFER_LENGTH;
}
#endif
/* Decipher stream buffer based on block cipher mode */
Context->DecipherStream ( Context, (BLOWFISH_PCULONG)CipherTextStream, (BLOWFISH_PULONG)PlainTextStream, StreamLength >> 2 );
return BLOWFISH_RC_SUCCESS;
}
BLOWFISH_RC BLOWFISH_DecipherBuffer ( BLOWFISH_PCONTEXT Context, BLOWFISH_PCUCHAR CipherTextBuffer, BLOWFISH_PUCHAR PlainTextBuffer, BLOWFISH_SIZE_T BufferLength )
{
/* Ensure the context and buffer pointers are non null */
if ( Context == 0 || CipherTextBuffer == 0 || PlainTextBuffer == 0 )
{
return BLOWFISH_RC_INVALID_PARAMETER;
}
/* Ensure the buffer length is a multiple of 8 */
if ( ( BufferLength & ~0x07 ) == 0 )
{
return BLOWFISH_RC_BAD_BUFFER_LENGTH;
}
#ifdef _OPENMP
/* Ensure the buffer length is not negative */
if ( BufferLength < 0 )
{
return BLOWFISH_RC_BAD_BUFFER_LENGTH;
}
#endif
/* Decipher buffer as a stream based on the block cipher mode */
_BLOWFISH_BEGINSTREAM ( Context );
Context->DecipherStream ( Context, (BLOWFISH_PCULONG)CipherTextBuffer, (BLOWFISH_PULONG)PlainTextBuffer, BufferLength >> 2 );
_BLOWFISH_ENDSTREAM ( Context );
return BLOWFISH_RC_SUCCESS;
}
/** @} */