added libtomcrypt-0.79

This commit is contained in:
Tom St Denis 2003-03-03 01:02:10 +00:00 committed by Steffen Jaeckel
parent 2ef59575df
commit d5fbe63b70
35 changed files with 1918 additions and 709 deletions

View File

@ -25,7 +25,7 @@ tomstdenis@yahoo.com.
6) Clay Culver
Submitted a fix for "rsa.c" which cleaned up some code.
Submitted a fix for "rsa.c" which cleaned up some code. Submited some other fixes too. :-)
7) Jason Klapste

View File

@ -91,7 +91,7 @@ int base64_decode(const unsigned char *in, unsigned long len,
if (c == 254) { c = 0; g--; }
t = (t<<6)|c;
if (++y == 4) {
if (z + g > *outlen) goto error;
if (z + g > *outlen) { return CRYPT_BUFFER_OVERFLOW; }
out[z++] = (unsigned char)((t>>16)&255);
if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
if (g > 2) out[z++] = (unsigned char)(t&255);
@ -103,8 +103,6 @@ int base64_decode(const unsigned char *in, unsigned long len,
}
*outlen = z;
return CRYPT_OK;
error:
return CRYPT_BUFFER_OVERFLOW;
}
#endif

25
changes
View File

@ -1,3 +1,28 @@
Dec 14th, 2002
v0.79 -- Change to PK code [binary and source]. I made it so you have to pass the buffer size to the *_decrypt_key and
*_verify_hash functions. This prevents malformed packets from performing buffer overflows. I've also trimmed
the packet header size [by 4 bytes].
-- Made the test program halt on the first error it occurs. Also made it trap more errors than before.
-- Wrote the first chapter of my new book [DRAFT!], not in this package but check my website!
-- Included a perl script "config.pl" that will make "makefile.out" according to the users needs.
-- Added shell script to look for latest release
-- Merge DH and ECC key defines from mycrypt_cfg.h into the makefiles
-- updated the makefile to use BSD friendly archiving invokations
-- Changed the DH and ECC code to use base64 static key settings [e.g. the primes]. Dropped the code size by 3KB
and is ever-so-slightly faster than before.
-- added "mp_shrink" function to shrink the size of bignums. Specially useful for PK code :-)
-- Added new exptmod function that calculates a^b mod c with fewer multiplies then before [~20% for crypto
sized numbers]. Also added a "low mem" variant that doesn't use more than 20KB [upto 4096 bit nums] of
heap todo the calculation. Both are #define'able controlled
-- Added XREALLOC macro to provide realloc() functionality.
-- Added fix where in rsa_import() if you imported a public key or a non-optimized key it would free the mp_int's
not being used.
-- Fixed potential bug in the ECC code. Only would occur on platforms where char is not eight bits [which isn't
often!]
-- Fixed up the ECC point multiplication, its about 15% faster now
-- While I was at it [since the lib isn't binary backwards compatible anyways] I've fixed the PK export routines
so they export as "unsigned" types saving 1 byte per bignum outputted. Not a lot but heck why not.
Nov 28th, 2002
v0.78 -- Made the default ARGCHK macro a function call instead which reduced the code size from 264KB to 239KB.
-- Fixed a bug in the XTEA keysize function which called ARGCHK incorrectly.

143
config.pl Normal file
View File

@ -0,0 +1,143 @@
#!/usr/bin/perl
#
# Generates a makefile based on user input
#
# Tom St Denis, tomstdenis@yahoo.com, http://tom.iahu.ca
@settings = (
"CC,Compiler,gcc",
"AR,Archiver,ar",
"LD,Linker,ld",
"CFLAGS,Optimizations,-Os",
"CFLAGS,Warnings,-Wall -Wsign-compare -W -Wno-unused -Werror",
"CFLAGS,Include Paths,-I./",
"CFLAGS,Other compiler options,",
"CFLAGS,XMALLOC,-DXMALLOC=malloc",
"CFLAGS,XCALLOC,-DXCALLOC=calloc",
"CFLAGS,XFREE,-DXFREE=free",
"CFLAGS,XCLOCK,-DXCLOCK=clock",
"CFLAGS,XCLOCKS_PER_SEC,-DXCLOCKS_PER_SEC=CLOCKS_PER_SEC",
);
@opts = (
"SMALL_CODE,Use small code where possible (slower code),y",
"NO_FILE,Avoid file I/O calls,n",
"CLEAN_STACK,Clean the stack within functions,n",
"BLOWFISH,Include Blowfish block cipher,y",
"RC2,Include RC2 block cipher,y",
"RC5,Include RC5 block cipher,y",
"RC6,Include RC6 block cipher,y",
"SERPENT,Include Serpent block cipher,y",
"SAFERP,Include Safer+ block cipher,y",
"SAFER,Include Safer-64 block ciphers,y",
"RIJNDAEL,Include Rijndael (AES) block cipher,y",
"XTEA,Include XTEA block cipher,y",
"TWOFISH,Include Twofish block cipher,y",
"TWOFISH_SMALL,Include Use a low ram variant of Twofish,n",
"TWOFISH_TABLES,Include Use precomputed tables to speed up the low-ram variant,n",
"DES,Include DES and 3DES block ciphers,y",
"CAST5,Include CAST5 (aka CAST-128) block cipher,y",
"NOEKEON,Include Noekeon block cipher,y",
"CFB,Include CFB block mode of operation,y",
"OFB,Include OFB block mode of operation,y",
"ECB,Include ECB block mode of operation,y",
"CBC,Include CBC block mode of operation,y",
"CTR,Include CTR block mode of operation,y",
"SHA512,Include SHA512 one-way hash,y",
"SHA384,Include SHA384 one-way hash (requires SHA512),y",
"SHA256,Include SHA256 one-way hash,y",
"TIGER,Include TIGER one-way hash,y",
"SHA1,Include SHA1 one-way hash,y",
"MD5,Include MD5 one-way hash,y",
"MD4,Include MD4 one-way hash,y",
"MD2,Include MD2 one-way hash,y",
"HMAC,Include Hash based Message Authentication Support,y",
"BASE64,Include Base64 encoding support,y",
"YARROW,Include Yarrow PRNG,y",
"SPRNG,Include Secure PRNG base on RNG code,y",
"RC4,Include RC4 PRNG,y",
"DEVRANDOM,Use /dev/random or /dev/urandom if available?,y",
"TRY_URANDOM_FIRST,Try /dev/urandom before /dev/random?,n",
"MRSA,Include RSA public key support,y",
"MDH,Include Diffie-Hellman (over Z/pZ) public key support,y",
"MECC,Include Eliptic Curve public key crypto support,y",
"MDSA,Include Digital Signature Algoritm (DSA) support\n(not required for signatures in the other three),y",
"KR,Include Keyring support (groups all three PK systems),y",
"DH768,768-bit DH key support,y",
"DH1024,1024-bit DH key support,y",
"DH1280,1280-bit DH key support,y",
"DH1536,1280-bit DH key support,y",
"DH1792,1792-bit DH key support,y",
"DH2048,2048-bit DH key support,y",
"DH2560,2560-bit DH key support,y",
"DH3072,3072-bit DH key support,y",
"DH4096,4096-bit DH key support,y",
"ECC160,160-bit ECC key support,y",
"ECC192,192-bit ECC key support,y",
"ECC224,224-bit ECC key support,y",
"ECC256,256-bit ECC key support,y",
"ECC384,384-bit ECC key support,y",
"ECC521,521-bit ECC key support,y",
"DSA1024,1024-bit (160-bit) DSA key support,y",
"DSA2048,2048-bit (256-bit) DSA key support,y",
"DSA4096,4096-bit (512-bit) DSA key support,y",
"GF,Include GF(2^w) math support (not used internally),n",
"MPI,Include MPI big integer math support (required by the public key code),y",
"MPI_FASTEXPT,Use the faster exponentiation code (uses some heap but is faster),y",
"MPI_FASTEXPT_LOWMEM,Use the low ram variant of the fast code\nRequires the fast code to enabled,n",
);
# scan for switches and make variables
for (@settings) {
@m = split(",", $_);
print "@m[1]: [@m[2]] ";
$r = <>; $r = @m[2] if ($r eq "\n");
chomp($r);
@vars{@m[0]} = @vars{@m[0]} . $r . " ";
}
# scan for build flags
for (@opts) {
@m = split(",", $_);
print "@m[1]: [@m[2]]";
$r = <>; @vars{'CFLAGS'} = @vars{'CFLAGS'} . "-D" . $m[0] . " " if (($r eq "y\n") || ($r eq "\n" && @m[2] eq "y"));
}
open(OUT,">makefile.out");
print OUT "#makefile generated with config.pl\n#\n#Tom St Denis (tomstdenis\@yahoo.com, http://tom.iahu.ca) \n\n";
# output unique vars first
for (@settings) {
@m = split(",", $_);
print OUT "@m[0] = @vars{@m[0]}\n" if (@vars{@m[0]} ne "" && @m[0] ne "CFLAGS");
print OUT "CFLAGS += @vars{@m[0]}\n" if (@vars{@m[0]} ne "" && @m[0] eq "CFLAGS");
@vars{@m[0]} = "";
}
# output objects
print OUT "\ndefault: library\n\n";
print OUT "OBJECTS = keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o\n\n";
# some depends
print OUT "rsa.o: rsa_sys.c\ndh.o: dh_sys.c\necc.o: ecc_sys.c\n\n";
# targets
print OUT "library: \$(OBJECTS)\n\t \$(AR) rs libtomcrypt.a \$(OBJECTS)\n\n";
print OUT "clean:\n\trm -f \$(OBJECTS) libtomcrypt.a \n\n";
close OUT;
print "\n\nmakefile.out was written.\n";

57
crypt.c
View File

@ -1,7 +1,9 @@
#include "mycrypt.h"
#include <signal.h>
struct _cipher_descriptor cipher_descriptor[32] = {
#define TAB_SIZE 32
struct _cipher_descriptor cipher_descriptor[TAB_SIZE] = {
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
@ -35,7 +37,7 @@ struct _cipher_descriptor cipher_descriptor[32] = {
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL } };
struct _hash_descriptor hash_descriptor[32] = {
struct _hash_descriptor hash_descriptor[TAB_SIZE] = {
{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
@ -69,7 +71,7 @@ struct _hash_descriptor hash_descriptor[32] = {
{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL } };
struct _prng_descriptor prng_descriptor[32] = {
struct _prng_descriptor prng_descriptor[TAB_SIZE] = {
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
@ -103,26 +105,27 @@ struct _prng_descriptor prng_descriptor[32] = {
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL } };
#if (ARGTYPE == 0) && defined(SMALL_CODE)
/* ch1-01-1 */
#if (ARGTYPE == 0)
void crypt_argchk(char *v, char *s, int d)
{
#ifdef SONY_PS2
printf("_ARGCHK '%s' failure on line %d of file %s\n", v, d, s);
printf("_ARGCHK '%s' failure on line %d of file %s\n",
v, d, s);
#else
fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", v, d, s);
fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n",
v, d, s);
#endif
raise(SIGABRT);
}
#endif
/* ch1-01-1 */
int find_cipher(const char *name)
{
int x;
_ARGCHK(name != NULL);
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name != NULL && !strcmp(cipher_descriptor[x].name, name)) {
return x;
}
@ -134,7 +137,7 @@ int find_hash(const char *name)
{
int x;
_ARGCHK(name != NULL);
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].name != NULL && !strcmp(hash_descriptor[x].name, name)) {
return x;
}
@ -146,7 +149,7 @@ int find_prng(const char *name)
{
int x;
_ARGCHK(name != NULL);
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if ((prng_descriptor[x].name != NULL) && !strcmp(prng_descriptor[x].name, name)) {
return x;
}
@ -157,7 +160,7 @@ int find_prng(const char *name)
int find_cipher_id(unsigned char ID)
{
int x;
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].ID == ID) {
return (cipher_descriptor[x].name == NULL) ? -1 : x;
}
@ -168,7 +171,7 @@ int find_cipher_id(unsigned char ID)
int find_hash_id(unsigned char ID)
{
int x;
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].ID == ID) {
return (hash_descriptor[x].name == NULL) ? -1 : x;
}
@ -186,7 +189,7 @@ int find_cipher_any(const char *name, int blocklen, int keylen)
x = find_cipher(name);
if (x != -1) return x;
for (x = 0; cipher_descriptor[x].name != NULL; x++) {
for (x = 0; cipher_descriptor[x].name != NULL && x < TAB_SIZE; x++) {
if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) {
return x;
}
@ -201,14 +204,14 @@ int register_cipher(const struct _cipher_descriptor *cipher)
_ARGCHK(cipher != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) {
return x;
}
}
/* find a blank spot */
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name == NULL) {
memcpy(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor));
return x;
@ -226,7 +229,7 @@ int unregister_cipher(const struct _cipher_descriptor *cipher)
_ARGCHK(cipher != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (!memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor))) {
cipher_descriptor[x].name = NULL;
cipher_descriptor[x].ID = 255;
@ -243,14 +246,14 @@ int register_hash(const struct _hash_descriptor *hash)
_ARGCHK(hash != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (!memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor))) {
return x;
}
}
/* find a blank spot */
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].name == NULL) {
memcpy(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor));
return x;
@ -268,7 +271,7 @@ int unregister_hash(const struct _hash_descriptor *hash)
_ARGCHK(hash != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (!memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor))) {
hash_descriptor[x].name = NULL;
return CRYPT_OK;
@ -284,14 +287,14 @@ int register_prng(const struct _prng_descriptor *prng)
_ARGCHK(prng != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (!memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor))) {
return x;
}
}
/* find a blank spot */
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (prng_descriptor[x].name == NULL) {
memcpy(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor));
return x;
@ -309,7 +312,7 @@ int unregister_prng(const struct _prng_descriptor *prng)
_ARGCHK(prng != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
for (x = 0; x < TAB_SIZE; x++) {
if (!memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor))) {
prng_descriptor[x].name = NULL;
return CRYPT_OK;
@ -320,7 +323,7 @@ int unregister_prng(const struct _prng_descriptor *prng)
int cipher_is_valid(int idx)
{
if (idx < 0 || idx > 32 || cipher_descriptor[idx].name == NULL) {
if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) {
return CRYPT_INVALID_CIPHER;
}
return CRYPT_OK;
@ -328,7 +331,7 @@ int cipher_is_valid(int idx)
int hash_is_valid(int idx)
{
if (idx < 0 || idx > 32 || hash_descriptor[idx].name == NULL) {
if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) {
return CRYPT_INVALID_HASH;
}
return CRYPT_OK;
@ -336,7 +339,7 @@ int hash_is_valid(int idx)
int prng_is_valid(int idx)
{
if (idx < 0 || idx > 32 || prng_descriptor[idx].name == NULL) {
if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) {
return CRYPT_INVALID_PRNG;
}
return CRYPT_OK;

BIN
crypt.pdf

Binary file not shown.

View File

@ -44,7 +44,7 @@
\def\gap{\vspace{0.5ex}}
\makeindex
\begin{document}
\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.78}
\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.79}
\author{Tom St Denis \\
Algonquin College \\
\\
@ -192,6 +192,7 @@ I would like to give thanks to the following people (in no particular order) for
\item Wayne Scott
\item Andrew Tyler
\item Sky Schulz
\item Christopher Imes
\end{enumerate}
\chapter{The Application Programming Interface (API)}
@ -1367,15 +1368,18 @@ int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
unsigned char *outkey, unsigned long *outlen,
prng_state *prng, int wprng, rsa_key *key);
int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, rsa_key *key);
int rsa_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
rsa_key *key);
\end{verbatim}
The ``rsa\_encrypt\_key()'' function accepts a symmetric key (limited to 32 bytes) as input in ``inkey''. ``inlen''
is the size of the input key in bytes. The function will then ``rsa\_pad()'' the key and encrypt it using the RSA
algorithm. It will store the result in ``outkey'' along with the length in ``outlen''. The ``rsa\_decrypt\_key()'' function
performs the opposite. The ``in'' variable is where the RSA packet goes and it will store the original symmetric key in
the ``outkey'' variable along with its length in ``keylen''.
algorithm. It will store the result in ``outkey'' along with the length in ``outlen''.
The ``rsa\_decrypt\_key()'' function performs the opposite. The ``in'' variable is where the RSA packet of length
``inlen'' goes and it will store the original symmetric key in the ``outkey'' variable along with its length in
``keylen''.
Similarly to sign or verify a hash of a message the following two messages are provided. The idea is to hash your
message then use these functions to RSA sign the hash.
@ -1384,8 +1388,8 @@ int rsa_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
rsa_key *key);
int rsa_verify_hash(const unsigned char *sig, const unsigned char *hash,
int *stat, rsa_key *key);
int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, int *stat, rsa_key *key);
\end{verbatim}
For ``rsa\_sign\_hash'' the input is intended to be the hash of a message the user wants to sign. The output is the
RSA signed packet which ``rsa\_verify\_hash'' can verify. For the verification function ``sig'' is the RSA signature
@ -1633,12 +1637,13 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
prng_state *prng, int wprng, int hash,
dh_key *key);
int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, dh_key *key);
int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
dh_key *key);
\end{verbatim}
Where ``inkey'' is an input symmetric key of no more than 32 bytes. Essentially these routines created a random public key
and find the hash of the shared secret. The message digest is than XOR'ed against the symmetric key. All of the required
data is placed in ``out'' by ``dh\_encrypt\_key()''. The hash must produce a message digest at least as large
and find the hash of the shared secret. The message digest is than XOR'ed against the symmetric key. All of the
required data is placed in ``out'' by ``dh\_encrypt\_key()''. The hash must produce a message digest at least as large
as the symmetric key you are trying to share.
Similar to the RSA system you can sign and verify a hash of a message.
@ -1647,9 +1652,9 @@ int dh_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, dh_key *key);
int dh_verify_hash(const unsigned char *sig, const unsigned char *hash,
unsigned long inlen, int *stat,
dh_key *key);
int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, dh_key *key);
\end{verbatim}
The ``dh\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a DH packet in ``out''.
@ -1742,8 +1747,9 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
prng_state *prng, int wprng, int hash,
ecc_key *key);
int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, ecc_key *key);
int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
ecc_key *key);
\end{verbatim}
Where ``inkey'' is an input symmetric key of no more than 32 bytes. Essentially these routines created a random public key
@ -1757,9 +1763,9 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, ecc_key *key);
int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
unsigned long inlen, int *stat,
ecc_key *key);
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, ecc_key *key);
\end{verbatim}
The ``ecc\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a ECC packet in ``out''.

View File

@ -63,23 +63,23 @@ void store_tests(void)
STORE32L(L, &buf[0]);
L = 0;
LOAD32L(L, &buf[0]);
if (L != 0x12345678UL) printf("LOAD/STORE32 Little don't work\n");
if (L != 0x12345678UL) { printf("LOAD/STORE32 Little don't work\n"); exit(-1); }
LL = CONST64(0x01020304050607);
STORE64L(LL, &buf[0]);
LL = 0;
LOAD64L(LL, &buf[0])
if (LL != CONST64(0x01020304050607)) printf("LOAD/STORE64 Little don't work\n");
if (LL != CONST64(0x01020304050607)) { printf("LOAD/STORE64 Little don't work\n"); exit(-1); }
L = 0x12345678UL;
STORE32H(L, &buf[0]);
L = 0;
LOAD32H(L, &buf[0]);
if (L != 0x12345678UL) printf("LOAD/STORE32 High don't work\n");
if (L != 0x12345678UL) { printf("LOAD/STORE32 High don't work\n"); exit(-1); }
LL = CONST64(0x01020304050607);
STORE64H(LL, &buf[0]);
LL = 0;
LOAD64H(LL, &buf[0])
if (LL != CONST64(0x01020304050607)) printf("LOAD/STORE64 High don't work\n");
if (LL != CONST64(0x01020304050607)) { printf("LOAD/STORE64 High don't work\n"); exit(-1); }
}
void cipher_tests(void) {
@ -103,11 +103,13 @@ void ecb_tests(void)
for (x = 0; cipher_descriptor[x].name != NULL; x++) {
printf(" %12s: ",
cipher_descriptor[x].name);
if ((errno = cipher_descriptor[x].test()) != CRYPT_OK)
if ((errno = cipher_descriptor[x].test()) != CRYPT_OK) {
printf(" **failed** Reason: %s\n", error_to_string(errno));
else
exit(-1);
} else {
printf("passed\n");
}
}
}
#ifdef CBC
@ -124,11 +126,15 @@ void cbc_tests(void)
for (x = 0; x < 32; x++) blk[x] = IV[x] = x;
/* now lets start a cbc session */
if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) {
printf("CBC Setup: %s\n", error_to_string(errno)); exit(-1); }
/* now lets encode 32 bytes */
for (x = 0; x < 4; x++)
cbc_encrypt(blk+8*x, ct+8*x, &cbc);
for (x = 0; x < 4; x++) {
if ((errno = cbc_encrypt(blk+8*x, ct+8*x, &cbc)) != CRYPT_OK) {
printf("CBC encrypt: %s\n", error_to_string(errno)); exit(-1);
}
}
zeromem(blk, sizeof(blk));
@ -137,11 +143,16 @@ void cbc_tests(void)
for (x = 0; x < 32; x++) IV[x] = x;
/* now lets start a cbc session */
if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) {
printf("CBC Setup: %s\n", error_to_string(errno)); exit(-1); }
/* now lets decode 32 bytes */
for (x = 0; x < 4; x++)
cbc_decrypt(ct+8*x, blk+8*x, &cbc);
for (x = 0; x < 4; x++) {
if ((errno = cbc_decrypt(ct+8*x, blk+8*x, &cbc)) != CRYPT_OK) {
printf("CBC decrypt: %s\n", error_to_string(errno)); exit(-1);
}
}
/* print output */
for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1;
@ -157,6 +168,7 @@ void cbc_tests(void)
printf("CBC failed logical testing.\n");
for (x = 0; x < 16; x++) printf("%02x ", ct[x]);
printf("\n");
exit(-1);
} else {
printf("CBC passed logical testing.\n");
}
@ -178,11 +190,15 @@ void ofb_tests(void)
for (x = 0; x < 32; x++) blk[x] = IV[x] = x;
/* now lets start a ofb session */
if ((errno = ofb_start(find_cipher("blowfish"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = ofb_start(find_cipher("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) {
printf("OFB Setup: %s\n", error_to_string(errno)); exit(-1); }
/* now lets encode 32 bytes */
for (x = 0; x < 4; x++)
ofb_encrypt(blk+8*x, ct+8*x, 8, &ofb);
for (x = 0; x < 4; x++) {
if ((errno = ofb_encrypt(blk+8*x, ct+8*x, 8, &ofb)) != CRYPT_OK) {
printf("OFB encrypt: %s\n", error_to_string(errno)); exit(-1);
}
}
zeromem(blk, sizeof(blk));
@ -191,15 +207,20 @@ void ofb_tests(void)
for (x = 0; x < 32; x++) IV[x] = x;
/* now lets start a ofb session */
if ((errno = ofb_start(find_cipher("blowfish"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = ofb_start(find_cipher("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) {
printf("OFB setup: %s\n", error_to_string(errno)); exit(-1); }
/* now lets decode 32 bytes */
for (x = 0; x < 4; x++)
ofb_decrypt(ct+8*x, blk+8*x, 8, &ofb);
for (x = 0; x < 4; x++) {
if ((errno = ofb_decrypt(ct+8*x, blk+8*x, 8, &ofb)) != CRYPT_OK) {
printf("OFB decrypt: %s\n", error_to_string(errno)); exit(-1);
}
}
/* print output */
for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1;
printf(" %s\n", y?"failed":"passed");
if (y) exit(-1);
}
#else
void ofb_tests(void) { printf("OFB not compiled in\n"); }
@ -218,11 +239,15 @@ void cfb_tests(void)
for (x = 0; x < 32; x++) blk[x] = IV[x] = x;
/* now lets start a cfb session */
if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) {
printf("CFB setup: %s\n", error_to_string(errno)); exit(-1); }
/* now lets encode 32 bytes */
for (x = 0; x < 4; x++)
cfb_encrypt(blk+8*x, ct+8*x, 8, &cfb);
for (x = 0; x < 4; x++) {
if ((errno = cfb_encrypt(blk+8*x, ct+8*x, 8, &cfb)) != CRYPT_OK) {
printf("CFB encrypt: %s\n", error_to_string(errno)); exit(-1);
}
}
zeromem(blk, sizeof(blk));
@ -231,15 +256,20 @@ void cfb_tests(void)
for (x = 0; x < 32; x++) IV[x] = x;
/* now lets start a cfb session */
if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) {
printf("CFB Setup: %s\n", error_to_string(errno)); exit(-1); }
/* now lets decode 32 bytes */
for (x = 0; x < 4; x++)
cfb_decrypt(ct+8*x, blk+8*x, 8, &cfb);
for (x = 0; x < 4; x++) {
if ((errno = cfb_decrypt(ct+8*x, blk+8*x, 8, &cfb)) != CRYPT_OK) {
printf("CFB decrypt: %s\n", error_to_string(errno)); exit(-1);
}
}
/* print output */
for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1;
printf(" %s\n", y?"failed":"passed");
if (y) exit(-1);
}
#else
void cfb_tests(void) { printf("CFB not compiled in\n"); }
@ -259,11 +289,15 @@ void ctr_tests(void)
for (x = 0; x < 32; x++) blk[x] = count[x] = x;
/* now lets start a ctr session */
if ((errno = ctr_start(find_cipher("aes"), count, key, 16, 0, &ctr)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = ctr_start(find_cipher("xtea"), count, key, 16, 0, &ctr)) != CRYPT_OK) {
printf("CTR Setup: %s\n", error_to_string(errno)); exit(-1); }
/* now lets encode 32 bytes */
for (x = 0; x < 4; x++)
ctr_encrypt(blk+8*x, ct+8*x, 8, &ctr);
for (x = 0; x < 4; x++) {
if ((errno = ctr_encrypt(blk+8*x, ct+8*x, 8, &ctr)) != CRYPT_OK) {
printf("CTR encrypt: %s\n", error_to_string(errno)); exit(-1);
}
}
zeromem(blk, sizeof(blk));
@ -272,15 +306,20 @@ void ctr_tests(void)
for (x = 0; x < 32; x++) count[x] = x;
/* now lets start a cbc session */
if ((errno = ctr_start(find_cipher("aes"), count, key, 16, 0, &ctr)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = ctr_start(find_cipher("xtea"), count, key, 16, 0, &ctr)) != CRYPT_OK) {
printf("CTR Setup: %s\n", error_to_string(errno)); exit(-1); }
/* now lets decode 32 bytes */
for (x = 0; x < 4; x++)
ctr_decrypt(ct+8*x, blk+8*x, 8, &ctr);
for (x = 0; x < 4; x++) {
if ((errno = ctr_decrypt(ct+8*x, blk+8*x, 8, &ctr)) != CRYPT_OK) {
printf("CTR decrypt: %s\n", error_to_string(errno)); exit(-1);
}
}
/* print output */
for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1;
printf(" %s\n", y?"failed":"passed");
if (y) exit(-1);
/* lets actually check the bytes */
memset(count, 0, 8); count[0] = 0xFF; /* IV = FF 00 00 00 00 00 00 00 */
@ -325,17 +364,18 @@ void pad_test(void)
/* pad the message so that random filler is placed before and after it */
y = 100;
if ((errno = rsa_pad(in, 16, out, &y, find_prng("yarrow"), &prng)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = rsa_pad(in, 16, out, &y, find_prng("yarrow"), &prng)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno)); exit(-1); }
/* depad the message to get the original content */
memset(in, 0, sizeof(in));
x = 100;
if ((errno = rsa_depad(out, y, in, &x)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = rsa_depad(out, y, in, &x)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
/* check outcome */
printf("rsa_pad: ");
if (x != 16) { printf("Failed. Wrong size.\n"); return; }
for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed. Expected %02lx and got %02x.\n", x, in[x]); return; }
if (x != 16) { printf("Failed. Wrong size.\n"); exit(-1); }
for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed. Expected %02lx and got %02x.\n", x, in[x]); exit(-1); }
printf("passed.\n");
}
@ -349,100 +389,40 @@ void rsa_test(void)
/* ---- SINGLE ENCRYPT ---- */
/* encrypt a short 8 byte string */
if ((errno = rsa_make_key(&prng, find_prng("yarrow"), 1024/8, 65537, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = rsa_make_key(&prng, find_prng("yarrow"), 1024/8, 65537, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno)); exit(-1); }
for (x = 0; x < 8; x++) in[x] = (unsigned char)(x+1);
y = sizeof(in);
if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno)); exit(-1); }
/* decrypt it */
zeromem(in, sizeof(in));
x = sizeof(out);
if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno)); exit(-1); }
/* compare */
printf("RSA : ");
for (x = 0; x < 8; x++) if (in[x] != (x+1)) { printf("Failed. x==%02lx, in[%ld]==%02x\n", x, x, in[x]); }
for (x = 0; x < 8; x++) if (in[x] != (x+1)) { printf("Failed. x==%02lx, in[%ld]==%02x\n", x, x, in[x]); exit(-1); }
printf("passed.\n");
#ifdef PK_PACKET
/* ---- BLOCK ENCRYPT ---- */
/* now lets test rsa_encrypt() */
for (x = 0; x < 8; x++) in[x] = (unsigned char)x;
x = sizeof(out);
if ((errno = rsa_encrypt(in, 8, out, &x, &prng, find_prng("yarrow"), find_cipher("aes"), &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
/* test rsa_decrypt() */
zeromem(in, sizeof(in));
y = sizeof(in);
if ((errno = rsa_decrypt(out, x, in, &y, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("rsa_encrypt()/rsa_decrypt(): ");
for (y = 0; y < 8; y++) if (in[y] != y) { printf("failed.\n"); return; }
printf("Passed.\n");
/* ---- SIGNATURES ---- */
x = sizeof(in);
if ((errno = rsa_sign("hello", 5, in, &x, find_hash("md5"), &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
if ((errno = rsa_verify(in, "hello", 5, &stat, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("RSA Signatures: %s, ", (stat==1)?"pass":"fail");
if ((errno = rsa_verify(in, "abcde", 5, &stat, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("%s\n", (stat==0)?"pass":"fail");
/* ---- EXPORT/IMPORT ---- */
x = sizeof(out);
if ((errno = rsa_export(out, &x, PK_PRIVATE_OPTIMIZED, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("RSA Export takes %lu bytes\n", x);
rsa_free(&key);
if ((errno = rsa_import(out, &key, x)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("RSA Import: ");
if ((errno = rsa_verify(in, "hello", 5, &stat, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("%s, ", (stat==1)?"pass":"fail");
if ((errno = rsa_verify(in, "abcde", 5, &stat, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("%s\n", (stat==0)?"pass":"fail");
#endif
/* test the rsa_encrypt_key functions */
for (x = 0; x < 16; x++) in[x] = x;
y = sizeof(out);
if ((errno = rsa_encrypt_key(in, 16, out, &y, &prng, find_prng("yarrow"), &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
zeromem(in, sizeof(in));
x = sizeof(in);
if ((errno = rsa_decrypt_key(out, in, &x, &key)) != CRYPT_OK) {
if ((errno = rsa_decrypt_key(out, y, in, &x, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf("RSA en/de crypt key routines: ");
if (x != 16) { printf("Failed (length)\n"); return; }
for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed (contents)\n"); return; }
if (x != 16) { printf("Failed (length)\n"); exit(-1); }
for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed (contents)\n"); exit(-1); }
printf("Passed\n");
/* test sign_hash functions */
@ -450,24 +430,25 @@ void rsa_test(void)
x = sizeof(in);
if ((errno = rsa_sign_hash(in, 16, out, &x, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf("RSA signed hash: %lu bytes\n", x);
if ((errno = rsa_verify_hash(out, in, &stat, &key)) != CRYPT_OK) {
if ((errno = rsa_verify_hash(out, x, in, &stat, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf("Verify hash: %s, ", stat?"passed":"failed");
in[0] ^= 1;
if ((errno = rsa_verify_hash(out, in, &stat, &key)) != CRYPT_OK) {
if ((errno = rsa_verify_hash(out, x, in, &stat, &key)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf("%s\n", (!stat)?"passed":"failed");
if (stat) exit(-1);
rsa_free(&key);
/* make a RSA key */
#ifdef SONY_PS2
#ifdef SONY_PS2_NOPE
limit = 1024;
#else
limit = 2048;
@ -475,21 +456,21 @@ void rsa_test(void)
for (z = 1024; z <= limit; z += 512) {
t = XCLOCK();
if ((errno = rsa_make_key(&prng, find_prng("yarrow"), z/8, 65537, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = rsa_make_key(&prng, find_prng("yarrow"), z/8, 65537, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
t = XCLOCK() - t;
printf("Took %.0f ms to make a %ld-bit RSA key.\n", 1000.0 * ((double)t / (double)XCLOCKS_PER_SEC), z);
/* time encryption */
y = sizeof(in);
t = XCLOCK();
if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
t = XCLOCK() - t;
printf("Took %.0f ms to encrypt with a %ld-bit RSA key.\n", 1000.0 * ((double)t / (double)XCLOCKS_PER_SEC), z);
/* time decryption */
x = sizeof(out);
t = XCLOCK();
if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
t = XCLOCK() - t;
printf("Took %.0f ms to decrypt with a %ld-bit RSA key.\n", 1000.0 * ((double)t / (double)XCLOCKS_PER_SEC), z);
rsa_free(&key);
@ -516,19 +497,19 @@ void base64_test(void)
x = 100;
if (base64_encode(buf[0], 16, buf[1], &x) != CRYPT_OK) {
printf(" error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf(" encoded 16 bytes to %ld bytes...[%s]\n", x, buf[1]);
memset(buf[0], 0, 100);
y = 100;
if (base64_decode(buf[1], x, buf[0], &y) != CRYPT_OK) {
printf(" error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf(" decoded %ld bytes to %ld bytes\n", x, y);
for (x = 0; x < 16; x++) if (buf[0][x] != x) {
printf(" **failed**\n");
return;
exit(-1);
}
printf(" passed\n");
}
@ -642,50 +623,50 @@ void dh_tests(void)
/* make up two keys */
if ((errno = dh_make_key(&prng, find_prng("yarrow"), 96, &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
if ((errno = dh_make_key(&prng, find_prng("yarrow"), 96, &userb)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
/* make the shared secret */
x = 4096;
if ((errno = dh_shared_secret(&usera, &userb, buf[0], &x)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
y = 4096;
if ((errno = dh_shared_secret(&userb, &usera, buf[1], &y)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
if (y != x) { printf("DH Shared keys are not same size.\n"); return; }
if (memcmp(buf[0], buf[1], x)) { printf("DH Shared keys not same contents.\n"); return; }
if (y != x) { printf("DH Shared keys are not same size.\n"); exit(-1); }
if (memcmp(buf[0], buf[1], x)) { printf("DH Shared keys not same contents.\n"); exit(-1); }
/* now export userb */
y = 4096;
if ((errno = dh_export(buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
dh_free(&userb);
/* import and make the shared secret again */
if ((errno = dh_import(buf[1], y, &userb)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
z = 4096;
if ((errno = dh_shared_secret(&usera, &userb, buf[2], &z)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf("DH routines: ");
if (z != x) { printf("failed. Size don't match?\n"); return; }
if (memcmp(buf[0], buf[2], x)) { printf("Failed. Content didn't match.\n"); return; }
if (z != x) { printf("failed. Size don't match?\n"); exit(-1); }
if (memcmp(buf[0], buf[2], x)) { printf("Failed. Content didn't match.\n"); exit(-1); }
printf("Passed\n");
dh_free(&usera);
dh_free(&userb);
@ -703,7 +684,7 @@ void dh_tests(void)
printf("Make dh-1024 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
dh_free(&usera);
#ifndef SONY_PS2
#ifndef SONY_PS2_NOPE
t1 = XCLOCK();
dh_make_key(&prng, find_prng("yarrow"), 160, &usera);
t1 = XCLOCK() - t1;
@ -735,71 +716,23 @@ void dh_tests(void)
dh_free(&usera);
#endif
#ifdef PK_PACKET
/* try dh packet stuff */
for (x = 0; x < 16; x++) buf[0][x] = (unsigned char)x;
dh_make_key(&prng, find_prng("yarrow"), 24, &usera);
x = 4096;
if (dh_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("aes"),
find_hash("sha1"), &usera) != CRYPT_OK) {
printf("dh_encrypt says %s\n", error_to_string(errno));
return;
}
printf("dh encrypted 16 bytes into %ld bytes!\n", x);
y = 4096;
if ((errno = dh_decrypt(buf[1], x, buf[2], &y, &usera)) != CRYPT_OK) {
printf("dh_decrypt says %s\n", error_to_string(errno));
return;
}
printf("dh packet: ");
if (16 != y) { printf("Failed: Sizes different! 16 vs %ld\n", y); return; }
if (memcmp(buf[0], buf[2], 16)) { printf("Failed; Content mismatch.\n"); return; }
printf("Passed!\n");
dh_free(&usera);
/* try dh signatures */
dh_make_key(&prng, find_prng("yarrow"), 96, &usera);
x = 4096;
if ((errno = dh_sign("hello", 5, buf[0], &x, find_hash("sha1"), &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("dh-768 Signature took %ld bytes\n", x);
if ((errno = dh_verify(buf[0], "hello", 5, &stat, &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
if ((errno = dh_verify(buf[0], "hellp", 5, &stat2, &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("dh Signatures: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2);
dh_free(&usera);
#endif
/* test encrypt_key */
dh_make_key(&prng, find_prng("yarrow"), 96, &usera);
for (x = 0; x < 16; x++) buf[0][x] = x;
y = sizeof(buf[1]);
if ((errno = dh_encrypt_key(buf[0], 16, buf[1], &y, &prng, find_prng("yarrow"), find_hash("md5"), &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
zeromem(buf[0], sizeof(buf[0]));
x = sizeof(buf[0]);
if ((errno = dh_decrypt_key(buf[1], buf[0], &x, &usera)) != CRYPT_OK) {
if ((errno = dh_decrypt_key(buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf("DH en/de crypt key routines: ");
if (x != 16) { printf("Failed (length)\n"); return; }
for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); return; }
if (x != 16) { printf("Failed (length)\n"); exit(-1); }
for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); exit(-1); }
printf("Passed (size %lu)\n", y);
/* test sign_hash */
@ -807,16 +740,16 @@ void dh_tests(void)
x = sizeof(buf[1]);
if ((errno = dh_sign_hash(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
if (dh_verify_hash(buf[1], buf[0], 16, &stat, &usera)) {
if (dh_verify_hash(buf[1], x, buf[0], 16, &stat, &usera)) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
buf[0][0] ^= 1;
if (dh_verify_hash(buf[1], buf[0], 16, &stat2, &usera)) {
if (dh_verify_hash(buf[1], x, buf[0], 16, &stat2, &usera)) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf("dh_sign/verify_hash: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2);
dh_free(&usera);
@ -868,7 +801,7 @@ void ecc_tests(void)
ecc_key usera, userb;
clock_t t1;
if ((errno = ecc_test()) != CRYPT_OK) printf("ecc Error: %s\n", error_to_string(errno));
if ((errno = ecc_test()) != CRYPT_OK) { printf("ecc Error: %s\n", error_to_string(errno)); exit(-1); }
ecc_sizes(&low, &high);
printf("ecc Keys from %d to %d supported.\n", low*8, high*8);
@ -876,35 +809,35 @@ void ecc_tests(void)
/* make up two keys */
if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 24, &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 24, &userb)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
/* make the shared secret */
x = 4096;
if ((errno = ecc_shared_secret(&usera, &userb, buf[0], &x)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
y = 4096;
if ((errno = ecc_shared_secret(&userb, &usera, buf[1], &y)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
if (y != x) { printf("ecc Shared keys are not same size.\n"); return; }
if (y != x) { printf("ecc Shared keys are not same size.\n"); exit(-1); }
if (memcmp(buf[0], buf[1], x)) { printf("ecc Shared keys not same contents.\n"); return; }
if (memcmp(buf[0], buf[1], x)) { printf("ecc Shared keys not same contents.\n"); exit(-1); }
/* now export userb */
y = 4096;
if ((errno = ecc_export(buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
ecc_free(&userb);
printf("ECC-192 export took %ld bytes\n", y);
@ -912,142 +845,94 @@ void ecc_tests(void)
/* import and make the shared secret again */
if ((errno = ecc_import(buf[1], y, &userb)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
z = 4096;
if ((errno = ecc_shared_secret(&usera, &userb, buf[2], &z)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf("ecc routines: ");
if (z != x) { printf("failed. Size don't match?\n"); return; }
if (memcmp(buf[0], buf[2], x)) { printf("Failed. Content didn't match.\n"); return; }
if (z != x) { printf("failed. Size don't match?\n"); exit(-1); }
if (memcmp(buf[0], buf[2], x)) { printf("Failed. Content didn't match.\n"); exit(-1); }
printf("Passed\n");
ecc_free(&usera);
ecc_free(&userb);
/* time stuff */
t1 = XCLOCK();
ecc_make_key(&prng, find_prng("yarrow"), 20, &usera);
if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 20, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
t1 = XCLOCK() - t1;
printf("Make ECC-160 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
ecc_free(&usera);
t1 = XCLOCK();
ecc_make_key(&prng, find_prng("yarrow"), 24, &usera);
if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 24, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
t1 = XCLOCK() - t1;
printf("Make ECC-192 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
ecc_free(&usera);
t1 = XCLOCK();
ecc_make_key(&prng, find_prng("yarrow"), 28, &usera);
if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 28, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
t1 = XCLOCK() - t1;
printf("Make ECC-224 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
ecc_free(&usera);
#ifndef SONY_PS2
t1 = XCLOCK();
ecc_make_key(&prng, find_prng("yarrow"), 32, &usera);
if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 32, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
t1 = XCLOCK() - t1;
printf("Make ECC-256 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
ecc_free(&usera);
t1 = XCLOCK();
ecc_make_key(&prng, find_prng("yarrow"), 48, &usera);
if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 48, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
t1 = XCLOCK() - t1;
printf("Make ECC-384 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
ecc_free(&usera);
t1 = XCLOCK();
ecc_make_key(&prng, find_prng("yarrow"), 65, &usera);
if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 65, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
t1 = XCLOCK() - t1;
printf("Make ECC-521 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
ecc_free(&usera);
#endif
#ifdef PK_PACKET
/* try ECC packet stuff */
for (x = 0; x < 16; x++) buf[0][x] = (unsigned char)x;
ecc_make_key(&prng, find_prng("yarrow"), 20, &usera);
x = 4096;
if (ecc_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("aes"),
find_hash("tiger"), &usera) != CRYPT_OK) {
printf("ecc_encrypt says %s\n", error_to_string(errno));
return;
}
printf("Ecc encrypted 16 bytes into %ld bytes!\n", x);
y = 4096;
if ((errno = ecc_decrypt(buf[1], x, buf[2], &y, &usera)) != CRYPT_OK) {
printf("ecc_decrypt says %s\n", error_to_string(errno));
return;
}
printf("ECC packet: ");
if (16 != y) { printf("Failed: Sizes different! 16 vs %ld\n", y); return; }
if (memcmp(buf[0], buf[2], 16)) { printf("Failed; Content mismatch.\n"); return; }
printf("Passed!\n");
ecc_free(&usera);
/* try ECC signatures */
ecc_make_key(&prng, find_prng("yarrow"), 20, &usera);
x = 4096;
if ((errno = ecc_sign("hello", 5, buf[0], &x, find_hash("sha1"), &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("ECC-160 Signature took %ld bytes\n", x);
if ((errno = ecc_verify(buf[0], "hello", 5, &stat, &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
if ((errno = ecc_verify(buf[0], "hellp", 5, &stat2, &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
}
printf("ECC Signatures: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2);
ecc_free(&usera);
#endif
/* test encrypt_key */
ecc_make_key(&prng, find_prng("yarrow"), 32, &usera);
for (x = 0; x < 16; x++) buf[0][x] = x;
y = sizeof(buf[1]);
if ((errno = ecc_encrypt_key(buf[0], 16, buf[1], &y, &prng, find_prng("yarrow"), find_hash("md5"), &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
zeromem(buf[0], sizeof(buf[0]));
x = sizeof(buf[0]);
if ((errno = ecc_decrypt_key(buf[1],buf[0], &x, &usera)) != CRYPT_OK) {
if ((errno = ecc_decrypt_key(buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf("ECC en/de crypt key routines: ");
if (x != 16) { printf("Failed (length)\n"); return; }
for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); return; }
if (x != 16) { printf("Failed (length)\n"); exit(-1); }
for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); exit(-1); }
printf("Passed (size: %lu)\n", y);
/* test sign_hash */
for (x = 0; x < 16; x++) buf[0][x] = x;
x = sizeof(buf[1]);
if ((errno = ecc_sign_hash(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
if (ecc_verify_hash(buf[1], buf[0], 16, &stat, &usera)) {
if (ecc_verify_hash(buf[1], x, buf[0], 16, &stat, &usera)) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
buf[0][0] ^= 1;
if (ecc_verify_hash(buf[1], buf[0], 16, &stat2, &usera)) {
if (ecc_verify_hash(buf[1], x, buf[0], 16, &stat2, &usera)) {
printf("Error: %s\n", error_to_string(errno));
return;
exit(-1);
}
printf("ecc_sign/verify_hash: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2);
ecc_free(&usera);
@ -1185,15 +1070,16 @@ void register_all_algs(void)
register_cipher(&null_desc);
#ifdef SHA1
register_hash(&sha1_desc);
#endif
#ifdef SHA256
register_hash(&sha256_desc);
#endif
#ifdef TIGER
register_hash(&tiger_desc);
#endif
#ifdef SHA1
register_hash(&sha1_desc);
#endif
#ifdef MD5
register_hash(&md5_desc);
#endif
@ -1383,18 +1269,18 @@ void kr_test(void)
len = sizeof(buf2);
if ((errno = kr_sign_hash(kr, _kr->ID, buf, 32, buf2, &len, &prng, find_prng("yarrow"))) != CRYPT_OK) {
printf("kr_sign_hash failed, %i, %lu\n", i, len);
printf("kr_sign_hash failed, %i, %s\n", i, error_to_string(errno));
exit(-1);
}
printf("kr_sign_hash: ");
if ((errno = kr_verify_hash(kr, buf2, buf, 32, &stat)) != CRYPT_OK) {
printf("kr_sign_hash failed, %i, %lu\n", i, len);
printf("kr_sign_hash failed, %i, %s\n", i, error_to_string(errno));
exit(-1);
}
printf("%s, ", stat?"passed":"failed");
buf[15] ^= 1;
if ((errno = kr_verify_hash(kr, buf2, buf, 32, &stat)) != CRYPT_OK) {
printf("kr_sign_hash failed, %i, %lu\n", i, len);
printf("kr_sign_hash failed, %i, %s\n", i, error_to_string(errno));
exit(-1);
}
printf("%s\n", (!stat)?"passed":"failed");

173
dh.c
View File

@ -12,10 +12,9 @@ static const struct {
96,
"DH-768",
"2",
"2893527720709661239493896562339544088620375736490408468011883030469939904368"
"0860923364582982212457078989335831907131881773994018526277492109945959747917"
"8279025394653904396221302707492255957231214118178743427870878320796645901947"
"9487"
"1tH+dRFGpEYyVLe4ydZcYyGDpeAxnChz0yk+pNCtkEXwUsOORyguBtx8spUD"
"FAjEDS8PutUBTEu2q4USqu19dUbCLj9D2jY7y3871RnSccurMBsMm35ILcyQ"
"rpN0MQKc/"
},
#endif
#ifdef DH1024
@ -23,11 +22,9 @@ static const struct {
128,
"DH-1024",
"2",
"3477431594398766260792527967974222231775354473882066076071816639030459075912"
"0194047822362172211817327089848758298713770865641434468581617942085516098634"
"0457973820182883508387588163122354089264395604796675278966117567294812714812"
"7968205965648764507160662831267200108590414847865290564578963676831229604111"
"36319"
"Uypu+t9nfUnCj7xD+xokM+Cd6mASW4ofg1jpC2BpQasC5edtA1dJC+RjbOBZ"
"z+5mvq5VYT8Wfjmlpjm9tQxHOYB0+3Myl7gbCQ5SRljWT2oBLukLNvgFjiU4"
"wiWkmu41Ern/j6uxwKb740C+VIgDAdeUY4fA5hyfr3/+DWYb14/"
},
#endif
#ifdef DH1280
@ -35,12 +32,10 @@ static const struct {
160,
"DH-1280",
"2",
"2618298020488323341377089635550383393554460131909411928885489146533597039863"
"5379029297773089246854323581071445272213255646852180580463169755159411503866"
"4190218001872082125570169842848154404911652982668791288605239288293106162305"
"7236093554796242806887062958692596037823904832542385180840218330924392268465"
"0197244314233248991982159235832322194332167923655574170280697353556560854901"
"280047"
"520QV4Tsq4NwK9Mt5CGR9xk4slvaikgi/ax3OPky5GERKTsoqEXOlFyMzURP"
"P8jYzCVz1izKd2zTDxbFfLxrJry0ceaQ5YZa5N4teByCPVlQh4v6iQl+944+"
"/NDlKzvWpx7HG7k8cGKhva7aFF8bP/CvLpaQhrfXlOX+X9pcmML9QH63tUjq"
"B80l8Yx9KN0dC3iNnsTV3DnqnEvFQkoqql"
},
#endif
#ifdef DH1536
@ -48,13 +43,11 @@ static const struct {
192,
"DH-1536",
"3",
"2992593690703251306835100868059076484222548092264611010748654597096560864537"
"1704684310938824733433085888971827086341295918925237859522548192211945291282"
"1170570153374563548621496076860061698150233114892317627457427359445435608693"
"5625000902194809114890745455404045166957722404567939575618007347432055137282"
"3291711752537781447636541738638119983678441628437171377508654097130147131310"
"9209393805685590941710151477648542896503595482724205166251069428524927527085"
"2602467"
"1FTWXrPcY1w74oZ0ouIzSN8uZcRiOf6U11fx0ka6+7fqIAezPhd3Ab43QnDf"
"KFg+or/fFRGEWAxF8WIE2jx8iTOu010yNEQyH14CK0RAyy2zY4gRs2MpnU5r"
"/feWf60OkLtnPzN34+Xnlg5xf7Jl00wkHRCeJG17L3SklOidAPxWnE+Wm4BS"
"SOzdQBgiZOjlhrYS1+TIU3NP5H7BrtKFcf+ZwBULibf29L7LkDOgQbie1+43"
"lU+8SHAyBwAeGYMfZ"
},
#endif
#ifdef DH1792
@ -62,14 +55,11 @@ static const struct {
224,
"DH-1792",
"2",
"3210090394251532205679207425273650879078185529033544241951292722086520015900"
"0402371844205168176419829949232601235193754977706171541009393172204470047690"
"6659627844880912479392592056697278305733615369406596661203184035142652643118"
"1379603333858737848321053048184938839622944591194935387992479717305577175500"
"2554620614907177847128950276247571809502831255425929468853285490357704941968"
"3407102520889651917659577334897408316217748346860775479727332331727022096550"
"7718799868459391361770854814013613619048768630587629568449528005570971478547"
"34960319"
"IPo3wjvfS7vBYnFHwJHmesA51od9fnR8Aenezif4qLE2HX+YCv1tpvHA8yLH"
"yYbKe9QfSHHtOgVjK8AYEyPirpXxlmdykGuj+dX7EiWMRGYc+v1kKkqmCn0o"
"5tU416O/1HXTpQ2Hps0buchUD+HlCMrSgnIqRxK6Fjr0ZfiCS4XgAD6sLgi0"
"BxKFMxDsVzpGMNwF5Lj2R/cJiTi0cNDDY3gn4lK/PRUsJtRKU+9sxy0q5Yof"
"aG5VO8VcHkZJVwUKhDFHkZYWMHV808TGHXM2RQ9kRa2QvS2mXxMrDSCloQ/"
},
#endif
#ifdef DH2048
@ -77,15 +67,12 @@ static const struct {
256,
"DH-2048",
"2",
"4726642895635639316469736509812041897640060270607231273592407174543853221823"
"7979333351774907308168340693326687317443721193266215155735814510792148768576"
"4984911991227443513994894535335532038333186916782632419417062569961974604240"
"2901241901263467186228353234265630967717360250949841797609150915436003989316"
"5037637034737020327399910409885798185771003505320583967737293415979917317338"
"9858373857347474783642420203804168920566508414708692945275435973492502995396"
"8243060517332102902655554683247304860032703684578197028928889831788842751736"
"4945316709081173840186150794397479045034008257793436817683392375274635794835"
"245695887"
"5sR1VmdsQQzzjN0iridVVyveug6sAC3+/jTIHSgEoimPOREXQ05r2WJZJAF2"
"CRu8kuusiPw2ivRli+fdLr63v1uZG5nQa28uLwNxZEsu4gu6TrGjepXeXm4Z"
"CVOC1HMmi660fLZ2ruHLa4v2NWex2Zx91/y4ygPlZM+K//iy+Gft9Ma9Ayn0"
"eYwofZeUL9vJSfutPVp2ZrIEUQDBKMvMm0SRSLiUjDtzXqrH+b/wuwIFG1K4"
"var3ucsT45mDzD9qb3tBdksSPZbr6yrELV8h+qmjiBr15oHKEglS0XwSvCap"
"abUn5XPPVoaKv13+tOnG9mGgzQ8JeClVXN63Q+GGEF"
},
#endif
#ifdef DH2560
@ -93,17 +80,14 @@ static const struct {
320,
"DH-2560",
"3",
"4364638085059577685748948703943497396233464406019459611612544400721432981520"
"4010567649104824811014627875285783993051576616744140702150122992472133564455"
"7342265864606569000117714935185566842453630868849121480179691838399545644365"
"5711067577313173717585579907818806913366955847993133136872874688941488237617"
"8558298254958618375680644901754262226787427510387748147553499120184991222267"
"0102069951687572917937634467778042874315463238062009202992087620963771759666"
"4482665328580794026699200252242206134194410697184828373996126449788399252071"
"0987084027819404215874884544513172913711709852902888677006373648742061314404"
"5836803985635654192482395882603511950547826439092832800532152534003936926017"
"6124466061356551464456206233957889787267447285030586700468858762515271223502"
"75750995227"
"G7UVKk+N6LfpGkdBP6XLB4QJ3wzee5YH/3o6tBDMwr4FS8YjCmeP6l4gu0hX"
"dzY2Rive4TYOu4Akm4naZuv32d71/2lQeNcO23BNYOEPxtn9BU8uYfaHP9Mo"
"M+m76oUCiI5uqpag5RH3BO34FyE4BiKkzjEXq9xxc8ERacG8Mo8DNiXu79p9"
"Q/0wsRz+W/lIN4gYw3w4iLMooAGnDrhcj5cZb0HysHWYfqmFo+jTBP6Egi0g"
"cmVO2qWQh2cZIQMfppaf1Ffq0XGIJpgDFyOHPl3NVxDabVK1tkVct+hathxJ"
"UTdqZmR2VFwMASXjfgj4VFdvFCUxV8Xr8JcwXkwlMjOJbAl0LoCa4M7hpYvz"
"G/0XviGCpv7qQaONKtsiQ6mHhMcyo9hBCRZXtNPkfPMZkPeV05akvaDs6Ek7"
"DZ62oKR"
},
#endif
#ifdef DH3072
@ -111,19 +95,15 @@ static const struct {
384,
"DH-3072",
"2",
"1142416747335183639807830604262436227795642944052113706188970261176634876069"
"2206243140413411077394583180726863277012016602279290144126785129569474909173"
"5847898223419867427192303319460727303195559844849117167970588759054009995043"
"0587724584911968750902323279027363746682105257685923245298206183100977078603"
"1785669030271542286603956118755585683996118896215213488875253101894663403069"
"6777459483058938495054342017637452328957807119724320113448575216910178963168"
"6140320644942133224365885545343578400651720289418164056243357539082138421096"
"0117518650374602256601091379644034244332285065935413233557998331562749140202"
"9658442193362989700115138825649355387042894469683222814519074873620465114612"
"2132979989735099337056069750580968643878203623537213701573130477907243026098"
"6460269894522159103008260495503005267165927542949439526272736586626709581721"
"0321895327263896436255906801057848442461527026701693042037830722750891947548"
"89511973916207"
"1zsV6XgY57R/hu2RR4H/BjwRqmQL9h+Dc5rgoWOcqiTS8qpVTWafi1KFV77V"
"rUcjcer1EDgCV0tpzlemtyrC2pHpw7hr3EEl2evfWOvg05FRI6mKc2UPNv2c"
"2Bjww4LD/tdsLleX7AHHXCXFSSyd6C3qWq7BqABZriSpQeaEtXbWfeC6ytFe"
"2i3VeQsLa40XQ21UxwhPAjamjSOfYzkW7xi0fwI1e+4OQiFcWOfOuvswoaEf"
"MIICyAmVp67vjGo66dk81dMemyplipgXAWPdl7ppnDd6cEjyN4N90D7kQiNg"
"lVmJlKLecldOUtdIqMnbJCbiN/t/3/AEFaokGO9om5ckc6M9gG5PG0T7Oh1N"
"dSx/PstGdxwvs9DOwjyo5wl5C9QSLtUYJl2+GZYMj6WfsgCrb6jjRJJJQe2C"
"y7wUcBILbRsP3lYT8s14zm4xFBrfMUoLN287j3wQ1TNUXjYSCi4ZLKT1XDai"
"93345OiutLOqGGikFg6ypnymJK3yeHuul"
},
#endif
#ifdef DH4096
@ -131,23 +111,18 @@ static const struct {
512,
"DH-4096",
"3",
"1214855636816562637502584060163403830270705000634713483015101384881871978446"
"8012247985361554068958233050354675916325310675478909486951171720769542207270"
"7568804875102242119871203284889005635784597424656074834791863005085393369779"
"2254955890439720297560693579400297062396904306270145886830719309296352765295"
"7121830407731464190228751653827780070401099576097395898755908857011261979060"
"6362013395489321661267883850754077713843779770560245371955901763398648664952"
"3611975865005712371194067612263330335590526176087004421363598470302731349138"
"7732059014477046821815179040647356365184624522427916765417252923789255682968"
"5801015185232631677751193503753101741391050692192245066693320227848902452126"
"3798482237150056835746454842662048692127173834433089016107854491097456725016"
"3277096631997382384421648431471327891537255132571679155551620949708535844479"
"9312548860769600816980737473671129700747381225627224548940589847029717873802"
"9484459690836250560495461579533254473316340608217876781986188705928270735695"
"7528308255279638383554197625162460286802809880204019145518254873499903069763"
"0409310938445143881325121105159739212749146489879740678917545306796007200859"
"0614886532333015881171367104445044718144312416815712216611576221546455968770"
"801413440778423979"
"Id8ukxZdao3hS0NGTKAXdt3c8PpiyigIyBY8lwOHjM2cqkaZgwvr1pA6OowS"
"32kJkeOqKB8gNTZZZVqOFkPXgvC4WveUgA5a7rhTj28pDidNROmMO70CCcSw"
"aHI3GLFuEMz3JJyvQKGaGwpV3C9gS70dFWTxEfNRzdYEdvIic8/SXI79VgNP"
"LGR68nzd4qxCgaLpVBnWsanRp7mfEj52S/7Kxjs14lrbAOMjCuHgN4F6THWh"
"PNhG0VXfFFIwAMW2unrfpdo+gQHNclqCf2N1FALpABzvUesgs3wIP+QTMqms"
"os/AkuulG7MusbeFl3SoCtaoW12CF038ZbqW+e+DKI1zObhtsLanvaiZm/N4"
"BsJirW7avcWNQYm1oYjZ2bR/jYqfoJ0CLXLO/vqHb8J9a5VE9nz7cqMD3/MH"
"k/g7BapsOtKuol6ipbUvxQPtf4KCwqQQ40JeqgS6amivI/aLu05S7bAxKOwE"
"Yu8YxjN6lXm3co5Wy+BmNSuRlzKhxICyHEqMfKwUtm48XHzHuPaGQzHgkn6H"
"3A+FQjQGLHewADYlbfdTF3sHYyc5k9h/9cYVkbmv7bQze53CJGr3T1hZYbN6"
"+fuz0SPnfjiKu+bWD+8RYtZpLs2+f32huMz3OqoryGfULxC2aEjL2rdBn+ZR"
"PT0+ZAUyLSAVHbsul++cawh"
},
#endif
{
@ -180,9 +155,8 @@ int dh_test(void)
#if 0
printf("dh_test():testing size %d-bits\n", sets[x].size * 8);
#endif
/* see if g^((p-1)/2) == 1 mod p. */
if (mp_read_radix(&g, sets[x].base, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[x].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&g, sets[x].base, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[x].prime, 64) != MP_OKAY) { goto error; }
/* ensure p is prime */
if ((res = is_prime(&p, &primality)) != CRYPT_OK) { goto done; }
@ -276,18 +250,21 @@ int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key)
if (mp_init_multi(&g, &p, &key->x, &key->y, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
if (mp_read_radix(&g, sets[x].base, 10) != MP_OKAY) { goto error2; }
if (mp_read_radix(&p, sets[x].prime, 10) != MP_OKAY) { goto error2; }
if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY) { goto error; }
/* load the x value */
mp_read_raw(&key->x, buf, keysize+1);
if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY) { goto error2; }
if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY) { goto error; }
key->type = PK_PRIVATE;
if (mp_shrink(&key->x) != MP_OKAY) { goto error; }
if (mp_shrink(&key->y) != MP_OKAY) { goto error; }
/* free up ram */
res = CRYPT_OK;
goto done2;
error2:
error:
res = CRYPT_MEM;
mp_clear_multi(&key->x, &key->y, NULL);
done2:
@ -304,10 +281,10 @@ void dh_free(dh_key *key)
#define OUTPUT_BIGNUM(num, buf2, y, z) \
{ \
z = mp_raw_size(num); \
z = mp_unsigned_bin_size(num); \
STORE32L(z, buf2+y); \
y += 4; \
mp_toraw(num, buf2+y); \
mp_to_unsigned_bin(num, buf2+y); \
y += z; \
}
@ -329,11 +306,15 @@ void dh_free(dh_key *key)
} \
\
/* load it */ \
if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\
if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\
errno = CRYPT_MEM; \
goto error; \
} \
y += x; \
if (mp_shrink(num) != MP_OKAY) { \
errno = CRYPT_MEM; \
goto error; \
} \
}
@ -374,14 +355,16 @@ int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key)
}
/* store header */
packet_store_header(buf2, PACKET_SECT_DH, PACKET_SUB_KEY, y);
packet_store_header(buf2, PACKET_SECT_DH, PACKET_SUB_KEY);
/* output it */
*outlen = y;
memcpy(out, buf2, y);
/* clear mem */
#ifdef CLEAN_STACK
zeromem(buf2, sizeof(buf2));
#endif
return CRYPT_OK;
}
@ -436,6 +419,12 @@ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
if (key->type == PK_PRIVATE) {
INPUT_BIGNUM(&key->x, in, x, y);
}
/* eliminate private key if public */
if (key->type == PK_PUBLIC) {
mp_clear(&key->x);
}
return CRYPT_OK;
error:
mp_clear_multi(&key->y, &key->x, NULL);
@ -469,7 +458,7 @@ int dh_shared_secret(dh_key *private_key, dh_key *public_key,
return CRYPT_MEM;
}
if (mp_read_radix(&p, sets[private_key->idx].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[private_key->idx].prime, 64) != MP_OKAY) { goto error; }
if (mp_exptmod(&public_key->y, &private_key->x, &p, &tmp) != MP_OKAY) { goto error; }
/* enough space for output? */

View File

@ -80,7 +80,7 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
}
/* store header */
packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY, y);
packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY);
#ifdef CLEAN_STACK
/* clean up */
@ -93,8 +93,9 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
return CRYPT_OK;
}
int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, dh_key *key)
int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
dh_key *key)
{
unsigned char shared_secret[1536], skey[MAXBLOCKSIZE];
unsigned long x, y, z, res, hashsize, keysize;
@ -111,6 +112,13 @@ int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
return CRYPT_PK_NOT_PRIVATE;
}
/* check if initial header should fit */
if (inlen < PACKET_SIZE+1+4+4) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= PACKET_SIZE+1+4+4;
}
/* is header correct? */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
return errno;
@ -128,6 +136,14 @@ int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
/* get public key */
LOAD32L(x, in+y);
/* now check if the imported key will fit */
if (inlen < x) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= x;
}
y += 4;
if ((errno = dh_import(in+y, x, &pubkey)) != CRYPT_OK) {
return errno;
@ -149,6 +165,14 @@ int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
/* load in the encrypted key */
LOAD32L(keysize, in+y);
/* will the outkey fit as part of the input */
if (inlen < keysize) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= keysize;
}
if (keysize > *keylen) {
res = CRYPT_BUFFER_OVERFLOW;
goto done;
@ -223,8 +247,8 @@ int dh_sign_hash(const unsigned char *in, unsigned long inlen,
if (mp_read_raw(&k, buf, sets[key->idx].size) != MP_OKAY) { goto error; }
/* load g, p and p1 */
if (mp_read_radix(&g, sets[key->idx].base, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY) { goto error; }
if (mp_sub_d(&p, 1, &p1) != MP_OKAY) { goto error; }
if (mp_div_2(&p1, &p1) != MP_OKAY) { goto error; } /* p1 = (p-1)/2 */
@ -256,7 +280,7 @@ int dh_sign_hash(const unsigned char *in, unsigned long inlen,
}
/* store header */
packet_store_header(buf, PACKET_SECT_DH, PACKET_SUB_SIGNED, y);
packet_store_header(buf, PACKET_SECT_DH, PACKET_SUB_SIGNED);
/* store it */
memcpy(out, buf, y);
@ -275,9 +299,9 @@ done:
return res;
}
int dh_verify_hash(const unsigned char *sig, const unsigned char *hash,
unsigned long inlen, int *stat,
dh_key *key)
int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, dh_key *key)
{
mp_int a, b, p, g, m, tmp;
unsigned char md[MAXBLOCKSIZE];
@ -292,6 +316,13 @@ int dh_verify_hash(const unsigned char *sig, const unsigned char *hash,
/* default to invalid */
*stat = 0;
/* check initial input length */
if (siglen < PACKET_SIZE+4+4) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= PACKET_SIZE + 4 + 4;
}
/* header ok? */
if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return errno;
@ -302,7 +333,7 @@ int dh_verify_hash(const unsigned char *sig, const unsigned char *hash,
/* hash the message */
md[0] = 0;
memcpy(md+1, hash, MIN(sizeof(md) - 1, inlen));
memcpy(md+1, hash, MIN(sizeof(md) - 1, hashlen));
/* init all bignums */
if (mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL) != MP_OKAY) {
@ -311,21 +342,32 @@ int dh_verify_hash(const unsigned char *sig, const unsigned char *hash,
/* load a and b */
LOAD32L(x, sig+y);
if (siglen < x) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= x;
}
y += 4;
if (mp_read_raw(&a, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; }
y += x;
LOAD32L(x, sig+y);
if (siglen < x) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= x;
}
y += 4;
if (mp_read_raw(&b, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; }
y += x;
/* load p and g */
if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&g, sets[key->idx].base, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY) { goto error; }
/* load m */
if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1, inlen)) != MP_OKAY) { goto error; }
if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1, hashlen)) != MP_OKAY) { goto error; }
/* find g^m mod p */
if (mp_exptmod(&g, &m, &p, &m) != MP_OKAY) { goto error; } /* m = g^m mod p */

398
dsa.c Normal file
View File

@ -0,0 +1,398 @@
/* Implementation of the Digital Signature Algorithm (DSA) by Tom St Denis */
#ifdef MDSA
#include <mycrypt.h>
static const struct {
int size, osize;
char *order,
*prime,
*base;
} sets[] = {
#ifdef DSA1024
{
1024, 160,
"PE6GbKzFwpeAAMtC3PUsqsRQMWl",
"PyhJv87GTec3fBvC8BQT4yQ8gSYB8rk6DfLRfeirnZsQaQBVwh8PZ7V1hKfD"
"SGGUgr1cAb3YrnZw97HvyaKmypY2dM19OxeNWNI4f6IyYwj/mcAiJpkjxMmZ"
"mYVrTbGxBG8OaKBD9vFd9/Jif8djJ18GnaRsdRoCBDec+W++x6D",
"3uYLnHhrVRR6hATv30lj/XX5AecEE2tJVgtWcHkbwKuR3WEqqvP8xBUG70Ve"
"p6kUchz/E/kZaGIJ0mrqme6bNDIxoNqtshyDfska/Zfm/QHuDZWljVGbPx68"
"eSBw1vzkRKFCmR8QgpT+R887JufEgQRRIQOuLK8c1ND61efJH2t"
},
#endif
#ifdef DSA2048
{
2048, 256,
"TZLgPgD7D46uoATLyNSgKsgh6LglcVDwlPFvT6dcOdN",
"EUlAFvO8lXjhXn/6BobNq4bo0st12+zwgpshNJgoUap/LFCQcGeVGt/s/ocD"
"M+4v+bU3dNKjFJEYzb+sxmy5dbzQsa15+Ud4v1UJ/7D4p0IyA+h9aeU9i/C9"
"tJQC824mQhmL5cxx7SbQPMD/2+P04hLyeDOir1L1vmvE1tWZg43Jbza2LTQJ"
"52wi/Sguai3vFZVMObEPBfbXzg9b8pH1i75Q1os9w0LtfJ4pYQJD3Xn66jYF"
"mpLVqK4yuMXOOq07bkM5Nx+jQvFpGuRiD5e4a2FB1NjXbCGMtRxu6eurPAIY"
"F5dw3QWXkZm74SFmLTi0GW+3pipDWiBSUu9pUpp6rr",
"79PG50FKgZgffOnFiUuuZLhWicqFZ6EwvWXQi7uBmvMQUoXNEBschAhRtLQE"
"ev5iHrR2g41rEEundwwFTbRdyq2txBS2bClkFjGlojPwayWvXLAaDltfkhws"
"TjS/gNKch4qD1nPu+Kd1RmjWp1B1JzBXnlcj/z5qMaF8oL4bk9qGGEmaeOLs"
"90vW0Z/7QWBC8h+65SohFBmydUWwXhs4rAa7NwHbPltnXdF6kZHpQOtT5h+4"
"hYA83eYzdeOl5rYrFDiyJ+nfOptgLiLIHB9L0wkOhFrb52+S7qKpgYe1+oof"
"K1/Rd4D8fL5qvGyXWz1dB8W2iqAXeXKlkWZrvHQdMM"
},
#endif
#ifdef DSA4096
{
4096, 512,
"4GO4hUY+2MqiwNBYFx/JqRejRKXXJfcaY7mIBYksn2Dwn6JQZp9Qpg3bbnOJ"
"kt5ZqH2dtEjbV9B/AXF51jOkW/",
"Jddrq1iN+f03IKVqcDSOz7IquBVxzb34Cwzmc7rHpIOW3DqW7IjMz47ETtWu"
"KvG3JxFdYaiv69lAE+X38DEqQSTE8Ba9jfNYs9PYeH4RfsT5op/u3r41anRW"
"jJTHMhnvwwQ0eQrZ+9d7LQePnQSUs3eXb8ZdNsh8/h30b3gIMk+08bZoJejF"
"6Y2vMtMQUHmmoM/+IlrMz7TZ4tu0jkYWBp1y74WLGemXkYvU6pqH8dTQX1MM"
"oG93eBKQ87jHbtBJ+L6EbcqO/jVa6lwUivEbBs9UtKf4lC0pe3SZqfFhrJde"
"2b5LfbPBLk2pNdC5MJCsIVz7TUL28SWYwx7Nx7ybxtKd76L8kgbLfoOYiJRx"
"WIFGRE40Q9/0zuqzz6D1WHKQE4wg5oy6WQeO3Q5BN1UC6O4EUSkD7mC3KmWA"
"MgxNDZYMA+BSCTirVL2eS90WCA4LkTsHhoLgafwZT5xanUKGY/cZix29sy21"
"J1Ut4cbPFjxg76OVu9obONitMLg+63dz3Ho8LMhXaKN43yl5Kc4PxeUCQWVU"
"gHXg8RSldQMOvhwohHFibiMUrRkkCs2//Ts6hVdS3cEFgfYhpnzeEiGBCuat"
"ZZYpaWKZlmrlcUYH7Rg9SyHH1h4DLrki5ySIjGxozT6JhIrMme8uQcN9YOiq"
"GwRhjR3AM1QiOUfolENTYCn",
"3VIJLic34uyamh2TbNHEjECeH289m938S2wvHYe/3xPNiCjVhBxl6RAgom+Q"
"3X7+r8EII4QQKXXdqR3Ad/nXzJkgMUJVvt5d5lIwwKM7+ffbLmhJWldO0Jkc"
"7oZQr7t81khBUG4wgPVZO8OwjB66v9npPCcBLNLO6DAWE82CM8YfPJzQt0tr"
"JSHwcgixvkFft25SdI0V9zg2H6sj2Q/yAYUEAPzyDfQVvLzqEN2tmIhturnR"
"wUW4WLy8PSls/tt5eWjdI++ofdGHNJmKaZjHgym52GhNQmWZYWzK/hcllWtC"
"U8vCw7GY3nE4uF74YuTYC6LGx7wXS5ivj531KTPe4EarZ4j+aVw9ZJhfy/h+"
"K0esj9ALQP9jSz3OMDKeYaJKjj/scC5NrPdSjeJf7EvlVf41ufZHNGrFVmVW"
"kqaEuNZr+SmC6/2buPEmL4UO94H1z4QItK+rHqNWEQP6ptST0lcFwHO4uESR"
"qp8scA2/Fh+G0TfJ/rg8wImqbWsgrUwGnmDmKtFLRiX4aMPIsyFIsJvPQECT"
"EIR6yd6QIRVGZbCRiVsCqMrHsn0KZWSeKdtW9TRt/yNu+VKcgRZFfU991Nab"
"OBxkAS1kw9kyj/HZYxPG4NrqL0j5bnb1VjqQZKEEQMSBAyMMfDuMyWhrmsxV"
"ffmF/sYGxFHCbacGeu06C3U"
},
#endif
{
0, 0,
NULL,
NULL,
NULL
}
};
int dsa_test(void)
{
mp_int q, p, g, t;
int errno, i, res, primality;
/* init memory */
if (mp_init_multi(&q, &p, &g, &t, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
res = CRYPT_MEM;
for (i = 0; i < sets[i].size; i++) {
#if 0
printf("Testing size: %d\n", sets[i].size);
#endif
/* read in order, prime, generator */
if (mp_read_radix(&q, sets[i].order, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[i].prime, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&g, sets[i].base, 64) != MP_OKAY) { goto error; }
/* now see if the order and modulus are prime */
if ((errno = is_prime(&q, &primality)) != CRYPT_OK) {
res = errno;
goto error;
}
if (primality == 0) {
res = CRYPT_FAIL_TESTVECTOR;
goto error;
}
if ((errno = is_prime(&p, &primality)) != CRYPT_OK) {
res = errno;
goto error;
}
if (primality == 0) {
res = CRYPT_FAIL_TESTVECTOR;
goto error;
}
/* now see what g^q mod p is (should be 1) */
if (mp_exptmod(&g, &q, &p, &t) != MP_OKAY) { goto error; }
if (mp_cmp_d(&t, 1)) {
res = CRYPT_FAIL_TESTVECTOR;
goto error;
}
}
res = CRYPT_OK;
error:
mp_clear_multi(&t, &g, &p, &q, NULL);
return res;
}
int dsa_make_key(prng_state *prng, int wprng, int keysize, dsa_key *key)
{
mp_int g, p, q;
unsigned char buf[64];
int errno, idx, x;
_ARGCHK(prng != NULL);
_ARGCHK(key != NULL);
/* good prng? */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
/* find key size */
for (x = 0; (keysize > sets[x].size) && (sets[x].size); x++);
if (sets[x].size == 0) {
return CRYPT_INVALID_KEYSIZE;
}
key->idx = x;
keysize = sets[x].osize;
/* read prng */
if (prng_descriptor[wprng].read(buf, keysize, prng) != (unsigned long)keysize) {
return CRYPT_ERROR_READPRNG;
}
/* init parameters */
if (mp_init_multi(&g, &p, &q, &key->x, &key->y, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
if (mp_read_radix(&q, sets[x].order, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&g, sets[x].base, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[x].prime, 64) != MP_OKAY) { goto error; }
/* load exponent */
if (mp_read_unsigned_bin(&key->x, buf, keysize) != MP_OKAY) { goto error; }
if (mp_mod(&key->x, &q, &key->x) != MP_OKAY) { goto error; }
/* calc public key */
if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY) { goto error; }
key->type = PK_PRIVATE;
/* shrink values */
if (mp_shrink(&key->x) != MP_OKAY) { goto error; }
if (mp_shrink(&key->y) != MP_OKAY) { goto error; }
/* free temps */
mp_clear_multi(&g, &q, &p, NULL);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
error:
mp_clear_multi(&g, &q, &p, &key->x, &key->y, NULL);
return CRYPT_MEM;
}
void dsa_free(dsa_key *key)
{
_ARGCHK(key != NULL);
mp_clear_multi(&key->x, &key->y, NULL);
}
static int is_valid_idx(int n)
{
int x;
for (x = 0; sets[x].size; x++);
if ((n < 0) || (n >= x)) {
return 0;
}
return 1;
}
int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key)
{
unsigned char buf[4096];
unsigned long x, y;
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
if (is_valid_idx(key->idx) == 0) {
return CRYPT_PK_INVALID_TYPE;
}
if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
y = PACKET_SIZE;
buf[y++] = type;
buf[y++] = sets[key->idx].osize/8;
x = mp_unsigned_bin_size(&key->y);
STORE32L(x, &buf[y]);
y += 4;
mp_to_unsigned_bin(&key->y, &buf[y]);
y += x;
if (type == PK_PRIVATE) {
x = mp_unsigned_bin_size(&key->x);
STORE32L(x, &buf[y]);
y += 4;
mp_to_unsigned_bin(&key->x, &buf[y]);
y += x;
}
/* check for overflow */
if (*outlen < y) {
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_BUFFER_OVERFLOW;
}
/* store header */
packet_store_header(buf, PACKET_SECT_DSA, PACKET_SUB_KEY);
/* output it */
*outlen = y;
memcpy(out, buf, y);
/* clear mem */
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
}
#define INPUT_BIGNUM(num, in, x, y) \
{ \
/* load value */ \
if (y + 4 > inlen) { \
errno = CRYPT_INVALID_PACKET; \
goto error; \
} \
LOAD32L(x, in+y); \
y += 4; \
\
/* sanity check... */ \
if (x+y > inlen) { \
errno = CRYPT_INVALID_PACKET; \
goto error; \
} \
\
/* load it */ \
if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\
errno = CRYPT_MEM; \
goto error; \
} \
y += x; \
if (mp_shrink(num) != MP_OKAY) { \
errno = CRYPT_MEM; \
goto error; \
} \
}
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
{
unsigned long x, y, s;
int errno;
_ARGCHK(in != NULL);
_ARGCHK(key != NULL);
/* check type byte */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DSA, PACKET_SUB_KEY)) != CRYPT_OK) {
return errno;
}
if (2+PACKET_SIZE > inlen) {
return CRYPT_INVALID_PACKET;
}
/* init */
if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
y = PACKET_SIZE;
key->type = in[y++];
s = (long)in[y++] * 8;
for (x = 0; (s > (unsigned long)sets[x].osize) && (sets[x].osize); x++);
if (sets[x].osize == 0) {
errno = CRYPT_INVALID_KEYSIZE;
goto error;
}
key->idx = x;
/* type check both values */
if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) {
errno = CRYPT_PK_TYPE_MISMATCH;
goto error;
}
/* is the key idx valid? */
if (!is_valid_idx(key->idx)) {
errno = CRYPT_PK_TYPE_MISMATCH;
goto error;
}
/* load public value g^x mod p*/
INPUT_BIGNUM(&key->y, in, x, y);
if (key->type == PK_PRIVATE) {
INPUT_BIGNUM(&key->x, in, x, y);
}
/* eliminate private key if public */
if (key->type == PK_PUBLIC) {
mp_clear(&key->x);
}
return CRYPT_OK;
error:
mp_clear_multi(&key->y, &key->x, NULL);
return errno;
}
int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, dsa_key *key)
{
mp_int g, q, p, k, tmp;
unsigned char buf[4096];
int x, y, errno;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(prng != NULL);
_ARGCHK(key != NULL);
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
if (is_valid_idx(key->idx) == 0) {
return CRYPT_PK_INVALID_TYPE;
}
return 0;
}
#endif /* MDSA */

221
ecc.c
View File

@ -18,15 +18,15 @@ static const struct {
20,
"ECC-160",
/* prime */
"1461501637330902918203684832716283019655932542983",
"G00000000000000000000000007",
/* B */
"1C9E7C2E5891CBE097BD46",
"1oUV2vOaSlWbxr6",
/* order */
"1461501637330902918203686297565868358251373258181",
"G0000000000004sCQUtDxaqDUN5",
/* Gx */
"2DCF462904B478D868A7FF3F2BF1FCD9",
"jpqOf1BHus6Yd/pyhyVpP",
/* Gy */
"DFFAF2EE3848FA75FB967CEC7B9A399E085ACED8",
"D/wykuuIFfr+vPyx7kQEPu8MixO",
},
#endif
#ifdef ECC192
@ -34,19 +34,19 @@ static const struct {
24,
"ECC-192",
/* prime */
"6277101735386680763835789423207666416083908700390324961279",
"/////////////////////l//////////",
/* B */
"64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
"P2456UMSWESFf+chSYGmIVwutkp1Hhcn",
/* order */
"6277101735386680763835789423176059013767194773182842284081",
"////////////////cTxuDXHhoR6qqYWn",
/* Gx */
"188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
"68se3h0maFPylo3hGw680FJ/2ls2/n0I",
/* Gy */
"07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
"1nahbV/8sdXZ417jQoJDrNFvTw4UUKWH"
},
#endif
#ifdef ECC224
@ -55,19 +55,19 @@ static const struct {
"ECC-224",
/* prime */
"26959946667150639794667015087019630673637144422540572481103610249951",
"400000000000000000000000000000000000BV",
/* B */
"2051BA041508CED34B3",
"21HkWGL2CxJIp",
/* order */
"26959946667150639794667015087019637467111563745054605861463538557247",
"4000000000000000000Kxnixk9t8MLzMiV264/",
/* Gx */
"2DCF462904B478D868A7FF3F2BF1FCD9",
"jpqOf1BHus6Yd/pyhyVpP",
/* Gy */
"CF337F320BC44A15C3EDB8C4258BB958E57A0CAFA73EB46E9C4BA9AE",
"3FCtyo2yHA5SFjkCGbYxbOvNeChwS+j6wSIwck",
},
#endif
#ifdef ECC256
@ -75,19 +75,19 @@ static const struct {
32,
"ECC-256",
/* Prime */
"115792089210356248762697446949407573530086143415290314195533631308867097853951",
"F////y000010000000000000000////////////////",
/* B */
"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
"5h6DTYgEfFdi+kzLNQOXhnb7GQmp5EmzZlEF3udqc1B",
/* Order */
"115792089210356248762697446949407573529996955224135760342422259061068512044369",
"F////y00000//////////+yvlgjfnUUXFEvoiByOoLH",
/* Gx */
"6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
"6iNqVBXB497+BpcvMEaGF9t0ts1BUipeFIXEKNOcCAM",
/* Gy */
"4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
"4/ZGkB+6d+RZkVhIdmFdXOhpZDNQp5UpiksG6Wtlr7r"
},
#endif
#ifdef ECC384
@ -95,22 +95,23 @@ static const struct {
48,
"ECC-384",
/* prime */
"394020061963944792122790401001436138050797392704654466679482934042457217714968"
"70329047266088258938001861606973112319",
"//////////////////////////////////////////x/////00000000003/"
"////",
/* B */
"b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed1"
"9d2a85c8edd3ec2aef",
"ip4lf+8+v+IOZWLhu/Wj6HWTd6x+WK4I0nG8Zr0JXrh6LZcDYYxHdIg5oEtJ"
"x2hl",
/* Order */
"394020061963944792122790401001436138050797392704654466679469052796276593991132"
"63569398956308152294913554433653942643",
"////////////////////////////////nsDDWVGtBTzO6WsoIB2dUkpi6MhC"
"nIbp",
/* Gx and Gy */
"aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf5529"
"6c3a545e3872760ab7",
"3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e81"
"9d7a431d7c90ea0e5f"
"geVA8hwB1JUEiSSUyo2jT6uTEsABfvkOMVT1u89KAZXL0l9TlrKfR3fKNZXo"
"TWgt",
"DXVUIfOcB6zTdfY/afBSAVZq7RqecXHywTen4xNmkC0AOB7E7Nw1dNf37NoG"
"wWvV"
},
#endif
#ifdef ECC521
@ -118,22 +119,23 @@ static const struct {
65,
"ECC-521",
/* prime */
"686479766013060971498190079908139321726943530014330540939446345918554318339765"
"6052122559640661454554977296311391480858037121987999716643812574028291115057151",
"V///////////////////////////////////////////////////////////"
"///////////////////////////",
/* B */
"051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7"
"e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
"56LFhbXZXoQ7vAQ8Q2sXK3kejfoMvcp5VEuj8cHZl49uLOPEL7iVfDx5bB0l"
"JknlmSrSz+8FImqyUz57zHhK3y0",
/* Order */
"686479766013060971498190079908139321726943530014330540939446345918554318339765"
"5394245057746333217197532963996371363321113864768612440380340372808892707005449",
"V//////////////////////////////////////////+b66XuE/BvPhVym1I"
"FS9fT0xjScuYPn7hhjljnwHE6G9",
/* Gx and Gy */
"c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe7"
"5928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
"11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef"
"42640c550b9013fad0761353c7086a272c24088be94769fd16650",
"CQ5ZWQt10JfpPu+osOZbRH2d6I1EGK/jI7uAAzWQqqzkg5BNdVlvrae/Xt19"
"wB/gDupIBF1XMf2c/b+VZ72vRrc",
"HWvAMfucZl015oANxGiVHlPcFL4ILURH6WNhxqN9pvcB9VkSfbUz2P0nL2v0"
"J+j1s4rF726edB2G8Y+b7QVqMPG",
},
#endif
{
@ -329,59 +331,103 @@ done:
/* perform R = kG where k == integer and G == ecc_point */
static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus, int idx)
{
ecc_point *tG;
int i, j, z, first, res;
ecc_point *tG, *M[14];
int i, j, m, z, first, res;
mp_digit d;
unsigned char bits[768];
/* init M tab */
for (i = 0; i < 14; i++) {
M[i] = new_point();
if (M[i] == NULL) {
for (j = 0; j < i; j++) {
del_point(M[j]);
}
return CRYPT_MEM;
}
}
/* get bits of k */
first = m = 0;
for (z = i = 0; z < (int)USED(k); z++) {
d = DIGIT(k, z);
for (j = 0; j < (int)MP_DIGIT_BIT; j++) {
first |= (d&1)<<(m++);
if (m == 4) {
bits[i++] = first;
first = m = 0;
}
d >>= 1;
}
}
#define DO1 bits[i++] = d&1; d >>= 1;
#define DO2 DO1 DO1
#define DO4 DO2 DO2
DO4; DO4; DO4; DO4
#undef DO4
#undef DO2
#undef DO1
/* residue of multiplicand [if any] */
if (m) {
bits[i++] = first;
}
/* make a copy of G incase R==G */
tG = new_point();
if (tG == NULL) {
return CRYPT_MEM;
if (tG == NULL) { goto error; }
/* skip leading digits which are zero */
--i; while (i && bits[i] == 0) { --i; }
if (i == 0) {
res = CRYPT_INVALID_ARG;
goto done;
}
/* now calc the M tab, note that there are only 14 spots, the normal M[0] is a no-op, and M[1] is the input
point (saves ram)
*/
/* M[0] now is 2*G */
if (dbl_point(G, M[0], modulus) != CRYPT_OK) { goto error; }
for (j = 1; j < 14; j++) {
if (add_point(M[j-1], G, M[j], modulus) != CRYPT_OK) { goto error; }
}
/* tG = G */
if (mp_copy(&G->x, &tG->x) != MP_OKAY) { goto error; }
if (mp_copy(&G->y, &tG->y) != MP_OKAY) { goto error; }
/* set result to G, R = G */
/* set result M[bits[i]] */
if (bits[i] == 1) {
if (mp_copy(&G->x, &R->x) != MP_OKAY) { goto error; }
if (mp_copy(&G->y, &R->y) != MP_OKAY) { goto error; }
first = 0;
} else if (bits[i]>=2) {
if (mp_copy(&M[bits[i]-2]->x, &R->x) != MP_OKAY) { goto error; }
if (mp_copy(&M[bits[i]-2]->y, &R->y) != MP_OKAY) { goto error; }
}
/* now do dbl+add through all the bits */
for (j = i-1; j >= 0; j--) {
if (first) {
while (--i >= 0) {
/* double */
for (j = 0; j < 4; j++) {
if (dbl_point(R, R, modulus) != CRYPT_OK) { goto error; }
}
if (bits[j] == 1) {
if (first) {
/* now based on the value of bits[i] we do ops */
if (bits[i] == 0) {
/* nop */
} else if (bits[i] == 1) {
/* add base point */
if (add_point(R, tG, R, modulus) != CRYPT_OK) { goto error; }
}
first = 1;
} else {
/* other case */
if (add_point(R, M[bits[i]-2], R, modulus) != CRYPT_OK) { goto error; }
}
}
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
del_point(tG);
for (i = 0; i < 14; i++) {
del_point(M[i]);
}
#ifdef CLEAN_STACK
zeromem(bits, sizeof(bits));
#endif
@ -412,8 +458,11 @@ int ecc_test(void)
}
for (i = 0; sets[i].size; i++) {
if (mp_read_radix(&modulus, (unsigned char *)sets[i].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&order, (unsigned char *)sets[i].order, 10) != MP_OKAY) { goto error; }
#if 0
printf("Testing %d\n", sets[i].size);
#endif
if (mp_read_radix(&modulus, (unsigned char *)sets[i].prime, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&order, (unsigned char *)sets[i].order, 64) != MP_OKAY) { goto error; }
/* is prime actually prime? */
if (is_prime(&modulus, &primality) != CRYPT_OK) { goto error; }
@ -429,8 +478,8 @@ int ecc_test(void)
goto done1;
}
if (mp_read_radix(&G->x, (unsigned char *)sets[i].Gx, 16) != MP_OKAY) { goto error; }
if (mp_read_radix(&G->y, (unsigned char *)sets[i].Gy, 16) != MP_OKAY) { goto error; }
if (mp_read_radix(&G->x, (unsigned char *)sets[i].Gx, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&G->y, (unsigned char *)sets[i].Gy, 64) != MP_OKAY) { goto error; }
/* then we should have G == (order + 1)G */
if (mp_add_d(&order, 1, &order) != MP_OKAY) { goto error; }
@ -509,15 +558,20 @@ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
}
/* read in the specs for this key */
if (mp_read_radix(&prime, (unsigned char *)sets[x].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&base->x, (unsigned char *)sets[x].Gx, 16) != MP_OKAY) { goto error; }
if (mp_read_radix(&base->y, (unsigned char *)sets[x].Gy, 16) != MP_OKAY) { goto error; }
if (mp_read_radix(&prime, (unsigned char *)sets[key->idx].prime, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&base->x, (unsigned char *)sets[key->idx].Gx, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&base->y, (unsigned char *)sets[key->idx].Gy, 64) != MP_OKAY) { goto error; }
if (mp_read_raw(&key->k, (unsigned char *)buf, keysize+1) != MP_OKAY) { goto error; }
/* make the public key */
if (ecc_mulmod(&key->k, base, &key->pubkey, &prime, x) != CRYPT_OK) { goto error; }
key->type = PK_PRIVATE;
/* shrink key */
if (mp_shrink(&key->k) != MP_OKAY) { goto error; }
if (mp_shrink(&key->pubkey.x) != MP_OKAY) { goto error; }
if (mp_shrink(&key->pubkey.y) != MP_OKAY) { goto error; }
/* free up ram */
res = CRYPT_OK;
goto done;
@ -551,12 +605,12 @@ static int compress_y_point(ecc_point *pt, int idx, int *result)
}
/* get x^3 - 3x + b */
if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 16) != MP_OKAY) { goto error; } /* p = B */
if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 64) != MP_OKAY) { goto error; } /* p = B */
if (mp_expt_d(&pt->x, 3, &tmp) != MP_OKAY) { goto error; } /* tmp = pX^3 */
if (mp_mul_d(&pt->x, 3, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */
if (mp_sub(&tmp, &tmp2, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */
if (mp_add(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp + p */
if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 10) != MP_OKAY) { goto error; } /* p = prime */
if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 64) != MP_OKAY) { goto error; } /* p = prime */
if (mp_mod(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp mod p */
/* now find square root */
@ -593,12 +647,12 @@ static int expand_y_point(ecc_point *pt, int idx, int result)
}
/* get x^3 - 3x + b */
if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 16) != MP_OKAY) { goto error; } /* p = B */
if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 64) != MP_OKAY) { goto error; } /* p = B */
if (mp_expt_d(&pt->x, 3, &tmp) != MP_OKAY) { goto error; } /* tmp = pX^3 */
if (mp_mul_d(&pt->x, 3, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */
if (mp_sub(&tmp, &tmp2, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */
if (mp_add(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp + p */
if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 10) != MP_OKAY) { goto error; } /* p = prime */
if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 64) != MP_OKAY) { goto error; } /* p = prime */
if (mp_mod(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp mod p */
/* now find square root */
@ -625,10 +679,10 @@ done:
#define OUTPUT_BIGNUM(num, buf2, y, z) \
{ \
z = mp_raw_size(num); \
z = mp_unsigned_bin_size(num); \
STORE32L(z, buf2+y); \
y += 4; \
mp_toraw(num, buf2+y); \
mp_to_unsigned_bin(num, buf2+y); \
y += z; \
}
@ -650,11 +704,15 @@ done:
} \
\
/* load it */ \
if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\
if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\
errno = CRYPT_MEM; \
goto error; \
} \
y += x; \
if (mp_shrink(num) != MP_OKAY) { \
errno = CRYPT_MEM; \
goto error; \
} \
}
int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
@ -696,7 +754,7 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key
}
/* store header */
packet_store_header(buf2, PACKET_SECT_ECC, PACKET_SUB_KEY, y);
packet_store_header(buf2, PACKET_SECT_ECC, PACKET_SUB_KEY);
memcpy(out, buf2, y);
*outlen = y;
@ -765,10 +823,15 @@ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
/* load private key */
INPUT_BIGNUM(&key->k, in, x, y);
}
/* eliminate private key if public */
if (key->type == PK_PUBLIC) {
mp_clear(&key->k);
}
return CRYPT_OK;
error:
mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL);
done:
return errno;
}
@ -805,7 +868,7 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
return CRYPT_MEM;
}
if (mp_read_radix(&prime, (unsigned char *)sets[private_key->idx].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&prime, (unsigned char *)sets[private_key->idx].prime, 64) != MP_OKAY) { goto error; }
if ((errno = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime, private_key->idx)) != CRYPT_OK) { res = errno; goto done1; }
x = mp_raw_size(&result->x);

View File

@ -84,7 +84,7 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
}
/* store header */
packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY, y);
packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY);
#ifdef CLEAN_STACK
/* clean up */
@ -96,8 +96,9 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
return CRYPT_OK;
}
int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, ecc_key *key)
int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
ecc_key *key)
{
unsigned char shared_secret[256], skey[MAXBLOCKSIZE];
unsigned long x, y, z, res, hashsize, keysize;
@ -114,6 +115,13 @@ int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
return CRYPT_PK_NOT_PRIVATE;
}
/* correct length ? */
if (inlen < PACKET_SIZE+1+4+4) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= PACKET_SIZE+1+4+4;
}
/* is header correct? */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
return errno;
@ -131,6 +139,11 @@ int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
/* get public key */
LOAD32L(x, in+y);
if (inlen < x) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= x;
}
y += 4;
if ((errno = ecc_import(in+y, x, &pubkey)) != CRYPT_OK) {
return errno;
@ -151,6 +164,11 @@ int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
}
LOAD32L(keysize, in+y);
if (inlen < keysize) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= keysize;
}
y += 4;
if (*keylen < keysize) {
@ -223,7 +241,7 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
ecc_free(&pubkey);
return CRYPT_MEM;
}
if (mp_read_radix(&p, (unsigned char *)sets[key->idx].order, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, (unsigned char *)sets[key->idx].order, 64) != MP_OKAY) { goto error; }
if (mp_read_raw(&b, md, 1+MIN(sizeof(md)-1,inlen)) != MP_OKAY) { goto error; }
/* find b = (m - x)/k */
@ -266,7 +284,7 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
}
/* store header */
packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED, y);
packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED);
/* clear memory */
*outlen = y;
@ -286,9 +304,9 @@ done1:
}
/* verify that mG = (bA + Y) */
int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
unsigned long inlen, int *stat,
ecc_key *key)
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long inlen,
int *stat, ecc_key *key)
{
ecc_point *mG;
ecc_key pubkey;
@ -305,6 +323,12 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
/* default to invalid signature */
*stat = 0;
if (siglen < PACKET_SIZE+4+4) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= PACKET_SIZE+4+4;
}
/* is the message format correct? */
if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return errno;
@ -315,6 +339,11 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
/* get size of public key */
LOAD32L(x, sig+y);
if (siglen < x) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= x;
}
y += 4;
/* load the public key */
@ -325,6 +354,11 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
/* load size of 'b' */
LOAD32L(x, sig+y);
if (siglen < x) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= x;
}
y += 4;
/* init values */
@ -350,7 +384,7 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1,inlen)) != MP_OKAY) { goto error; }
/* load prime */
if (mp_read_radix(&p, (unsigned char *)sets[key->idx].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, (unsigned char *)sets[key->idx].prime, 64) != MP_OKAY) { goto error; }
/* get bA */
if (ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p, key->idx) != CRYPT_OK) { goto error; }
@ -359,8 +393,8 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
if (add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p) != CRYPT_OK) { goto error; }
/* get mG */
if (mp_read_radix(&mG->x, (unsigned char *)sets[key->idx].Gx, 16) != MP_OKAY) { goto error; }
if (mp_read_radix(&mG->y, (unsigned char *)sets[key->idx].Gy, 16) != MP_OKAY) { goto error; }
if (mp_read_radix(&mG->x, (unsigned char *)sets[key->idx].Gx, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&mG->y, (unsigned char *)sets[key->idx].Gy, 64) != MP_OKAY) { goto error; }
if (ecc_mulmod(&m, mG, mG, &p, key->idx) != CRYPT_OK) { goto error; }
/* compare mG to bA + Y */

18
examples/ch1-01.c Normal file
View File

@ -0,0 +1,18 @@
/*
* Name : ch1-01.c
* Purpose : Demonstration of a basic libtomcrypt program
* Author : Tom St Denis
*
* History : v0.79 Initial release
*/
/* ch1-01-1 */
/* Include the default headers and libtomcrypt headers */
#include <mycrypt.h>
int main(void)
{
return 0;
}
/* ch1-01-1 */

25
examples/ch1-02.c Normal file
View File

@ -0,0 +1,25 @@
/*
* Name : ch1-02.c
* Purpose : Demonstration of error handling
* Author : Tom St Denis
*
* History : v0.79 Initial release
*/
/* ch1-01-1 */
#include <mycrypt.h>
int main(void)
{
int errno;
if ((errno = some_func(...)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return EXIT_FAILURE;
}
return 0;
}
/*ch1-01-1 */

29
examples/ch1-03.c Normal file
View File

@ -0,0 +1,29 @@
/*
* Name : ch1-03.c
* Purpose : Demonstration of variable length outputs
* Author : Tom St Denis
*
* History : v0.79 Initial release
*/
/* ch1-01-1 */
#include <mycrypt.h>
int main(void)
{
unsigned long length;
unsigned char buffer[512];
int errno;
length = sizeof(buffer);
if ((errno = some_func(..., buffer, &length)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return EXIT_FAILURE;
}
printf("Size of output is %lu bytes\n", length);
return 0;
}
/* ch1-01-1 */

View File

@ -70,6 +70,7 @@ static const unsigned long crc_table[256] = {
static unsigned long crc32 (unsigned long crc, const unsigned char *buf, unsigned long len)
{
//_ARGCHK(buf != NULL && len == 0);
crc = crc ^ 0xffffffffL;
while (len >= 8) {
DO8 (buf);
@ -587,25 +588,26 @@ int kr_encrypt_key(pk_key *pk, unsigned long ID,
STORE32L(kr->ID,buf+4);
/* now encrypt it */
len = sizeof(buf)-8;
len = sizeof(buf)-12;
switch (kr->system) {
case RSA_KEY:
if ((errno = rsa_encrypt_key(in, inlen, buf+8, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) {
if ((errno = rsa_encrypt_key(in, inlen, buf+12, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) {
return errno;
}
break;
case DH_KEY:
if ((errno = dh_encrypt_key(in, inlen, buf+8, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) {
if ((errno = dh_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) {
return errno;
}
break;
case ECC_KEY:
if ((errno = ecc_encrypt_key(in, inlen, buf+8, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) {
if ((errno = ecc_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) {
return errno;
}
break;
}
len += 8;
STORE32L(len,buf+8);
len += 12;
if (len > *outlen) {
#ifdef CLEAN_STACK
@ -626,7 +628,7 @@ int kr_decrypt_key(pk_key *pk, const unsigned char *in,
unsigned char *out, unsigned long *outlen)
{
unsigned char buf[8192];
unsigned long len, ID;
unsigned long pklen, len, ID;
pk_key *kr;
int errno;
@ -653,20 +655,21 @@ int kr_decrypt_key(pk_key *pk, const unsigned char *in,
}
/* now try and decrypt it */
LOAD32L(pklen,in+8);
len = sizeof(buf);
switch (kr->system) {
case RSA_KEY:
if ((errno = rsa_decrypt_key(in+8, buf, &len, &(kr->key.rsa))) != CRYPT_OK) {
if ((errno = rsa_decrypt_key(in+12, pklen, buf, &len, &(kr->key.rsa))) != CRYPT_OK) {
return errno;
}
break;
case DH_KEY:
if ((errno = dh_decrypt_key(in+8, buf, &len, &(kr->key.dh))) != CRYPT_OK) {
if ((errno = dh_decrypt_key(in+12, pklen, buf, &len, &(kr->key.dh))) != CRYPT_OK) {
return errno;
}
break;
case ECC_KEY:
if ((errno = ecc_decrypt_key(in+8, buf, &len, &(kr->key.ecc))) != CRYPT_OK) {
if ((errno = ecc_decrypt_key(in+12, pklen, buf, &len, &(kr->key.ecc))) != CRYPT_OK) {
return errno;
}
break;
@ -720,26 +723,27 @@ int kr_sign_hash(pk_key *pk, unsigned long ID,
STORE32L(kr->ID,buf+4);
/* now sign it */
len = sizeof(buf)-12;
len = sizeof(buf)-16;
switch (kr->system) {
case RSA_KEY:
if ((errno = rsa_sign_hash(in, inlen, buf+12, &len, &(kr->key.rsa))) != CRYPT_OK) {
if ((errno = rsa_sign_hash(in, inlen, buf+16, &len, &(kr->key.rsa))) != CRYPT_OK) {
return errno;
}
break;
case DH_KEY:
if ((errno = dh_sign_hash(in, inlen, buf+12, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) {
if ((errno = dh_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) {
return errno;
}
break;
case ECC_KEY:
if ((errno = ecc_sign_hash(in, inlen, buf+12, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) {
if ((errno = ecc_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) {
return errno;
}
break;
}
STORE32L(inlen,buf+8);
len += 12;
STORE32L(len,buf+12);
len += 16;
if (len > *outlen) {
#ifdef CLEAN_STACK
@ -759,7 +763,7 @@ int kr_sign_hash(pk_key *pk, unsigned long ID,
int kr_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *hash,
unsigned long hashlen, int *stat)
{
unsigned long inlen, ID;
unsigned long inlen, pklen, ID;
pk_key *kr;
int errno;
@ -785,23 +789,24 @@ int kr_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *has
/* now try and verify it */
LOAD32L(inlen,in+8); /* this is the length of the original inlen */
LOAD32L(pklen,in+12); /* size of the PK packet */
if (inlen != hashlen) { /* size doesn't match means the signature is invalid */
return CRYPT_OK;
}
switch (kr->system) {
case RSA_KEY:
if ((errno = rsa_verify_hash(in+12, hash, stat, &(kr->key.rsa))) != CRYPT_OK) {
if ((errno = rsa_verify_hash(in+16, pklen, hash, stat, &(kr->key.rsa))) != CRYPT_OK) {
return errno;
}
break;
case DH_KEY:
if ((errno = dh_verify_hash(in+12, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) {
if ((errno = dh_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) {
return errno;
}
break;
case ECC_KEY:
if ((errno = ecc_verify_hash(in+12, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) {
if ((errno = ecc_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) {
return errno;
}
break;

146
makefile
View File

@ -9,62 +9,77 @@
# a build. This is easy to remedy though, for those that have problems.
# The version
VERSION=0.78
VERSION=0.79
#Compiler and Linker Names
#ch1-01-1
# Compiler and Linker Names
CC=gcc
LD=ld
#Archiver [makes .a files]
# Archiver [makes .a files]
AR=ar
ARFLAGS=rs
ARFLAGS=r
#ch1-01-1
#here you can set the malloc/calloc/free functions you want
#ch1-01-2
# here you can set the malloc/calloc/free functions you want
XMALLOC=malloc
XCALLOC=calloc
XREALLOC=realloc
XFREE=free
#you can redefine the clock
# you can redefine the clock
XCLOCK=clock
XCLOCKS_PER_SEC=CLOCKS_PER_SEC
#ch1-01-2
#Compilation flags. Note the += does not write over the user's CFLAGS!
#ch1-01-3
# Compilation flags. Note the += does not write over the user's CFLAGS!
CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror \
-DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \
-DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) \
-DXREALLOC=$(XREALLOC) -DXCLOCK=$(XCLOCK) \
-DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
#optimize for SPEED (comment out SIZE/DEBUG line as well)
# optimize for SPEED
#CFLAGS += -O3 -funroll-loops
#optimize for SIZE (comment out SPEED/DEBUG line as well)
# optimize for SIZE
CFLAGS += -Os
#Use small code variants of functions when possible? (Slows it down!)
CFLAGS += -DSMALL_CODE
#compile for DEBUGGING
# compile for DEBUGGING
#CFLAGS += -g3
#ch1-01-3
#These flags control how the library gets built.
#no file support, when defined the library will not have any functions that can read/write files
#(comment out to have file support)
#ch1-01-4
# Use small code variants of functions when possible?
CFLAGS += -DSMALL_CODE
# no file support, when defined the library will not
# have any functions that can read/write files
# (comment out to have file support)
#CFLAGS += -DNO_FILE
#Support the UNIX /dev/random or /dev/urandom
# Support the UNIX /dev/random or /dev/urandom
CFLAGS += -DDEVRANDOM
# Use /dev/urandom first on devices where /dev/random is too slow */
# Use /dev/urandom first on devices where
# /dev/random is too slow
#CFLAGS += -DTRY_URANDOM_FIRST
# Clean the stack after sensitive functions. Not always required...
# With this defined most of the ciphers and hashes will clean their stack area
# after usage with a (sometimes) huge penalty in speed. Normally this is not
# required if you simply lock your stack and wipe it when your program is done.
# Clean the stack after sensitive functions. Not
# always required... With this defined most of
# the ciphers and hashes will clean their stack area
# after usage with a (sometimes) huge penalty in speed.
# Normally this is not required if you simply lock your
# stack and wipe it when your program is done.
#
#CFLAGS += -DCLEAN_STACK
#ch1-01-4
# What algorithms to include? comment out and rebuild to remove em
#ch1-01-5
# What algorithms to include? comment out and rebuild to remove them
CFLAGS += -DBLOWFISH
CFLAGS += -DRC2
CFLAGS += -DRC5
@ -78,6 +93,7 @@ CFLAGS += -DTWOFISH
CFLAGS += -DDES
CFLAGS += -DCAST5
CFLAGS += -DNOEKEON
#ch1-01-5
#You can also customize the Twofish code. All four combinations
#of the flags are possible but only three of them make sense.
@ -90,17 +106,23 @@ CFLAGS += -DNOEKEON
#_TABLES defined: Very fast, not faster than if both were undefined. Code is ~1KB bigger
# faster keysetup though...
# Small Ram Variant of Twofish. For this you must have TWOFISH defined. This
# variant requires about 4kb less memory but is considerably slower. It is ideal
# when high throughput is less important than conserving memory. By default it is
# not defined which means the larger ram (about 4.2Kb used) variant is built.
#ch1-01-6
# Small Ram Variant of Twofish. For this you must have TWOFISH
# defined. This variant requires about 4kb less memory but
# is considerably slower. It is ideal when high throughput is
# less important than conserving memory. By default it is not
# defined which means the larger ram (about 4.2Kb used) variant
# is built.
#CFLAGS += -DTWOFISH_SMALL
# Tell Twofish to use precomputed tables. If you want to use the small table
# variant of Twofish you may want to turn this on. Essentially it tells Twofish to use
# precomputed S-boxes (Q0 and Q1) as well as precomputed GF multiplications [in the MDS].
# This speeds up the cipher somewhat.
# Tell Twofish to use precomputed tables. If you want to use
# the small table variant of Twofish you may want to turn
# this on. Essentially it tells Twofish to use precomputed
# S-boxes (Q0 and Q1) as well as precomputed GF
# multiplications [in the MDS]. This speeds up the cipher
# somewhat.
#CFLAGS += -DTWOFISH_TABLES
#ch1-01-6
#Use fast PK routines. Basically this limits the size of the private key in the
#DH system to 256 bits. The group order remains unchanged so the best
@ -110,13 +132,16 @@ CFLAGS += -DNOEKEON
#security so its by default not turned on. USE AT YOUR RISK!
#CFLAGS += -DFAST_PK
#ch1-01-7
# Chaining modes
CFLAGS += -DCFB
CFLAGS += -DOFB
CFLAGS += -DECB
CFLAGS += -DCBC
CFLAGS += -DCTR
#ch1-01-7
#ch1-01-8
#One-way hashes
CFLAGS += -DSHA512
CFLAGS += -DSHA384
@ -126,29 +151,73 @@ CFLAGS += -DSHA1
CFLAGS += -DMD5
CFLAGS += -DMD4
CFLAGS += -DMD2
#ch1-01-8
# base64
CFLAGS += -DBASE64
#ch1-01-9
# prngs
CFLAGS += -DYARROW
CFLAGS += -DSPRNG
CFLAGS += -DRC4
#ch1-01-9
#ch1-01-10
# PK code
CFLAGS += -DMRSA
CFLAGS += -DMDH
CFLAGS += -DMECC
#CFLAGS += -DMDSA
CFLAGS += -DKR
#ch1-01-10
# include GF math routines? (not currently used by anything internally)
#ch1-01-12
# Control which built in DH or ECC key paramaters
# are to be allowed
CFLAGS += -DDH768
CFLAGS += -DDH1024
CFLAGS += -DDH1280
CFLAGS += -DDH1536
CFLAGS += -DDH1792
CFLAGS += -DDH2048
CFLAGS += -DDH2560
CFLAGS += -DDH3072
CFLAGS += -DDH4096
CFLAGS += -DECC160
CFLAGS += -DECC192
CFLAGS += -DECC224
CFLAGS += -DECC256
CFLAGS += -DECC384
CFLAGS += -DECC521
CFLAGS += -DDSA1024
CFLAGS += -DDSA2048
CFLAGS += -DDSA4096
#ch1-01-12
#ch1-01-11
# base64
CFLAGS += -DBASE64
# include GF math routines?
# (not currently used by anything internally)
#CFLAGS += -DGF
# include large integer math routines? (required by the PK code)
CFLAGS += -DMPI
# use the fast exptmod operation (used in dsa/rsa/dh and is_prime)
# This uses slightly more heap than the old code [only during the function call]
# this is also fairly faster than the previous code
CFLAGS += -DMPI_FASTEXPT
# use a "low" mem variant of the fast exptmod. It is still always
# faster then the old exptmod but its savings drops off after
# 1024 to 2048-bits
#CFLAGS += -DMPI_FASTEXPT_LOWMEM
# include HMAC support
CFLAGS += -DHMAC
#ch1-01-11
#Output filenames for various targets.
LIBNAME=libtomcrypt.a
@ -163,7 +232,7 @@ LIBPATH=/usr/lib
INCPATH=/usr/include
#List of objects to compile.
OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \
OBJECTS=keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o \
bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \
md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \
safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \
@ -199,6 +268,7 @@ sha512.o: sha512.c sha384.c
#This rule makes the libtomcrypt library.
library: $(OBJECTS)
$(AR) $(ARFLAGS) $(LIBNAME) $(OBJECTS)
ranlib $(LIBNAME)
#This rule makes the test program included with libtomcrypt
test: library $(TESTOBJECTS)
@ -219,9 +289,11 @@ small: library $(SMALLOBJECTS)
#This rule installs the library and the header files. This must be run
#as root in order to have a high enough permission to write to the correct
#directories and to set the owner and group to root.
install: library
install: library docs
install -g root -o root $(LIBNAME) $(LIBPATH)
install -g root -o root $(HEADERS) $(INCPATH)
mkdir -p /usr/doc/libtomcrypt/pdf
cp crypt.pdf /usr/doc/libtomcrypt/pdf/
#This rule cleans the source tree of all compiled code, not including the pdf
#documentation.

23
makefile.out Normal file
View File

@ -0,0 +1,23 @@
#makefile generated with config.pl
#
#Tom St Denis (tomstdenis@yahoo.com, http://tom.iahu.ca)
CC = gcc
AR = ar
LD = ld
CFLAGS += -Os -Wall -Wsign-compare -W -Wno-unused -Werror -I./ -DXMALLOC=malloc -DXCALLOC=calloc -DXFREE=free -DXCLOCK=clock -DXCLOCKS_PER_SEC=CLOCKS_PER_SEC -DSMALL_CODE -DBLOWFISH -DRC2 -DRC5 -DRC6 -DSERPENT -DSAFERP -DSAFER -DRIJNDAEL -DXTEA -DTWOFISH -DDES -DCAST5 -DNOEKEON -DCFB -DOFB -DECB -DCBC -DCTR -DSHA512 -DSHA384 -DSHA256 -DTIGER -DSHA1 -DMD5 -DMD4 -DMD2 -DHMAC -DBASE64 -DYARROW -DSPRNG -DRC4 -DDEVRANDOM -DMRSA -DMDH -DMECC -DMDSA -DKR -DDH768 -DDH1024 -DDH1280 -DDH1536 -DDH1792 -DDH2048 -DDH2560 -DDH3072 -DDH4096 -DECC160 -DECC192 -DECC224 -DECC256 -DECC384 -DECC521 -DDSA1024 -DDSA2048 -DDSA4096 -DMPI -DMPI_FASTEXPT
default: library
OBJECTS = keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o
rsa.o: rsa_sys.c
dh.o: dh_sys.c
ecc.o: ecc_sys.c
library: $(OBJECTS)
$(AR) rs libtomcrypt.a $(OBJECTS)
clean:
rm -f $(OBJECTS) libtomcrypt.a

View File

@ -32,6 +32,7 @@ ARFLAGS=rs
#here you can set the malloc/calloc/free functions you want
XMALLOC=malloc
XCALLOC=calloc
XREALLOC=realloc
XFREE=free
#you can redefine the clock
@ -40,7 +41,8 @@ XCLOCKS_PER_SEC=576000
#Compilation flags. Note the += does not write over the user's CFLAGS!
CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror \
-DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \
-DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) \
-DXREALLOC=$(XREALLOC) -DXCLOCK=$(XCLOCK) \
-DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
#optimize for SPEED (comment out SIZE line as well)
@ -103,14 +105,6 @@ CFLAGS += -DNOEKEON
# This speeds up the cipher somewhat.
# CFLAGS += -DTWOFISH_TABLES
#Small code variant of the SAFER+ cipher, uses same RAM but less code space
#With this defined the cipher is slower. On my x86 with GCC 3.2 it required 50KB less space
CFLAGS += -DSAFERP_SMALL
#Small Rijndael [saves 13KB on an x86]
#With this defined the cipher is slower (by 50Mbit/sec on an Athon XP)
CFLAGS += -DRIJNDAEL_SMALL
#Use fast PK routines. Basically this limits the size of the private key in the
#DH system to 256 bits. The group order remains unchanged so the best
#attacks are still GNFS (for DH upto 2560-bits)
@ -148,14 +142,48 @@ CFLAGS += -DRC4
CFLAGS += -DMRSA
CFLAGS += -DMDH
CFLAGS += -DMECC
#CFLAGS += -DDSA
CFLAGS += -DKR
# Control which built in DH or ECC key paramaters
# are to be allowed
CFLAGS += -DDH768
CFLAGS += -DDH1024
CFLAGS += -DDH1280
CFLAGS += -DDH1536
CFLAGS += -DDH1792
CFLAGS += -DDH2048
CFLAGS += -DDH2560
CFLAGS += -DDH3072
CFLAGS += -DDH4096
CFLAGS += -DECC160
CFLAGS += -DECC192
CFLAGS += -DECC224
CFLAGS += -DECC256
CFLAGS += -DECC384
CFLAGS += -DECC521
CFLAGS += -DDSA1024
CFLAGS += -DDSA2048
CFLAGS += -DDSA4096
# include GF math routines? (not currently used by anything internally)
#CFLAGS += -DGF
# include large integer math routines? (required by the PK code)
CFLAGS += -DMPI
# use the fast exptmod operation (used in dsa/rsa/dh and is_prime)
# This uses slightly more heap than the old code [only during the function call]
# this is also fairly faster than the previous code
CFLAGS += -DMPI_FASTEXPT
# use a "low" mem variant of the fast exptmod. It is still always
# faster then the old exptmod but its savings drops off after
# 1024-bits
CFLAGS += -DMPI_FASTEXPT_LOWMEM
# include HMAC support
CFLAGS += -DHMAC
@ -175,7 +203,7 @@ LIBPATH=/usr/lib
INCPATH=/usr/include
#List of objects to compile.
OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \
OBJECTS=keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o \
bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \
md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \
safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \

View File

@ -8,13 +8,14 @@ AR=lib
#here you can set the malloc/calloc/free functions you want
XMALLOC=malloc
XCALLOC=calloc
XREALLOC=realloc
XFREE=free
#you can redefine the clock
XCLOCK=clock
XCLOCKS_PER_SEC=CLOCKS_PER_SEC
CFLAGS = /c /Ogisy1 /Gs /I. /W3 /DWIN32 /DXMALLOC=$(XMALLOC) /DXCALLOC=$(XCALLOC) /DXFREE=$(XFREE) /DXCLOCK=$(XCLOCK) /DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
CFLAGS = /c /Ogisy1 /Gs /I. /W3 /DWIN32 /DXREALLOC=$(XREALLOC) /DXMALLOC=$(XMALLOC) /DXCALLOC=$(XCALLOC) /DXFREE=$(XFREE) /DXCLOCK=$(XCLOCK) /DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
#Small code (smaller variants of some block ciphers)
CFLAGS += /DSMALL_CODE
@ -113,14 +114,49 @@ CFLAGS += /DRC4
CFLAGS += /DMRSA
CFLAGS += /DMDH
CFLAGS += /DMECC
#CFLAGS += /DDSA
CFLAGS += /DKR
# Control which built in DH or ECC key paramaters
# are to be allowed
CFLAGS += /DDH768
CFLAGS += /DDH1024
CFLAGS += /DDH1280
CFLAGS += /DDH1536
CFLAGS += /DDH1792
CFLAGS += /DDH2048
CFLAGS += /DDH2560
CFLAGS += /DDH3072
CFLAGS += /DDH4096
CFLAGS += /DECC160
CFLAGS += /DECC192
CFLAGS += /DECC224
CFLAGS += /DECC256
CFLAGS += /DECC384
CFLAGS += /DECC521
CFLAGS += /DDSA1024
CFLAGS += /DDSA2048
CFLAGS += /DDSA4096
# include GF math routines? (not currently used by anything internally)
#CFLAGS += /DGF
# include large integer math routines? (required by the PK code)
CFLAGS += /DMPI
# use the fast exptmod operation (used in dsa/rsa/dh and is_prime)
# This uses slightly more heap than the old code [only during the function call]
# this is also fairly faster than the previous code
CFLAGS += /DMPI_FASTEXPT
# use a "low" mem variant of the fast exptmod. It is still always
# faster then the old exptmod but its savings drops off after
# 1024-bits
#CFLAGS += /DMPI_FASTEXPT_LOWMEM
# include HMAC support
CFLAGS += /DHMAC
@ -216,6 +252,8 @@ cast5.obj: cast5.c
$(CC) $(CFLAGS) cast5.c
noekeon.obj: noekeon.c
$(CC) $(CFLAGS) noekeon.c
dsa.obj: dsa.c
$(CC) $(CFLAGS) dsa.c
demos/test.obj: demos/test.c
$(CC) $(CFLAGS) demos/test.c
@ -223,11 +261,11 @@ demos/test.obj: demos/test.c
demos/hashsum.obj: demos/hashsum.c
$(CC) $(CFLAGS) demos/hashsum.c
tomcrypt.lib: keyring.obj gf.obj mem.obj sprng.obj ecc.obj base64.obj dh.obj rsa.obj bits.obj hmac.obj \
tomcrypt.lib: keyring.obj gf.obj mem.obj sprng.obj dsa.obj ecc.obj base64.obj dh.obj rsa.obj bits.obj hmac.obj \
yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj md2.obj md5.obj md4.obj sha256.obj sha512.obj xtea.obj \
aes.obj serpent.obj safer_tab.obj safer.obj safer+.obj cast5.obj noekeon.obj rc2.obj rc6.obj rc5.obj des.obj blowfish.obj crypt.obj ampi.obj \
strings.obj mpi.obj prime.obj twofish.obj packet.obj
$(AR) /out:tomcrypt.lib keyring.obj gf.obj mem.obj sprng.obj ecc.obj base64.obj dh.obj rsa.obj hmac.obj \
$(AR) /out:tomcrypt.lib keyring.obj gf.obj mem.obj sprng.obj dsa.obj ecc.obj base64.obj dh.obj rsa.obj hmac.obj \
bits.obj yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj md2.obj md5.obj md4.obj sha256.obj \
strings.obj sha512.obj xtea.obj aes.obj serpent.obj safer_tab.obj safer.obj safer+.obj cast5.obj noekeon.obj rc2.obj rc6.obj rc5.obj des.obj \
blowfish.obj crypt.obj ampi.obj mpi.obj prime.obj twofish.obj packet.obj

213
mpi.c
View File

@ -1635,8 +1635,159 @@ mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c)
/* }}} */
/* shrinks the memory required to store a mp_int if possible */
mp_err mp_shrink(mp_int *a)
{
if (a->used != a->alloc) {
if ((a->dp = XREALLOC(a->dp, a->used * sizeof(mp_digit))) == NULL) {
return MP_MEM;
} else {
a->alloc = a->used;
return MP_OKAY;
}
} else {
return MP_OKAY;
}
}
/* {{{ mp_exptmod(a, b, m, c) */
#ifdef MPI_FASTEXPT
/* computes y == g^x mod p */
mp_err mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y)
{
mp_int *M, tx, mu, res;
int QQQ, QQ, Q, x, *vals, err;
/* determine the value of Q */
x = (USED(X) - 1) * DIGIT_BIT;
Q = DIGIT(X, USED(X)-1);
while (Q) {
++x;
Q >>= 1;
}
if (x <= 8) { Q = 2; }
else if (x <= 64) { Q = 3; }
else if (x <= 256) { Q = 4; }
else if (x <= 950) { Q = 5; }
else if (x <= 2755) { Q = 6; }
else { Q = 7; }
#ifdef MPI_FASTEXPT_LOWMEM
if (Q > 5) {
Q = 5;
}
#endif
/* alloc room for table */
vals = XCALLOC(sizeof(int), USED(X)*((DIGIT_BIT/Q)+((DIGIT_BIT%Q)?1:0)));
if (vals == NULL) { err = MP_MEM; goto _ERR; }
M = XCALLOC(sizeof(mp_int), 1<<Q);
if (M == NULL) { err = MP_MEM; goto _VALS; }
/* init M table */
for (x = 0; x < (1<<Q); x++) {
if (mp_init(&M[x]) != MP_OKAY) {
for (Q = 0; Q < x; Q++) {
mp_clear(&M[x]);
}
err = MP_MEM;
goto __M;
}
}
/* init the barett reduction */
/* mu = b^2k / m */
if ((err = mp_init(&mu)) != MP_OKAY) {
goto _M;
}
if ((err = mp_init(&res)) != MP_OKAY) {
goto _MU;
}
mp_set(&mu, 1);
s_mp_lshd(&mu, 2 * USED(P));
if((err = mp_div(&mu, P, &mu, NULL)) != MP_OKAY){
goto _RES;
}
/* now init the M array with powers of the base */
mp_set(&M[0], 1);
if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { goto _RES; }
/* shrink first two */
for (x = 0; x < 2; x++) {
if ((err = mp_shrink(&M[x])) != MP_OKAY) { goto _RES; }
}
for (x = 2; x < (1<<Q); x++) {
if (USED(&M[x]) == 1 && DIGIT(&M[x], 0) == 0) {
if ((err = mp_mul(&M[x-1], &M[1], &M[x])) != MP_OKAY) { goto _RES; }
if ((err = s_mp_reduce(&M[x], P, &mu)) != MP_OKAY) { goto _RES; }
if ((err = mp_shrink(&M[x])) != MP_OKAY) { goto _RES; }
QQQ = x;
QQ = x * 2;
while (QQ < (1<<Q)) {
if ((err = mp_sqr(&M[QQQ], &M[QQ])) != MP_OKAY) { goto _RES; }
if ((err = s_mp_reduce(&M[QQ], P, &mu)) != MP_OKAY) { goto _RES; }
if ((err = mp_shrink(&M[QQ])) != MP_OKAY) { goto _RES; }
QQQ = QQ;
QQ *= 2;
}
}
}
/* now grab the bits */
if ((err = mp_init_copy(&tx, X)) != MP_OKAY) {
goto _RES;
}
x = 0;
while (mp_cmp_d(&tx, 0)) {
vals[x++] = DIGIT(&tx, 0) & ((1<<Q)-1);
s_mp_div_2d(&tx, Q);
}
/* now set output equal to the first digit exponent */
if ((err = mp_copy(&M[vals[--x]], &res)) != MP_OKAY) { goto _TX; }
while (--x >= 0) {
for (QQ = 0; QQ < Q; QQ++) {
if ((err = s_mp_sqr(&res)) != MP_OKAY) { goto _TX; }
if ((err = s_mp_reduce(&res, P, &mu)) != MP_OKAY) { goto _TX; }
}
if (vals[x] != 0) {
if ((err = s_mp_mul(&res, &M[vals[x]])) != MP_OKAY) { goto _TX; }
if ((err = s_mp_reduce(&res, P, &mu)) != MP_OKAY) { goto _TX; }
}
}
s_mp_exch(&res, Y);
/* free ram */
_TX:
mp_clear(&tx);
_RES:
mp_clear(&res);
_MU:
mp_clear(&mu);
_M:
for (x = 0; x < (1<<Q); x++) {
mp_clear(&M[x]);
}
__M:
XFREE(M);
_VALS:
XFREE(vals);
_ERR:
return err;
}
#else
/*
mp_exptmod(a, b, m, c)
@ -1731,6 +1882,8 @@ mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
} /* end mp_exptmod() */
#endif
/* }}} */
/* {{{ mp_exptmod_d(a, d, m, c) */
@ -2888,7 +3041,9 @@ void s_mp_rshd(mp_int *mp, mp_size p)
for(ix = p; ix < USED(mp); ix++)
dp[ix - p] = dp[ix];
/* Fill the top digits with zeroes */
ix -= p;
while(ix < USED(mp))
dp[ix++] = 0;
@ -2966,10 +3121,14 @@ void s_mp_mod_2d(mp_int *mp, mp_digit d)
dp[ndig] &= dmask;
/* Flush all digits above the one with 2^d in it */
/*
for(ix = ndig + 1; ix < USED(mp); ix++)
dp[ix] = 0;
s_mp_clamp(mp);
*/
USED(mp) = ndig;
} /* end s_mp_mod_2d() */
@ -3431,6 +3590,56 @@ mp_err s_mp_mul(mp_int *a, mp_int *b)
} /* end s_mp_mul() */
/* Compute a = |a| * |b| max of digs digits */
mp_err s_mp_mul_dig(mp_int *a, mp_int *b, int digs)
{
mp_word w, k = 0;
mp_int tmp;
mp_err res;
mp_size ix, jx, ua = USED(a), ub = USED(b);
mp_digit *pa, *pb, *pt, *pbt;
if((res = mp_init_size(&tmp, digs+1)) != MP_OKAY)
return res;
/* This has the effect of left-padding with zeroes... */
USED(&tmp) = digs+1;
/* We're going to need the base value each iteration */
pbt = DIGITS(&tmp);
/* Outer loop: Digits of b */
pb = DIGITS(b);
for(ix = 0; ix < ub; ++ix, ++pb) {
if(*pb == 0)
continue;
/* Inner product: Digits of a */
pa = DIGITS(a);
for(jx = 0; jx < ua; ++jx, ++pa) {
if ((int)(ix+jx) > digs) { break; }
pt = pbt + ix + jx;
w = *pb * *pa + k + *pt;
*pt = ACCUM(w);
k = CARRYOUT(w);
}
if ((int)(ix + jx) < digs) {
pbt[ix + jx] = k;
}
k = 0;
}
USED(&tmp) = digs;
s_mp_clamp(&tmp);
s_mp_exch(&tmp, a);
mp_clear(&tmp);
return MP_OKAY;
} /* end s_mp_mul() */
/* }}} */
/* {{{ s_mp_kmul(a, b, out, len) */
@ -3763,8 +3972,8 @@ mp_err s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu)
s_mp_mod_2d(x, (mp_digit)(DIGIT_BIT * (um + 1)));
/* q = q * m mod b^(k+1), quick (no division) */
s_mp_mul(&q, m);
s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1)));
s_mp_mul_dig(&q, m, um + 1);
// s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1)));
/* x = x - q */
if((res = mp_sub(x, &q, x)) != MP_OKAY)

5
mpi.h
View File

@ -98,6 +98,8 @@ void mp_clear_array(mp_int mp[], int count);
void mp_zero(mp_int *mp);
void mp_set(mp_int *mp, mp_digit d);
mp_err mp_set_int(mp_int *mp, long z);
mp_err mp_shrink(mp_int *a);
/*------------------------------------------------------------------------*/
/* Single digit arithmetic */
@ -149,6 +151,9 @@ mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c);
#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
#endif
mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
mp_err s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu);
mp_err s_mp_lshd(mp_int *mp, mp_size p);
mp_err s_mp_mul_dig(mp_int *a, mp_int *b, int digs);
mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c);
#endif /* MP_MODARITH */

View File

@ -13,46 +13,48 @@ extern "C" {
#endif
/* version */
#define CRYPT 0x0078
#define SCRYPT "0.78"
#define CRYPT 0x0079
#define SCRYPT "0.79"
/* max size of either a cipher/hash block or symmetric key [largest of the two] */
#define MAXBLOCKSIZE 128
/* ch1-01-1 */
/* error codes [will be expanded in future releases] */
enum {
CRYPT_OK=0,
CRYPT_ERROR,
CRYPT_OK=0, /* Result OK */
CRYPT_ERROR, /* Generic Error */
CRYPT_INVALID_KEYSIZE,
CRYPT_INVALID_ROUNDS,
CRYPT_FAIL_TESTVECTOR,
CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
CRYPT_BUFFER_OVERFLOW,
CRYPT_INVALID_PACKET,
CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
CRYPT_INVALID_PACKET, /* Invalid input packet given */
CRYPT_INVALID_PRNGSIZE,
CRYPT_ERROR_READPRNG,
CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
CRYPT_INVALID_CIPHER,
CRYPT_INVALID_HASH,
CRYPT_INVALID_PRNG,
CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
CRYPT_INVALID_HASH, /* Invalid hash specified */
CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
CRYPT_MEM,
CRYPT_MEM, /* Out of memory */
CRYPT_PK_TYPE_MISMATCH,
CRYPT_PK_NOT_PRIVATE,
CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
CRYPT_INVALID_ARG,
CRYPT_INVALID_ARG, /* Generic invalid argument */
CRYPT_PK_INVALID_TYPE,
CRYPT_PK_INVALID_SYSTEM,
CRYPT_PK_DUP,
CRYPT_PK_NOT_FOUND,
CRYPT_PK_INVALID_SIZE,
CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */
CRYPT_PK_DUP, /* Duplicate key already in key ring */
CRYPT_PK_NOT_FOUND, /* Key not found in keyring */
CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
CRYPT_INVALID_PRIME_SIZE
CRYPT_INVALID_PRIME_SIZE/* Invalid size of prime requested */
};
/* ch1-01-1 */
#include <mycrypt_cfg.h>
#include <mycrypt_macros.h>
@ -63,10 +65,8 @@ enum {
#include <mycrypt_gf.h>
#include <mycrypt_misc.h>
#include <mycrypt_kr.h>
#include <mycrypt_argchk.h>
#ifdef __cplusplus
}
#endif

View File

@ -1,26 +1,14 @@
/* Defines the _ARGCHK macro used within the library */
/* ch1-01-1 */
/* ARGTYPE is defined in mycrypt_cfg.h */
#if ARGTYPE == 0
#include <signal.h>
/* this is the default LibTomCrypt macro
*
* On embedded platforms you can change the fprintf() to be a routine that would display a message
* somehow
*/
#ifdef SMALL_CODE
extern void crypt_argchk(char *v, char *s, int d);
#define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
#else
#ifdef SONY_PS2
#define _ARGCHK(x) if (!(x)) { printf("_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); raise(SIGABRT); }
#else
#define _ARGCHK(x) if (!(x)) { fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); raise(SIGABRT); }
#endif
#endif
/* this is the default LibTomCrypt macro */
extern void crypt_argchk(char *v, char *s, int d);
#define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
#elif ARGTYPE == 1
@ -32,4 +20,5 @@
#define _ARGCHK(x)
#endif
/* ch1-01-1 */

View File

@ -9,14 +9,17 @@
/* you can change how memory allocation works ... */
extern void *XMALLOC(size_t n);
extern void *REALLOC(void *p, size_t n);
extern void *XCALLOC(size_t n, size_t s);
extern void XFREE(void *p);
/* change the clock function too */
extern clock_t XCLOCK(void);
/* ch1-01-1 */
/* type of argument checking, 0=default, 1=fatal and 2=none */
#define ARGTYPE 0
/* ch1-01-1 */
/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code */
/* detect x86-32 machines somewhat */
@ -53,7 +56,7 @@ extern clock_t XCLOCK(void);
#ifdef YARROW
#ifndef CTR
#error YARROW Requires CTR mode
#error YARROW requires CTR chaining mode to be defined!
#endif
#endif
@ -62,12 +65,13 @@ extern clock_t XCLOCK(void);
#define PACKET
/* size of a packet header in bytes */
#define PACKET_SIZE 8
#define PACKET_SIZE 4
/* Section tags */
#define PACKET_SECT_RSA 0
#define PACKET_SECT_DH 1
#define PACKET_SECT_ECC 2
#define PACKET_SECT_DSA 4
/* Subsection Tags for the first three sections */
#define PACKET_SUB_KEY 0
@ -76,33 +80,6 @@ extern clock_t XCLOCK(void);
#define PACKET_SUB_ENC_KEY 3
#endif
/* Diffie-Hellman key settings you can omit ones you don't want to save space */
#ifdef MDH
#define DH768
#define DH1024
#define DH1280
#define DH1536
#define DH1792
#define DH2048
#define DH2560
#define DH3072
#define DH4096
#endif /* MDH */
/* ECC Key settings */
#ifdef MECC
#define ECC160
#define ECC192
#define ECC224
#define ECC256
#define ECC384
#define ECC521
#endif /* MECC */
#ifdef MPI
#include "mpi.h"
#else
@ -115,6 +92,9 @@ extern clock_t XCLOCK(void);
#ifdef MDH
#error DH requires the big int library
#endif
#ifdef MDSA
#error DSA requires the big int library
#endif
#endif /* MPI */
#endif /* MYCRYPT_CFG_H */

View File

@ -11,6 +11,8 @@ extern int base64_decode(const unsigned char *in, unsigned long len,
extern void zeromem(void *dst, unsigned long len);
extern void burn_stack(unsigned long len);
/* ch1-01-1*/
extern const char *error_to_string(int errno);
/* ch1-01-1*/
extern const char *crypt_build_settings;

View File

@ -17,7 +17,7 @@ extern void mp_clear_multi(mp_int* mp, ...);
/* ---- PACKET ---- */
#ifdef PACKET
extern void packet_store_header(unsigned char *dst, int section, int subsection, unsigned long length);
extern void packet_store_header(unsigned char *dst, int section, int subsection);
extern int packet_valid_header(unsigned char *src, int section, int subsection);
#endif
@ -56,15 +56,16 @@ extern int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
unsigned char *outkey, unsigned long *outlen,
prng_state *prng, int wprng, rsa_key *key);
extern int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, rsa_key *key);
extern int rsa_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
rsa_key *key);
extern int rsa_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
rsa_key *key);
extern int rsa_verify_hash(const unsigned char *sig, const unsigned char *hash,
int *stat, rsa_key *key);
extern int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, int *stat, rsa_key *key);
extern int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key);
extern int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
@ -96,16 +97,17 @@ extern int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
prng_state *prng, int wprng, int hash,
dh_key *key);
extern int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, dh_key *key);
extern int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
dh_key *key);
extern int dh_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, dh_key *key);
extern int dh_verify_hash(const unsigned char *sig, const unsigned char *hash,
unsigned long inlen, int *stat,
dh_key *key);
extern int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, dh_key *key);
#endif
@ -140,15 +142,35 @@ extern int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
prng_state *prng, int wprng, int hash,
ecc_key *key);
extern int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, ecc_key *key);
extern int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
ecc_key *key);
extern int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, ecc_key *key);
extern int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
unsigned long inlen, int *stat,
ecc_key *key);
extern int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, ecc_key *key);
#endif
#ifdef MDSA
typedef struct {
int type, idx;
mp_int x, y;
} dsa_key;
extern int dsa_test(void);
extern int dsa_make_key(prng_state *prng, int wprng, int keysize, dsa_key *key);
extern void dsa_free(dsa_key *key);
extern int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
extern int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
#endif

View File

@ -2,7 +2,7 @@
#ifdef PACKET
void packet_store_header(unsigned char *dst, int section, int subsection, unsigned long length)
void packet_store_header(unsigned char *dst, int section, int subsection)
{
_ARGCHK(dst != NULL);
@ -14,8 +14,6 @@ void packet_store_header(unsigned char *dst, int section, int subsection, unsign
dst[2] = section & 255;
dst[3] = subsection & 255;
/* store length */
STORE32L(length, &dst[4]);
}
int packet_valid_header(unsigned char *src, int section, int subsection)

View File

@ -230,8 +230,6 @@ done:
return res;
}
int rand_prime(mp_int *N, long len, prng_state *prng, int wprng)
{
unsigned char buf[260];

33
rsa.c
View File

@ -74,6 +74,18 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
if (mp_copy(&p, &key->p) != MP_OKAY) { goto error2; }
if (mp_copy(&q, &key->q) != MP_OKAY) { goto error2; }
/* shrink ram required */
if (mp_shrink(&key->e) != MP_OKAY) { goto error2; }
if (mp_shrink(&key->d) != MP_OKAY) { goto error2; }
if (mp_shrink(&key->N) != MP_OKAY) { goto error2; }
if (mp_shrink(&key->dQ) != MP_OKAY) { goto error2; }
if (mp_shrink(&key->dP) != MP_OKAY) { goto error2; }
if (mp_shrink(&key->qP) != MP_OKAY) { goto error2; }
if (mp_shrink(&key->pQ) != MP_OKAY) { goto error2; }
if (mp_shrink(&key->p) != MP_OKAY) { goto error2; }
if (mp_shrink(&key->q) != MP_OKAY) { goto error2; }
res = CRYPT_OK;
key->type = PK_PRIVATE_OPTIMIZED;
goto done;
@ -293,10 +305,10 @@ int rsa_depad(const unsigned char *in, unsigned long inlen,
#define OUTPUT_BIGNUM(num, buf2, y, z) \
{ \
z = mp_raw_size(num); \
z = mp_unsigned_bin_size(num); \
STORE32L(z, buf2+y); \
y += 4; \
mp_toraw(num, buf2+y); \
mp_to_unsigned_bin(num, buf2+y); \
y += z; \
}
@ -318,11 +330,16 @@ int rsa_depad(const unsigned char *in, unsigned long inlen,
} \
\
/* load it */ \
if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\
if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\
errno = CRYPT_MEM; \
goto error2; \
} \
y += x; \
\
if (mp_shrink(num) != MP_OKAY) { \
errno = CRYPT_MEM; \
goto error2; \
} \
}
int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
@ -371,7 +388,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key
}
/* store packet header */
packet_store_header(buf2, PACKET_SECT_RSA, PACKET_SUB_KEY, y);
packet_store_header(buf2, PACKET_SECT_RSA, PACKET_SUB_KEY);
/* copy to the user buffer */
memcpy(out, buf2, y);
@ -432,6 +449,14 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
INPUT_BIGNUM(&key->q, in, x, y);
}
/* free up ram not required */
if (key->type != PK_PRIVATE_OPTIMIZED) {
mp_clear_multi(&key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL);
}
if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
mp_clear(&key->d);
}
return CRYPT_OK;
error2:
mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,

View File

@ -49,7 +49,7 @@ int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
}
/* store header */
packet_store_header(outkey, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY, y);
packet_store_header(outkey, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY);
#ifdef CLEAN_STACK
/* clean up */
@ -60,8 +60,9 @@ int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
return CRYPT_OK;
}
int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, rsa_key *key)
int rsa_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
rsa_key *key)
{
unsigned char sym_key[MAXBLOCKSIZE], rsa_in[4096], rsa_out[4096];
unsigned long x, y, z, i, rsa_size;
@ -77,6 +78,12 @@ int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
return CRYPT_PK_NOT_PRIVATE;
}
if (inlen < PACKET_SIZE+4) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= PACKET_SIZE+4;
}
/* check the header */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
return errno;
@ -84,7 +91,12 @@ int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
/* grab length of the rsa key */
y = PACKET_SIZE;
LOAD32L(rsa_size, (in+y))
LOAD32L(rsa_size, (in+y));
if (inlen < rsa_size) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= rsa_size;
}
y += 4;
/* read it in */
@ -94,8 +106,9 @@ int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
/* decrypt it */
x = sizeof(rsa_out);
if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK)
if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK) {
return errno;
}
/* depad it */
z = sizeof(sym_key);
@ -170,7 +183,7 @@ int rsa_sign_hash(const unsigned char *in, unsigned long inlen,
}
/* store header */
packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED, y);
packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED);
#ifdef CLEAN_STACK
/* clean up */
@ -181,8 +194,8 @@ int rsa_sign_hash(const unsigned char *in, unsigned long inlen,
return CRYPT_OK;
}
int rsa_verify_hash(const unsigned char *sig, const unsigned char *md,
int *stat, rsa_key *key)
int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *md, int *stat, rsa_key *key)
{
unsigned long rsa_size, x, y, z;
unsigned char rsa_in[4096], rsa_out[4096];
@ -196,6 +209,12 @@ int rsa_verify_hash(const unsigned char *sig, const unsigned char *md,
/* always be incorrect by default */
*stat = 0;
if (siglen < PACKET_SIZE+4) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= PACKET_SIZE+4;
}
/* verify header */
if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_RSA, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return errno;
@ -204,6 +223,11 @@ int rsa_verify_hash(const unsigned char *sig, const unsigned char *md,
/* get the len */
y = PACKET_SIZE;
LOAD32L(rsa_size, (sig+y));
if (siglen < rsa_size) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= rsa_size;
}
y += 4;
/* load the signature */

3
sha1.c
View File

@ -25,7 +25,7 @@ static void _sha1_compress(hash_state *md)
static void sha1_compress(hash_state *md)
#endif
{
unsigned long a,b,c,d,e,W[80],i,j;
unsigned long a,b,c,d,e,W[80],i,j,j2,j3;
_ARGCHK(md != NULL);
@ -47,6 +47,7 @@ static void sha1_compress(hash_state *md)
W[i] = ROL(j, 1);
}
/* compress */
/* round one */
for (i = 0; i < 20; i++) {

View File

@ -38,7 +38,7 @@ static const char *err_2_str[] =
const char *error_to_string(int errno)
{
if (errno < 0 || errno > (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
if (errno < 0 || errno >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
return "Invalid error code.";
} else {
return err_2_str[errno];

131
update_libtomcrypt.sh Normal file
View File

@ -0,0 +1,131 @@
#!/bin/tcsh
# Get latest copy of libtomcrypt and install it using "tcsh"
#
# Tom St Denis
echo libtomcrypt update script, Tom St Denis
echo "http://libtomcrypt.iahu.ca\n"
if ($1 == "--help") then
echo "update_libtomcrypt.sh [makefile] [sig]-- Download and optionally build the libtomcrypt project.\n"
echo "\t[makefile] --\tYou can optionally specify which makefile you want to build with. If you specify "
echo "\t\t\t'nobuild' then the library is not built, just downloaded and unzipped. If you "
echo "\t\t\tleave it empty the default 'makefile' is used to build the library.\n"
echo "\t[sig] -- \tOptionally verify [via GPG] the signature of the package."
exit
endif
if ($1 == "" || $1 == "sig") then
set make = "makefile"
else
set make = $1;
endif
if ($1 == "sig" || $2 == "sig") then
set sig = "sig"
else
set sig = ""
endif
rm -f latest
echo Getting latest version number from website.
wget -q http://iahu.ca:8080/download/latest
if (-r latest) then
set a = `cat latest`
echo "Latest release is v$a.\n"
if (-d "libtomcrypt-$a" && (-r "libtomcrypt-$a/libtomcrypt.a" || $make == "nobuild")) then
echo Libtomcrypt v$a is already installed on your system.
else
echo "Downloading libtomcrypt v$a ..."
if (-r "crypt-$a.tar.bz2") then
rm -f crypt-$a.tar.bz2
endif
wget http://iahu.ca:8080/download/crypt-$a.tar.bz2
if (-r "crypt-$a.tar.bz2") then
if (-d "libtomcrypt-$a") then
echo "WARNING! Directory libtomcrypt-$a already exists. Cannot continue.\n"
exit
endif
if ($sig == "sig") then
if (!(-r public.asc)) then
echo "Downloading and installing code signing key...\n"
wget -q http://iahu.ca:8080/download/public.asc
if (-r public.asc) then
gpg --import public.asc
if ($? != 0) then
echo Could not import signing key required to verify the package.
exit
else
echo "\n********************************************************************************"
echo "A new key has been imported to your keyring. You should check that it is valid."
echo "********************************************************************************"
endif
else
echo "Could not download the key to import."
exit
endif
endif
echo Verifying signature...
wget -q http://iahu.ca:8080/download/crypt-$a.tar.bz2.asc
if (!(-r "crypt-$a.tar.bz2.asc")) then
echo Could not download signature to test.
exit
endif
gpg -q --verify crypt-$a.tar.bz2.asc
if ($? != 0) then
echo "\n\nSignature for crypt-$a.tar.bz2 is ****not**** valid.\n\n"
exit
else
echo "\n\nSignature for crypt-$a.tar.bz2 is valid.\n\n"
endif
endif
bzip2 -d -c crypt-$a.tar.bz2 | tar -x
if (-d "libtomcrypt-$a") then
if (-r "libtomcrypt-$a/$make") then
cd libtomcrypt-$a
make -f $make
if (-r "libtomcrypt.a") then
echo "\n\n*****************************************************************"
echo The library has been built and you can now install it either with
echo
echo "cd libtomcrypt-$a ; make install"
echo
echo Or by editing the makefile and changing the user you wish to install
echo it with, or simply copy "libtomcrypt.a" to your library directory and
echo copy "*.h" to your include directory
echo "*****************************************************************"
else
echo "\n\n*****************************************************************"
echo The library failed to build. Please note the errors and send them to tomstdenis@yahoo.com
echo "*****************************************************************"
endif
else if ($make == "nobuild") then
echo "\n\n*****************************************************************"
echo "The library was downloaded and unzipped into libtomcrypt-$a/"
echo "*****************************************************************"
else
echo "The makefile '$make' was not found in the archive.\n";
endif
else
echo "Could not unpack the libtomcrypt archive (corrupt?)."
endif
cd ..
else
echo "Could not download the libtomcrypt archive from server."
endif
endif
if (-r "libtomcrypt-$a/changes") then
perl <<!
open(IN,"<libtomcrypt-$a/changes") or die "Can't open libtomcrypt change log.";
print "\nChange log for v$a :\n";
\$a = <IN>; print \$a; \$a = <IN>;
while (<IN>) {
if (\$_ =~ m/^(v\d\.\d\d)/) { close(IN); exit(0); }
print "\$a"; \$a = \$_;
}
!
else
echo "Change log not found. Is the package really installed?"
endif
else
echo "Could not download latest file from server to check version."
endif