fix EC2N skipping of optional seed, switch to public domain MARS code, deliver vc80.pdb to OutDir

This commit is contained in:
weidai 2009-03-28 03:08:27 +00:00
parent 88e0d157d7
commit 3be02e9a1a
12 changed files with 219 additions and 150 deletions

View File

@ -3,12 +3,7 @@ This copyright applies only to this software distribution package
as a compilation, and does not imply a copyright on any particular
file in the package.
The following files are copyrighted by their respective original authors,
and their use is subject to additional licenses included in these files.
mars.cpp - Copyright 1998 Brian Gladman.
All other files in this compilation are placed in the public domain by
All individual files in this compilation are placed in the public domain by
Wei Dai and other contributors.
I would like to thank the following authors for placing their works into

View File

@ -1,5 +1,5 @@
Crypto++: a C++ Class Library of Cryptographic Schemes
Version 5.6.0 (3/15/2009)
Version 5.6.1 (in development)
Crypto++ Library is a free C++ class library of cryptographic schemes.
Currently the library contains the following algorithms:
@ -28,7 +28,7 @@ Currently the library contains the following algorithms:
RIPEMD-256, RIPEMD-160, RIPEMD-320
RSA, DSA, ElGamal, Nyberg-Rueppel (NR),
public-key cryptography Rabin, Rabin-Williams (RW), LUC, LUCELG,
public-key cryptography Rabin-Williams (RW), LUC, LUCELG,
DLIES (variants of DHAES), ESIGN
padding schemes for public-key PKCS#1 v2.0, OAEP, PSS, PSSR, IEEE P1363
@ -417,6 +417,7 @@ the mailing list.
5.6 - added AuthenticatedSymmetricCipher interface class and Filter wrappers
- added CCM, GCM (with SSE2 assembly), EAX, CMAC, XSalsa20, and SEED
- added support for variable length IVs
- added OIDs for Brainpool elliptic curve parameters
- improved AES and SHA-256 speed on x86 and x64
- fixed incorrect VMAC computation on message lengths
that are >64 mod 128 (x86 assembly version is not affected)
@ -425,5 +426,7 @@ the mailing list.
- fixed HashFilter bug when putMessage=true
- removed WORD64_AVAILABLE; compiler support for 64-bit int is now required
- ported to GCC 4.3, C++Builder 2009, Sun CC 5.10, Intel C++ Compiler 11
5.6.1 - switched to a public domain implementation of MARS
Written by Wei Dai

View File

@ -26,3 +26,4 @@ Test: TestVectors/ccm.txt
Test: TestVectors/gcm.txt
Test: TestVectors/cmac.txt
Test: TestVectors/eax.txt
Test: TestVectors/mars.txt

66
TestVectors/mars.txt Normal file
View File

@ -0,0 +1,66 @@
AlgorithmType: SymmetricCipher
Name: MARS/ECB
Key: 80000000000000000000000000000000
Plaintext: 00000000000000000000000000000000
Ciphertext: B3E2AD5608AC1B6733A7CB4FDF8F9952
Test: Encrypt
Key: 00000000000000000000000000000000
Plaintext: 00000000000000000000000000000000
Ciphertext: DCC07B8DFB0738D6E30A22DFCF27E886
Test: Encrypt
Key: 00000000000000000000000000000000
Plaintext: DCC07B8DFB0738D6E30A22DFCF27E886
Ciphertext: 33CAFFBDDC7F1DDA0F9C15FA2F30E2FF
Test: Encrypt
Key: CB14A1776ABBC1CDAFE7243DEF2CEA02
Plaintext: F94512A9B42D034EC4792204D708A69B
Ciphertext: 225DA2CB64B73F79069F21A5E3CB8522
Test: Encrypt
Key: 86EDF4DA31824CABEF6A4637C40B0BAB
Plaintext: 4DF955AD5B398D66408D620A2B27E1A9
Ciphertext: A4B737340AE6D2CAFD930BA97D86129F
Test: Encrypt
Key: 000000000000000000000000000000000000000000000000
Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Ciphertext: 97778747D60E425C2B4202599DB856FB
Test: Encrypt
Key: D158860838874D9500000000000000000000000000000000
Plaintext: 93A953A82C10411DD158860838874D95
Ciphertext: 4FA0E5F64893131712F01408D233E9F7
Test: Encrypt
Key: 791739A58B04581A93A953A82C10411DD158860838874D95
Plaintext: 6761C42D3E6142D2A84FBFADB383158F
Ciphertext: F706BC0FD97E28B6F1AF4E17D8755FFF
Test: Encrypt
Key: 0000000000000000000000000000000000000000000000000000000000000000
Plaintext: 62E45B4CF3477F1DD65063729D9ABA8F
Ciphertext: 0F4B897EA014D21FBC20F1054A42F719
Test: Encrypt
Key: FBA167983E7AEF22317CE28C02AAE1A3E8E5CC3CEDBEA82A99DBC39AD65E7227
Plaintext: 1344ABA4D3C44708A8A72116D4F49384
Ciphertext: 458335D95EA42A9F4DCCD41AECC2390D
Test: Encrypt
Key: 00000000000000000000000000000000
Plaintext: 00000000000000000000000000000000
Ciphertext: 3FE24DC09173D15F4616A849D396F7E3
Test: EncryptionMCT
Key: 00000000000000000000000000000000
Plaintext: 24BD3D2FC6FEE152D1D64545E2230584
Ciphertext: 00000000000000000000000000000000
Test: DecryptionMCT
Key: 000000000000000000000000000000000000000000000000
Plaintext: 00000000000000000000000000000000
Ciphertext: 34EC834E2F30741ECB476DA7E9662BBD
Test: EncryptionMCT
Key: 000000000000000000000000000000000000000000000000
Plaintext: 7F27C3397A8CEEF1BDF859459690FEA8
Ciphertext: 00000000000000000000000000000000
Test: DecryptionMCT
Key: 0000000000000000000000000000000000000000000000000000000000000000
Plaintext: 00000000000000000000000000000000
Ciphertext: EDE145C10E279501D921C5E3B04420A6
Test: EncryptionMCT
Key: 0000000000000000000000000000000000000000000000000000000000000000
Plaintext: 95615ADB0DDF6613A5E84F849AC8C00D
Ciphertext: 00000000000000000000000000000000
Test: DecryptionMCT

View File

@ -68,6 +68,7 @@
EnableEnhancedInstructionSet="1"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
@ -167,6 +168,7 @@
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
@ -263,6 +265,7 @@
EnableEnhancedInstructionSet="1"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
@ -357,6 +360,7 @@
RuntimeLibrary="1"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"

View File

@ -780,6 +780,10 @@
RelativePath=".\TestVectors\hmac.txt"
>
</File>
<File
RelativePath=".\TestVectors\mars.txt"
>
</File>
<File
RelativePath=".\TestVectors\nr.txt"
>

View File

@ -55,6 +55,7 @@
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
@ -127,6 +128,7 @@
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
@ -199,6 +201,7 @@
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true"
@ -273,6 +276,7 @@
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true"
@ -341,6 +345,7 @@
EnableEnhancedInstructionSet="1"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
@ -408,6 +413,7 @@
RuntimeLibrary="1"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
@ -474,6 +480,7 @@
RuntimeLibrary="1"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true"
@ -542,6 +549,7 @@
RuntimeLibrary="1"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="pch.h"
ProgramDataBaseFileName="$(OutDir)\vc80.pdb"
WarningLevel="3"
SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true"

View File

@ -306,7 +306,7 @@ void TestSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
TestDataNameValuePairs testDataPairs(v);
CombinedNameValuePairs pairs(overrideParameters, testDataPairs);
if (test == "Encrypt" || test == "EncryptXorDigest" || test == "Resync")
if (test == "Encrypt" || test == "EncryptXorDigest" || test == "Resync" || test == "EncryptionMCT" || test == "DecryptionMCT")
{
static member_ptr<SymmetricCipher> encryptor, decryptor;
static std::string lastName;
@ -339,7 +339,46 @@ void TestSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
encryptor->Seek(seek);
decryptor->Seek(seek);
}
std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest;
if (test == "EncryptionMCT" || test == "DecryptionMCT")
{
SymmetricCipher *cipher = encryptor.get();
SecByteBlock buf((byte *)plaintext.data(), plaintext.size()), keybuf((byte *)key.data(), key.size());
if (test == "DecryptionMCT")
{
cipher = decryptor.get();
ciphertext = GetDecodedDatum(v, "Ciphertext");
buf.Assign((byte *)ciphertext.data(), ciphertext.size());
}
for (int i=0; i<400; i++)
{
encrypted.reserve(10000 * plaintext.size());
for (int j=0; j<10000; j++)
{
cipher->ProcessString(buf.begin(), buf.size());
encrypted.append((char *)buf.begin(), buf.size());
}
encrypted.erase(0, encrypted.size() - keybuf.size());
xorbuf(keybuf.begin(), (const byte *)encrypted.data(), keybuf.size());
cipher->SetKey(keybuf, keybuf.size());
}
encrypted.assign((char *)buf.begin(), buf.size());
ciphertext = GetDecodedDatum(v, test == "EncryptionMCT" ? "Ciphertext" : "Plaintext");
if (encrypted != ciphertext)
{
std::cout << "incorrectly encrypted: ";
StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
xx.Pump(256); xx.Flush(false);
std::cout << "\n";
SignalTestFailure();
}
return;
}
StringSource ss(plaintext, false, new StreamTransformationFilter(*encryptor, new StringSink(encrypted), StreamTransformationFilter::NO_PADDING));
ss.Pump(plaintext.size()/2 + 1);
ss.PumpAll();

View File

@ -20,7 +20,11 @@ EC2N::EC2N(BufferedTransformation &bt)
m_field->BERDecodeElement(seq, m_b);
// skip optional seed
if (!seq.EndReached())
BERDecodeOctetString(seq, TheBitBucket());
{
SecByteBlock seed;
unsigned int unused;
BERDecodeBitString(seq, seed, unused);
}
seq.MessageEnd();
}

222
mars.cpp
View File

@ -1,18 +1,6 @@
// mars.cpp - modified by Sean Woods from Brian Gladman's mars6.c for Crypto++
// key setup updated by Wei Dai to reflect IBM's "tweak" proposed in August 1999
// mars.cpp - written and placed in the public domain by Wei Dai
/* This is an independent implementation of the MARS encryption */
/* algorithm designed by a team at IBM as a candidate for the US */
/* NIST Advanced Encryption Standard (AES) effort. The algorithm */
/* is subject to Patent action by IBM, who intend to offer royalty */
/* free use if a Patent is granted. */
/* */
/* Copyright in this implementation is held by Dr B R Gladman but */
/* I hereby give permission for its free direct or derivative use */
/* subject to acknowledgment of its origin and compliance with any */
/* constraints that IBM place on the use of the MARS algorithm. */
/* */
/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 4th October 1998 */
// includes IBM's key setup "tweak" proposed in August 1999 (http://www.research.ibm.com/security/key-setup.txt)
#include "pch.h"
#include "mars.h"
@ -20,24 +8,6 @@
NAMESPACE_BEGIN(CryptoPP)
ANONYMOUS_NAMESPACE_BEGIN
static word32 gen_mask(word32 x)
{
word32 m;
m = (~x ^ (x >> 1)) & 0x7fffffff;
m &= (m >> 1) & (m >> 2); m &= (m >> 3) & (m >> 6);
if(!m)
return 0;
m <<= 1; m |= (m << 1); m |= (m << 2); m |= (m << 4);
m |= (m << 1) & ~x & 0x80000000;
return m & 0xfffffffc;
};
NAMESPACE_END
void MARS::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
{
AssertValidKeyLength(length);
@ -61,148 +31,122 @@ void MARS::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const
// Store next 10 key words into K[]
for (i=0; i<10; i++)
EK[10*j+i] = T[4*i%15];
m_k[10*j+i] = T[4*i%15];
}
// Modify multiplication key-words
for(unsigned int i = 5; i < 37; i += 2)
{
word32 w = EK[i] | 3;
word32 m = gen_mask(w);
if(m)
w ^= (rotlMod(Sbox[265 + (EK[i] & 3)], EK[i-1]) & m);
EK[i] = w;
word32 m, w = m_k[i] | 3;
m = (~w ^ (w<<1)) & (~w ^ (w>>1)) & 0x7ffffffe;
m &= m>>1; m &= m>>2; m &= m>>4;
m |= m<<1; m |= m<<2; m |= m<<4;
m &= 0x7ffffffc;
w ^= rotlMod(Sbox[265 + (m_k[i] & 3)], m_k[i-1]) & m;
m_k[i] = w;
}
}
#define f_mix(a,b,c,d) \
r = rotrFixed(a, 8); \
b ^= Sbox[a & 255]; \
b += Sbox[(r & 255) + 256]; \
r = rotrFixed(a, 16); \
a = rotrFixed(a, 24); \
c += Sbox[r & 255]; \
d ^= Sbox[(a & 255) + 256]
#define b_mix(a,b,c,d) \
r = rotlFixed(a, 8); \
b ^= Sbox[(a & 255) + 256]; \
c -= Sbox[r & 255]; \
r = rotlFixed(a, 16); \
a = rotlFixed(a, 24); \
d -= Sbox[(r & 255) + 256]; \
d ^= Sbox[a & 255]
#define f_ktr(a,b,c,d,i) \
m = a + EK[i]; \
a = rotlFixed(a, 13); \
r = a * EK[i + 1]; \
l = Sbox[m & 511]; \
r = rotlFixed(r, 5); \
l ^= r; \
c += rotlMod(m, r); \
r = rotlFixed(r, 5); \
l ^= r; \
d ^= r; \
b += rotlMod(l, r)
#define r_ktr(a,b,c,d,i) \
r = a * EK[i + 1]; \
a = rotrFixed(a, 13); \
m = a + EK[i]; \
l = Sbox[m & 511]; \
r = rotlFixed(r, 5); \
l ^= r; \
c -= rotlMod(m, r); \
r = rotlFixed(r, 5); \
l ^= r; \
d ^= r; \
b -= rotlMod(l, r)
#define S(a) Sbox[(a)&0x1ff]
#define S0(a) Sbox[(a)&0xff]
#define S1(a) Sbox[((a)&0xff) + 256]
typedef BlockGetAndPut<word32, LittleEndian> Block;
void MARS::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
word32 a, b, c, d, l, m, r;
unsigned int i;
word32 a, b, c, d, l, m, r, t;
const word32 *k = m_k;
Block::Get(inBlock)(a)(b)(c)(d);
a += EK[0];
b += EK[1];
c += EK[2];
d += EK[3];
a += k[0]; b += k[1]; c += k[2]; d += k[3];
int i;
for (i = 0; i < 2; i++) {
f_mix(a,b,c,d);
a += d;
f_mix(b,c,d,a);
b += c;
f_mix(c,d,a,b);
f_mix(d,a,b,c);
for (i=0; i<8; i++)
{
b = (b ^ S0(a)) + S1(a>>8);
c += S0(a>>16);
a = rotrFixed(a, 24);
d ^= S1(a);
a += (i%4==0) ? d : 0;
a += (i%4==1) ? b : 0;
t = a; a = b; b = c; c = d; d = t;
}
f_ktr(a,b,c,d, 4); f_ktr(b,c,d,a, 6); f_ktr(c,d,a,b, 8); f_ktr(d,a,b,c,10);
f_ktr(a,b,c,d,12); f_ktr(b,c,d,a,14); f_ktr(c,d,a,b,16); f_ktr(d,a,b,c,18);
f_ktr(a,d,c,b,20); f_ktr(b,a,d,c,22); f_ktr(c,b,a,d,24); f_ktr(d,c,b,a,26);
f_ktr(a,d,c,b,28); f_ktr(b,a,d,c,30); f_ktr(c,b,a,d,32); f_ktr(d,c,b,a,34);
for (i = 0; i < 2; i++) {
b_mix(a,b,c,d);
b_mix(b,c,d,a);
c -= b;
b_mix(c,d,a,b);
d -= a;
b_mix(d,a,b,c);
for (i=0; i<16; i++)
{
t = rotlFixed(a, 13);
r = rotlFixed(t * k[2*i+5], 10);
m = a + k[2*i+4];
l = rotlMod((S(m) ^ rotrFixed(r, 5) ^ r), r);
c += rotlMod(m, rotrFixed(r, 5));
(i<8 ? b : d) += l;
(i<8 ? d : b) ^= r;
a = b; b = c; c = d; d = t;
}
a -= EK[36];
b -= EK[37];
c -= EK[38];
d -= EK[39];
for (i=0; i<8; i++)
{
a -= (i%4==2) ? d : 0;
a -= (i%4==3) ? b : 0;
b ^= S1(a);
c -= S0(a>>24);
t = rotlFixed(a, 24);
d = (d - S1(a>>16)) ^ S0(t);
a = b; b = c; c = d; d = t;
}
a -= k[36]; b -= k[37]; c -= k[38]; d -= k[39];
Block::Put(xorBlock, outBlock)(a)(b)(c)(d);
}
void MARS::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
word32 a, b, c, d, l, m, r;
unsigned int i;
word32 a, b, c, d, l, m, r, t;
const word32 *k = m_k;
Block::Get(inBlock)(d)(c)(b)(a);
d += EK[36];
c += EK[37];
b += EK[38];
a += EK[39];
d += k[36]; c += k[37]; b += k[38]; a += k[39];
int i;
for (i = 0; i < 2; i++) {
f_mix(a,b,c,d);
a += d;
f_mix(b,c,d,a);
b += c;
f_mix(c,d,a,b);
f_mix(d,a,b,c);
for (i=0; i<8; i++)
{
b = (b ^ S0(a)) + S1(a>>8);
c += S0(a>>16);
a = rotrFixed(a, 24);
d ^= S1(a);
a += (i%4==0) ? d : 0;
a += (i%4==1) ? b : 0;
t = a; a = b; b = c; c = d; d = t;
}
r_ktr(a,b,c,d,34); r_ktr(b,c,d,a,32); r_ktr(c,d,a,b,30); r_ktr(d,a,b,c,28);
r_ktr(a,b,c,d,26); r_ktr(b,c,d,a,24); r_ktr(c,d,a,b,22); r_ktr(d,a,b,c,20);
r_ktr(a,d,c,b,18); r_ktr(b,a,d,c,16); r_ktr(c,b,a,d,14); r_ktr(d,c,b,a,12);
r_ktr(a,d,c,b,10); r_ktr(b,a,d,c, 8); r_ktr(c,b,a,d, 6); r_ktr(d,c,b,a, 4);
for (i = 0; i < 2; i++) {
b_mix(a,b,c,d);
b_mix(b,c,d,a);
c -= b;
b_mix(c,d,a,b);
d -= a;
b_mix(d,a,b,c);
for (i=0; i<16; i++)
{
t = rotrFixed(a, 13);
r = rotlFixed(a * k[35-2*i], 10);
m = t + k[34-2*i];
l = rotlMod((S(m) ^ rotrFixed(r, 5) ^ r), r);
c -= rotlMod(m, rotrFixed(r, 5));
(i<8 ? b : d) -= l;
(i<8 ? d : b) ^= r;
a = b; b = c; c = d; d = t;
}
d -= EK[0];
c -= EK[1];
b -= EK[2];
a -= EK[3];
for (i=0; i<8; i++)
{
a -= (i%4==2) ? d : 0;
a -= (i%4==3) ? b : 0;
b ^= S1(a);
c -= S0(a>>24);
t = rotlFixed(a, 24);
d = (d - S1(a>>16)) ^ S0(t);
a = b; b = c; c = d; d = t;
}
d -= k[0]; c -= k[1]; b -= k[2]; a -= k[3];
Block::Put(xorBlock, outBlock)(d)(c)(b)(a);
}

2
mars.h
View File

@ -26,7 +26,7 @@ class MARS : public MARS_Info, public BlockCipherDocumentation
protected:
static const word32 Sbox[512];
FixedSizeSecBlock<word32, 40> EK;
FixedSizeSecBlock<word32, 40> m_k;
};
class CRYPTOPP_NO_VTABLE Enc : public Base

View File

@ -120,6 +120,7 @@ void RegisterFactories()
RegisterSymmetricCipherDefaultFactories<CTR_Mode<Serpent> >();
RegisterSymmetricCipherDefaultFactories<CTR_Mode<CAST256> >();
RegisterSymmetricCipherDefaultFactories<CTR_Mode<RC6> >();
RegisterSymmetricCipherDefaultFactories<ECB_Mode<MARS> >();
RegisterSymmetricCipherDefaultFactories<CTR_Mode<MARS> >();
RegisterSymmetricCipherDefaultFactories<CTR_Mode<SHACAL2> >();
RegisterSymmetricCipherDefaultFactories<CTR_Mode<DES> >();