- Renamed include directory to polarssl

This commit is contained in:
Paul Bakker 2009-01-03 21:22:43 +00:00
commit 5121ce5bdb
119 changed files with 27558 additions and 0 deletions

57
library/Makefile Normal file
View file

@ -0,0 +1,57 @@
# Also see "include/xyssl/config.h"
CFLAGS = -I../include -D_FILE_OFFSET_BITS=64
OFLAGS = -O
# MicroBlaze specific options:
# CFLAGS += -mno-xl-soft-mul -mxl-barrel-shift
# To compile on Plan9:
# CFLAGS += -D_BSD_EXTENSION
# To compile as a shared library:
# CFLAGS += -fPIC
DLEXT=so
# OSX shared library extension:
# DLEXT=dylib
OBJS= aes.o arc4.o base64.o \
bignum.o certs.o debug.o \
des.o dhm.o havege.o \
md2.o md4.o md5.o \
net.o padlock.o rsa.o \
sha1.o sha2.o sha4.o \
ssl_cli.o ssl_srv.o ssl_tls.o \
timing.o x509parse.o
.SILENT:
all: static
static: libxyssl.a
shared: libxyssl.$(DLEXT)
libxyssl.a: $(OBJS)
echo " AR $@"
ar r $@ $(OBJS)
echo " RL $@"
ranlib $@
libxyssl.so: libxyssl.a
echo " LD $@"
$(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS)
libxyssl.dylib: libxyssl.a
echo " LD $@"
$(CC) -dynamiclib -o $@ $(OBJS)
.c.o:
echo " CC $<"
$(CC) $(CFLAGS) $(OFLAGS) -c $<
clean:
rm -f *.o libxyssl.*

1134
library/aes.c Normal file

File diff suppressed because it is too large Load diff

158
library/arc4.c Normal file
View file

@ -0,0 +1,158 @@
/*
* An implementation of the ARCFOUR algorithm
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The ARCFOUR algorithm was publicly disclosed on 94/09.
*
* http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
*/
#include "xyssl/config.h"
#if defined(XYSSL_ARC4_C)
#include "xyssl/arc4.h"
/*
* ARC4 key schedule
*/
void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen )
{
int i, j, k, a;
unsigned char *m;
ctx->x = 0;
ctx->y = 0;
m = ctx->m;
for( i = 0; i < 256; i++ )
m[i] = (unsigned char) i;
j = k = 0;
for( i = 0; i < 256; i++, k++ )
{
if( k >= keylen ) k = 0;
a = m[i];
j = ( j + a + key[k] ) & 0xFF;
m[i] = m[j];
m[j] = (unsigned char) a;
}
}
/*
* ARC4 cipher function
*/
void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen )
{
int i, x, y, a, b;
unsigned char *m;
x = ctx->x;
y = ctx->y;
m = ctx->m;
for( i = 0; i < buflen; i++ )
{
x = ( x + 1 ) & 0xFF; a = m[x];
y = ( y + a ) & 0xFF; b = m[y];
m[x] = (unsigned char) b;
m[y] = (unsigned char) a;
buf[i] = (unsigned char)
( buf[i] ^ m[(unsigned char)( a + b )] );
}
ctx->x = x;
ctx->y = y;
}
#if defined(XYSSL_SELF_TEST)
#include <string.h>
#include <stdio.h>
/*
* ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
*
* http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
*/
static const unsigned char arc4_test_key[3][8] =
{
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
};
static const unsigned char arc4_test_pt[3][8] =
{
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
};
static const unsigned char arc4_test_ct[3][8] =
{
{ 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
{ 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
{ 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
};
/*
* Checkup routine
*/
int arc4_self_test( int verbose )
{
int i;
unsigned char buf[8];
arc4_context ctx;
for( i = 0; i < 3; i++ )
{
if( verbose != 0 )
printf( " ARC4 test #%d: ", i + 1 );
memcpy( buf, arc4_test_pt[i], 8 );
arc4_setup( &ctx, (unsigned char *) arc4_test_key[i], 8 );
arc4_crypt( &ctx, buf, 8 );
if( memcmp( buf, arc4_test_ct[i], 8 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
#endif

249
library/base64.c Normal file
View file

@ -0,0 +1,249 @@
/*
* RFC 1521 base64 encoding/decoding
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "xyssl/config.h"
#if defined(XYSSL_BASE64_C)
#include "xyssl/base64.h"
static const unsigned char base64_enc_map[64] =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/'
};
static const unsigned char base64_dec_map[128] =
{
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 127, 127, 127, 127, 127
};
/*
* Encode a buffer into base64 format
*/
int base64_encode( unsigned char *dst, int *dlen,
unsigned char *src, int slen )
{
int i, n;
int C1, C2, C3;
unsigned char *p;
if( slen == 0 )
return( 0 );
n = (slen << 3) / 6;
switch( (slen << 3) - (n * 6) )
{
case 2: n += 3; break;
case 4: n += 2; break;
default: break;
}
if( *dlen < n + 1 )
{
*dlen = n + 1;
return( XYSSL_ERR_BASE64_BUFFER_TOO_SMALL );
}
n = (slen / 3) * 3;
for( i = 0, p = dst; i < n; i += 3 )
{
C1 = *src++;
C2 = *src++;
C3 = *src++;
*p++ = base64_enc_map[(C1 >> 2) & 0x3F];
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
*p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
*p++ = base64_enc_map[C3 & 0x3F];
}
if( i < slen )
{
C1 = *src++;
C2 = ((i + 1) < slen) ? *src++ : 0;
*p++ = base64_enc_map[(C1 >> 2) & 0x3F];
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
if( (i + 1) < slen )
*p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
else *p++ = '=';
*p++ = '=';
}
*dlen = p - dst;
*p = 0;
return( 0 );
}
/*
* Decode a base64-formatted buffer
*/
int base64_decode( unsigned char *dst, int *dlen,
unsigned char *src, int slen )
{
int i, j, n;
unsigned long x;
unsigned char *p;
for( i = j = n = 0; i < slen; i++ )
{
if( ( slen - i ) >= 2 &&
src[i] == '\r' && src[i + 1] == '\n' )
continue;
if( src[i] == '\n' )
continue;
if( src[i] == '=' && ++j > 2 )
return( XYSSL_ERR_BASE64_INVALID_CHARACTER );
if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
return( XYSSL_ERR_BASE64_INVALID_CHARACTER );
if( base64_dec_map[src[i]] < 64 && j != 0 )
return( XYSSL_ERR_BASE64_INVALID_CHARACTER );
n++;
}
if( n == 0 )
return( 0 );
n = ((n * 6) + 7) >> 3;
if( *dlen < n )
{
*dlen = n;
return( XYSSL_ERR_BASE64_BUFFER_TOO_SMALL );
}
for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
{
if( *src == '\r' || *src == '\n' )
continue;
j -= ( base64_dec_map[*src] == 64 );
x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
if( ++n == 4 )
{
n = 0;
if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
if( j > 2 ) *p++ = (unsigned char)( x );
}
}
*dlen = p - dst;
return( 0 );
}
#if defined(XYSSL_SELF_TEST)
#include <string.h>
#include <stdio.h>
static const unsigned char base64_test_dec[64] =
{
0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
};
static const unsigned char base64_test_enc[] =
"JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
"swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
/*
* Checkup routine
*/
int base64_self_test( int verbose )
{
int len;
unsigned char *src, buffer[128];
if( verbose != 0 )
printf( " Base64 encoding test: " );
len = sizeof( buffer );
src = (unsigned char *) base64_test_dec;
if( base64_encode( buffer, &len, src, 64 ) != 0 ||
memcmp( base64_test_enc, buffer, 88 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n Base64 decoding test: " );
len = sizeof( buffer );
src = (unsigned char *) base64_test_enc;
if( base64_decode( buffer, &len, src, 88 ) != 0 ||
memcmp( base64_test_dec, buffer, 64 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n\n" );
return( 0 );
}
#endif
#endif

1955
library/bignum.c Normal file

File diff suppressed because it is too large Load diff

211
library/certs.c Normal file
View file

@ -0,0 +1,211 @@
/*
* X.509 test certificates
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "xyssl/config.h"
#if defined(XYSSL_CERTS_C)
char test_ca_crt[] =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIDpTCCAo2gAwIBAgIBADANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJGUjEO\r\n"
"MAwGA1UEBxMFUGFyaXMxDjAMBgNVBAoTBVh5U1NMMRYwFAYDVQQDEw1YeVNTTCBU\r\n"
"ZXN0IENBMB4XDTA3MDcwNzA1MDAxOFoXDTE3MDcwNzA1MDAxOFowRTELMAkGA1UE\r\n"
"BhMCRlIxDjAMBgNVBAcTBVBhcmlzMQ4wDAYDVQQKEwVYeVNTTDEWMBQGA1UEAxMN\r\n"
"WHlTU0wgVGVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM+k\r\n"
"gt70fIPiYqmvXr+9uPmWoN405eoSzxdiRLLCHqL4V/Ts0E/H+JNfHS4DHlAgxrJu\r\n"
"+ZIadvSJuHkI6e1iMkAh5SU1DqaF3jrrFdJCooM6a077M4CRkE1tdAeZDf+BYp0q\r\n"
"BeMU9Y2+j7ibsQaPAizunbXLf4QdteExCwhYRJ8OVXSEaSNt339gJzTD6kOhES3b\r\n"
"lEN3qbx6lqFaJ5MLHTix5uNVc2rvbOizV5oLhJNqm52AKOp11tv6WTiI8loagvAc\r\n"
"jlhEZRNb9el5SL6Jai/uFcqXKzfXNKW3FYPQHFGobmiMfGt1lUSBJ3F2mrqEC7gC\r\n"
"wHy/FDvAI64/k5LZAFkCAwEAAaOBnzCBnDAMBgNVHRMEBTADAQH/MB0GA1UdDgQW\r\n"
"BBS87h+Y6Porg+SkfV7DdXKTMdkyZzBtBgNVHSMEZjBkgBS87h+Y6Porg+SkfV7D\r\n"
"dXKTMdkyZ6FJpEcwRTELMAkGA1UEBhMCRlIxDjAMBgNVBAcTBVBhcmlzMQ4wDAYD\r\n"
"VQQKEwVYeVNTTDEWMBQGA1UEAxMNWHlTU0wgVGVzdCBDQYIBADANBgkqhkiG9w0B\r\n"
"AQUFAAOCAQEAIHdoh0NCg6KAAhwDSmfEgSbKUI8/Zr/d56uw42HO0sj/uKPQzUco\r\n"
"3Mx2BYE1m1itg7q5OhrkB7J4ZB78EtNZM84nV+y6od3YpR0Z9VUxCx7948MozYRy\r\n"
"TKF5x/lKHRx1PJKfEO4clKdWTFAtWtGhewXrHJQ8C+ENh2Up2wTVh3Z+pEzuZNv3\r\n"
"u/JYu1H+vkt3l1WCy/9mxUnu+anW1DzxPWnjy4lx6Mi0BD2qfKBWLjVS+7v6ALcj\r\n"
"S2oRWWr4LUvXT7z9BBAvw2eJQD+a4uAya6EURG7AsAvr5MnWn/r0wLWmBJ6fB1Yp\r\n"
"F1kOmamOFvstLMf74rLX+LGKeJ/nwuI5FQ==\r\n"
"-----END CERTIFICATE-----\r\n";
char test_ca_key[] =
"-----BEGIN RSA PRIVATE KEY-----\r\n"
"Proc-Type: 4,ENCRYPTED\r\n"
"DEK-Info: DES-EDE3-CBC,7BDC280BA4C2F45C\r\n"
"\r\n"
"KI6rmwY0ChjF/0/Q7d1vE2jojZQTuF8j0wJUOf02PUUD4en8/FCLj69Pf3/lvOlu\r\n"
"F8hU4IuBHxN2+feuXp6xTmGd/VyKdWh4+NGtKr2V1gXfk2wqHk3/P/YuF7QhOQjZ\r\n"
"BlNF7n5o76Nufr3iwBbtIABCGQfNRUwGzrvmFXLIrSqns8ppv83qaD5jHVQQj5MM\r\n"
"cGIoidwmNORdVmBCVZ17dQ+lMPfqjhN27GBhzXbp9a2EP3w+IqrXOvcl4DqSY+DU\r\n"
"PIhS6KuQZ4iek4dI93wmw2D8Q67omcKYOX/BjCkZ/v6oq481qOej6MicIY/L9LxH\r\n"
"r91jqIYLJC+1w20YavB3kIkSe5zys30RzhPTOtG60j8kgiQ4Fh+L/nKBP5noOXGE\r\n"
"uzDBa051HCEYfufOVkXr6wBCFo9boqM1p/GI0Ze5gCsYY+Vzyu96gu+OGv55Jtyo\r\n"
"fY2yEwVKhfqNy+xJ+8dwf8dcc5vQLatXebDynuSPI2jbaos6MJT6n0LoY2TpAz47\r\n"
"vNE7UtEEdgZPPVwE4xO+dVa0kCqJxuG8b+ZZTHZidlQ6MBiebL4vXbeIFieQRzUM\r\n"
"06IQ7YqsiBVLYxicMlApdFpJ4QM2fFKlZRo+fHg8EN9HEbRpgxIf4IwAAFjOgsiO\r\n"
"ll7OmyzSF12NUIrRsIo02E4Y8X6xSFeYnOIiqZqdxG4xz/DZKoX6Js8WdYbtzrDv\r\n"
"7gYYEZy1cuR9PJzMDKXoLz/mjBqDsh11Vgm1nAHbhBqFaWSuueH/LV2rgRijUBKh\r\n"
"yMTnGXrz56DeJ85bYLjVEOM3xhvjsz6Fq5xLqXRTAzyQn7QuqRg2szLtCnN8olCh\r\n"
"rdS1Gd7EV5g24WnF9gTzYJ4lwO9oxOsPKKCD1Z77B+lbZLoxTu7+rakTtqLikWMv\r\n"
"7OILfR4iaIu1nKxhhXpwnze3u+1OWcuk0UnBjSnF519tlrgV3dmA0P2LHd6h6xru\r\n"
"vIgUFHbigCV0i55peEPxtcy9JGLGJ3WvHA3NGSsqkkB/ymdfEaMmEH7403UKqQqq\r\n"
"+K9Z1cYmeZlfoXClmdSjsxkYeN5raB0kOOSV/MEOySG+lztyLUGB4n46AZG2PgXN\r\n"
"A9g9tv2gqc51Vl+55qwTg5429DigjiByRkcmBU3A1aF8yzD1QerwobPmqeNZ0mWv\r\n"
"SllAvgVs2uy2Wf9/5gEWm+HjnJwS9VPNTocG/r+4BnDK8XG0Jy4oI+jSPxj/Y8Jt\r\n"
"0ejFPM5A7HGngiaPFYHxcwPwo4Aa4HZnk+keFrA+vF9eDd1IOj195a9TESL+IGt1\r\n"
"nuNmmuYjyJqM9Uvi1Mutv0UQ6Fl6yv4XxaUtMZKl4LtrAaMdW1T0PEgUG0tjSIxX\r\n"
"hBd1W+Ob4nmK29aa4iuXaOxeAA3QK7KCZo18CJFgnp1w97qohwlKf+4FuNXHL64Q\r\n"
"FgmpycV9nfP8G9aUYKAxs1+xutNv/B6opHmfLNL6d0cwi8dvGsrDdGlcyi8Dk/PF\r\n"
"GKSqlQTF5V7l4UOanefB51tuziEBY+LWcXP4XgqNGPQknPF90NnbH1EglQG2paqb\r\n"
"5bLyT8G6kfCSY4uHxs9lPuvfOjk9ptjy2FwfyBb3Sl4K+IFEE8XTNuNErh83AKh2\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
char test_ca_pwd[] = "test";
char test_srv_crt[] =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIDPjCCAiagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJGUjEO\r\n"
"MAwGA1UEBxMFUGFyaXMxDjAMBgNVBAoTBVh5U1NMMRYwFAYDVQQDEw1YeVNTTCBU\r\n"
"ZXN0IENBMB4XDTA3MDcwNzA1MDEyOVoXDTA4MDcwNjA1MDEyOVowMTELMAkGA1UE\r\n"
"BhMCRlIxDjAMBgNVBAoTBVh5U1NMMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0G\r\n"
"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC40PDcGTgmHkt6noXDfkjVuymjiNYB\r\n"
"gjtiL7uA1Ke3tXStacEecQek/OJxYqYr7ffcWalS29LL6HbKpi0xLZKBbD9ACkDh\r\n"
"1Z/SvHlyQPILJdYb9DMw+kzZds5myXUjzn7Aem1YjoxMZUAMyc34i2900X2pL0v2\r\n"
"SfCeJ9Ym4MOnZxYl217+dX9ZbkgIgrT6uY2IYK4boDwxbTcyT8i/NPsVsiMwtWPM\r\n"
"rnQMr+XbgS98sUzcZE70Pe1TlV9Iy8j/8d2OiFo+qTyMu/6UpM2s3gdkQkMzx+Sm\r\n"
"4QitRUjzmEXeUePRUjEgHIv7vz069xuVBzrks36w5BXiVAhLke/OTKVPAgMBAAGj\r\n"
"TTBLMAkGA1UdEwQCMAAwHQYDVR0OBBYEFNkOyCTx64SDdPySGWl/tzD7/WMSMB8G\r\n"
"A1UdIwQYMBaAFLzuH5jo+iuD5KR9XsN1cpMx2TJnMA0GCSqGSIb3DQEBBQUAA4IB\r\n"
"AQBelJv5t+suaqy5Lo5bjNeHjNZfgg8EigDQ7NqaosvlQZAsh2N34Gg5YdkGyVdg\r\n"
"s32I/K5aaywyUbG9qVXQxCM2T95qBqyK56h9yJoZKWQD9H//+zB8kCK/16WvRfv3\r\n"
"VA7eSR19qOFWlHe+1qGh2YhxeDUfyi+fm4D36dGxqC2A34tZjo0QPHKtIeqM0kJy\r\n"
"zzL65TlbJQKkyTuRHofFv0jW9ZFG2wkGysVgCY5fjuLI1do/sWUaXd2987iNFa+K\r\n"
"FrHsTi6urSfZuGlZNxDXDHEE7Q2snAvvev+KR7DD9X4DJGcPX9gA4CGJj+9ZzyAA\r\n"
"ZTGpOzk1hIH44RFs2lJMZRlE\r\n"
"-----END CERTIFICATE-----\r\n";
char test_srv_key[] =
"-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEowIBAAKCAQEAuNDw3Bk4Jh5Lep6Fw35I1bspo4jWAYI7Yi+7gNSnt7V0rWnB\r\n"
"HnEHpPzicWKmK+333FmpUtvSy+h2yqYtMS2SgWw/QApA4dWf0rx5ckDyCyXWG/Qz\r\n"
"MPpM2XbOZsl1I85+wHptWI6MTGVADMnN+ItvdNF9qS9L9knwnifWJuDDp2cWJdte\r\n"
"/nV/WW5ICIK0+rmNiGCuG6A8MW03Mk/IvzT7FbIjMLVjzK50DK/l24EvfLFM3GRO\r\n"
"9D3tU5VfSMvI//HdjohaPqk8jLv+lKTNrN4HZEJDM8fkpuEIrUVI85hF3lHj0VIx\r\n"
"IByL+789OvcblQc65LN+sOQV4lQIS5HvzkylTwIDAQABAoIBABeah8h0aBlmMRmd\r\n"
"+VN4Y3D4kF7UcRCMQ21Mz1Oq1Si/QgGLyiBLK0DFE16LzNE7eTZpNRjh/lAQhmtn\r\n"
"QcpQGa/x1TomlRbCo8DUVWZkKQWHdYroa0lMDliPtdimzhEepE2M1T5EJmLzY3S+\r\n"
"qVGe7UMsJjJfWgJAezyXteANQK+2YSt+CjPIqIHch1KexUnvdN9++1oEx6AbuZ8T\r\n"
"4avhFYZQP15tZNGsk2LfQlYS/NfbowkCsd0/TVubJBmDGUML/E5MbxjxLzlaNB2M\r\n"
"V59cBNgsgA35CODAUF4xOyoSfZGqG1Rb9qQrv1E6Jz56dG8SsKF3HqnDjxiPOVBN\r\n"
"FBnVJ+ECgYEA29MhAsKMm4XqBUKp6pIMFTgm/s1E5vxig70vqIiL+guvBhhQ7zs1\r\n"
"8UMTNXZoMELNoB/ev9fN0Cjc1Vr46b/x/yDw7wMb96i+vzENOzu4RHWi3OWpCPbp\r\n"
"qBKEi3hzN8M+BulPX8CDQx3aLRrfxw51J5EuA0NeybngbItgxTi0u6kCgYEA1zr0\r\n"
"6P5YdOhYHtSWDlkeD49MApcVuzaHnsHZVAhUqu3Rwiy9LRaJLZfr7fQDb9DYJbZp\r\n"
"sxTRLG6LSAcsR7mw+m+GvNqGt/9pSqbtW+L/VwVWSyF+YYklxZUD3UAAyrDVcDEC\r\n"
"a5S+jad4Csi/lVHt5ulWIckWL1fJvadn5ubKNDcCgYA+71xVGPP+lsFgTiytfrC8\r\n"
"5n2rl4MxinJ9+w0I+EbzCKNMYGvTgiU4dJasSMEdiBKs1FMGo7dF8F0BLHF1IsIa\r\n"
"5Ah2tXItXn9154o9OiTQXMmK6qmRaneM6fhOoeaCwYAhpGxYIpqx/Xr4TOhiag46\r\n"
"jMMaphAeOvw4t1K2RDziOQKBgQCyPCCU0gxuw/o1jda2CxbZy9EmU/erEX09+0n+\r\n"
"TOfQpSEPq/z9WaxAFY9LfsdZ0ZktoeHma1bNdL3i6A3DWAM3YSQzQMRPmzOWnqXx\r\n"
"cgoCBmlvzkzaeLjO5phMoLQHJmmafvuCG6uxov3F8Hi3LyHUF2c8k0nL6ucmJ3vj\r\n"
"uzu4AQKBgBSASMAJS63M9UJB1Eazy2v2NWw04CmzNxUfWrHuKpd/C2ik4QKu0sRO\r\n"
"r9KnkDgxxEhjDm7lXhlW12PU42yORst5I3Eaa1Cfi4KPFn/ozt+iNBYrzd8Tyvnb\r\n"
"qkdECl0+G2Fo/ER4NRCv7a24WNEsOMGzGRqw5cnSJrjbZLYMaIyK\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
char test_cli_crt[] =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIDPTCCAiWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJGUjEO\r\n"
"MAwGA1UEBxMFUGFyaXMxDjAMBgNVBAoTBVh5U1NMMRYwFAYDVQQDEw1YeVNTTCBU\r\n"
"ZXN0IENBMB4XDTA3MDcwNzA1MDEyMFoXDTA4MDcwNjA1MDEyMFowMDELMAkGA1UE\r\n"
"BhMCRlIxDjAMBgNVBAoTBVh5U1NMMREwDwYDVQQDEwhKb2UgVXNlcjCCASIwDQYJ\r\n"
"KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKZkg8ANl6kGmLGqKc6KUHb9IsZwb2+K\r\n"
"jBw83Qb0KuvPVnu3MzEcXFvOZ83g0PL/z8ob5PKr8HP6bVYzhsD65imcCDEEVPk2\r\n"
"9r0XGTggGjB601Fd8aTShUWE4NLrKw6YNXTXgTNdvhHNxXwqmdNVLkmZjj3ZwYUc\r\n"
"cEE8eE5jHs8cMDXJLMCwgKIM7Sax22OhSHQHKwifVO4/Fdw5G+Suys8PhMX2jDXM\r\n"
"ICFwq8ld+bZGoNUtgp48FWhAMfJyTEaHh9LC46KkqGSDRIzx7/4cPB6QqrpzJN0o\r\n"
"Kr8kH7vdRDTFDmO23D4C5l0Bw/2aC76DhEJpB2bGA4iIszJs+F/PIL8CAwEAAaNN\r\n"
"MEswCQYDVR0TBAIwADAdBgNVHQ4EFgQUiWX1IvjRdYGt0zz5Sq16x01k0o4wHwYD\r\n"
"VR0jBBgwFoAUvO4fmOj6K4PkpH1ew3VykzHZMmcwDQYJKoZIhvcNAQEFBQADggEB\r\n"
"AGdqD7VThJmC+oeeMUHk2TQX2wZNU+GsC+RLjtlenckny95KnljGvMtCznyLkS5D\r\n"
"fAjLKfR1No8pk5gRdscqgyIuQx5WnHNv4QBZmMsmvDICxzRQaxuPFHbS4aLXldeL\r\n"
"yOWm5Z4qkMHpCKvA86blYsEkksGDV47fF9ZkOQ8nkh7Z4eY4/5TwqTY72ww5g4NL\r\n"
"6DZtWpcpGbX99NRaNVzcq9D+ElxkgHnH4YWafOKBclSgqrutbRLi2uZx/QpvuF+i\r\n"
"sUbe+HFPMWwU5lBv/oOhQkz0VD+HusYtXWS2lG88cT40aNly2CkYUugdTR/b9Uea\r\n"
"p/i862sL/lO40qlQ0xV5N7U=\r\n"
"-----END CERTIFICATE-----\r\n";
char test_cli_key[] =
"-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEowIBAAKCAQEApmSDwA2XqQaYsaopzopQdv0ixnBvb4qMHDzdBvQq689We7cz\r\n"
"MRxcW85nzeDQ8v/Pyhvk8qvwc/ptVjOGwPrmKZwIMQRU+Tb2vRcZOCAaMHrTUV3x\r\n"
"pNKFRYTg0usrDpg1dNeBM12+Ec3FfCqZ01UuSZmOPdnBhRxwQTx4TmMezxwwNcks\r\n"
"wLCAogztJrHbY6FIdAcrCJ9U7j8V3Dkb5K7Kzw+ExfaMNcwgIXCryV35tkag1S2C\r\n"
"njwVaEAx8nJMRoeH0sLjoqSoZINEjPHv/hw8HpCqunMk3SgqvyQfu91ENMUOY7bc\r\n"
"PgLmXQHD/ZoLvoOEQmkHZsYDiIizMmz4X88gvwIDAQABAoIBAE0nBkAjDVN+j4ax\r\n"
"1DjEwZKqxVkmAUXDBDyDrCjxRoWY2gz7YW1ALUMUbeV0fO5v1zVrwbkUKKZeVBxI\r\n"
"QA9zRw28H8A6tfvolHgRIcx4dixMh3ePC+DVDJ6zglvKV2ipAwBufKYIrX0r4Io2\r\n"
"ZqUrNg9CeEYNlkHWceaN12rhYwO82pgHxnB1p5pI42pY7lzyLgSddf5n+M5UBOJI\r\n"
"gsNCkvbGdv7WQPVFTRDiRgEnCJ3rI8oPSK6MOUWJw3rh2hbkx+ex8NPvEKbzEXiU\r\n"
"p5j1AlbHIWP5sYBbA1YviFtryAV4fyfLcWPfoqa33Oozofjlwoj0Aixz+6rerLjZ\r\n"
"cpTSrAECgYEA2oCffUo6HH3Lq9oeWhFCoOyG3YjZmFrJaJwjHnvroX9/pXHqYKog\r\n"
"TehcjUJBtFZw0klcetYbZCFqT8v9nf0uPlgaiVGCtXf1MSbFXDUFKkYBiFwzdWMT\r\n"
"Ysmvhff82jMWZ8ecsXTyDRl858SR5WPZ52qEsCc5X2un7QENm6FtVT8CgYEAwvKS\r\n"
"zQNzuoJETqZX7AalmK3JM8Fdam+Qm5LNMcbvhbKwI8HKMS1VMuqaR0XdAX/iMXAx\r\n"
"P1VhSsmoSDbsMpxBEZIptpCen/GcqctITxANTakrBHxqb2aQ5EEu7SzgfHZWse3/\r\n"
"vQEyfcFTBlPIdcZUDzk4/w7WmyivpYtCWoAh1IECgYEA0UYZ+1UJfVpapRj+swMP\r\n"
"DrQbo7i7t7lUaFYLKNpFX2OPLTWC5txqnlOruTu5VHDqE+5hneDNUUTT3uOg4B2q\r\n"
"mdmmaNjh2M6wz0e0BVFexhNQynqMaqTe32IOM8DFs3L0xacgg7JfVn6P7CeQGOVe\r\n"
"wc96kICw6ZxhtJSqpOGipt8CgYBI/0Pw+IXxJK4nNSpe+u4vCYP5mUI9hKEFYCbt\r\n"
"qKwvyAUknn/zgiIQ+r/iSErFMPmlwXjvWi0gL/qPb+Fp4hCLX8u2zNhY08Px4Gin\r\n"
"Ej+pANtWxq+kHyfKEI5dyRwV/snfvlqwjy404JsSF3VMhIMdYDPzbb72Qnni5w5l\r\n"
"jO0eAQKBgBqt9jJMd1JdpemC2dm0BuuDIz2h3/MH+CMjfaDLenVpKykn17B6N92h\r\n"
"klMesqK3RQzDGwauDw431LQw0R69onn9fCM3wJw2yEC6wC9sF8I8hsNZbt64yZhZ\r\n"
"4Bi2YRTiHhpEuBqKlhHLDFHneo3SMYh8PU/PDQQcyWGHHUi9z1RE\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
char xyssl_ca_crt[] =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh\r\n"
"MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE\r\n"
"YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3\r\n"
"MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo\r\n"
"ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg\r\n"
"MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN\r\n"
"ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA\r\n"
"PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w\r\n"
"wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi\r\n"
"EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY\r\n"
"avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+\r\n"
"YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE\r\n"
"sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h\r\n"
"/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5\r\n"
"IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj\r\n"
"YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD\r\n"
"ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy\r\n"
"OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P\r\n"
"TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ\r\n"
"HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER\r\n"
"dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf\r\n"
"ReYNnyicsbkqWletNw+vHX/bvZ8=\r\n"
"-----END CERTIFICATE-----\r\n";
#endif

202
library/debug.c Normal file
View file

@ -0,0 +1,202 @@
/*
* Debugging routines
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "xyssl/config.h"
#if defined(XYSSL_DEBUG_C)
#include "xyssl/debug.h"
#include <stdarg.h>
#include <stdlib.h>
#if defined _MSC_VER && !defined snprintf
#define snprintf _snprintf
#endif
#if defined _MSC_VER && !defined vsnprintf
#define vsnprintf _vsnprintf
#endif
char *debug_fmt( const char *format, ... )
{
va_list argp;
static char str[512];
int maxlen = sizeof( str ) - 1;
va_start( argp, format );
vsnprintf( str, maxlen, format, argp );
va_end( argp );
str[maxlen] = '\0';
return( str );
}
void debug_print_msg( ssl_context *ssl, int level,
char *file, int line, char *text )
{
char str[512];
int maxlen = sizeof( str ) - 1;
if( ssl->f_dbg == NULL )
return;
snprintf( str, maxlen, "%s(%04d): %s\n", file, line, text );
str[maxlen] = '\0';
ssl->f_dbg( ssl->p_dbg, level, str );
}
void debug_print_ret( ssl_context *ssl, int level,
char *file, int line, char *text, int ret )
{
char str[512];
int maxlen = sizeof( str ) - 1;
if( ssl->f_dbg == NULL )
return;
snprintf( str, maxlen, "%s(%04d): %s() returned %d (0x%x)\n",
file, line, text, ret, ret );
str[maxlen] = '\0';
ssl->f_dbg( ssl->p_dbg, level, str );
}
void debug_print_buf( ssl_context *ssl, int level,
char *file, int line, char *text,
unsigned char *buf, int len )
{
char str[512];
int i, maxlen = sizeof( str ) - 1;
if( ssl->f_dbg == NULL || len < 0 )
return;
snprintf( str, maxlen, "%s(%04d): dumping '%s' (%d bytes)\n",
file, line, text, len );
str[maxlen] = '\0';
ssl->f_dbg( ssl->p_dbg, level, str );
for( i = 0; i < len; i++ )
{
if( i >= 4096 )
break;
if( i % 16 == 0 )
{
if( i > 0 )
ssl->f_dbg( ssl->p_dbg, level, "\n" );
snprintf( str, maxlen, "%s(%04d): %04x: ", file, line, i );
str[maxlen] = '\0';
ssl->f_dbg( ssl->p_dbg, level, str );
}
snprintf( str, maxlen, " %02x", (unsigned int) buf[i] );
str[maxlen] = '\0';
ssl->f_dbg( ssl->p_dbg, level, str );
}
if( len > 0 )
ssl->f_dbg( ssl->p_dbg, level, "\n" );
}
void debug_print_mpi( ssl_context *ssl, int level,
char *file, int line, char *text, mpi *X )
{
char str[512];
int i, j, k, n, maxlen = sizeof( str ) - 1;
if( ssl->f_dbg == NULL || X == NULL )
return;
for( n = X->n - 1; n >= 0; n-- )
if( X->p[n] != 0 )
break;
snprintf( str, maxlen, "%s(%04d): value of '%s' (%d bits) is:\n",
file, line, text, ((n + 1) * sizeof( t_int )) << 3 );
str[maxlen] = '\0';
ssl->f_dbg( ssl->p_dbg, level, str );
for( i = n, j = 0; i >= 0; i--, j++ )
{
if( j % ( 16 / sizeof( t_int ) ) == 0 )
{
if( j > 0 )
ssl->f_dbg( ssl->p_dbg, level, "\n" );
snprintf( str, maxlen, "%s(%04d): ", file, line );
str[maxlen] = '\0';
ssl->f_dbg( ssl->p_dbg, level, str );
}
for( k = sizeof( t_int ) - 1; k >= 0; k-- )
{
snprintf( str, maxlen, " %02x", (unsigned int)
( X->p[i] >> (k << 3) ) & 0xFF );
str[maxlen] = '\0';
ssl->f_dbg( ssl->p_dbg, level, str );
}
}
ssl->f_dbg( ssl->p_dbg, level, "\n" );
}
void debug_print_crt( ssl_context *ssl, int level,
char *file, int line, char *text, x509_cert *crt )
{
char str[512], prefix[64], *p;
int i = 0, maxlen = sizeof( prefix ) - 1;
if( ssl->f_dbg == NULL || crt == NULL )
return;
snprintf( prefix, maxlen, "%s(%04d): ", file, line );
prefix[maxlen] = '\0';
maxlen = sizeof( str ) - 1;
while( crt != NULL && crt->next != NULL )
{
p = x509parse_cert_info( prefix, crt );
snprintf( str, maxlen, "%s(%04d): %s #%d:\n%s",
file, line, text, ++i, p );
str[maxlen] = '\0';
ssl->f_dbg( ssl->p_dbg, level, str );
debug_print_mpi( ssl, level, file, line,
"crt->rsa.N", &crt->rsa.N );
debug_print_mpi( ssl, level, file, line,
"crt->rsa.E", &crt->rsa.E );
crt = crt->next;
}
}
#endif

876
library/des.c Normal file
View file

@ -0,0 +1,876 @@
/*
* FIPS-46-3 compliant Triple-DES implementation
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* DES, on which TDES is based, was originally designed by Horst Feistel
* at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
*
* http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
*/
#include "xyssl/config.h"
#if defined(XYSSL_DES_C)
#include "xyssl/des.h"
#include <string.h>
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
| ( (unsigned long) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*
* Expanded DES S-boxes
*/
static const unsigned long SB1[64] =
{
0x01010400, 0x00000000, 0x00010000, 0x01010404,
0x01010004, 0x00010404, 0x00000004, 0x00010000,
0x00000400, 0x01010400, 0x01010404, 0x00000400,
0x01000404, 0x01010004, 0x01000000, 0x00000004,
0x00000404, 0x01000400, 0x01000400, 0x00010400,
0x00010400, 0x01010000, 0x01010000, 0x01000404,
0x00010004, 0x01000004, 0x01000004, 0x00010004,
0x00000000, 0x00000404, 0x00010404, 0x01000000,
0x00010000, 0x01010404, 0x00000004, 0x01010000,
0x01010400, 0x01000000, 0x01000000, 0x00000400,
0x01010004, 0x00010000, 0x00010400, 0x01000004,
0x00000400, 0x00000004, 0x01000404, 0x00010404,
0x01010404, 0x00010004, 0x01010000, 0x01000404,
0x01000004, 0x00000404, 0x00010404, 0x01010400,
0x00000404, 0x01000400, 0x01000400, 0x00000000,
0x00010004, 0x00010400, 0x00000000, 0x01010004
};
static const unsigned long SB2[64] =
{
0x80108020, 0x80008000, 0x00008000, 0x00108020,
0x00100000, 0x00000020, 0x80100020, 0x80008020,
0x80000020, 0x80108020, 0x80108000, 0x80000000,
0x80008000, 0x00100000, 0x00000020, 0x80100020,
0x00108000, 0x00100020, 0x80008020, 0x00000000,
0x80000000, 0x00008000, 0x00108020, 0x80100000,
0x00100020, 0x80000020, 0x00000000, 0x00108000,
0x00008020, 0x80108000, 0x80100000, 0x00008020,
0x00000000, 0x00108020, 0x80100020, 0x00100000,
0x80008020, 0x80100000, 0x80108000, 0x00008000,
0x80100000, 0x80008000, 0x00000020, 0x80108020,
0x00108020, 0x00000020, 0x00008000, 0x80000000,
0x00008020, 0x80108000, 0x00100000, 0x80000020,
0x00100020, 0x80008020, 0x80000020, 0x00100020,
0x00108000, 0x00000000, 0x80008000, 0x00008020,
0x80000000, 0x80100020, 0x80108020, 0x00108000
};
static const unsigned long SB3[64] =
{
0x00000208, 0x08020200, 0x00000000, 0x08020008,
0x08000200, 0x00000000, 0x00020208, 0x08000200,
0x00020008, 0x08000008, 0x08000008, 0x00020000,
0x08020208, 0x00020008, 0x08020000, 0x00000208,
0x08000000, 0x00000008, 0x08020200, 0x00000200,
0x00020200, 0x08020000, 0x08020008, 0x00020208,
0x08000208, 0x00020200, 0x00020000, 0x08000208,
0x00000008, 0x08020208, 0x00000200, 0x08000000,
0x08020200, 0x08000000, 0x00020008, 0x00000208,
0x00020000, 0x08020200, 0x08000200, 0x00000000,
0x00000200, 0x00020008, 0x08020208, 0x08000200,
0x08000008, 0x00000200, 0x00000000, 0x08020008,
0x08000208, 0x00020000, 0x08000000, 0x08020208,
0x00000008, 0x00020208, 0x00020200, 0x08000008,
0x08020000, 0x08000208, 0x00000208, 0x08020000,
0x00020208, 0x00000008, 0x08020008, 0x00020200
};
static const unsigned long SB4[64] =
{
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802080, 0x00800081, 0x00800001, 0x00002001,
0x00000000, 0x00802000, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00800080, 0x00800001,
0x00000001, 0x00002000, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002001, 0x00002080,
0x00800081, 0x00000001, 0x00002080, 0x00800080,
0x00002000, 0x00802080, 0x00802081, 0x00000081,
0x00800080, 0x00800001, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00000000, 0x00802000,
0x00002080, 0x00800080, 0x00800081, 0x00000001,
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802081, 0x00000081, 0x00000001, 0x00002000,
0x00800001, 0x00002001, 0x00802080, 0x00800081,
0x00002001, 0x00002080, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002000, 0x00802080
};
static const unsigned long SB5[64] =
{
0x00000100, 0x02080100, 0x02080000, 0x42000100,
0x00080000, 0x00000100, 0x40000000, 0x02080000,
0x40080100, 0x00080000, 0x02000100, 0x40080100,
0x42000100, 0x42080000, 0x00080100, 0x40000000,
0x02000000, 0x40080000, 0x40080000, 0x00000000,
0x40000100, 0x42080100, 0x42080100, 0x02000100,
0x42080000, 0x40000100, 0x00000000, 0x42000000,
0x02080100, 0x02000000, 0x42000000, 0x00080100,
0x00080000, 0x42000100, 0x00000100, 0x02000000,
0x40000000, 0x02080000, 0x42000100, 0x40080100,
0x02000100, 0x40000000, 0x42080000, 0x02080100,
0x40080100, 0x00000100, 0x02000000, 0x42080000,
0x42080100, 0x00080100, 0x42000000, 0x42080100,
0x02080000, 0x00000000, 0x40080000, 0x42000000,
0x00080100, 0x02000100, 0x40000100, 0x00080000,
0x00000000, 0x40080000, 0x02080100, 0x40000100
};
static const unsigned long SB6[64] =
{
0x20000010, 0x20400000, 0x00004000, 0x20404010,
0x20400000, 0x00000010, 0x20404010, 0x00400000,
0x20004000, 0x00404010, 0x00400000, 0x20000010,
0x00400010, 0x20004000, 0x20000000, 0x00004010,
0x00000000, 0x00400010, 0x20004010, 0x00004000,
0x00404000, 0x20004010, 0x00000010, 0x20400010,
0x20400010, 0x00000000, 0x00404010, 0x20404000,
0x00004010, 0x00404000, 0x20404000, 0x20000000,
0x20004000, 0x00000010, 0x20400010, 0x00404000,
0x20404010, 0x00400000, 0x00004010, 0x20000010,
0x00400000, 0x20004000, 0x20000000, 0x00004010,
0x20000010, 0x20404010, 0x00404000, 0x20400000,
0x00404010, 0x20404000, 0x00000000, 0x20400010,
0x00000010, 0x00004000, 0x20400000, 0x00404010,
0x00004000, 0x00400010, 0x20004010, 0x00000000,
0x20404000, 0x20000000, 0x00400010, 0x20004010
};
static const unsigned long SB7[64] =
{
0x00200000, 0x04200002, 0x04000802, 0x00000000,
0x00000800, 0x04000802, 0x00200802, 0x04200800,
0x04200802, 0x00200000, 0x00000000, 0x04000002,
0x00000002, 0x04000000, 0x04200002, 0x00000802,
0x04000800, 0x00200802, 0x00200002, 0x04000800,
0x04000002, 0x04200000, 0x04200800, 0x00200002,
0x04200000, 0x00000800, 0x00000802, 0x04200802,
0x00200800, 0x00000002, 0x04000000, 0x00200800,
0x04000000, 0x00200800, 0x00200000, 0x04000802,
0x04000802, 0x04200002, 0x04200002, 0x00000002,
0x00200002, 0x04000000, 0x04000800, 0x00200000,
0x04200800, 0x00000802, 0x00200802, 0x04200800,
0x00000802, 0x04000002, 0x04200802, 0x04200000,
0x00200800, 0x00000000, 0x00000002, 0x04200802,
0x00000000, 0x00200802, 0x04200000, 0x00000800,
0x04000002, 0x04000800, 0x00000800, 0x00200002
};
static const unsigned long SB8[64] =
{
0x10001040, 0x00001000, 0x00040000, 0x10041040,
0x10000000, 0x10001040, 0x00000040, 0x10000000,
0x00040040, 0x10040000, 0x10041040, 0x00041000,
0x10041000, 0x00041040, 0x00001000, 0x00000040,
0x10040000, 0x10000040, 0x10001000, 0x00001040,
0x00041000, 0x00040040, 0x10040040, 0x10041000,
0x00001040, 0x00000000, 0x00000000, 0x10040040,
0x10000040, 0x10001000, 0x00041040, 0x00040000,
0x00041040, 0x00040000, 0x10041000, 0x00001000,
0x00000040, 0x10040040, 0x00001000, 0x00041040,
0x10001000, 0x00000040, 0x10000040, 0x10040000,
0x10040040, 0x10000000, 0x00040000, 0x10001040,
0x00000000, 0x10041040, 0x00040040, 0x10000040,
0x10040000, 0x10001000, 0x10001040, 0x00000000,
0x10041040, 0x00041000, 0x00041000, 0x00001040,
0x00001040, 0x00040040, 0x10000000, 0x10041000
};
/*
* PC1: left and right halves bit-swap
*/
static const unsigned long LHs[16] =
{
0x00000000, 0x00000001, 0x00000100, 0x00000101,
0x00010000, 0x00010001, 0x00010100, 0x00010101,
0x01000000, 0x01000001, 0x01000100, 0x01000101,
0x01010000, 0x01010001, 0x01010100, 0x01010101
};
static const unsigned long RHs[16] =
{
0x00000000, 0x01000000, 0x00010000, 0x01010000,
0x00000100, 0x01000100, 0x00010100, 0x01010100,
0x00000001, 0x01000001, 0x00010001, 0x01010001,
0x00000101, 0x01000101, 0x00010101, 0x01010101,
};
/*
* Initial Permutation macro
*/
#define DES_IP(X,Y) \
{ \
T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \
T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \
X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \
}
/*
* Final Permutation macro
*/
#define DES_FP(X,Y) \
{ \
X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \
T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \
Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \
T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
}
/*
* DES round macro
*/
#define DES_ROUND(X,Y) \
{ \
T = *SK++ ^ X; \
Y ^= SB8[ (T ) & 0x3F ] ^ \
SB6[ (T >> 8) & 0x3F ] ^ \
SB4[ (T >> 16) & 0x3F ] ^ \
SB2[ (T >> 24) & 0x3F ]; \
\
T = *SK++ ^ ((X << 28) | (X >> 4)); \
Y ^= SB7[ (T ) & 0x3F ] ^ \
SB5[ (T >> 8) & 0x3F ] ^ \
SB3[ (T >> 16) & 0x3F ] ^ \
SB1[ (T >> 24) & 0x3F ]; \
}
#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
static void des_setkey( unsigned long SK[32], unsigned char key[8] )
{
int i;
unsigned long X, Y, T;
GET_ULONG_BE( X, key, 0 );
GET_ULONG_BE( Y, key, 4 );
/*
* Permuted Choice 1
*/
T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4);
T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T );
X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2)
| (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] )
| (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
| (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2)
| (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] )
| (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
| (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
X &= 0x0FFFFFFF;
Y &= 0x0FFFFFFF;
/*
* calculate subkeys
*/
for( i = 0; i < 16; i++ )
{
if( i < 2 || i == 8 || i == 15 )
{
X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF;
Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF;
}
else
{
X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF;
Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF;
}
*SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000)
| ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
| ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000)
| ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000)
| ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000)
| ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000)
| ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400)
| ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100)
| ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010)
| ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004)
| ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
*SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
| ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
| ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000)
| ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
| ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000)
| ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000)
| ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000)
| ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400)
| ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100)
| ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011)
| ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002);
}
}
/*
* DES key schedule (56-bit, encryption)
*/
void des_setkey_enc( des_context *ctx, unsigned char key[8] )
{
des_setkey( ctx->sk, key );
}
/*
* DES key schedule (56-bit, decryption)
*/
void des_setkey_dec( des_context *ctx, unsigned char key[8] )
{
int i;
des_setkey( ctx->sk, key );
for( i = 0; i < 16; i += 2 )
{
SWAP( ctx->sk[i ], ctx->sk[30 - i] );
SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
}
}
static void des3_set2key( unsigned long esk[96],
unsigned long dsk[96],
unsigned char key[16] )
{
int i;
des_setkey( esk, key );
des_setkey( dsk + 32, key + 8 );
for( i = 0; i < 32; i += 2 )
{
dsk[i ] = esk[30 - i];
dsk[i + 1] = esk[31 - i];
esk[i + 32] = dsk[62 - i];
esk[i + 33] = dsk[63 - i];
esk[i + 64] = esk[i ];
esk[i + 65] = esk[i + 1];
dsk[i + 64] = dsk[i ];
dsk[i + 65] = dsk[i + 1];
}
}
/*
* Triple-DES key schedule (112-bit, encryption)
*/
void des3_set2key_enc( des3_context *ctx, unsigned char key[16] )
{
unsigned long sk[96];
des3_set2key( ctx->sk, sk, key );
memset( sk, 0, sizeof( sk ) );
}
/*
* Triple-DES key schedule (112-bit, decryption)
*/
void des3_set2key_dec( des3_context *ctx, unsigned char key[16] )
{
unsigned long sk[96];
des3_set2key( sk, ctx->sk, key );
memset( sk, 0, sizeof( sk ) );
}
static void des3_set3key( unsigned long esk[96],
unsigned long dsk[96],
unsigned char key[24] )
{
int i;
des_setkey( esk, key );
des_setkey( dsk + 32, key + 8 );
des_setkey( esk + 64, key + 16 );
for( i = 0; i < 32; i += 2 )
{
dsk[i ] = esk[94 - i];
dsk[i + 1] = esk[95 - i];
esk[i + 32] = dsk[62 - i];
esk[i + 33] = dsk[63 - i];
dsk[i + 64] = esk[30 - i];
dsk[i + 65] = esk[31 - i];
}
}
/*
* Triple-DES key schedule (168-bit, encryption)
*/
void des3_set3key_enc( des3_context *ctx, unsigned char key[24] )
{
unsigned long sk[96];
des3_set3key( ctx->sk, sk, key );
memset( sk, 0, sizeof( sk ) );
}
/*
* Triple-DES key schedule (168-bit, decryption)
*/
void des3_set3key_dec( des3_context *ctx, unsigned char key[24] )
{
unsigned long sk[96];
des3_set3key( sk, ctx->sk, key );
memset( sk, 0, sizeof( sk ) );
}
/*
* DES-ECB block encryption/decryption
*/
void des_crypt_ecb( des_context *ctx,
unsigned char input[8],
unsigned char output[8] )
{
int i;
unsigned long X, Y, T, *SK;
SK = ctx->sk;
GET_ULONG_BE( X, input, 0 );
GET_ULONG_BE( Y, input, 4 );
DES_IP( X, Y );
for( i = 0; i < 8; i++ )
{
DES_ROUND( Y, X );
DES_ROUND( X, Y );
}
DES_FP( Y, X );
PUT_ULONG_BE( Y, output, 0 );
PUT_ULONG_BE( X, output, 4 );
}
/*
* DES-CBC buffer encryption/decryption
*/
void des_crypt_cbc( des_context *ctx,
int mode,
int length,
unsigned char iv[8],
unsigned char *input,
unsigned char *output )
{
int i;
unsigned char temp[8];
if( mode == DES_ENCRYPT )
{
while( length > 0 )
{
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( input[i] ^ iv[i] );
des_crypt_ecb( ctx, output, output );
memcpy( iv, output, 8 );
input += 8;
output += 8;
length -= 8;
}
}
else /* DES_DECRYPT */
{
while( length > 0 )
{
memcpy( temp, input, 8 );
des_crypt_ecb( ctx, input, output );
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( output[i] ^ iv[i] );
memcpy( iv, temp, 8 );
input += 8;
output += 8;
length -= 8;
}
}
}
/*
* 3DES-ECB block encryption/decryption
*/
void des3_crypt_ecb( des3_context *ctx,
unsigned char input[8],
unsigned char output[8] )
{
int i;
unsigned long X, Y, T, *SK;
SK = ctx->sk;
GET_ULONG_BE( X, input, 0 );
GET_ULONG_BE( Y, input, 4 );
DES_IP( X, Y );
for( i = 0; i < 8; i++ )
{
DES_ROUND( Y, X );
DES_ROUND( X, Y );
}
for( i = 0; i < 8; i++ )
{
DES_ROUND( X, Y );
DES_ROUND( Y, X );
}
for( i = 0; i < 8; i++ )
{
DES_ROUND( Y, X );
DES_ROUND( X, Y );
}
DES_FP( Y, X );
PUT_ULONG_BE( Y, output, 0 );
PUT_ULONG_BE( X, output, 4 );
}
/*
* 3DES-CBC buffer encryption/decryption
*/
void des3_crypt_cbc( des3_context *ctx,
int mode,
int length,
unsigned char iv[8],
unsigned char *input,
unsigned char *output )
{
int i;
unsigned char temp[8];
if( mode == DES_ENCRYPT )
{
while( length > 0 )
{
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( input[i] ^ iv[i] );
des3_crypt_ecb( ctx, output, output );
memcpy( iv, output, 8 );
input += 8;
output += 8;
length -= 8;
}
}
else /* DES_DECRYPT */
{
while( length > 0 )
{
memcpy( temp, input, 8 );
des3_crypt_ecb( ctx, input, output );
for( i = 0; i < 8; i++ )
output[i] = (unsigned char)( output[i] ^ iv[i] );
memcpy( iv, temp, 8 );
input += 8;
output += 8;
length -= 8;
}
}
}
#if defined(XYSSL_SELF_TEST)
#include <stdio.h>
/*
* DES and 3DES test vectors from:
*
* http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip
*/
static const unsigned char des3_test_keys[24] =
{
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
};
static const unsigned char des3_test_iv[8] =
{
0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
};
static const unsigned char des3_test_buf[8] =
{
0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
};
static const unsigned char des3_test_ecb_dec[3][8] =
{
{ 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
{ 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
{ 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
};
static const unsigned char des3_test_ecb_enc[3][8] =
{
{ 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
{ 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
{ 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
};
static const unsigned char des3_test_cbc_dec[3][8] =
{
{ 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
{ 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
{ 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
};
static const unsigned char des3_test_cbc_enc[3][8] =
{
{ 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
{ 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
{ 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
};
/*
* Checkup routine
*/
int des_self_test( int verbose )
{
int i, j, u, v;
des_context ctx;
des3_context ctx3;
unsigned char key[24];
unsigned char buf[8];
unsigned char prv[8];
unsigned char iv[8];
memset( key, 0, 24 );
/*
* ECB mode
*/
for( i = 0; i < 6; i++ )
{
u = i >> 1;
v = i & 1;
if( verbose != 0 )
printf( " DES%c-ECB-%3d (%s): ",
( u == 0 ) ? ' ' : '3', 56 + u * 56,
( v == DES_DECRYPT ) ? "dec" : "enc" );
memcpy( buf, des3_test_buf, 8 );
switch( i )
{
case 0:
des_setkey_dec( &ctx, (unsigned char *) des3_test_keys );
break;
case 1:
des_setkey_enc( &ctx, (unsigned char *) des3_test_keys );
break;
case 2:
des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys );
break;
case 3:
des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys );
break;
case 4:
des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys );
break;
case 5:
des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys );
break;
default:
return( 1 );
}
for( j = 0; j < 10000; j++ )
{
if( u == 0 )
des_crypt_ecb( &ctx, buf, buf );
else
des3_crypt_ecb( &ctx3, buf, buf );
}
if( ( v == DES_DECRYPT &&
memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
( v != DES_DECRYPT &&
memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
/*
* CBC mode
*/
for( i = 0; i < 6; i++ )
{
u = i >> 1;
v = i & 1;
if( verbose != 0 )
printf( " DES%c-CBC-%3d (%s): ",
( u == 0 ) ? ' ' : '3', 56 + u * 56,
( v == DES_DECRYPT ) ? "dec" : "enc" );
memcpy( iv, des3_test_iv, 8 );
memcpy( prv, des3_test_iv, 8 );
memcpy( buf, des3_test_buf, 8 );
switch( i )
{
case 0:
des_setkey_dec( &ctx, (unsigned char *) des3_test_keys );
break;
case 1:
des_setkey_enc( &ctx, (unsigned char *) des3_test_keys );
break;
case 2:
des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys );
break;
case 3:
des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys );
break;
case 4:
des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys );
break;
case 5:
des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys );
break;
default:
return( 1 );
}
if( v == DES_DECRYPT )
{
for( j = 0; j < 10000; j++ )
{
if( u == 0 )
des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
else
des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
}
}
else
{
for( j = 0; j < 10000; j++ )
{
unsigned char tmp[8];
if( u == 0 )
des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
else
des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
memcpy( tmp, prv, 8 );
memcpy( prv, buf, 8 );
memcpy( buf, tmp, 8 );
}
memcpy( buf, prv, 8 );
}
if( ( v == DES_DECRYPT &&
memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
( v != DES_DECRYPT &&
memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
#endif

253
library/dhm.c Normal file
View file

@ -0,0 +1,253 @@
/*
* Diffie-Hellman-Merkle key exchange
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* Reference:
*
* http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12)
*/
#include "xyssl/config.h"
#if defined(XYSSL_DHM_C)
#include "xyssl/dhm.h"
#include <string.h>
/*
* helper to validate the mpi size and import it
*/
static int dhm_read_bignum( mpi *X,
unsigned char **p,
unsigned char *end )
{
int ret, n;
if( end - *p < 2 )
return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
n = ( (*p)[0] << 8 ) | (*p)[1];
(*p) += 2;
if( (int)( end - *p ) < n )
return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 )
return( XYSSL_ERR_DHM_READ_PARAMS_FAILED | ret );
(*p) += n;
return( 0 );
}
/*
* Parse the ServerKeyExchange parameters
*/
int dhm_read_params( dhm_context *ctx,
unsigned char **p,
unsigned char *end )
{
int ret, n;
memset( ctx, 0, sizeof( dhm_context ) );
if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
return( ret );
ctx->len = mpi_size( &ctx->P );
if( end - *p < 2 )
return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
n = ( (*p)[0] << 8 ) | (*p)[1];
(*p) += 2;
if( end != *p + n )
return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
return( 0 );
}
/*
* Setup and write the ServerKeyExchange parameters
*/
int dhm_make_params( dhm_context *ctx, int x_size,
unsigned char *output, int *olen,
int (*f_rng)(void *), void *p_rng )
{
int i, ret, n, n1, n2, n3;
unsigned char *p;
/*
* generate X and calculate GX = G^X mod P
*/
n = x_size / sizeof( t_int );
MPI_CHK( mpi_grow( &ctx->X, n ) );
MPI_CHK( mpi_lset( &ctx->X, 0 ) );
n = x_size >> 3;
p = (unsigned char *) ctx->X.p;
for( i = 0; i < n; i++ )
*p++ = (unsigned char) f_rng( p_rng );
while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
mpi_shift_r( &ctx->X, 1 );
MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
&ctx->P , &ctx->RP ) );
/*
* export P, G, GX
*/
#define DHM_MPI_EXPORT(X,n) \
MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \
*p++ = (unsigned char)( n >> 8 ); \
*p++ = (unsigned char)( n ); p += n;
n1 = mpi_size( &ctx->P );
n2 = mpi_size( &ctx->G );
n3 = mpi_size( &ctx->GX );
p = output;
DHM_MPI_EXPORT( &ctx->P , n1 );
DHM_MPI_EXPORT( &ctx->G , n2 );
DHM_MPI_EXPORT( &ctx->GX, n3 );
*olen = p - output;
ctx->len = n1;
cleanup:
if( ret != 0 )
return( ret | XYSSL_ERR_DHM_MAKE_PARAMS_FAILED );
return( 0 );
}
/*
* Import the peer's public value G^Y
*/
int dhm_read_public( dhm_context *ctx,
unsigned char *input, int ilen )
{
int ret;
if( ctx == NULL || ilen < 1 || ilen > ctx->len )
return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
return( XYSSL_ERR_DHM_READ_PUBLIC_FAILED | ret );
return( 0 );
}
/*
* Create own private value X and export G^X
*/
int dhm_make_public( dhm_context *ctx, int x_size,
unsigned char *output, int olen,
int (*f_rng)(void *), void *p_rng )
{
int ret, i, n;
unsigned char *p;
if( ctx == NULL || olen < 1 || olen > ctx->len )
return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
/*
* generate X and calculate GX = G^X mod P
*/
n = x_size / sizeof( t_int );
MPI_CHK( mpi_grow( &ctx->X, n ) );
MPI_CHK( mpi_lset( &ctx->X, 0 ) );
n = x_size >> 3;
p = (unsigned char *) ctx->X.p;
for( i = 0; i < n; i++ )
*p++ = (unsigned char) f_rng( p_rng );
while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
mpi_shift_r( &ctx->X, 1 );
MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
&ctx->P , &ctx->RP ) );
MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) );
cleanup:
if( ret != 0 )
return( XYSSL_ERR_DHM_MAKE_PUBLIC_FAILED | ret );
return( 0 );
}
/*
* Derive and export the shared secret (G^Y)^X mod P
*/
int dhm_calc_secret( dhm_context *ctx,
unsigned char *output, int *olen )
{
int ret;
if( ctx == NULL || *olen < ctx->len )
return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
&ctx->P, &ctx->RP ) );
*olen = mpi_size( &ctx->K );
MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
cleanup:
if( ret != 0 )
return( XYSSL_ERR_DHM_CALC_SECRET_FAILED | ret );
return( 0 );
}
/*
* Free the components of a DHM key
*/
void dhm_free( dhm_context *ctx )
{
mpi_free( &ctx->RP, &ctx->K, &ctx->GY,
&ctx->GX, &ctx->X, &ctx->G,
&ctx->P, NULL );
}
#if defined(XYSSL_SELF_TEST)
/*
* Checkup routine
*/
int dhm_self_test( int verbose )
{
return( verbose++ );
}
#endif
#endif

261
library/havege.c Normal file
View file

@ -0,0 +1,261 @@
/*
* HAVEGE: HArdware Volatile Entropy Gathering and Expansion
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The HAVEGE RNG was designed by Andre Seznec in 2002.
*
* http://www.irisa.fr/caps/projects/hipsor/publi.php
*
* Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
*/
#include <string.h>
#include <time.h>
#include "xyssl/config.h"
#if defined(XYSSL_HAVEGE_C)
#include "xyssl/havege.h"
#include "xyssl/timing.h"
/* ------------------------------------------------------------------------
* On average, one iteration accesses two 8-word blocks in the havege WALK
* table, and generates 16 words in the RES array.
*
* The data read in the WALK table is updated and permuted after each use.
* The result of the hardware clock counter read is used for this update.
*
* 25 conditional tests are present. The conditional tests are grouped in
* two nested groups of 12 conditional tests and 1 test that controls the
* permutation; on average, there should be 6 tests executed and 3 of them
* should be mispredicted.
* ------------------------------------------------------------------------
*/
#define SWAP(X,Y) { int *T = X; X = Y; Y = T; }
#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
#define TST1_LEAVE U1++; }
#define TST2_LEAVE U2++; }
#define ONE_ITERATION \
\
PTEST = PT1 >> 20; \
\
TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
\
TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
\
PTX = (PT1 >> 18) & 7; \
PT1 &= 0x1FFF; \
PT2 &= 0x1FFF; \
CLK = (int) hardclock(); \
\
i = 0; \
A = &WALK[PT1 ]; RES[i++] ^= *A; \
B = &WALK[PT2 ]; RES[i++] ^= *B; \
C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \
D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \
\
IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \
*A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \
*B = IN ^ U1; \
*C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \
*D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \
\
A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \
B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \
C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \
D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \
\
if( PTEST & 1 ) SWAP( A, C ); \
\
IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
*A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
*B = IN; CLK = (int) hardclock(); \
*C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
*D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
\
A = &WALK[PT1 ^ 4]; \
B = &WALK[PT2 ^ 1]; \
\
PTEST = PT2 >> 1; \
\
PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \
PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \
PTY = (PT2 >> 10) & 7; \
\
TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
\
TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
\
C = &WALK[PT1 ^ 5]; \
D = &WALK[PT2 ^ 5]; \
\
RES[i++] ^= *A; \
RES[i++] ^= *B; \
RES[i++] ^= *C; \
RES[i++] ^= *D; \
\
IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \
*A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \
*B = IN ^ U2; \
*C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \
*D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \
\
A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \
B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \
C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \
D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \
\
IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \
*A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \
*B = IN; \
*C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \
*D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \
\
PT1 = ( RES[(i - 8) ^ PTX] ^ \
WALK[PT1 ^ PTX ^ 7] ) & (~1); \
PT1 ^= (PT2 ^ 0x10) & 0x10; \
\
for( n++, i = 0; i < 16; i++ ) \
hs->pool[n % COLLECT_SIZE] ^= RES[i];
/*
* Entropy gathering function
*/
static void havege_fill( havege_state *hs )
{
int i, n = 0;
int U1, U2, *A, *B, *C, *D;
int PT1, PT2, *WALK, RES[16];
int PTX, PTY, CLK, PTEST, IN;
WALK = hs->WALK;
PT1 = hs->PT1;
PT2 = hs->PT2;
PTX = U1 = 0;
PTY = U2 = 0;
memset( RES, 0, sizeof( RES ) );
while( n < COLLECT_SIZE * 4 )
{
ONE_ITERATION
ONE_ITERATION
ONE_ITERATION
ONE_ITERATION
}
hs->PT1 = PT1;
hs->PT2 = PT2;
hs->offset[0] = 0;
hs->offset[1] = COLLECT_SIZE / 2;
}
/*
* HAVEGE initialization
*/
void havege_init( havege_state *hs )
{
memset( hs, 0, sizeof( havege_state ) );
havege_fill( hs );
}
/*
* HAVEGE rand function
*/
int havege_rand( void *p_rng )
{
int ret;
havege_state *hs = (havege_state *) p_rng;
if( hs->offset[1] >= COLLECT_SIZE )
havege_fill( hs );
ret = hs->pool[hs->offset[0]++];
ret ^= hs->pool[hs->offset[1]++];
return( ret );
}
#if defined(XYSSL_RAND_TEST)
#include <stdio.h>
int main( int argc, char *argv[] )
{
FILE *f;
time_t t;
int i, j, k;
havege_state hs;
unsigned char buf[1024];
if( argc < 2 )
{
fprintf( stderr, "usage: %s <output filename>\n", argv[0] );
return( 1 );
}
if( ( f = fopen( argv[1], "wb+" ) ) == NULL )
{
printf( "failed to open '%s' for writing.\n", argv[0] );
return( 1 );
}
havege_init( &hs );
t = time( NULL );
for( i = 0, k = 32768; i < k; i++ )
{
for( j = 0; j < sizeof( buf ); j++ )
buf[j] = havege_rand( &hs );
fwrite( buf, sizeof( buf ), 1, f );
printf( "Generating 32Mb of data in file '%s'... %04.1f" \
"%% done\r", argv[1], (100 * (float) (i + 1)) / k );
fflush( stdout );
}
if( t == time( NULL ) )
t--;
fclose( f );
return( 0 );
}
#endif
#endif

343
library/md2.c Normal file
View file

@ -0,0 +1,343 @@
/*
* RFC 1115/1319 compliant MD2 implementation
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The MD2 algorithm was designed by Ron Rivest in 1989.
*
* http://www.ietf.org/rfc/rfc1115.txt
* http://www.ietf.org/rfc/rfc1319.txt
*/
#include "xyssl/config.h"
#if defined(XYSSL_MD2_C)
#include "xyssl/md2.h"
#include <string.h>
#include <stdio.h>
static const unsigned char PI_SUBST[256] =
{
0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
};
/*
* MD2 context setup
*/
void md2_starts( md2_context *ctx )
{
memset( ctx, 0, sizeof( md2_context ) );
}
static void md2_process( md2_context *ctx )
{
int i, j;
unsigned char t = 0;
for( i = 0; i < 16; i++ )
{
ctx->state[i + 16] = ctx->buffer[i];
ctx->state[i + 32] =
(unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
}
for( i = 0; i < 18; i++ )
{
for( j = 0; j < 48; j++ )
{
ctx->state[j] = (unsigned char)
( ctx->state[j] ^ PI_SUBST[t] );
t = ctx->state[j];
}
t = (unsigned char)( t + i );
}
t = ctx->cksum[15];
for( i = 0; i < 16; i++ )
{
ctx->cksum[i] = (unsigned char)
( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
t = ctx->cksum[i];
}
}
/*
* MD2 process buffer
*/
void md2_update( md2_context *ctx, unsigned char *input, int ilen )
{
int fill;
while( ilen > 0 )
{
if( ctx->left + ilen > 16 )
fill = 16 - ctx->left;
else
fill = ilen;
memcpy( ctx->buffer + ctx->left, input, fill );
ctx->left += fill;
input += fill;
ilen -= fill;
if( ctx->left == 16 )
{
ctx->left = 0;
md2_process( ctx );
}
}
}
/*
* MD2 final digest
*/
void md2_finish( md2_context *ctx, unsigned char output[16] )
{
int i;
unsigned char x;
x = (unsigned char)( 16 - ctx->left );
for( i = ctx->left; i < 16; i++ )
ctx->buffer[i] = x;
md2_process( ctx );
memcpy( ctx->buffer, ctx->cksum, 16 );
md2_process( ctx );
memcpy( output, ctx->state, 16 );
}
/*
* output = MD2( input buffer )
*/
void md2( unsigned char *input, int ilen, unsigned char output[16] )
{
md2_context ctx;
md2_starts( &ctx );
md2_update( &ctx, input, ilen );
md2_finish( &ctx, output );
memset( &ctx, 0, sizeof( md2_context ) );
}
/*
* output = MD2( file contents )
*/
int md2_file( char *path, unsigned char output[16] )
{
FILE *f;
size_t n;
md2_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( 1 );
md2_starts( &ctx );
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
md2_update( &ctx, buf, (int) n );
md2_finish( &ctx, output );
memset( &ctx, 0, sizeof( md2_context ) );
if( ferror( f ) != 0 )
{
fclose( f );
return( 2 );
}
fclose( f );
return( 0 );
}
/*
* MD2 HMAC context setup
*/
void md2_hmac_starts( md2_context *ctx, unsigned char *key, int keylen )
{
int i;
unsigned char sum[16];
if( keylen > 64 )
{
md2( key, keylen, sum );
keylen = 16;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
md2_starts( ctx );
md2_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* MD2 HMAC process buffer
*/
void md2_hmac_update( md2_context *ctx, unsigned char *input, int ilen )
{
md2_update( ctx, input, ilen );
}
/*
* MD2 HMAC final digest
*/
void md2_hmac_finish( md2_context *ctx, unsigned char output[16] )
{
unsigned char tmpbuf[16];
md2_finish( ctx, tmpbuf );
md2_starts( ctx );
md2_update( ctx, ctx->opad, 64 );
md2_update( ctx, tmpbuf, 16 );
md2_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* output = HMAC-MD2( hmac key, input buffer )
*/
void md2_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
unsigned char output[16] )
{
md2_context ctx;
md2_hmac_starts( &ctx, key, keylen );
md2_hmac_update( &ctx, input, ilen );
md2_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( md2_context ) );
}
#if defined(XYSSL_SELF_TEST)
/*
* RFC 1319 test vectors
*/
static const char md2_test_str[7][81] =
{
{ "" },
{ "a" },
{ "abc" },
{ "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ "12345678901234567890123456789012345678901234567890123456789012" \
"345678901234567890" }
};
static const unsigned char md2_test_sum[7][16] =
{
{ 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
{ 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
{ 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
{ 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
{ 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
{ 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
{ 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
};
/*
* Checkup routine
*/
int md2_self_test( int verbose )
{
int i;
unsigned char md2sum[16];
for( i = 0; i < 7; i++ )
{
if( verbose != 0 )
printf( " MD2 test #%d: ", i + 1 );
md2( (unsigned char *) md2_test_str[i],
strlen( md2_test_str[i] ), md2sum );
if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
#endif

442
library/md4.c Normal file
View file

@ -0,0 +1,442 @@
/*
* RFC 1186/1320 compliant MD4 implementation
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The MD4 algorithm was designed by Ron Rivest in 1990.
*
* http://www.ietf.org/rfc/rfc1186.txt
* http://www.ietf.org/rfc/rfc1320.txt
*/
#include "xyssl/config.h"
#if defined(XYSSL_MD4_C)
#include "xyssl/md4.h"
#include <string.h>
#include <stdio.h>
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_ULONG_LE
#define GET_ULONG_LE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] ) \
| ( (unsigned long) (b)[(i) + 1] << 8 ) \
| ( (unsigned long) (b)[(i) + 2] << 16 ) \
| ( (unsigned long) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef PUT_ULONG_LE
#define PUT_ULONG_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
}
#endif
/*
* MD4 context setup
*/
void md4_starts( md4_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
}
static void md4_process( md4_context *ctx, unsigned char data[64] )
{
unsigned long X[16], A, B, C, D;
GET_ULONG_LE( X[ 0], data, 0 );
GET_ULONG_LE( X[ 1], data, 4 );
GET_ULONG_LE( X[ 2], data, 8 );
GET_ULONG_LE( X[ 3], data, 12 );
GET_ULONG_LE( X[ 4], data, 16 );
GET_ULONG_LE( X[ 5], data, 20 );
GET_ULONG_LE( X[ 6], data, 24 );
GET_ULONG_LE( X[ 7], data, 28 );
GET_ULONG_LE( X[ 8], data, 32 );
GET_ULONG_LE( X[ 9], data, 36 );
GET_ULONG_LE( X[10], data, 40 );
GET_ULONG_LE( X[11], data, 44 );
GET_ULONG_LE( X[12], data, 48 );
GET_ULONG_LE( X[13], data, 52 );
GET_ULONG_LE( X[14], data, 56 );
GET_ULONG_LE( X[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
#define F(x, y, z) ((x & y) | ((~x) & z))
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
P( A, B, C, D, X[ 0], 3 );
P( D, A, B, C, X[ 1], 7 );
P( C, D, A, B, X[ 2], 11 );
P( B, C, D, A, X[ 3], 19 );
P( A, B, C, D, X[ 4], 3 );
P( D, A, B, C, X[ 5], 7 );
P( C, D, A, B, X[ 6], 11 );
P( B, C, D, A, X[ 7], 19 );
P( A, B, C, D, X[ 8], 3 );
P( D, A, B, C, X[ 9], 7 );
P( C, D, A, B, X[10], 11 );
P( B, C, D, A, X[11], 19 );
P( A, B, C, D, X[12], 3 );
P( D, A, B, C, X[13], 7 );
P( C, D, A, B, X[14], 11 );
P( B, C, D, A, X[15], 19 );
#undef P
#undef F
#define F(x,y,z) ((x & y) | (x & z) | (y & z))
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
P( A, B, C, D, X[ 0], 3 );
P( D, A, B, C, X[ 4], 5 );
P( C, D, A, B, X[ 8], 9 );
P( B, C, D, A, X[12], 13 );
P( A, B, C, D, X[ 1], 3 );
P( D, A, B, C, X[ 5], 5 );
P( C, D, A, B, X[ 9], 9 );
P( B, C, D, A, X[13], 13 );
P( A, B, C, D, X[ 2], 3 );
P( D, A, B, C, X[ 6], 5 );
P( C, D, A, B, X[10], 9 );
P( B, C, D, A, X[14], 13 );
P( A, B, C, D, X[ 3], 3 );
P( D, A, B, C, X[ 7], 5 );
P( C, D, A, B, X[11], 9 );
P( B, C, D, A, X[15], 13 );
#undef P
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
P( A, B, C, D, X[ 0], 3 );
P( D, A, B, C, X[ 8], 9 );
P( C, D, A, B, X[ 4], 11 );
P( B, C, D, A, X[12], 15 );
P( A, B, C, D, X[ 2], 3 );
P( D, A, B, C, X[10], 9 );
P( C, D, A, B, X[ 6], 11 );
P( B, C, D, A, X[14], 15 );
P( A, B, C, D, X[ 1], 3 );
P( D, A, B, C, X[ 9], 9 );
P( C, D, A, B, X[ 5], 11 );
P( B, C, D, A, X[13], 15 );
P( A, B, C, D, X[ 3], 3 );
P( D, A, B, C, X[11], 9 );
P( C, D, A, B, X[ 7], 11 );
P( B, C, D, A, X[15], 15 );
#undef F
#undef P
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
}
/*
* MD4 process buffer
*/
void md4_update( md4_context *ctx, unsigned char *input, int ilen )
{
int fill;
unsigned long left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (unsigned long) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
md4_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
md4_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char md4_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* MD4 final digest
*/
void md4_finish( md4_context *ctx, unsigned char output[16] )
{
unsigned long last, padn;
unsigned long high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_ULONG_LE( low, msglen, 0 );
PUT_ULONG_LE( high, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
md4_update( ctx, (unsigned char *) md4_padding, padn );
md4_update( ctx, msglen, 8 );
PUT_ULONG_LE( ctx->state[0], output, 0 );
PUT_ULONG_LE( ctx->state[1], output, 4 );
PUT_ULONG_LE( ctx->state[2], output, 8 );
PUT_ULONG_LE( ctx->state[3], output, 12 );
}
/*
* output = MD4( input buffer )
*/
void md4( unsigned char *input, int ilen, unsigned char output[16] )
{
md4_context ctx;
md4_starts( &ctx );
md4_update( &ctx, input, ilen );
md4_finish( &ctx, output );
memset( &ctx, 0, sizeof( md4_context ) );
}
/*
* output = MD4( file contents )
*/
int md4_file( char *path, unsigned char output[16] )
{
FILE *f;
size_t n;
md4_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( 1 );
md4_starts( &ctx );
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
md4_update( &ctx, buf, (int) n );
md4_finish( &ctx, output );
memset( &ctx, 0, sizeof( md4_context ) );
if( ferror( f ) != 0 )
{
fclose( f );
return( 2 );
}
fclose( f );
return( 0 );
}
/*
* MD4 HMAC context setup
*/
void md4_hmac_starts( md4_context *ctx, unsigned char *key, int keylen )
{
int i;
unsigned char sum[16];
if( keylen > 64 )
{
md4( key, keylen, sum );
keylen = 16;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
md4_starts( ctx );
md4_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* MD4 HMAC process buffer
*/
void md4_hmac_update( md4_context *ctx, unsigned char *input, int ilen )
{
md4_update( ctx, input, ilen );
}
/*
* MD4 HMAC final digest
*/
void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
{
unsigned char tmpbuf[16];
md4_finish( ctx, tmpbuf );
md4_starts( ctx );
md4_update( ctx, ctx->opad, 64 );
md4_update( ctx, tmpbuf, 16 );
md4_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* output = HMAC-MD4( hmac key, input buffer )
*/
void md4_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
unsigned char output[16] )
{
md4_context ctx;
md4_hmac_starts( &ctx, key, keylen );
md4_hmac_update( &ctx, input, ilen );
md4_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( md4_context ) );
}
#if defined(XYSSL_SELF_TEST)
/*
* RFC 1320 test vectors
*/
static const char md4_test_str[7][81] =
{
{ "" },
{ "a" },
{ "abc" },
{ "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ "12345678901234567890123456789012345678901234567890123456789012" \
"345678901234567890" }
};
static const unsigned char md4_test_sum[7][16] =
{
{ 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
{ 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
{ 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
{ 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
{ 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
{ 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
{ 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
};
/*
* Checkup routine
*/
int md4_self_test( int verbose )
{
int i;
unsigned char md4sum[16];
for( i = 0; i < 7; i++ )
{
if( verbose != 0 )
printf( " MD4 test #%d: ", i + 1 );
md4( (unsigned char *) md4_test_str[i],
strlen( md4_test_str[i] ), md4sum );
if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
#endif

565
library/md5.c Normal file
View file

@ -0,0 +1,565 @@
/*
* RFC 1321 compliant MD5 implementation
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The MD5 algorithm was designed by Ron Rivest in 1991.
*
* http://www.ietf.org/rfc/rfc1321.txt
*/
#include "xyssl/config.h"
#if defined(XYSSL_MD5_C)
#include "xyssl/md5.h"
#include <string.h>
#include <stdio.h>
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_ULONG_LE
#define GET_ULONG_LE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] ) \
| ( (unsigned long) (b)[(i) + 1] << 8 ) \
| ( (unsigned long) (b)[(i) + 2] << 16 ) \
| ( (unsigned long) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef PUT_ULONG_LE
#define PUT_ULONG_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
}
#endif
/*
* MD5 context setup
*/
void md5_starts( md5_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
}
static void md5_process( md5_context *ctx, unsigned char data[64] )
{
unsigned long X[16], A, B, C, D;
GET_ULONG_LE( X[ 0], data, 0 );
GET_ULONG_LE( X[ 1], data, 4 );
GET_ULONG_LE( X[ 2], data, 8 );
GET_ULONG_LE( X[ 3], data, 12 );
GET_ULONG_LE( X[ 4], data, 16 );
GET_ULONG_LE( X[ 5], data, 20 );
GET_ULONG_LE( X[ 6], data, 24 );
GET_ULONG_LE( X[ 7], data, 28 );
GET_ULONG_LE( X[ 8], data, 32 );
GET_ULONG_LE( X[ 9], data, 36 );
GET_ULONG_LE( X[10], data, 40 );
GET_ULONG_LE( X[11], data, 44 );
GET_ULONG_LE( X[12], data, 48 );
GET_ULONG_LE( X[13], data, 52 );
GET_ULONG_LE( X[14], data, 56 );
GET_ULONG_LE( X[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define P(a,b,c,d,k,s,t) \
{ \
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
#define F(x,y,z) (z ^ (x & (y ^ z)))
P( A, B, C, D, 0, 7, 0xD76AA478 );
P( D, A, B, C, 1, 12, 0xE8C7B756 );
P( C, D, A, B, 2, 17, 0x242070DB );
P( B, C, D, A, 3, 22, 0xC1BDCEEE );
P( A, B, C, D, 4, 7, 0xF57C0FAF );
P( D, A, B, C, 5, 12, 0x4787C62A );
P( C, D, A, B, 6, 17, 0xA8304613 );
P( B, C, D, A, 7, 22, 0xFD469501 );
P( A, B, C, D, 8, 7, 0x698098D8 );
P( D, A, B, C, 9, 12, 0x8B44F7AF );
P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
P( B, C, D, A, 11, 22, 0x895CD7BE );
P( A, B, C, D, 12, 7, 0x6B901122 );
P( D, A, B, C, 13, 12, 0xFD987193 );
P( C, D, A, B, 14, 17, 0xA679438E );
P( B, C, D, A, 15, 22, 0x49B40821 );
#undef F
#define F(x,y,z) (y ^ (z & (x ^ y)))
P( A, B, C, D, 1, 5, 0xF61E2562 );
P( D, A, B, C, 6, 9, 0xC040B340 );
P( C, D, A, B, 11, 14, 0x265E5A51 );
P( B, C, D, A, 0, 20, 0xE9B6C7AA );
P( A, B, C, D, 5, 5, 0xD62F105D );
P( D, A, B, C, 10, 9, 0x02441453 );
P( C, D, A, B, 15, 14, 0xD8A1E681 );
P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
P( A, B, C, D, 9, 5, 0x21E1CDE6 );
P( D, A, B, C, 14, 9, 0xC33707D6 );
P( C, D, A, B, 3, 14, 0xF4D50D87 );
P( B, C, D, A, 8, 20, 0x455A14ED );
P( A, B, C, D, 13, 5, 0xA9E3E905 );
P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
P( C, D, A, B, 7, 14, 0x676F02D9 );
P( B, C, D, A, 12, 20, 0x8D2A4C8A );
#undef F
#define F(x,y,z) (x ^ y ^ z)
P( A, B, C, D, 5, 4, 0xFFFA3942 );
P( D, A, B, C, 8, 11, 0x8771F681 );
P( C, D, A, B, 11, 16, 0x6D9D6122 );
P( B, C, D, A, 14, 23, 0xFDE5380C );
P( A, B, C, D, 1, 4, 0xA4BEEA44 );
P( D, A, B, C, 4, 11, 0x4BDECFA9 );
P( C, D, A, B, 7, 16, 0xF6BB4B60 );
P( B, C, D, A, 10, 23, 0xBEBFBC70 );
P( A, B, C, D, 13, 4, 0x289B7EC6 );
P( D, A, B, C, 0, 11, 0xEAA127FA );
P( C, D, A, B, 3, 16, 0xD4EF3085 );
P( B, C, D, A, 6, 23, 0x04881D05 );
P( A, B, C, D, 9, 4, 0xD9D4D039 );
P( D, A, B, C, 12, 11, 0xE6DB99E5 );
P( C, D, A, B, 15, 16, 0x1FA27CF8 );
P( B, C, D, A, 2, 23, 0xC4AC5665 );
#undef F
#define F(x,y,z) (y ^ (x | ~z))
P( A, B, C, D, 0, 6, 0xF4292244 );
P( D, A, B, C, 7, 10, 0x432AFF97 );
P( C, D, A, B, 14, 15, 0xAB9423A7 );
P( B, C, D, A, 5, 21, 0xFC93A039 );
P( A, B, C, D, 12, 6, 0x655B59C3 );
P( D, A, B, C, 3, 10, 0x8F0CCC92 );
P( C, D, A, B, 10, 15, 0xFFEFF47D );
P( B, C, D, A, 1, 21, 0x85845DD1 );
P( A, B, C, D, 8, 6, 0x6FA87E4F );
P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
P( C, D, A, B, 6, 15, 0xA3014314 );
P( B, C, D, A, 13, 21, 0x4E0811A1 );
P( A, B, C, D, 4, 6, 0xF7537E82 );
P( D, A, B, C, 11, 10, 0xBD3AF235 );
P( C, D, A, B, 2, 15, 0x2AD7D2BB );
P( B, C, D, A, 9, 21, 0xEB86D391 );
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
}
/*
* MD5 process buffer
*/
void md5_update( md5_context *ctx, unsigned char *input, int ilen )
{
int fill;
unsigned long left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (unsigned long) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
md5_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
md5_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char md5_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* MD5 final digest
*/
void md5_finish( md5_context *ctx, unsigned char output[16] )
{
unsigned long last, padn;
unsigned long high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_ULONG_LE( low, msglen, 0 );
PUT_ULONG_LE( high, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
md5_update( ctx, (unsigned char *) md5_padding, padn );
md5_update( ctx, msglen, 8 );
PUT_ULONG_LE( ctx->state[0], output, 0 );
PUT_ULONG_LE( ctx->state[1], output, 4 );
PUT_ULONG_LE( ctx->state[2], output, 8 );
PUT_ULONG_LE( ctx->state[3], output, 12 );
}
/*
* output = MD5( input buffer )
*/
void md5( unsigned char *input, int ilen, unsigned char output[16] )
{
md5_context ctx;
md5_starts( &ctx );
md5_update( &ctx, input, ilen );
md5_finish( &ctx, output );
memset( &ctx, 0, sizeof( md5_context ) );
}
/*
* output = MD5( file contents )
*/
int md5_file( char *path, unsigned char output[16] )
{
FILE *f;
size_t n;
md5_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( 1 );
md5_starts( &ctx );
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
md5_update( &ctx, buf, (int) n );
md5_finish( &ctx, output );
memset( &ctx, 0, sizeof( md5_context ) );
if( ferror( f ) != 0 )
{
fclose( f );
return( 2 );
}
fclose( f );
return( 0 );
}
/*
* MD5 HMAC context setup
*/
void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen )
{
int i;
unsigned char sum[16];
if( keylen > 64 )
{
md5( key, keylen, sum );
keylen = 16;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
md5_starts( ctx );
md5_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* MD5 HMAC process buffer
*/
void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen )
{
md5_update( ctx, input, ilen );
}
/*
* MD5 HMAC final digest
*/
void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
{
unsigned char tmpbuf[16];
md5_finish( ctx, tmpbuf );
md5_starts( ctx );
md5_update( ctx, ctx->opad, 64 );
md5_update( ctx, tmpbuf, 16 );
md5_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* output = HMAC-MD5( hmac key, input buffer )
*/
void md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
unsigned char output[16] )
{
md5_context ctx;
md5_hmac_starts( &ctx, key, keylen );
md5_hmac_update( &ctx, input, ilen );
md5_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( md5_context ) );
}
#if defined(XYSSL_SELF_TEST)
/*
* RFC 1321 test vectors
*/
static unsigned char md5_test_buf[7][81] =
{
{ "" },
{ "a" },
{ "abc" },
{ "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ "12345678901234567890123456789012345678901234567890123456789012" \
"345678901234567890" }
};
static const int md5_test_buflen[7] =
{
0, 1, 3, 14, 26, 62, 80
};
static const unsigned char md5_test_sum[7][16] =
{
{ 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
{ 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
{ 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
{ 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
{ 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
{ 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
{ 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
};
/*
* RFC 2202 test vectors
*/
static unsigned char md5_hmac_test_key[7][26] =
{
{ "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
{ "Jefe" },
{ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
{ "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
{ "" }, /* 0xAA 80 times */
{ "" }
};
static const int md5_hmac_test_keylen[7] =
{
16, 4, 16, 25, 16, 80, 80
};
static unsigned char md5_hmac_test_buf[7][74] =
{
{ "Hi There" },
{ "what do ya want for nothing?" },
{ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
{ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
{ "Test With Truncation" },
{ "Test Using Larger Than Block-Size Key - Hash Key First" },
{ "Test Using Larger Than Block-Size Key and Larger"
" Than One Block-Size Data" }
};
static const int md5_hmac_test_buflen[7] =
{
8, 28, 50, 50, 20, 54, 73
};
static const unsigned char md5_hmac_test_sum[7][16] =
{
{ 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
{ 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
{ 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
{ 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
{ 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
0xF9, 0xBA, 0xB9, 0x95 },
{ 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
{ 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
};
/*
* Checkup routine
*/
int md5_self_test( int verbose )
{
int i, buflen;
unsigned char buf[1024];
unsigned char md5sum[16];
md5_context ctx;
for( i = 0; i < 7; i++ )
{
if( verbose != 0 )
printf( " MD5 test #%d: ", i + 1 );
md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
for( i = 0; i < 7; i++ )
{
if( verbose != 0 )
printf( " HMAC-MD5 test #%d: ", i + 1 );
if( i == 5 || i == 6 )
{
memset( buf, '\xAA', buflen = 80 );
md5_hmac_starts( &ctx, buf, buflen );
}
else
md5_hmac_starts( &ctx, md5_hmac_test_key[i],
md5_hmac_test_keylen[i] );
md5_hmac_update( &ctx, md5_hmac_test_buf[i],
md5_hmac_test_buflen[i] );
md5_hmac_finish( &ctx, md5sum );
buflen = ( i == 4 ) ? 12 : 16;
if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
#endif

346
library/net.c Normal file
View file

@ -0,0 +1,346 @@
/*
* TCP networking functions
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "xyssl/config.h"
#if defined(XYSSL_NET_C)
#include "xyssl/net.h"
#if defined(WIN32) || defined(_WIN32_WCE)
#include <winsock2.h>
#include <windows.h>
#if defined(_WIN32_WCE)
#pragma comment( lib, "ws2.lib" )
#else
#pragma comment( lib, "ws2_32.lib" )
#endif
#define read(fd,buf,len) recv(fd,buf,len,0)
#define write(fd,buf,len) send(fd,buf,len,0)
#define close(fd) closesocket(fd)
static int wsa_init_done = 0;
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
/*
* htons() is not always available
*/
static unsigned short net_htons( int port )
{
unsigned char buf[4];
buf[0] = (unsigned char)( port >> 8 );
buf[1] = (unsigned char)( port );
buf[2] = buf[3] = 0;
return( *(unsigned short *) buf );
}
/*
* Initiate a TCP connection with host:port
*/
int net_connect( int *fd, char *host, int port )
{
struct sockaddr_in server_addr;
struct hostent *server_host;
#if defined(WIN32) || defined(_WIN32_WCE)
WSADATA wsaData;
if( wsa_init_done == 0 )
{
if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
return( XYSSL_ERR_NET_SOCKET_FAILED );
wsa_init_done = 1;
}
#else
signal( SIGPIPE, SIG_IGN );
#endif
if( ( server_host = gethostbyname( host ) ) == NULL )
return( XYSSL_ERR_NET_UNKNOWN_HOST );
if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
return( XYSSL_ERR_NET_SOCKET_FAILED );
memcpy( (void *) &server_addr.sin_addr,
(void *) server_host->h_addr,
server_host->h_length );
server_addr.sin_family = AF_INET;
server_addr.sin_port = net_htons( port );
if( connect( *fd, (struct sockaddr *) &server_addr,
sizeof( server_addr ) ) < 0 )
{
close( *fd );
return( XYSSL_ERR_NET_CONNECT_FAILED );
}
return( 0 );
}
/*
* Create a listening socket on bind_ip:port
*/
int net_bind( int *fd, char *bind_ip, int port )
{
int n, c[4];
struct sockaddr_in server_addr;
#if defined(WIN32) || defined(_WIN32_WCE)
WSADATA wsaData;
if( wsa_init_done == 0 )
{
if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
return( XYSSL_ERR_NET_SOCKET_FAILED );
wsa_init_done = 1;
}
#else
signal( SIGPIPE, SIG_IGN );
#endif
if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
return( XYSSL_ERR_NET_SOCKET_FAILED );
n = 1;
setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &n, sizeof( n ) );
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_family = AF_INET;
server_addr.sin_port = net_htons( port );
if( bind_ip != NULL )
{
memset( c, 0, sizeof( c ) );
sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] );
for( n = 0; n < 4; n++ )
if( c[n] < 0 || c[n] > 255 )
break;
if( n == 4 )
server_addr.sin_addr.s_addr =
( (unsigned long) c[0] << 24 ) |
( (unsigned long) c[1] << 16 ) |
( (unsigned long) c[2] << 8 ) |
( (unsigned long) c[3] );
}
if( bind( *fd, (struct sockaddr *) &server_addr,
sizeof( server_addr ) ) < 0 )
{
close( *fd );
return( XYSSL_ERR_NET_BIND_FAILED );
}
if( listen( *fd, 10 ) != 0 )
{
close( *fd );
return( XYSSL_ERR_NET_LISTEN_FAILED );
}
return( 0 );
}
/*
* Check if the current operation is blocking
*/
static int net_is_blocking( void )
{
#if defined(WIN32) || defined(_WIN32_WCE)
return( WSAGetLastError() == WSAEWOULDBLOCK );
#else
switch( errno )
{
#if defined EAGAIN
case EAGAIN:
#endif
#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
return( 1 );
}
return( 0 );
#endif
}
/*
* Accept a connection from a remote client
*/
int net_accept( int bind_fd, int *client_fd, void *client_ip )
{
struct sockaddr_in client_addr;
#if defined(__socklen_t_defined)
socklen_t n = (socklen_t) sizeof( client_addr );
#else
int n = (int) sizeof( client_addr );
#endif
*client_fd = accept( bind_fd, (struct sockaddr *)
&client_addr, &n );
if( *client_fd < 0 )
{
if( net_is_blocking() != 0 )
return( XYSSL_ERR_NET_TRY_AGAIN );
return( XYSSL_ERR_NET_ACCEPT_FAILED );
}
if( client_ip != NULL )
memcpy( client_ip, &client_addr.sin_addr.s_addr,
sizeof( client_addr.sin_addr.s_addr ) );
return( 0 );
}
/*
* Set the socket blocking or non-blocking
*/
int net_set_block( int fd )
{
#if defined(WIN32) || defined(_WIN32_WCE)
long n = 0;
return( ioctlsocket( fd, FIONBIO, &n ) );
#else
return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) );
#endif
}
int net_set_nonblock( int fd )
{
#if defined(WIN32) || defined(_WIN32_WCE)
long n = 1;
return( ioctlsocket( fd, FIONBIO, &n ) );
#else
return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) );
#endif
}
/*
* Portable usleep helper
*/
void net_usleep( unsigned long usec )
{
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = usec;
select( 0, NULL, NULL, NULL, &tv );
}
/*
* Read at most 'len' characters
*/
int net_recv( void *ctx, unsigned char *buf, int len )
{
int ret = read( *((int *) ctx), buf, len );
if( len > 0 && ret == 0 )
return( XYSSL_ERR_NET_CONN_RESET );
if( ret < 0 )
{
if( net_is_blocking() != 0 )
return( XYSSL_ERR_NET_TRY_AGAIN );
#if defined(WIN32) || defined(_WIN32_WCE)
if( WSAGetLastError() == WSAECONNRESET )
return( XYSSL_ERR_NET_CONN_RESET );
#else
if( errno == EPIPE || errno == ECONNRESET )
return( XYSSL_ERR_NET_CONN_RESET );
if( errno == EINTR )
return( XYSSL_ERR_NET_TRY_AGAIN );
#endif
return( XYSSL_ERR_NET_RECV_FAILED );
}
return( ret );
}
/*
* Write at most 'len' characters
*/
int net_send( void *ctx, unsigned char *buf, int len )
{
int ret = write( *((int *) ctx), buf, len );
if( ret < 0 )
{
if( net_is_blocking() != 0 )
return( XYSSL_ERR_NET_TRY_AGAIN );
#if defined(WIN32) || defined(_WIN32_WCE)
if( WSAGetLastError() == WSAECONNRESET )
return( XYSSL_ERR_NET_CONN_RESET );
#else
if( errno == EPIPE || errno == ECONNRESET )
return( XYSSL_ERR_NET_CONN_RESET );
if( errno == EINTR )
return( XYSSL_ERR_NET_TRY_AGAIN );
#endif
return( XYSSL_ERR_NET_SEND_FAILED );
}
return( ret );
}
/*
* Gracefully close the connection
*/
void net_close( int fd )
{
shutdown( fd, 2 );
close( fd );
}
#endif

159
library/padlock.c Normal file
View file

@ -0,0 +1,159 @@
/*
* VIA PadLock support functions
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* This implementation is based on the VIA PadLock Programming Guide:
*
* http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/
* programming_guide.pdf
*/
#include "xyssl/config.h"
#if defined(XYSSL_PADLOCK_C)
#include "xyssl/aes.h"
#include "xyssl/padlock.h"
#if defined(XYSSL_HAVE_X86)
#include <string.h>
/*
* PadLock detection routine
*/
int padlock_supports( int feature )
{
static int flags = -1;
int ebx, edx;
if( flags == -1 )
{
asm( "movl %%ebx, %0 \n" \
"movl $0xC0000000, %%eax \n" \
"cpuid \n" \
"cmpl $0xC0000001, %%eax \n" \
"movl $0, %%edx \n" \
"jb unsupported \n" \
"movl $0xC0000001, %%eax \n" \
"cpuid \n" \
"unsupported: \n" \
"movl %%edx, %1 \n" \
"movl %2, %%ebx \n"
: "=m" (ebx), "=m" (edx)
: "m" (ebx)
: "eax", "ecx", "edx" );
flags = edx;
}
return( flags & feature );
}
/*
* PadLock AES-ECB block en(de)cryption
*/
int padlock_xcryptecb( aes_context *ctx,
int mode,
unsigned char input[16],
unsigned char output[16] )
{
int ebx;
unsigned long *rk;
unsigned long *blk;
unsigned long *ctrl;
unsigned char buf[256];
rk = ctx->rk;
blk = PADLOCK_ALIGN16( buf );
memcpy( blk, input, 16 );
ctrl = blk + 4;
*ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 );
asm( "pushfl; popfl \n" \
"movl %%ebx, %0 \n" \
"movl $1, %%ecx \n" \
"movl %2, %%edx \n" \
"movl %3, %%ebx \n" \
"movl %4, %%esi \n" \
"movl %4, %%edi \n" \
".byte 0xf3,0x0f,0xa7,0xc8\n" \
"movl %1, %%ebx \n"
: "=m" (ebx)
: "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
: "ecx", "edx", "esi", "edi" );
memcpy( output, blk, 16 );
return( 0 );
}
/*
* PadLock AES-CBC buffer en(de)cryption
*/
int padlock_xcryptcbc( aes_context *ctx,
int mode,
int length,
unsigned char iv[16],
unsigned char *input,
unsigned char *output )
{
int ebx, count;
unsigned long *rk;
unsigned long *iw;
unsigned long *ctrl;
unsigned char buf[256];
if( ( (long) input & 15 ) != 0 ||
( (long) output & 15 ) != 0 )
return( 1 );
rk = ctx->rk;
iw = PADLOCK_ALIGN16( buf );
memcpy( iw, iv, 16 );
ctrl = iw + 4;
*ctrl = 0x80 | ctx->nr | ( ( ctx->nr + (mode^1) - 10 ) << 9 );
count = (length + 15) >> 4;
asm( "pushfl; popfl \n" \
"movl %%ebx, %0 \n" \
"movl %2, %%ecx \n" \
"movl %3, %%edx \n" \
"movl %4, %%ebx \n" \
"movl %5, %%esi \n" \
"movl %6, %%edi \n" \
"movl %7, %%eax \n" \
".byte 0xf3,0x0f,0xa7,0xd0\n" \
"movl %1, %%ebx \n"
: "=m" (ebx)
: "m" (ebx), "m" (count), "m" (ctrl),
"m" (rk), "m" (input), "m" (output), "m" (iw)
: "eax", "ecx", "edx", "esi", "edi" );
memcpy( iv, iw, 16 );
return( 0 );
}
#endif
#endif

730
library/rsa.c Normal file
View file

@ -0,0 +1,730 @@
/*
* The RSA public-key cryptosystem
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
*
* http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
* http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
*/
#include "xyssl/config.h"
#if defined(XYSSL_RSA_C)
#include "xyssl/rsa.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/*
* Initialize an RSA context
*/
void rsa_init( rsa_context *ctx,
int padding,
int hash_id,
int (*f_rng)(void *),
void *p_rng )
{
memset( ctx, 0, sizeof( rsa_context ) );
ctx->padding = padding;
ctx->hash_id = hash_id;
ctx->f_rng = f_rng;
ctx->p_rng = p_rng;
}
#if defined(XYSSL_GENPRIME)
/*
* Generate an RSA keypair
*/
int rsa_gen_key( rsa_context *ctx, int nbits, int exponent )
{
int ret;
mpi P1, Q1, H, G;
if( ctx->f_rng == NULL || nbits < 128 || exponent < 3 )
return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
mpi_init( &P1, &Q1, &H, &G, NULL );
/*
* find primes P and Q with Q < P so that:
* GCD( E, (P-1)*(Q-1) ) == 1
*/
MPI_CHK( mpi_lset( &ctx->E, exponent ) );
do
{
MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
ctx->f_rng, ctx->p_rng ) );
MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
ctx->f_rng, ctx->p_rng ) );
if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
mpi_swap( &ctx->P, &ctx->Q );
if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
continue;
MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
if( mpi_msb( &ctx->N ) != nbits )
continue;
MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
}
while( mpi_cmp_int( &G, 1 ) != 0 );
/*
* D = E^-1 mod ((P-1)*(Q-1))
* DP = D mod (P - 1)
* DQ = D mod (Q - 1)
* QP = Q^-1 mod P
*/
MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
cleanup:
mpi_free( &G, &H, &Q1, &P1, NULL );
if( ret != 0 )
{
rsa_free( ctx );
return( XYSSL_ERR_RSA_KEY_GEN_FAILED | ret );
}
return( 0 );
}
#endif
/*
* Check a public RSA key
*/
int rsa_check_pubkey( rsa_context *ctx )
{
if( ( ctx->N.p[0] & 1 ) == 0 ||
( ctx->E.p[0] & 1 ) == 0 )
return( XYSSL_ERR_RSA_KEY_CHECK_FAILED );
if( mpi_msb( &ctx->N ) < 128 ||
mpi_msb( &ctx->N ) > 4096 )
return( XYSSL_ERR_RSA_KEY_CHECK_FAILED );
if( mpi_msb( &ctx->E ) < 2 ||
mpi_msb( &ctx->E ) > 64 )
return( XYSSL_ERR_RSA_KEY_CHECK_FAILED );
return( 0 );
}
/*
* Check a private RSA key
*/
int rsa_check_privkey( rsa_context *ctx )
{
int ret;
mpi PQ, DE, P1, Q1, H, I, G;
if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
return( ret );
mpi_init( &PQ, &DE, &P1, &Q1, &H, &I, &G, NULL );
MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
MPI_CHK( mpi_mod_mpi( &I, &DE, &H ) );
MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
if( mpi_cmp_mpi( &PQ, &ctx->N ) == 0 &&
mpi_cmp_int( &I, 1 ) == 0 &&
mpi_cmp_int( &G, 1 ) == 0 )
{
mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, NULL );
return( 0 );
}
cleanup:
mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, NULL );
return( XYSSL_ERR_RSA_KEY_CHECK_FAILED | ret );
}
/*
* Do an RSA public key operation
*/
int rsa_public( rsa_context *ctx,
unsigned char *input,
unsigned char *output )
{
int ret, olen;
mpi T;
mpi_init( &T, NULL );
MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
{
mpi_free( &T, NULL );
return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
}
olen = ctx->len;
MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
MPI_CHK( mpi_write_binary( &T, output, olen ) );
cleanup:
mpi_free( &T, NULL );
if( ret != 0 )
return( XYSSL_ERR_RSA_PUBLIC_FAILED | ret );
return( 0 );
}
/*
* Do an RSA private key operation
*/
int rsa_private( rsa_context *ctx,
unsigned char *input,
unsigned char *output )
{
int ret, olen;
mpi T, T1, T2;
mpi_init( &T, &T1, &T2, NULL );
MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
{
mpi_free( &T, NULL );
return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
}
#if 0
MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
#else
/*
* faster decryption using the CRT
*
* T1 = input ^ dP mod P
* T2 = input ^ dQ mod Q
*/
MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
/*
* T = (T1 - T2) * (Q^-1 mod P) mod P
*/
MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
/*
* output = T2 + T * Q
*/
MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
#endif
olen = ctx->len;
MPI_CHK( mpi_write_binary( &T, output, olen ) );
cleanup:
mpi_free( &T, &T1, &T2, NULL );
if( ret != 0 )
return( XYSSL_ERR_RSA_PRIVATE_FAILED | ret );
return( 0 );
}
/*
* Add the message padding, then do an RSA operation
*/
int rsa_pkcs1_encrypt( rsa_context *ctx,
int mode, int ilen,
unsigned char *input,
unsigned char *output )
{
int nb_pad, olen;
unsigned char *p = output;
olen = ctx->len;
switch( ctx->padding )
{
case RSA_PKCS_V15:
if( ilen < 0 || olen < ilen + 11 )
return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
nb_pad = olen - 3 - ilen;
*p++ = 0;
*p++ = RSA_CRYPT;
while( nb_pad-- > 0 )
{
do {
*p = (unsigned char) rand();
} while( *p == 0 );
p++;
}
*p++ = 0;
memcpy( p, input, ilen );
break;
default:
return( XYSSL_ERR_RSA_INVALID_PADDING );
}
return( ( mode == RSA_PUBLIC )
? rsa_public( ctx, output, output )
: rsa_private( ctx, output, output ) );
}
/*
* Do an RSA operation, then remove the message padding
*/
int rsa_pkcs1_decrypt( rsa_context *ctx,
int mode, int *olen,
unsigned char *input,
unsigned char *output )
{
int ret, ilen;
unsigned char *p;
unsigned char buf[512];
ilen = ctx->len;
if( ilen < 16 || ilen > (int) sizeof( buf ) )
return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
ret = ( mode == RSA_PUBLIC )
? rsa_public( ctx, input, buf )
: rsa_private( ctx, input, buf );
if( ret != 0 )
return( ret );
p = buf;
switch( ctx->padding )
{
case RSA_PKCS_V15:
if( *p++ != 0 || *p++ != RSA_CRYPT )
return( XYSSL_ERR_RSA_INVALID_PADDING );
while( *p != 0 )
{
if( p >= buf + ilen - 1 )
return( XYSSL_ERR_RSA_INVALID_PADDING );
p++;
}
p++;
break;
default:
return( XYSSL_ERR_RSA_INVALID_PADDING );
}
*olen = ilen - (int)(p - buf);
memcpy( output, p, *olen );
return( 0 );
}
/*
* Do an RSA operation to sign the message digest
*/
int rsa_pkcs1_sign( rsa_context *ctx,
int mode,
int hash_id,
int hashlen,
unsigned char *hash,
unsigned char *sig )
{
int nb_pad, olen;
unsigned char *p = sig;
olen = ctx->len;
switch( ctx->padding )
{
case RSA_PKCS_V15:
switch( hash_id )
{
case RSA_RAW:
nb_pad = olen - 3 - hashlen;
break;
case RSA_MD2:
case RSA_MD4:
case RSA_MD5:
nb_pad = olen - 3 - 34;
break;
case RSA_SHA1:
nb_pad = olen - 3 - 35;
break;
default:
return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
}
if( nb_pad < 8 )
return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
*p++ = 0;
*p++ = RSA_SIGN;
memset( p, 0xFF, nb_pad );
p += nb_pad;
*p++ = 0;
break;
default:
return( XYSSL_ERR_RSA_INVALID_PADDING );
}
switch( hash_id )
{
case RSA_RAW:
memcpy( p, hash, hashlen );
break;
case RSA_MD2:
memcpy( p, ASN1_HASH_MDX, 18 );
memcpy( p + 18, hash, 16 );
p[13] = 2; break;
case RSA_MD4:
memcpy( p, ASN1_HASH_MDX, 18 );
memcpy( p + 18, hash, 16 );
p[13] = 4; break;
case RSA_MD5:
memcpy( p, ASN1_HASH_MDX, 18 );
memcpy( p + 18, hash, 16 );
p[13] = 5; break;
case RSA_SHA1:
memcpy( p, ASN1_HASH_SHA1, 15 );
memcpy( p + 15, hash, 20 );
break;
default:
return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
}
return( ( mode == RSA_PUBLIC )
? rsa_public( ctx, sig, sig )
: rsa_private( ctx, sig, sig ) );
}
/*
* Do an RSA operation and check the message digest
*/
int rsa_pkcs1_verify( rsa_context *ctx,
int mode,
int hash_id,
int hashlen,
unsigned char *hash,
unsigned char *sig )
{
int ret, len, siglen;
unsigned char *p, c;
unsigned char buf[512];
siglen = ctx->len;
if( siglen < 16 || siglen > (int) sizeof( buf ) )
return( XYSSL_ERR_RSA_BAD_INPUT_DATA );
ret = ( mode == RSA_PUBLIC )
? rsa_public( ctx, sig, buf )
: rsa_private( ctx, sig, buf );
if( ret != 0 )
return( ret );
p = buf;
switch( ctx->padding )
{
case RSA_PKCS_V15:
if( *p++ != 0 || *p++ != RSA_SIGN )
return( XYSSL_ERR_RSA_INVALID_PADDING );
while( *p != 0 )
{
if( p >= buf + siglen - 1 || *p != 0xFF )
return( XYSSL_ERR_RSA_INVALID_PADDING );
p++;
}
p++;
break;
default:
return( XYSSL_ERR_RSA_INVALID_PADDING );
}
len = siglen - (int)( p - buf );
if( len == 34 )
{
c = p[13];
p[13] = 0;
if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
return( XYSSL_ERR_RSA_VERIFY_FAILED );
if( ( c == 2 && hash_id == RSA_MD2 ) ||
( c == 4 && hash_id == RSA_MD4 ) ||
( c == 5 && hash_id == RSA_MD5 ) )
{
if( memcmp( p + 18, hash, 16 ) == 0 )
return( 0 );
else
return( XYSSL_ERR_RSA_VERIFY_FAILED );
}
}
if( len == 35 && hash_id == RSA_SHA1 )
{
if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
memcmp( p + 15, hash, 20 ) == 0 )
return( 0 );
else
return( XYSSL_ERR_RSA_VERIFY_FAILED );
}
if( len == hashlen && hash_id == RSA_RAW )
{
if( memcmp( p, hash, hashlen ) == 0 )
return( 0 );
else
return( XYSSL_ERR_RSA_VERIFY_FAILED );
}
return( XYSSL_ERR_RSA_INVALID_PADDING );
}
/*
* Free the components of an RSA key
*/
void rsa_free( rsa_context *ctx )
{
mpi_free( &ctx->RQ, &ctx->RP, &ctx->RN,
&ctx->QP, &ctx->DQ, &ctx->DP,
&ctx->Q, &ctx->P, &ctx->D,
&ctx->E, &ctx->N, NULL );
}
#if defined(XYSSL_SELF_TEST)
#include "xyssl/sha1.h"
/*
* Example RSA-1024 keypair, for test purposes
*/
#define KEY_LEN 128
#define RSA_N "9292758453063D803DD603D5E777D788" \
"8ED1D5BF35786190FA2F23EBC0848AEA" \
"DDA92CA6C3D80B32C4D109BE0F36D6AE" \
"7130B9CED7ACDF54CFC7555AC14EEBAB" \
"93A89813FBF3C4F8066D2D800F7C38A8" \
"1AE31942917403FF4946B0A83D3D3E05" \
"EE57C6F5F5606FB5D4BC6CD34EE0801A" \
"5E94BB77B07507233A0BC7BAC8F90F79"
#define RSA_E "10001"
#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
"66CA472BC44D253102F8B4A9D3BFA750" \
"91386C0077937FE33FA3252D28855837" \
"AE1B484A8A9A45F7EE8C0C634F99E8CD" \
"DF79C5CE07EE72C7F123142198164234" \
"CABB724CF78B8173B9F880FC86322407" \
"AF1FEDFDDE2BEB674CA15F3E81A1521E" \
"071513A1E85B5DFA031F21ECAE91A34D"
#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
"2C01CAD19EA484A87EA4377637E75500" \
"FCB2005C5C7DD6EC4AC023CDA285D796" \
"C3D9E75E1EFC42488BB4F1D13AC30A57"
#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
"E211C2B9E5DB1ED0BF61D0D9899620F4" \
"910E4168387E3C30AA1E00C339A79508" \
"8452DD96A9A5EA5D9DCA68DA636032AF"
#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
"3C94D22288ACD763FD8E5600ED4A702D" \
"F84198A5F06C2E72236AE490C93F07F8" \
"3CC559CD27BC2D1CA488811730BB5725"
#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
"D8AAEA56749EA28623272E4F7D0592AF" \
"7C1F1313CAC9471B5C523BFE592F517B" \
"407A1BD76C164B93DA2D32A383E58357"
#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
"F38D18D2B2F0E2DD275AA977E2BF4411" \
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
"A74206CEC169D74BF5A8C50D6F48EA08"
#define PT_LEN 24
#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
"\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
/*
* Checkup routine
*/
int rsa_self_test( int verbose )
{
int len;
rsa_context rsa;
unsigned char sha1sum[20];
unsigned char rsa_plaintext[PT_LEN];
unsigned char rsa_decrypted[PT_LEN];
unsigned char rsa_ciphertext[KEY_LEN];
memset( &rsa, 0, sizeof( rsa_context ) );
rsa.len = KEY_LEN;
mpi_read_string( &rsa.N , 16, RSA_N );
mpi_read_string( &rsa.E , 16, RSA_E );
mpi_read_string( &rsa.D , 16, RSA_D );
mpi_read_string( &rsa.P , 16, RSA_P );
mpi_read_string( &rsa.Q , 16, RSA_Q );
mpi_read_string( &rsa.DP, 16, RSA_DP );
mpi_read_string( &rsa.DQ, 16, RSA_DQ );
mpi_read_string( &rsa.QP, 16, RSA_QP );
if( verbose != 0 )
printf( " RSA key validation: " );
if( rsa_check_pubkey( &rsa ) != 0 ||
rsa_check_privkey( &rsa ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n PKCS#1 encryption : " );
memcpy( rsa_plaintext, RSA_PT, PT_LEN );
if( rsa_pkcs1_encrypt( &rsa, RSA_PUBLIC, PT_LEN,
rsa_plaintext, rsa_ciphertext ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n PKCS#1 decryption : " );
if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len,
rsa_ciphertext, rsa_decrypted ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n PKCS#1 data sign : " );
sha1( rsa_plaintext, PT_LEN, sha1sum );
if( rsa_pkcs1_sign( &rsa, RSA_PRIVATE, RSA_SHA1, 20,
sha1sum, rsa_ciphertext ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n PKCS#1 sig. verify: " );
if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, RSA_SHA1, 20,
sha1sum, rsa_ciphertext ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n\n" );
rsa_free( &rsa );
return( 0 );
}
#endif
#endif

607
library/sha1.c Normal file
View file

@ -0,0 +1,607 @@
/*
* FIPS-180-1 compliant SHA-1 implementation
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#include "xyssl/config.h"
#if defined(XYSSL_SHA1_C)
#include "xyssl/sha1.h"
#include <string.h>
#include <stdio.h>
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
| ( (unsigned long) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*
* SHA-1 context setup
*/
void sha1_starts( sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
static void sha1_process( sha1_context *ctx, unsigned char data[64] )
{
unsigned long temp, W[16], A, B, C, D, E;
GET_ULONG_BE( W[ 0], data, 0 );
GET_ULONG_BE( W[ 1], data, 4 );
GET_ULONG_BE( W[ 2], data, 8 );
GET_ULONG_BE( W[ 3], data, 12 );
GET_ULONG_BE( W[ 4], data, 16 );
GET_ULONG_BE( W[ 5], data, 20 );
GET_ULONG_BE( W[ 6], data, 24 );
GET_ULONG_BE( W[ 7], data, 28 );
GET_ULONG_BE( W[ 8], data, 32 );
GET_ULONG_BE( W[ 9], data, 36 );
GET_ULONG_BE( W[10], data, 40 );
GET_ULONG_BE( W[11], data, 44 );
GET_ULONG_BE( W[12], data, 48 );
GET_ULONG_BE( W[13], data, 52 );
GET_ULONG_BE( W[14], data, 56 );
GET_ULONG_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
void sha1_update( sha1_context *ctx, unsigned char *input, int ilen )
{
int fill;
unsigned long left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (unsigned long) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
sha1_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
sha1_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char sha1_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
void sha1_finish( sha1_context *ctx, unsigned char output[20] )
{
unsigned long last, padn;
unsigned long high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_ULONG_BE( high, msglen, 0 );
PUT_ULONG_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sha1_update( ctx, (unsigned char *) sha1_padding, padn );
sha1_update( ctx, msglen, 8 );
PUT_ULONG_BE( ctx->state[0], output, 0 );
PUT_ULONG_BE( ctx->state[1], output, 4 );
PUT_ULONG_BE( ctx->state[2], output, 8 );
PUT_ULONG_BE( ctx->state[3], output, 12 );
PUT_ULONG_BE( ctx->state[4], output, 16 );
}
/*
* output = SHA-1( input buffer )
*/
void sha1( unsigned char *input, int ilen, unsigned char output[20] )
{
sha1_context ctx;
sha1_starts( &ctx );
sha1_update( &ctx, input, ilen );
sha1_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}
/*
* output = SHA-1( file contents )
*/
int sha1_file( char *path, unsigned char output[20] )
{
FILE *f;
size_t n;
sha1_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( 1 );
sha1_starts( &ctx );
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
sha1_update( &ctx, buf, (int) n );
sha1_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
if( ferror( f ) != 0 )
{
fclose( f );
return( 2 );
}
fclose( f );
return( 0 );
}
/*
* SHA-1 HMAC context setup
*/
void sha1_hmac_starts( sha1_context *ctx, unsigned char *key, int keylen )
{
int i;
unsigned char sum[20];
if( keylen > 64 )
{
sha1( key, keylen, sum );
keylen = 20;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha1_starts( ctx );
sha1_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* SHA-1 HMAC process buffer
*/
void sha1_hmac_update( sha1_context *ctx, unsigned char *input, int ilen )
{
sha1_update( ctx, input, ilen );
}
/*
* SHA-1 HMAC final digest
*/
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
{
unsigned char tmpbuf[20];
sha1_finish( ctx, tmpbuf );
sha1_starts( ctx );
sha1_update( ctx, ctx->opad, 64 );
sha1_update( ctx, tmpbuf, 20 );
sha1_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* output = HMAC-SHA-1( hmac key, input buffer )
*/
void sha1_hmac( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[20] )
{
sha1_context ctx;
sha1_hmac_starts( &ctx, key, keylen );
sha1_hmac_update( &ctx, input, ilen );
sha1_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}
#if defined(XYSSL_SELF_TEST)
/*
* FIPS-180-1 test vectors
*/
static unsigned char sha1_test_buf[3][57] =
{
{ "abc" },
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
{ "" }
};
static const int sha1_test_buflen[3] =
{
3, 56, 1000
};
static const unsigned char sha1_test_sum[3][20] =
{
{ 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
{ 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
};
/*
* RFC 2202 test vectors
*/
static unsigned char sha1_hmac_test_key[7][26] =
{
{ "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
"\x0B\x0B\x0B\x0B" },
{ "Jefe" },
{ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
"\xAA\xAA\xAA\xAA" },
{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
{ "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
"\x0C\x0C\x0C\x0C" },
{ "" }, /* 0xAA 80 times */
{ "" }
};
static const int sha1_hmac_test_keylen[7] =
{
20, 4, 20, 25, 20, 80, 80
};
static unsigned char sha1_hmac_test_buf[7][74] =
{
{ "Hi There" },
{ "what do ya want for nothing?" },
{ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
{ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
{ "Test With Truncation" },
{ "Test Using Larger Than Block-Size Key - Hash Key First" },
{ "Test Using Larger Than Block-Size Key and Larger"
" Than One Block-Size Data" }
};
static const int sha1_hmac_test_buflen[7] =
{
8, 28, 50, 50, 20, 54, 73
};
static const unsigned char sha1_hmac_test_sum[7][20] =
{
{ 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
{ 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
{ 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
{ 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
{ 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
0x7B, 0xE1 },
{ 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
{ 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
};
/*
* Checkup routine
*/
int sha1_self_test( int verbose )
{
int i, j, buflen;
unsigned char buf[1024];
unsigned char sha1sum[20];
sha1_context ctx;
/*
* SHA-1
*/
for( i = 0; i < 3; i++ )
{
if( verbose != 0 )
printf( " SHA-1 test #%d: ", i + 1 );
sha1_starts( &ctx );
if( i == 2 )
{
memset( buf, 'a', buflen = 1000 );
for( j = 0; j < 1000; j++ )
sha1_update( &ctx, buf, buflen );
}
else
sha1_update( &ctx, sha1_test_buf[i],
sha1_test_buflen[i] );
sha1_finish( &ctx, sha1sum );
if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
for( i = 0; i < 7; i++ )
{
if( verbose != 0 )
printf( " HMAC-SHA-1 test #%d: ", i + 1 );
if( i == 5 || i == 6 )
{
memset( buf, '\xAA', buflen = 80 );
sha1_hmac_starts( &ctx, buf, buflen );
}
else
sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
sha1_hmac_test_keylen[i] );
sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
sha1_hmac_test_buflen[i] );
sha1_hmac_finish( &ctx, sha1sum );
buflen = ( i == 4 ) ? 12 : 20;
if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
#endif

688
library/sha2.c Normal file
View file

@ -0,0 +1,688 @@
/*
* FIPS-180-2 compliant SHA-256 implementation
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#include "xyssl/config.h"
#if defined(XYSSL_SHA2_C)
#include "xyssl/sha2.h"
#include <string.h>
#include <stdio.h>
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
| ( (unsigned long) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*
* SHA-256 context setup
*/
void sha2_starts( sha2_context *ctx, int is224 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is224 == 0 )
{
/* SHA-256 */
ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19;
}
else
{
/* SHA-224 */
ctx->state[0] = 0xC1059ED8;
ctx->state[1] = 0x367CD507;
ctx->state[2] = 0x3070DD17;
ctx->state[3] = 0xF70E5939;
ctx->state[4] = 0xFFC00B31;
ctx->state[5] = 0x68581511;
ctx->state[6] = 0x64F98FA7;
ctx->state[7] = 0xBEFA4FA4;
}
ctx->is224 = is224;
}
static void sha2_process( sha2_context *ctx, unsigned char data[64] )
{
unsigned long temp1, temp2, W[64];
unsigned long A, B, C, D, E, F, G, H;
GET_ULONG_BE( W[ 0], data, 0 );
GET_ULONG_BE( W[ 1], data, 4 );
GET_ULONG_BE( W[ 2], data, 8 );
GET_ULONG_BE( W[ 3], data, 12 );
GET_ULONG_BE( W[ 4], data, 16 );
GET_ULONG_BE( W[ 5], data, 20 );
GET_ULONG_BE( W[ 6], data, 24 );
GET_ULONG_BE( W[ 7], data, 28 );
GET_ULONG_BE( W[ 8], data, 32 );
GET_ULONG_BE( W[ 9], data, 36 );
GET_ULONG_BE( W[10], data, 40 );
GET_ULONG_BE( W[11], data, 44 );
GET_ULONG_BE( W[12], data, 48 );
GET_ULONG_BE( W[13], data, 52 );
GET_ULONG_BE( W[14], data, 56 );
GET_ULONG_BE( W[15], data, 60 );
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
/*
* SHA-256 process buffer
*/
void sha2_update( sha2_context *ctx, unsigned char *input, int ilen )
{
int fill;
unsigned long left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (unsigned long) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
sha2_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
sha2_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char sha2_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-256 final digest
*/
void sha2_finish( sha2_context *ctx, unsigned char output[32] )
{
unsigned long last, padn;
unsigned long high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_ULONG_BE( high, msglen, 0 );
PUT_ULONG_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sha2_update( ctx, (unsigned char *) sha2_padding, padn );
sha2_update( ctx, msglen, 8 );
PUT_ULONG_BE( ctx->state[0], output, 0 );
PUT_ULONG_BE( ctx->state[1], output, 4 );
PUT_ULONG_BE( ctx->state[2], output, 8 );
PUT_ULONG_BE( ctx->state[3], output, 12 );
PUT_ULONG_BE( ctx->state[4], output, 16 );
PUT_ULONG_BE( ctx->state[5], output, 20 );
PUT_ULONG_BE( ctx->state[6], output, 24 );
if( ctx->is224 == 0 )
PUT_ULONG_BE( ctx->state[7], output, 28 );
}
/*
* output = SHA-256( input buffer )
*/
void sha2( unsigned char *input, int ilen,
unsigned char output[32], int is224 )
{
sha2_context ctx;
sha2_starts( &ctx, is224 );
sha2_update( &ctx, input, ilen );
sha2_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha2_context ) );
}
/*
* output = SHA-256( file contents )
*/
int sha2_file( char *path, unsigned char output[32], int is224 )
{
FILE *f;
size_t n;
sha2_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( 1 );
sha2_starts( &ctx, is224 );
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
sha2_update( &ctx, buf, (int) n );
sha2_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha2_context ) );
if( ferror( f ) != 0 )
{
fclose( f );
return( 2 );
}
fclose( f );
return( 0 );
}
/*
* SHA-256 HMAC context setup
*/
void sha2_hmac_starts( sha2_context *ctx, unsigned char *key, int keylen,
int is224 )
{
int i;
unsigned char sum[32];
if( keylen > 64 )
{
sha2( key, keylen, sum, is224 );
keylen = ( is224 ) ? 28 : 32;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha2_starts( ctx, is224 );
sha2_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* SHA-256 HMAC process buffer
*/
void sha2_hmac_update( sha2_context *ctx, unsigned char *input, int ilen )
{
sha2_update( ctx, input, ilen );
}
/*
* SHA-256 HMAC final digest
*/
void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] )
{
int is224, hlen;
unsigned char tmpbuf[32];
is224 = ctx->is224;
hlen = ( is224 == 0 ) ? 32 : 28;
sha2_finish( ctx, tmpbuf );
sha2_starts( ctx, is224 );
sha2_update( ctx, ctx->opad, 64 );
sha2_update( ctx, tmpbuf, hlen );
sha2_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* output = HMAC-SHA-256( hmac key, input buffer )
*/
void sha2_hmac( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[32], int is224 )
{
sha2_context ctx;
sha2_hmac_starts( &ctx, key, keylen, is224 );
sha2_hmac_update( &ctx, input, ilen );
sha2_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha2_context ) );
}
#if defined(XYSSL_SELF_TEST)
/*
* FIPS-180-2 test vectors
*/
static unsigned char sha2_test_buf[3][57] =
{
{ "abc" },
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
{ "" }
};
static const int sha2_test_buflen[3] =
{
3, 56, 1000
};
static const unsigned char sha2_test_sum[6][32] =
{
/*
* SHA-224 test vectors
*/
{ 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
0xE3, 0x6C, 0x9D, 0xA7 },
{ 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
0x52, 0x52, 0x25, 0x25 },
{ 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
0x4E, 0xE7, 0xAD, 0x67 },
/*
* SHA-256 test vectors
*/
{ 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
{ 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
};
/*
* RFC 4231 test vectors
*/
static unsigned char sha2_hmac_test_key[7][26] =
{
{ "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
"\x0B\x0B\x0B\x0B" },
{ "Jefe" },
{ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
"\xAA\xAA\xAA\xAA" },
{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
{ "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
"\x0C\x0C\x0C\x0C" },
{ "" }, /* 0xAA 131 times */
{ "" }
};
static const int sha2_hmac_test_keylen[7] =
{
20, 4, 20, 25, 20, 131, 131
};
static unsigned char sha2_hmac_test_buf[7][153] =
{
{ "Hi There" },
{ "what do ya want for nothing?" },
{ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
{ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
{ "Test With Truncation" },
{ "Test Using Larger Than Block-Size Key - Hash Key First" },
{ "This is a test using a larger than block-size key "
"and a larger than block-size data. The key needs to "
"be hashed before being used by the HMAC algorithm." }
};
static const int sha2_hmac_test_buflen[7] =
{
8, 28, 50, 50, 20, 54, 152
};
static const unsigned char sha2_hmac_test_sum[14][32] =
{
/*
* HMAC-SHA-224 test vectors
*/
{ 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,
0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,
0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,
0x53, 0x68, 0x4B, 0x22 },
{ 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,
0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,
0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,
0x8F, 0xD0, 0x5E, 0x44 },
{ 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,
0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,
0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,
0xEC, 0x83, 0x33, 0xEA },
{ 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,
0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,
0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,
0xE7, 0xAF, 0xEC, 0x5A },
{ 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,
0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },
{ 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,
0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,
0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,
0x3F, 0xA6, 0x87, 0x0E },
{ 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,
0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,
0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,
0xF6, 0xF5, 0x65, 0xD1 },
/*
* HMAC-SHA-256 test vectors
*/
{ 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },
{ 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,
0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,
0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,
0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },
{ 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,
0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,
0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,
0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },
{ 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,
0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,
0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,
0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },
{ 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,
0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },
{ 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,
0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,
0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,
0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },
{ 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }
};
/*
* Checkup routine
*/
int sha2_self_test( int verbose )
{
int i, j, k, buflen;
unsigned char buf[1024];
unsigned char sha2sum[32];
sha2_context ctx;
for( i = 0; i < 6; i++ )
{
j = i % 3;
k = i < 3;
if( verbose != 0 )
printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 );
sha2_starts( &ctx, k );
if( j == 2 )
{
memset( buf, 'a', buflen = 1000 );
for( j = 0; j < 1000; j++ )
sha2_update( &ctx, buf, buflen );
}
else
sha2_update( &ctx, sha2_test_buf[j],
sha2_test_buflen[j] );
sha2_finish( &ctx, sha2sum );
if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
for( i = 0; i < 14; i++ )
{
j = i % 7;
k = i < 7;
if( verbose != 0 )
printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
if( j == 5 || j == 6 )
{
memset( buf, '\xAA', buflen = 131 );
sha2_hmac_starts( &ctx, buf, buflen, k );
}
else
sha2_hmac_starts( &ctx, sha2_hmac_test_key[j],
sha2_hmac_test_keylen[j], k );
sha2_hmac_update( &ctx, sha2_hmac_test_buf[j],
sha2_hmac_test_buflen[j] );
sha2_hmac_finish( &ctx, sha2sum );
buflen = ( j == 4 ) ? 16 : 32 - k * 4;
if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
#endif

743
library/sha4.c Normal file
View file

@ -0,0 +1,743 @@
/*
* FIPS-180-2 compliant SHA-384/512 implementation
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The SHA-512 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#include "xyssl/config.h"
#if defined(XYSSL_SHA4_C)
#include "xyssl/sha4.h"
#include <string.h>
#include <stdio.h>
/*
* 64-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT64_BE
#define GET_UINT64_BE(n,b,i) \
{ \
(n) = ( (unsigned int64) (b)[(i) ] << 56 ) \
| ( (unsigned int64) (b)[(i) + 1] << 48 ) \
| ( (unsigned int64) (b)[(i) + 2] << 40 ) \
| ( (unsigned int64) (b)[(i) + 3] << 32 ) \
| ( (unsigned int64) (b)[(i) + 4] << 24 ) \
| ( (unsigned int64) (b)[(i) + 5] << 16 ) \
| ( (unsigned int64) (b)[(i) + 6] << 8 ) \
| ( (unsigned int64) (b)[(i) + 7] ); \
}
#endif
#ifndef PUT_UINT64_BE
#define PUT_UINT64_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 7] = (unsigned char) ( (n) ); \
}
#endif
/*
* Round constants
*/
static const unsigned int64 K[80] =
{
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
};
/*
* SHA-512 context setup
*/
void sha4_starts( sha4_context *ctx, int is384 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is384 == 0 )
{
/* SHA-512 */
ctx->state[0] = UL64(0x6A09E667F3BCC908);
ctx->state[1] = UL64(0xBB67AE8584CAA73B);
ctx->state[2] = UL64(0x3C6EF372FE94F82B);
ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
ctx->state[4] = UL64(0x510E527FADE682D1);
ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
ctx->state[7] = UL64(0x5BE0CD19137E2179);
}
else
{
/* SHA-384 */
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
ctx->state[1] = UL64(0x629A292A367CD507);
ctx->state[2] = UL64(0x9159015A3070DD17);
ctx->state[3] = UL64(0x152FECD8F70E5939);
ctx->state[4] = UL64(0x67332667FFC00B31);
ctx->state[5] = UL64(0x8EB44A8768581511);
ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
}
ctx->is384 = is384;
}
static void sha4_process( sha4_context *ctx, unsigned char data[128] )
{
int i;
unsigned int64 temp1, temp2, W[80];
unsigned int64 A, B, C, D, E, F, G, H;
#define SHR(x,n) (x >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
for( i = 0; i < 16; i++ )
{
GET_UINT64_BE( W[i], data, i << 3 );
}
for( ; i < 80; i++ )
{
W[i] = S1(W[i - 2]) + W[i - 7] +
S0(W[i - 15]) + W[i - 16];
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
i = 0;
do
{
P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
}
while( i < 80 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
/*
* SHA-512 process buffer
*/
void sha4_update( sha4_context *ctx, unsigned char *input, int ilen )
{
int fill;
unsigned int64 left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x7F;
fill = (int)( 128 - left );
ctx->total[0] += ilen;
if( ctx->total[0] < (unsigned int64) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
sha4_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 128 )
{
sha4_process( ctx, input );
input += 128;
ilen -= 128;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char sha4_padding[128] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-512 final digest
*/
void sha4_finish( sha4_context *ctx, unsigned char output[64] )
{
int last, padn;
unsigned int64 high, low;
unsigned char msglen[16];
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT64_BE( high, msglen, 0 );
PUT_UINT64_BE( low, msglen, 8 );
last = (int)( ctx->total[0] & 0x7F );
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
sha4_update( ctx, (unsigned char *) sha4_padding, padn );
sha4_update( ctx, msglen, 16 );
PUT_UINT64_BE( ctx->state[0], output, 0 );
PUT_UINT64_BE( ctx->state[1], output, 8 );
PUT_UINT64_BE( ctx->state[2], output, 16 );
PUT_UINT64_BE( ctx->state[3], output, 24 );
PUT_UINT64_BE( ctx->state[4], output, 32 );
PUT_UINT64_BE( ctx->state[5], output, 40 );
if( ctx->is384 == 0 )
{
PUT_UINT64_BE( ctx->state[6], output, 48 );
PUT_UINT64_BE( ctx->state[7], output, 56 );
}
}
/*
* output = SHA-512( input buffer )
*/
void sha4( unsigned char *input, int ilen,
unsigned char output[64], int is384 )
{
sha4_context ctx;
sha4_starts( &ctx, is384 );
sha4_update( &ctx, input, ilen );
sha4_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha4_context ) );
}
/*
* output = SHA-512( file contents )
*/
int sha4_file( char *path, unsigned char output[64], int is384 )
{
FILE *f;
size_t n;
sha4_context ctx;
unsigned char buf[1024];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( 1 );
sha4_starts( &ctx, is384 );
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
sha4_update( &ctx, buf, (int) n );
sha4_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha4_context ) );
if( ferror( f ) != 0 )
{
fclose( f );
return( 2 );
}
fclose( f );
return( 0 );
}
/*
* SHA-512 HMAC context setup
*/
void sha4_hmac_starts( sha4_context *ctx, unsigned char *key, int keylen,
int is384 )
{
int i;
unsigned char sum[64];
if( keylen > 128 )
{
sha4( key, keylen, sum, is384 );
keylen = ( is384 ) ? 48 : 64;
key = sum;
}
memset( ctx->ipad, 0x36, 128 );
memset( ctx->opad, 0x5C, 128 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha4_starts( ctx, is384 );
sha4_update( ctx, ctx->ipad, 128 );
memset( sum, 0, sizeof( sum ) );
}
/*
* SHA-512 HMAC process buffer
*/
void sha4_hmac_update( sha4_context *ctx,
unsigned char *input, int ilen )
{
sha4_update( ctx, input, ilen );
}
/*
* SHA-512 HMAC final digest
*/
void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] )
{
int is384, hlen;
unsigned char tmpbuf[64];
is384 = ctx->is384;
hlen = ( is384 == 0 ) ? 64 : 48;
sha4_finish( ctx, tmpbuf );
sha4_starts( ctx, is384 );
sha4_update( ctx, ctx->opad, 128 );
sha4_update( ctx, tmpbuf, hlen );
sha4_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* output = HMAC-SHA-512( hmac key, input buffer )
*/
void sha4_hmac( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[64], int is384 )
{
sha4_context ctx;
sha4_hmac_starts( &ctx, key, keylen, is384 );
sha4_hmac_update( &ctx, input, ilen );
sha4_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha4_context ) );
}
#if defined(XYSSL_SELF_TEST)
/*
* FIPS-180-2 test vectors
*/
static unsigned char sha4_test_buf[3][113] =
{
{ "abc" },
{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
{ "" }
};
static const int sha4_test_buflen[3] =
{
3, 112, 1000
};
static const unsigned char sha4_test_sum[6][64] =
{
/*
* SHA-384 test vectors
*/
{ 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
{ 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
{ 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
/*
* SHA-512 test vectors
*/
{ 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
{ 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
{ 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
};
/*
* RFC 4231 test vectors
*/
static unsigned char sha4_hmac_test_key[7][26] =
{
{ "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
"\x0B\x0B\x0B\x0B" },
{ "Jefe" },
{ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
"\xAA\xAA\xAA\xAA" },
{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
{ "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
"\x0C\x0C\x0C\x0C" },
{ "" }, /* 0xAA 131 times */
{ "" }
};
static const int sha4_hmac_test_keylen[7] =
{
20, 4, 20, 25, 20, 131, 131
};
static unsigned char sha4_hmac_test_buf[7][153] =
{
{ "Hi There" },
{ "what do ya want for nothing?" },
{ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
{ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
{ "Test With Truncation" },
{ "Test Using Larger Than Block-Size Key - Hash Key First" },
{ "This is a test using a larger than block-size key "
"and a larger than block-size data. The key needs to "
"be hashed before being used by the HMAC algorithm." }
};
static const int sha4_hmac_test_buflen[7] =
{
8, 28, 50, 50, 20, 54, 152
};
static const unsigned char sha4_hmac_test_sum[14][64] =
{
/*
* HMAC-SHA-384 test vectors
*/
{ 0xAF, 0xD0, 0x39, 0x44, 0xD8, 0x48, 0x95, 0x62,
0x6B, 0x08, 0x25, 0xF4, 0xAB, 0x46, 0x90, 0x7F,
0x15, 0xF9, 0xDA, 0xDB, 0xE4, 0x10, 0x1E, 0xC6,
0x82, 0xAA, 0x03, 0x4C, 0x7C, 0xEB, 0xC5, 0x9C,
0xFA, 0xEA, 0x9E, 0xA9, 0x07, 0x6E, 0xDE, 0x7F,
0x4A, 0xF1, 0x52, 0xE8, 0xB2, 0xFA, 0x9C, 0xB6 },
{ 0xAF, 0x45, 0xD2, 0xE3, 0x76, 0x48, 0x40, 0x31,
0x61, 0x7F, 0x78, 0xD2, 0xB5, 0x8A, 0x6B, 0x1B,
0x9C, 0x7E, 0xF4, 0x64, 0xF5, 0xA0, 0x1B, 0x47,
0xE4, 0x2E, 0xC3, 0x73, 0x63, 0x22, 0x44, 0x5E,
0x8E, 0x22, 0x40, 0xCA, 0x5E, 0x69, 0xE2, 0xC7,
0x8B, 0x32, 0x39, 0xEC, 0xFA, 0xB2, 0x16, 0x49 },
{ 0x88, 0x06, 0x26, 0x08, 0xD3, 0xE6, 0xAD, 0x8A,
0x0A, 0xA2, 0xAC, 0xE0, 0x14, 0xC8, 0xA8, 0x6F,
0x0A, 0xA6, 0x35, 0xD9, 0x47, 0xAC, 0x9F, 0xEB,
0xE8, 0x3E, 0xF4, 0xE5, 0x59, 0x66, 0x14, 0x4B,
0x2A, 0x5A, 0xB3, 0x9D, 0xC1, 0x38, 0x14, 0xB9,
0x4E, 0x3A, 0xB6, 0xE1, 0x01, 0xA3, 0x4F, 0x27 },
{ 0x3E, 0x8A, 0x69, 0xB7, 0x78, 0x3C, 0x25, 0x85,
0x19, 0x33, 0xAB, 0x62, 0x90, 0xAF, 0x6C, 0xA7,
0x7A, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9C,
0xC5, 0x57, 0x7C, 0x6E, 0x1F, 0x57, 0x3B, 0x4E,
0x68, 0x01, 0xDD, 0x23, 0xC4, 0xA7, 0xD6, 0x79,
0xCC, 0xF8, 0xA3, 0x86, 0xC6, 0x74, 0xCF, 0xFB },
{ 0x3A, 0xBF, 0x34, 0xC3, 0x50, 0x3B, 0x2A, 0x23,
0xA4, 0x6E, 0xFC, 0x61, 0x9B, 0xAE, 0xF8, 0x97 },
{ 0x4E, 0xCE, 0x08, 0x44, 0x85, 0x81, 0x3E, 0x90,
0x88, 0xD2, 0xC6, 0x3A, 0x04, 0x1B, 0xC5, 0xB4,
0x4F, 0x9E, 0xF1, 0x01, 0x2A, 0x2B, 0x58, 0x8F,
0x3C, 0xD1, 0x1F, 0x05, 0x03, 0x3A, 0xC4, 0xC6,
0x0C, 0x2E, 0xF6, 0xAB, 0x40, 0x30, 0xFE, 0x82,
0x96, 0x24, 0x8D, 0xF1, 0x63, 0xF4, 0x49, 0x52 },
{ 0x66, 0x17, 0x17, 0x8E, 0x94, 0x1F, 0x02, 0x0D,
0x35, 0x1E, 0x2F, 0x25, 0x4E, 0x8F, 0xD3, 0x2C,
0x60, 0x24, 0x20, 0xFE, 0xB0, 0xB8, 0xFB, 0x9A,
0xDC, 0xCE, 0xBB, 0x82, 0x46, 0x1E, 0x99, 0xC5,
0xA6, 0x78, 0xCC, 0x31, 0xE7, 0x99, 0x17, 0x6D,
0x38, 0x60, 0xE6, 0x11, 0x0C, 0x46, 0x52, 0x3E },
/*
* HMAC-SHA-512 test vectors
*/
{ 0x87, 0xAA, 0x7C, 0xDE, 0xA5, 0xEF, 0x61, 0x9D,
0x4F, 0xF0, 0xB4, 0x24, 0x1A, 0x1D, 0x6C, 0xB0,
0x23, 0x79, 0xF4, 0xE2, 0xCE, 0x4E, 0xC2, 0x78,
0x7A, 0xD0, 0xB3, 0x05, 0x45, 0xE1, 0x7C, 0xDE,
0xDA, 0xA8, 0x33, 0xB7, 0xD6, 0xB8, 0xA7, 0x02,
0x03, 0x8B, 0x27, 0x4E, 0xAE, 0xA3, 0xF4, 0xE4,
0xBE, 0x9D, 0x91, 0x4E, 0xEB, 0x61, 0xF1, 0x70,
0x2E, 0x69, 0x6C, 0x20, 0x3A, 0x12, 0x68, 0x54 },
{ 0x16, 0x4B, 0x7A, 0x7B, 0xFC, 0xF8, 0x19, 0xE2,
0xE3, 0x95, 0xFB, 0xE7, 0x3B, 0x56, 0xE0, 0xA3,
0x87, 0xBD, 0x64, 0x22, 0x2E, 0x83, 0x1F, 0xD6,
0x10, 0x27, 0x0C, 0xD7, 0xEA, 0x25, 0x05, 0x54,
0x97, 0x58, 0xBF, 0x75, 0xC0, 0x5A, 0x99, 0x4A,
0x6D, 0x03, 0x4F, 0x65, 0xF8, 0xF0, 0xE6, 0xFD,
0xCA, 0xEA, 0xB1, 0xA3, 0x4D, 0x4A, 0x6B, 0x4B,
0x63, 0x6E, 0x07, 0x0A, 0x38, 0xBC, 0xE7, 0x37 },
{ 0xFA, 0x73, 0xB0, 0x08, 0x9D, 0x56, 0xA2, 0x84,
0xEF, 0xB0, 0xF0, 0x75, 0x6C, 0x89, 0x0B, 0xE9,
0xB1, 0xB5, 0xDB, 0xDD, 0x8E, 0xE8, 0x1A, 0x36,
0x55, 0xF8, 0x3E, 0x33, 0xB2, 0x27, 0x9D, 0x39,
0xBF, 0x3E, 0x84, 0x82, 0x79, 0xA7, 0x22, 0xC8,
0x06, 0xB4, 0x85, 0xA4, 0x7E, 0x67, 0xC8, 0x07,
0xB9, 0x46, 0xA3, 0x37, 0xBE, 0xE8, 0x94, 0x26,
0x74, 0x27, 0x88, 0x59, 0xE1, 0x32, 0x92, 0xFB },
{ 0xB0, 0xBA, 0x46, 0x56, 0x37, 0x45, 0x8C, 0x69,
0x90, 0xE5, 0xA8, 0xC5, 0xF6, 0x1D, 0x4A, 0xF7,
0xE5, 0x76, 0xD9, 0x7F, 0xF9, 0x4B, 0x87, 0x2D,
0xE7, 0x6F, 0x80, 0x50, 0x36, 0x1E, 0xE3, 0xDB,
0xA9, 0x1C, 0xA5, 0xC1, 0x1A, 0xA2, 0x5E, 0xB4,
0xD6, 0x79, 0x27, 0x5C, 0xC5, 0x78, 0x80, 0x63,
0xA5, 0xF1, 0x97, 0x41, 0x12, 0x0C, 0x4F, 0x2D,
0xE2, 0xAD, 0xEB, 0xEB, 0x10, 0xA2, 0x98, 0xDD },
{ 0x41, 0x5F, 0xAD, 0x62, 0x71, 0x58, 0x0A, 0x53,
0x1D, 0x41, 0x79, 0xBC, 0x89, 0x1D, 0x87, 0xA6 },
{ 0x80, 0xB2, 0x42, 0x63, 0xC7, 0xC1, 0xA3, 0xEB,
0xB7, 0x14, 0x93, 0xC1, 0xDD, 0x7B, 0xE8, 0xB4,
0x9B, 0x46, 0xD1, 0xF4, 0x1B, 0x4A, 0xEE, 0xC1,
0x12, 0x1B, 0x01, 0x37, 0x83, 0xF8, 0xF3, 0x52,
0x6B, 0x56, 0xD0, 0x37, 0xE0, 0x5F, 0x25, 0x98,
0xBD, 0x0F, 0xD2, 0x21, 0x5D, 0x6A, 0x1E, 0x52,
0x95, 0xE6, 0x4F, 0x73, 0xF6, 0x3F, 0x0A, 0xEC,
0x8B, 0x91, 0x5A, 0x98, 0x5D, 0x78, 0x65, 0x98 },
{ 0xE3, 0x7B, 0x6A, 0x77, 0x5D, 0xC8, 0x7D, 0xBA,
0xA4, 0xDF, 0xA9, 0xF9, 0x6E, 0x5E, 0x3F, 0xFD,
0xDE, 0xBD, 0x71, 0xF8, 0x86, 0x72, 0x89, 0x86,
0x5D, 0xF5, 0xA3, 0x2D, 0x20, 0xCD, 0xC9, 0x44,
0xB6, 0x02, 0x2C, 0xAC, 0x3C, 0x49, 0x82, 0xB1,
0x0D, 0x5E, 0xEB, 0x55, 0xC3, 0xE4, 0xDE, 0x15,
0x13, 0x46, 0x76, 0xFB, 0x6D, 0xE0, 0x44, 0x60,
0x65, 0xC9, 0x74, 0x40, 0xFA, 0x8C, 0x6A, 0x58 }
};
/*
* Checkup routine
*/
int sha4_self_test( int verbose )
{
int i, j, k, buflen;
unsigned char buf[1024];
unsigned char sha4sum[64];
sha4_context ctx;
for( i = 0; i < 6; i++ )
{
j = i % 3;
k = i < 3;
if( verbose != 0 )
printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
sha4_starts( &ctx, k );
if( j == 2 )
{
memset( buf, 'a', buflen = 1000 );
for( j = 0; j < 1000; j++ )
sha4_update( &ctx, buf, buflen );
}
else
sha4_update( &ctx, sha4_test_buf[j],
sha4_test_buflen[j] );
sha4_finish( &ctx, sha4sum );
if( memcmp( sha4sum, sha4_test_sum[i], 64 - k * 16 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
for( i = 0; i < 14; i++ )
{
j = i % 7;
k = i < 7;
if( verbose != 0 )
printf( " HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 );
if( j == 5 || j == 6 )
{
memset( buf, '\xAA', buflen = 131 );
sha4_hmac_starts( &ctx, buf, buflen, k );
}
else
sha4_hmac_starts( &ctx, sha4_hmac_test_key[j],
sha4_hmac_test_keylen[j], k );
sha4_hmac_update( &ctx, sha4_hmac_test_buf[j],
sha4_hmac_test_buflen[j] );
sha4_hmac_finish( &ctx, sha4sum );
buflen = ( j == 4 ) ? 16 : 64 - k * 16;
if( memcmp( sha4sum, sha4_hmac_test_sum[i], buflen ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
}
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif
#endif

768
library/ssl_cli.c Normal file
View file

@ -0,0 +1,768 @@
/*
* SSLv3/TLSv1 client-side functions
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "xyssl/config.h"
#if defined(XYSSL_SSL_CLI_C)
#include "xyssl/debug.h"
#include "xyssl/ssl.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
static int ssl_write_client_hello( ssl_context *ssl )
{
int ret, i, n;
unsigned char *buf;
unsigned char *p;
time_t t;
SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
ssl->major_ver = SSL_MAJOR_VERSION_3;
ssl->minor_ver = SSL_MINOR_VERSION_0;
ssl->max_major_ver = SSL_MAJOR_VERSION_3;
ssl->max_minor_ver = SSL_MINOR_VERSION_1;
/*
* 0 . 0 handshake type
* 1 . 3 handshake length
* 4 . 5 highest version supported
* 6 . 9 current UNIX time
* 10 . 37 random bytes
*/
buf = ssl->out_msg;
p = buf + 4;
*p++ = (unsigned char) ssl->max_major_ver;
*p++ = (unsigned char) ssl->max_minor_ver;
SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]",
buf[4], buf[5] ) );
t = time( NULL );
*p++ = (unsigned char)( t >> 24 );
*p++ = (unsigned char)( t >> 16 );
*p++ = (unsigned char)( t >> 8 );
*p++ = (unsigned char)( t );
SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
for( i = 28; i > 0; i-- )
*p++ = (unsigned char) ssl->f_rng( ssl->p_rng );
memcpy( ssl->randbytes, buf + 6, 32 );
SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 6, 32 );
/*
* 38 . 38 session id length
* 39 . 39+n session id
* 40+n . 41+n cipherlist length
* 42+n . .. cipherlist
* .. . .. compression alg. (0)
* .. . .. extensions (unused)
*/
n = ssl->session->length;
if( n < 16 || n > 32 || ssl->resume == 0 ||
t - ssl->session->start > ssl->timeout )
n = 0;
*p++ = (unsigned char) n;
for( i = 0; i < n; i++ )
*p++ = ssl->session->id[i];
SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n );
for( n = 0; ssl->ciphers[n] != 0; n++ );
*p++ = (unsigned char)( n >> 7 );
*p++ = (unsigned char)( n << 1 );
SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphers", n ) );
for( i = 0; i < n; i++ )
{
SSL_DEBUG_MSG( 3, ( "client hello, add cipher: %2d",
ssl->ciphers[i] ) );
*p++ = (unsigned char)( ssl->ciphers[i] >> 8 );
*p++ = (unsigned char)( ssl->ciphers[i] );
}
SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) );
SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", 0 ) );
*p++ = 1;
*p++ = SSL_COMPRESS_NULL;
if ( ssl->hostname != NULL )
{
SSL_DEBUG_MSG( 3, ( "client hello, server name extension: %s",
ssl->hostname ) );
*p++ = (unsigned char)( ( (ssl->hostname_len + 9) >> 8 ) & 0xFF );
*p++ = (unsigned char)( ( (ssl->hostname_len + 9) ) & 0xFF );
*p++ = (unsigned char)( ( TLS_EXT_SERVERNAME >> 8 ) & 0xFF );
*p++ = (unsigned char)( ( TLS_EXT_SERVERNAME ) & 0xFF );
*p++ = (unsigned char)( ( (ssl->hostname_len + 5) >> 8 ) & 0xFF );
*p++ = (unsigned char)( ( (ssl->hostname_len + 5) ) & 0xFF );
*p++ = (unsigned char)( ( (ssl->hostname_len + 3) >> 8 ) & 0xFF );
*p++ = (unsigned char)( ( (ssl->hostname_len + 3) ) & 0xFF );
*p++ = (unsigned char)( ( TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF );
*p++ = (unsigned char)( ( ssl->hostname_len >> 8 ) & 0xFF );
*p++ = (unsigned char)( ( ssl->hostname_len ) & 0xFF );
memcpy( p, ssl->hostname, ssl->hostname_len );
p += ssl->hostname_len;
}
ssl->out_msglen = p - buf;
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = SSL_HS_CLIENT_HELLO;
ssl->state++;
if( ( ret = ssl_write_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_write_record", ret );
return( ret );
}
SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
return( 0 );
}
static int ssl_parse_server_hello( ssl_context *ssl )
{
time_t t;
int ret, i, n;
int ext_len;
unsigned char *buf;
SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
/*
* 0 . 0 handshake type
* 1 . 3 handshake length
* 4 . 5 protocol version
* 6 . 9 UNIX time()
* 10 . 37 random bytes
*/
buf = ssl->in_msg;
if( ( ret = ssl_read_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_read_record", ret );
return( ret );
}
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
return( XYSSL_ERR_SSL_UNEXPECTED_MESSAGE );
}
SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
buf[4], buf[5] ) );
if( ssl->in_hslen < 42 ||
buf[0] != SSL_HS_SERVER_HELLO ||
buf[4] != SSL_MAJOR_VERSION_3 )
{
SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
}
if( buf[5] != SSL_MINOR_VERSION_0 &&
buf[5] != SSL_MINOR_VERSION_1 )
{
SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
}
ssl->minor_ver = buf[5];
t = ( (time_t) buf[6] << 24 )
| ( (time_t) buf[7] << 16 )
| ( (time_t) buf[8] << 8 )
| ( (time_t) buf[9] );
memcpy( ssl->randbytes + 32, buf + 6, 32 );
n = buf[38];
SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
/*
* 38 . 38 session id length
* 39 . 38+n session id
* 39+n . 40+n chosen cipher
* 41+n . 41+n chosen compression alg.
* 42+n . 43+n extensions length
* 44+n . 44+n+m extensions
*/
if( n < 0 || n > 32 || ssl->in_hslen > 42 + n )
{
ext_len = ( ( buf[42 + n] << 8 )
| ( buf[43 + n] ) ) + 2;
}
else
{
ext_len = 0;
}
if( n < 0 || n > 32 || ssl->in_hslen != 42 + n + ext_len )
{
SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
}
i = ( buf[39 + n] << 8 ) | buf[40 + n];
SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n );
/*
* Check if the session can be resumed
*/
if( ssl->resume == 0 || n == 0 ||
ssl->session->cipher != i ||
ssl->session->length != n ||
memcmp( ssl->session->id, buf + 39, n ) != 0 )
{
ssl->state++;
ssl->resume = 0;
ssl->session->start = time( NULL );
ssl->session->cipher = i;
ssl->session->length = n;
memcpy( ssl->session->id, buf + 39, n );
}
else
{
ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
ssl_derive_keys( ssl );
}
SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
ssl->resume ? "a" : "no" ) );
SSL_DEBUG_MSG( 3, ( "server hello, chosen cipher: %d", i ) );
SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[41 + n] ) );
i = 0;
while( 1 )
{
if( ssl->ciphers[i] == 0 )
{
SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
}
if( ssl->ciphers[i++] == ssl->session->cipher )
break;
}
if( buf[41 + n] != SSL_COMPRESS_NULL )
{
SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
}
/* TODO: Process extensions */
SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) );
return( 0 );
}
static int ssl_parse_server_key_exchange( ssl_context *ssl )
{
int ret, n;
unsigned char *p, *end;
unsigned char hash[36];
md5_context md5;
sha1_context sha1;
SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
if( ssl->session->cipher != SSL_EDH_RSA_DES_168_SHA &&
ssl->session->cipher != SSL_EDH_RSA_AES_256_SHA )
{
SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
ssl->state++;
return( 0 );
}
#if !defined(XYSSL_DHM_C)
SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
return( XYSSL_ERR_SSL_FEATURE_UNAVAILABLE );
#else
if( ( ret = ssl_read_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_read_record", ret );
return( ret );
}
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
return( XYSSL_ERR_SSL_UNEXPECTED_MESSAGE );
}
if( ssl->in_msg[0] != SSL_HS_SERVER_KEY_EXCHANGE )
{
SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
return( XYSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
}
/*
* Ephemeral DH parameters:
*
* struct {
* opaque dh_p<1..2^16-1>;
* opaque dh_g<1..2^16-1>;
* opaque dh_Ys<1..2^16-1>;
* } ServerDHParams;
*/
p = ssl->in_msg + 4;
end = ssl->in_msg + ssl->in_hslen;
if( ( ret = dhm_read_params( &ssl->dhm_ctx, &p, end ) ) != 0 )
{
SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
return( XYSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
}
if( (int)( end - p ) != ssl->peer_cert->rsa.len )
{
SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
return( XYSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
}
if( ssl->dhm_ctx.len < 64 || ssl->dhm_ctx.len > 256 )
{
SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
return( XYSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
}
SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P );
SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G );
SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY );
/*
* digitally-signed struct {
* opaque md5_hash[16];
* opaque sha_hash[20];
* };
*
* md5_hash
* MD5(ClientHello.random + ServerHello.random
* + ServerParams);
* sha_hash
* SHA(ClientHello.random + ServerHello.random
* + ServerParams);
*/
n = ssl->in_hslen - ( end - p ) - 6;
md5_starts( &md5 );
md5_update( &md5, ssl->randbytes, 64 );
md5_update( &md5, ssl->in_msg + 4, n );
md5_finish( &md5, hash );
sha1_starts( &sha1 );
sha1_update( &sha1, ssl->randbytes, 64 );
sha1_update( &sha1, ssl->in_msg + 4, n );
sha1_finish( &sha1, hash + 16 );
SSL_DEBUG_BUF( 3, "parameters hash", hash, 36 );
if( ( ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC,
RSA_RAW, 36, hash, p ) ) != 0 )
{
SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
return( ret );
}
ssl->state++;
SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) );
return( 0 );
#endif
}
static int ssl_parse_certificate_request( ssl_context *ssl )
{
int ret;
SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
/*
* 0 . 0 handshake type
* 1 . 3 handshake length
* 4 . 5 SSL version
* 6 . 6 cert type count
* 7 .. n-1 cert types
* n .. n+1 length of all DNs
* n+2 .. n+3 length of DN 1
* n+4 .. ... Distinguished Name #1
* ... .. ... length of DN 2, etc.
*/
if( ( ret = ssl_read_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_read_record", ret );
return( ret );
}
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
return( XYSSL_ERR_SSL_UNEXPECTED_MESSAGE );
}
ssl->client_auth = 0;
ssl->state++;
if( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST )
ssl->client_auth++;
SSL_DEBUG_MSG( 3, ( "got %s certificate request",
ssl->client_auth ? "a" : "no" ) );
SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) );
return( 0 );
}
static int ssl_parse_server_hello_done( ssl_context *ssl )
{
int ret;
SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
if( ssl->client_auth != 0 )
{
if( ( ret = ssl_read_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_read_record", ret );
return( ret );
}
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
return( XYSSL_ERR_SSL_UNEXPECTED_MESSAGE );
}
}
if( ssl->in_hslen != 4 ||
ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE )
{
SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
return( XYSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE );
}
ssl->state++;
SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) );
return( 0 );
}
static int ssl_write_client_key_exchange( ssl_context *ssl )
{
int ret, i, n;
SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
if( ssl->session->cipher == SSL_EDH_RSA_DES_168_SHA ||
ssl->session->cipher == SSL_EDH_RSA_AES_256_SHA )
{
#if !defined(XYSSL_DHM_C)
SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
return( XYSSL_ERR_SSL_FEATURE_UNAVAILABLE );
#else
/*
* DHM key exchange -- send G^X mod P
*/
n = ssl->dhm_ctx.len;
ssl->out_msg[4] = (unsigned char)( n >> 8 );
ssl->out_msg[5] = (unsigned char)( n );
i = 6;
ret = dhm_make_public( &ssl->dhm_ctx, 256,
&ssl->out_msg[i], n,
ssl->f_rng, ssl->p_rng );
if( ret != 0 )
{
SSL_DEBUG_RET( 1, "dhm_make_public", ret );
return( ret );
}
SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X );
SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX );
ssl->pmslen = ssl->dhm_ctx.len;
if( ( ret = dhm_calc_secret( &ssl->dhm_ctx,
ssl->premaster,
&ssl->pmslen ) ) != 0 )
{
SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
return( ret );
}
SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K );
#endif
}
else
{
/*
* RSA key exchange -- send rsa_public(pkcs1 v1.5(premaster))
*/
ssl->premaster[0] = (unsigned char) ssl->max_major_ver;
ssl->premaster[1] = (unsigned char) ssl->max_minor_ver;
ssl->pmslen = 48;
for( i = 2; i < ssl->pmslen; i++ )
ssl->premaster[i] = (unsigned char) ssl->f_rng( ssl->p_rng );
i = 4;
n = ssl->peer_cert->rsa.len;
if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
{
i += 2;
ssl->out_msg[4] = (unsigned char)( n >> 8 );
ssl->out_msg[5] = (unsigned char)( n );
}
ret = rsa_pkcs1_encrypt( &ssl->peer_cert->rsa, RSA_PUBLIC,
ssl->pmslen, ssl->premaster,
ssl->out_msg + i );
if( ret != 0 )
{
SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret );
return( ret );
}
}
ssl_derive_keys( ssl );
ssl->out_msglen = i + n;
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = SSL_HS_CLIENT_KEY_EXCHANGE;
ssl->state++;
if( ( ret = ssl_write_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_write_record", ret );
return( ret );
}
SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) );
return( 0 );
}
static int ssl_write_certificate_verify( ssl_context *ssl )
{
int ret, n;
unsigned char hash[36];
SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
if( ssl->client_auth == 0 )
{
SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
ssl->state++;
return( 0 );
}
if( ssl->rsa_key == NULL )
{
SSL_DEBUG_MSG( 1, ( "got no private key" ) );
return( XYSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
}
/*
* Make an RSA signature of the handshake digests
*/
ssl_calc_verify( ssl, hash );
n = ssl->rsa_key->len;
ssl->out_msg[4] = (unsigned char)( n >> 8 );
ssl->out_msg[5] = (unsigned char)( n );
if( ( ret = rsa_pkcs1_sign( ssl->rsa_key, RSA_PRIVATE, RSA_RAW,
36, hash, ssl->out_msg + 6 ) ) != 0 )
{
SSL_DEBUG_RET( 1, "rsa_pkcs1_sign", ret );
return( ret );
}
ssl->out_msglen = 6 + n;
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = SSL_HS_CERTIFICATE_VERIFY;
ssl->state++;
if( ( ret = ssl_write_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_write_record", ret );
return( ret );
}
SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) );
return( 0 );
}
/*
* SSL handshake -- client side
*/
int ssl_handshake_client( ssl_context *ssl )
{
int ret = 0;
SSL_DEBUG_MSG( 2, ( "=> handshake client" ) );
while( ssl->state != SSL_HANDSHAKE_OVER )
{
SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
if( ( ret = ssl_flush_output( ssl ) ) != 0 )
break;
switch( ssl->state )
{
case SSL_HELLO_REQUEST:
ssl->state = SSL_CLIENT_HELLO;
break;
/*
* ==> ClientHello
*/
case SSL_CLIENT_HELLO:
ret = ssl_write_client_hello( ssl );
break;
/*
* <== ServerHello
* Certificate
* ( ServerKeyExchange )
* ( CertificateRequest )
* ServerHelloDone
*/
case SSL_SERVER_HELLO:
ret = ssl_parse_server_hello( ssl );
break;
case SSL_SERVER_CERTIFICATE:
ret = ssl_parse_certificate( ssl );
break;
case SSL_SERVER_KEY_EXCHANGE:
ret = ssl_parse_server_key_exchange( ssl );
break;
case SSL_CERTIFICATE_REQUEST:
ret = ssl_parse_certificate_request( ssl );
break;
case SSL_SERVER_HELLO_DONE:
ret = ssl_parse_server_hello_done( ssl );
break;
/*
* ==> ( Certificate/Alert )
* ClientKeyExchange
* ( CertificateVerify )
* ChangeCipherSpec
* Finished
*/
case SSL_CLIENT_CERTIFICATE:
ret = ssl_write_certificate( ssl );
break;
case SSL_CLIENT_KEY_EXCHANGE:
ret = ssl_write_client_key_exchange( ssl );
break;
case SSL_CERTIFICATE_VERIFY:
ret = ssl_write_certificate_verify( ssl );
break;
case SSL_CLIENT_CHANGE_CIPHER_SPEC:
ret = ssl_write_change_cipher_spec( ssl );
break;
case SSL_CLIENT_FINISHED:
ret = ssl_write_finished( ssl );
break;
/*
* <== ChangeCipherSpec
* Finished
*/
case SSL_SERVER_CHANGE_CIPHER_SPEC:
ret = ssl_parse_change_cipher_spec( ssl );
break;
case SSL_SERVER_FINISHED:
ret = ssl_parse_finished( ssl );
break;
case SSL_FLUSH_BUFFERS:
SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
ssl->state = SSL_HANDSHAKE_OVER;
break;
default:
SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
return( XYSSL_ERR_SSL_BAD_INPUT_DATA );
}
if( ret != 0 )
break;
}
SSL_DEBUG_MSG( 2, ( "<= handshake client" ) );
return( ret );
}
#endif

930
library/ssl_srv.c Normal file
View file

@ -0,0 +1,930 @@
/*
* SSLv3/TLSv1 server-side functions
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "xyssl/config.h"
#if defined(XYSSL_SSL_SRV_C)
#include "xyssl/debug.h"
#include "xyssl/ssl.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
static int ssl_parse_client_hello( ssl_context *ssl )
{
int ret, i, j, n;
int ciph_len, sess_len;
int chal_len, comp_len;
unsigned char *buf, *p;
SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
return( ret );
}
buf = ssl->in_hdr;
if( ( buf[0] & 0x80 ) != 0 )
{
SSL_DEBUG_BUF( 4, "record header", buf, 5 );
SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d",
buf[2] ) );
SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d",
( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) );
SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]",
buf[3], buf[4] ) );
/*
* SSLv2 Client Hello
*
* Record layer:
* 0 . 1 message length
*
* SSL layer:
* 2 . 2 message type
* 3 . 4 protocol version
*/
if( buf[2] != SSL_HS_CLIENT_HELLO ||
buf[3] != SSL_MAJOR_VERSION_3 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF;
if( n < 17 || n > 512 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
ssl->max_major_ver = buf[3];
ssl->max_minor_ver = buf[4];
ssl->major_ver = SSL_MAJOR_VERSION_3;
ssl->minor_ver = ( buf[4] <= SSL_MINOR_VERSION_1 )
? buf[4] : SSL_MINOR_VERSION_1;
if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
return( ret );
}
md5_update( &ssl->fin_md5 , buf + 2, n );
sha1_update( &ssl->fin_sha1, buf + 2, n );
buf = ssl->in_msg;
n = ssl->in_left - 5;
/*
* 0 . 1 cipherlist length
* 2 . 3 session id length
* 4 . 5 challenge length
* 6 . .. cipherlist
* .. . .. session id
* .. . .. challenge
*/
SSL_DEBUG_BUF( 4, "record contents", buf, n );
ciph_len = ( buf[0] << 8 ) | buf[1];
sess_len = ( buf[2] << 8 ) | buf[3];
chal_len = ( buf[4] << 8 ) | buf[5];
SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d",
ciph_len, sess_len, chal_len ) );
/*
* Make sure each parameter length is valid
*/
if( ciph_len < 3 || ( ciph_len % 3 ) != 0 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
if( sess_len < 0 || sess_len > 32 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
if( chal_len < 8 || chal_len > 32 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
if( n != 6 + ciph_len + sess_len + chal_len )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
SSL_DEBUG_BUF( 3, "client hello, cipherlist",
buf + 6, ciph_len );
SSL_DEBUG_BUF( 3, "client hello, session id",
buf + 6 + ciph_len, sess_len );
SSL_DEBUG_BUF( 3, "client hello, challenge",
buf + 6 + ciph_len + sess_len, chal_len );
p = buf + 6 + ciph_len;
ssl->session->length = sess_len;
memset( ssl->session->id, 0, sizeof( ssl->session->id ) );
memcpy( ssl->session->id, p, ssl->session->length );
p += sess_len;
memset( ssl->randbytes, 0, 64 );
memcpy( ssl->randbytes + 32 - chal_len, p, chal_len );
for( i = 0; ssl->ciphers[i] != 0; i++ )
{
for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
{
if( p[0] == 0 &&
p[1] == 0 &&
p[2] == ssl->ciphers[i] )
goto have_cipher;
}
}
}
else
{
SSL_DEBUG_BUF( 4, "record header", buf, 5 );
SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d",
buf[0] ) );
SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d",
( buf[3] << 8 ) | buf[4] ) );
SSL_DEBUG_MSG( 3, ( "client hello v3, protocol ver: [%d:%d]",
buf[1], buf[2] ) );
/*
* SSLv3 Client Hello
*
* Record layer:
* 0 . 0 message type
* 1 . 2 protocol version
* 3 . 4 message length
*/
if( buf[0] != SSL_MSG_HANDSHAKE ||
buf[1] != SSL_MAJOR_VERSION_3 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
n = ( buf[3] << 8 ) | buf[4];
if( n < 45 || n > 512 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
if( ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
return( ret );
}
buf = ssl->in_msg;
n = ssl->in_left - 5;
md5_update( &ssl->fin_md5 , buf, n );
sha1_update( &ssl->fin_sha1, buf, n );
/*
* SSL layer:
* 0 . 0 handshake type
* 1 . 3 handshake length
* 4 . 5 protocol version
* 6 . 9 UNIX time()
* 10 . 37 random bytes
* 38 . 38 session id length
* 39 . 38+x session id
* 39+x . 40+x cipherlist length
* 41+x . .. cipherlist
* .. . .. compression alg.
* .. . .. extensions
*/
SSL_DEBUG_BUF( 4, "record contents", buf, n );
SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d",
buf[0] ) );
SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
SSL_DEBUG_MSG( 3, ( "client hello v3, max. version: [%d:%d]",
buf[4], buf[5] ) );
/*
* Check the handshake type and protocol version
*/
if( buf[0] != SSL_HS_CLIENT_HELLO ||
buf[4] != SSL_MAJOR_VERSION_3 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
ssl->major_ver = SSL_MAJOR_VERSION_3;
ssl->minor_ver = ( buf[5] <= SSL_MINOR_VERSION_1 )
? buf[5] : SSL_MINOR_VERSION_1;
ssl->max_major_ver = buf[4];
ssl->max_minor_ver = buf[5];
memcpy( ssl->randbytes, buf + 6, 32 );
/*
* Check the handshake message length
*/
if( buf[1] != 0 || n != 4 + ( ( buf[2] << 8 ) | buf[3] ) )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
/*
* Check the session length
*/
sess_len = buf[38];
if( sess_len < 0 || sess_len > 32 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
ssl->session->length = sess_len;
memset( ssl->session->id, 0, sizeof( ssl->session->id ) );
memcpy( ssl->session->id, buf + 39 , ssl->session->length );
/*
* Check the cipherlist length
*/
ciph_len = ( buf[39 + sess_len] << 8 )
| ( buf[40 + sess_len] );
if( ciph_len < 2 || ciph_len > 256 || ( ciph_len % 2 ) != 0 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
/*
* Check the compression algorithms length
*/
comp_len = buf[41 + sess_len + ciph_len];
if( comp_len < 1 || comp_len > 16 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
SSL_DEBUG_BUF( 3, "client hello, random bytes",
buf + 6, 32 );
SSL_DEBUG_BUF( 3, "client hello, session id",
buf + 38, sess_len );
SSL_DEBUG_BUF( 3, "client hello, cipherlist",
buf + 41 + sess_len, ciph_len );
SSL_DEBUG_BUF( 3, "client hello, compression",
buf + 42 + sess_len + ciph_len, comp_len );
/*
* Search for a matching cipher
*/
for( i = 0; ssl->ciphers[i] != 0; i++ )
{
for( j = 0, p = buf + 41 + sess_len; j < ciph_len;
j += 2, p += 2 )
{
if( p[0] == 0 && p[1] == ssl->ciphers[i] )
goto have_cipher;
}
}
}
SSL_DEBUG_MSG( 1, ( "got no ciphers in common" ) );
return( XYSSL_ERR_SSL_NO_CIPHER_CHOSEN );
have_cipher:
ssl->session->cipher = ssl->ciphers[i];
ssl->in_left = 0;
ssl->state++;
SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) );
return( 0 );
}
static int ssl_write_server_hello( ssl_context *ssl )
{
time_t t;
int ret, i, n;
unsigned char *buf, *p;
SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
/*
* 0 . 0 handshake type
* 1 . 3 handshake length
* 4 . 5 protocol version
* 6 . 9 UNIX time()
* 10 . 37 random bytes
*/
buf = ssl->out_msg;
p = buf + 4;
*p++ = (unsigned char) ssl->major_ver;
*p++ = (unsigned char) ssl->minor_ver;
SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
buf[4], buf[5] ) );
t = time( NULL );
*p++ = (unsigned char)( t >> 24 );
*p++ = (unsigned char)( t >> 16 );
*p++ = (unsigned char)( t >> 8 );
*p++ = (unsigned char)( t );
SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
for( i = 28; i > 0; i-- )
*p++ = (unsigned char) ssl->f_rng( ssl->p_rng );
memcpy( ssl->randbytes + 32, buf + 6, 32 );
SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
/*
* 38 . 38 session id length
* 39 . 38+n session id
* 39+n . 40+n chosen cipher
* 41+n . 41+n chosen compression alg.
*/
ssl->session->length = n = 32;
*p++ = (unsigned char) ssl->session->length;
if( ssl->s_get == NULL ||
ssl->s_get( ssl ) != 0 )
{
/*
* Not found, create a new session id
*/
ssl->resume = 0;
ssl->state++;
for( i = 0; i < n; i++ )
ssl->session->id[i] =
(unsigned char) ssl->f_rng( ssl->p_rng );
}
else
{
/*
* Found a matching session, resume it
*/
ssl->resume = 1;
ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
ssl_derive_keys( ssl );
}
memcpy( p, ssl->session->id, ssl->session->length );
p += ssl->session->length;
SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n );
SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
ssl->resume ? "a" : "no" ) );
*p++ = (unsigned char)( ssl->session->cipher >> 8 );
*p++ = (unsigned char)( ssl->session->cipher );
*p++ = SSL_COMPRESS_NULL;
SSL_DEBUG_MSG( 3, ( "server hello, chosen cipher: %d",
ssl->session->cipher ) );
SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", 0 ) );
ssl->out_msglen = p - buf;
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = SSL_HS_SERVER_HELLO;
ret = ssl_write_record( ssl );
SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
return( ret );
}
static int ssl_write_certificate_request( ssl_context *ssl )
{
int ret, n;
unsigned char *buf, *p;
x509_cert *crt;
SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
ssl->state++;
if( ssl->authmode == SSL_VERIFY_NONE )
{
SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
return( 0 );
}
/*
* 0 . 0 handshake type
* 1 . 3 handshake length
* 4 . 4 cert type count
* 5 .. n-1 cert types
* n .. n+1 length of all DNs
* n+2 .. n+3 length of DN 1
* n+4 .. ... Distinguished Name #1
* ... .. ... length of DN 2, etc.
*/
buf = ssl->out_msg;
p = buf + 4;
/*
* At the moment, only RSA certificates are supported
*/
*p++ = 1;
*p++ = 1;
p += 2;
crt = ssl->ca_chain;
while( crt != NULL && crt->next != NULL )
{
if( p - buf > 4096 )
break;
n = crt->subject_raw.len;
*p++ = (unsigned char)( n >> 8 );
*p++ = (unsigned char)( n );
memcpy( p, crt->subject_raw.p, n );
SSL_DEBUG_BUF( 3, "requested DN", p, n );
p += n; crt = crt->next;
}
ssl->out_msglen = n = p - buf;
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = SSL_HS_CERTIFICATE_REQUEST;
ssl->out_msg[6] = (unsigned char)( ( n - 8 ) >> 8 );
ssl->out_msg[7] = (unsigned char)( ( n - 8 ) );
ret = ssl_write_record( ssl );
SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
return( ret );
}
static int ssl_write_server_key_exchange( ssl_context *ssl )
{
int ret, n;
unsigned char hash[36];
md5_context md5;
sha1_context sha1;
SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
if( ssl->session->cipher != SSL_EDH_RSA_DES_168_SHA &&
ssl->session->cipher != SSL_EDH_RSA_AES_256_SHA )
{
SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
ssl->state++;
return( 0 );
}
#if !defined(XYSSL_DHM_C)
SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
return( XYSSL_ERR_SSL_FEATURE_UNAVAILABLE );
#else
/*
* Ephemeral DH parameters:
*
* struct {
* opaque dh_p<1..2^16-1>;
* opaque dh_g<1..2^16-1>;
* opaque dh_Ys<1..2^16-1>;
* } ServerDHParams;
*/
if( ( ret = dhm_make_params( &ssl->dhm_ctx, 256, ssl->out_msg + 4,
&n, ssl->f_rng, ssl->p_rng ) ) != 0 )
{
SSL_DEBUG_RET( 1, "dhm_make_params", ret );
return( ret );
}
SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X );
SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P );
SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G );
SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX );
/*
* digitally-signed struct {
* opaque md5_hash[16];
* opaque sha_hash[20];
* };
*
* md5_hash
* MD5(ClientHello.random + ServerHello.random
* + ServerParams);
* sha_hash
* SHA(ClientHello.random + ServerHello.random
* + ServerParams);
*/
md5_starts( &md5 );
md5_update( &md5, ssl->randbytes, 64 );
md5_update( &md5, ssl->out_msg + 4, n );
md5_finish( &md5, hash );
sha1_starts( &sha1 );
sha1_update( &sha1, ssl->randbytes, 64 );
sha1_update( &sha1, ssl->out_msg + 4, n );
sha1_finish( &sha1, hash + 16 );
SSL_DEBUG_BUF( 3, "parameters hash", hash, 36 );
ssl->out_msg[4 + n] = (unsigned char)( ssl->rsa_key->len >> 8 );
ssl->out_msg[5 + n] = (unsigned char)( ssl->rsa_key->len );
ret = rsa_pkcs1_sign( ssl->rsa_key, RSA_PRIVATE,
RSA_RAW, 36, hash, ssl->out_msg + 6 + n );
if( ret != 0 )
{
SSL_DEBUG_RET( 1, "rsa_pkcs1_sign", ret );
return( ret );
}
SSL_DEBUG_BUF( 3, "my RSA sig", ssl->out_msg + 6 + n,
ssl->rsa_key->len );
ssl->out_msglen = 6 + n + ssl->rsa_key->len;
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = SSL_HS_SERVER_KEY_EXCHANGE;
ssl->state++;
if( ( ret = ssl_write_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_write_record", ret );
return( ret );
}
SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
return( 0 );
#endif
}
static int ssl_write_server_hello_done( ssl_context *ssl )
{
int ret;
SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
ssl->out_msglen = 4;
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = SSL_HS_SERVER_HELLO_DONE;
ssl->state++;
if( ( ret = ssl_write_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_write_record", ret );
return( ret );
}
SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
return( 0 );
}
static int ssl_parse_client_key_exchange( ssl_context *ssl )
{
int ret, i, n;
SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
if( ( ret = ssl_read_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_read_record", ret );
return( ret );
}
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
if( ssl->in_msg[0] != SSL_HS_CLIENT_KEY_EXCHANGE )
{
SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
if( ssl->session->cipher == SSL_EDH_RSA_DES_168_SHA ||
ssl->session->cipher == SSL_EDH_RSA_AES_256_SHA )
{
#if !defined(XYSSL_DHM_C)
SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
return( XYSSL_ERR_SSL_FEATURE_UNAVAILABLE );
#else
/*
* Receive G^Y mod P, premaster = (G^Y)^X mod P
*/
n = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
if( n < 1 || n > ssl->dhm_ctx.len ||
n + 6 != ssl->in_hslen )
{
SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
if( ( ret = dhm_read_public( &ssl->dhm_ctx,
ssl->in_msg + 6, n ) ) != 0 )
{
SSL_DEBUG_RET( 1, "dhm_read_public", ret );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE | ret );
}
SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY );
ssl->pmslen = ssl->dhm_ctx.len;
if( ( ret = dhm_calc_secret( &ssl->dhm_ctx,
ssl->premaster, &ssl->pmslen ) ) != 0 )
{
SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE | ret );
}
SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K );
#endif
}
else
{
/*
* Decrypt the premaster using own private RSA key
*/
i = 4;
n = ssl->rsa_key->len;
ssl->pmslen = 48;
if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
{
i += 2;
if( ssl->in_msg[4] != ( ( n >> 8 ) & 0xFF ) ||
ssl->in_msg[5] != ( ( n ) & 0xFF ) )
{
SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
}
if( ssl->in_hslen != i + n )
{
SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
ret = rsa_pkcs1_decrypt( ssl->rsa_key, RSA_PRIVATE, &ssl->pmslen,
ssl->in_msg + i, ssl->premaster );
if( ret != 0 || ssl->pmslen != 48 ||
ssl->premaster[0] != ssl->max_major_ver ||
ssl->premaster[1] != ssl->max_minor_ver )
{
SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
/*
* Protection against Bleichenbacher's attack:
* invalid PKCS#1 v1.5 padding must not cause
* the connection to end immediately; instead,
* send a bad_record_mac later in the handshake.
*/
ssl->pmslen = 48;
for( i = 0; i < ssl->pmslen; i++ )
ssl->premaster[i] = (unsigned char) ssl->f_rng( ssl->p_rng );
}
}
ssl_derive_keys( ssl );
if( ssl->s_set != NULL )
ssl->s_set( ssl );
ssl->state++;
SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) );
return( 0 );
}
static int ssl_parse_certificate_verify( ssl_context *ssl )
{
int n1, n2, ret;
unsigned char hash[36];
SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
if( ssl->peer_cert == NULL )
{
SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
ssl->state++;
return( 0 );
}
ssl_calc_verify( ssl, hash );
if( ( ret = ssl_read_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_read_record", ret );
return( ret );
}
ssl->state++;
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
}
if( ssl->in_msg[0] != SSL_HS_CERTIFICATE_VERIFY )
{
SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
}
n1 = ssl->peer_cert->rsa.len;
n2 = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
if( n1 + 6 != ssl->in_hslen || n1 != n2 )
{
SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
return( XYSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
}
ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC,
RSA_RAW, 36, hash, ssl->in_msg + 6 );
if( ret != 0 )
{
SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
return( ret );
}
SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
return( 0 );
}
/*
* SSL handshake -- server side
*/
int ssl_handshake_server( ssl_context *ssl )
{
int ret = 0;
SSL_DEBUG_MSG( 2, ( "=> handshake server" ) );
while( ssl->state != SSL_HANDSHAKE_OVER )
{
SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );
if( ( ret = ssl_flush_output( ssl ) ) != 0 )
break;
switch( ssl->state )
{
case SSL_HELLO_REQUEST:
ssl->state = SSL_CLIENT_HELLO;
break;
/*
* <== ClientHello
*/
case SSL_CLIENT_HELLO:
ret = ssl_parse_client_hello( ssl );
break;
/*
* ==> ServerHello
* Certificate
* ( ServerKeyExchange )
* ( CertificateRequest )
* ServerHelloDone
*/
case SSL_SERVER_HELLO:
ret = ssl_write_server_hello( ssl );
break;
case SSL_SERVER_CERTIFICATE:
ret = ssl_write_certificate( ssl );
break;
case SSL_SERVER_KEY_EXCHANGE:
ret = ssl_write_server_key_exchange( ssl );
break;
case SSL_CERTIFICATE_REQUEST:
ret = ssl_write_certificate_request( ssl );
break;
case SSL_SERVER_HELLO_DONE:
ret = ssl_write_server_hello_done( ssl );
break;
/*
* <== ( Certificate/Alert )
* ClientKeyExchange
* ( CertificateVerify )
* ChangeCipherSpec
* Finished
*/
case SSL_CLIENT_CERTIFICATE:
ret = ssl_parse_certificate( ssl );
break;
case SSL_CLIENT_KEY_EXCHANGE:
ret = ssl_parse_client_key_exchange( ssl );
break;
case SSL_CERTIFICATE_VERIFY:
ret = ssl_parse_certificate_verify( ssl );
break;
case SSL_CLIENT_CHANGE_CIPHER_SPEC:
ret = ssl_parse_change_cipher_spec( ssl );
break;
case SSL_CLIENT_FINISHED:
ret = ssl_parse_finished( ssl );
break;
/*
* ==> ChangeCipherSpec
* Finished
*/
case SSL_SERVER_CHANGE_CIPHER_SPEC:
ret = ssl_write_change_cipher_spec( ssl );
break;
case SSL_SERVER_FINISHED:
ret = ssl_write_finished( ssl );
break;
case SSL_FLUSH_BUFFERS:
SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
ssl->state = SSL_HANDSHAKE_OVER;
break;
default:
SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
return( XYSSL_ERR_SSL_BAD_INPUT_DATA );
}
if( ret != 0 )
break;
}
SSL_DEBUG_MSG( 2, ( "<= handshake server" ) );
return( ret );
}
#endif

1977
library/ssl_tls.c Normal file

File diff suppressed because it is too large Load diff

250
library/timing.c Normal file
View file

@ -0,0 +1,250 @@
/*
* Portable interface to the CPU cycle counter
*
* Copyright (C) 2006-2007 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "xyssl/config.h"
#if defined(XYSSL_TIMING_C)
#include "xyssl/timing.h"
#if defined(WIN32)
#include <windows.h>
#include <winbase.h>
struct _hr_time
{
LARGE_INTEGER start;
};
#else
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <time.h>
struct _hr_time
{
struct timeval start;
};
#endif
#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
unsigned long hardclock( void )
{
unsigned long tsc;
__asm rdtsc
__asm mov [tsc], eax
return( tsc );
}
#else
#if defined(__GNUC__) && defined(__i386__)
unsigned long hardclock( void )
{
unsigned long tsc;
asm( "rdtsc" : "=a" (tsc) );
return( tsc );
}
#else
#if defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
unsigned long hardclock( void )
{
unsigned long lo, hi;
asm( "rdtsc" : "=a" (lo), "=d" (hi) );
return( lo | (hi << 32) );
}
#else
#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
unsigned long hardclock( void )
{
unsigned long tbl, tbu0, tbu1;
do
{
asm( "mftbu %0" : "=r" (tbu0) );
asm( "mftb %0" : "=r" (tbl ) );
asm( "mftbu %0" : "=r" (tbu1) );
}
while( tbu0 != tbu1 );
return( tbl );
}
#else
#if defined(__GNUC__) && defined(__sparc__)
unsigned long hardclock( void )
{
unsigned long tick;
asm( ".byte 0x83, 0x41, 0x00, 0x00" );
asm( "mov %%g1, %0" : "=r" (tick) );
return( tick );
}
#else
#if defined(__GNUC__) && defined(__alpha__)
unsigned long hardclock( void )
{
unsigned long cc;
asm( "rpcc %0" : "=r" (cc) );
return( cc & 0xFFFFFFFF );
}
#else
#if defined(__GNUC__) && defined(__ia64__)
unsigned long hardclock( void )
{
unsigned long itc;
asm( "mov %0 = ar.itc" : "=r" (itc) );
return( itc );
}
#else
static int hardclock_init = 0;
static struct timeval tv_init;
unsigned long hardclock( void )
{
struct timeval tv_cur;
if( hardclock_init == 0 )
{
gettimeofday( &tv_init, NULL );
hardclock_init = 1;
}
gettimeofday( &tv_cur, NULL );
return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000
+ ( tv_cur.tv_usec - tv_init.tv_usec ) );
}
#endif /* generic */
#endif /* IA-64 */
#endif /* Alpha */
#endif /* SPARC8 */
#endif /* PowerPC */
#endif /* AMD64 */
#endif /* i586+ */
int alarmed = 0;
#if defined(WIN32)
unsigned long get_timer( struct hr_time *val, int reset )
{
unsigned long delta;
LARGE_INTEGER offset, hfreq;
struct _hr_time *t = (struct _hr_time *) val;
QueryPerformanceCounter( &offset );
QueryPerformanceFrequency( &hfreq );
delta = (unsigned long)( ( 1000 *
( offset.QuadPart - t->start.QuadPart ) ) /
hfreq.QuadPart );
if( reset )
QueryPerformanceCounter( &t->start );
return( delta );
}
DWORD WINAPI TimerProc( LPVOID uElapse )
{
Sleep( (DWORD) uElapse );
alarmed = 1;
return( TRUE );
}
void set_alarm( int seconds )
{
DWORD ThreadId;
alarmed = 0;
CloseHandle( CreateThread( NULL, 0, TimerProc,
(LPVOID) ( seconds * 1000 ), 0, &ThreadId ) );
}
void m_sleep( int milliseconds )
{
Sleep( milliseconds );
}
#else
unsigned long get_timer( struct hr_time *val, int reset )
{
unsigned long delta;
struct timeval offset;
struct _hr_time *t = (struct _hr_time *) val;
gettimeofday( &offset, NULL );
delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
+ ( offset.tv_usec - t->start.tv_usec ) / 1000;
if( reset )
{
t->start.tv_sec = offset.tv_sec;
t->start.tv_usec = offset.tv_usec;
}
return( delta );
}
static void sighandler( int signum )
{
alarmed = 1;
signal( signum, sighandler );
}
void set_alarm( int seconds )
{
alarmed = 0;
signal( SIGALRM, sighandler );
alarm( seconds );
}
void m_sleep( int milliseconds )
{
struct timeval tv;
tv.tv_sec = milliseconds / 1000;
tv.tv_usec = milliseconds * 1000;
select( 0, NULL, NULL, NULL, &tv );
}
#endif
#endif

1749
library/x509parse.c Normal file

File diff suppressed because it is too large Load diff