contrib/package: remove px5g, uhttpd - moved to OpenWrt core packages

This commit is contained in:
Jo-Philipp Wich 2010-03-25 16:08:33 +00:00
parent e47ac7cabc
commit 11527683bf
36 changed files with 0 additions and 12327 deletions

View file

@ -1,39 +0,0 @@
#
# Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=px5g
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/px5g
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Standalone X.509 certificate generator
endef
define Package/px5g/description
Px5g is a tiny standalone X.509 certificate generator.
It suitable to create key files and certificates in DER
and PEM format for use with stunnel, uhttpd and others.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Package/px5g/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/px5g $(1)/usr/sbin/px5g
endef
$(eval $(call BuildPackage,px5g))

View file

@ -1,14 +0,0 @@
CFLAGS?=-O2
CFLAGS+=
SFLAGS:=--std=gnu99
WFLAGS:=-Wall -Werror -pedantic
LDFLAGS?=
BINARY:=px5g
all: $(BINARY)
$(BINARY): *.c library/*.c
$(CC) -I. $(CFLAGS) $(SFLAGS) $(WFLAGS) $(LDFLAGS) -o $@ $+
clean:
rm -f $(BINARY)

View file

@ -1,264 +0,0 @@
/*
* RFC 1521 base64 encoding/decoding
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "polarssl/config.h"
#if defined(POLARSSL_BASE64_C)
#include "polarssl/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( POLARSSL_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( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
if( base64_dec_map[src[i]] < 64 && j != 0 )
return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
n++;
}
if( n == 0 )
return( 0 );
n = ((n * 6) + 7) >> 3;
if( *dlen < n )
{
*dlen = n;
return( POLARSSL_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(POLARSSL_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

File diff suppressed because it is too large Load diff

View file

@ -1,276 +0,0 @@
/*
* HAVEGE: HArdware Volatile Entropy Gathering and Expansion
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The 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 "polarssl/config.h"
#if defined(POLARSSL_HAVEGE_C)
#include "polarssl/havege.h"
#include "polarssl/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(POLARSSL_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

View file

@ -1,750 +0,0 @@
/*
* The RSA public-key cryptosystem
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 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 "polarssl/config.h"
#if defined(POLARSSL_RSA_C)
#include "polarssl/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(POLARSSL_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( POLARSSL_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( POLARSSL_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( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
if( mpi_msb( &ctx->N ) < 128 ||
mpi_msb( &ctx->N ) > 4096 )
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
if( mpi_msb( &ctx->E ) < 2 ||
mpi_msb( &ctx->E ) > 64 )
return( POLARSSL_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( POLARSSL_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( POLARSSL_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( POLARSSL_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( POLARSSL_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( POLARSSL_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( POLARSSL_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( POLARSSL_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 output_max_len)
{
int ret, ilen;
unsigned char *p;
unsigned char buf[512];
ilen = ctx->len;
if( ilen < 16 || ilen > (int) sizeof( buf ) )
return( POLARSSL_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( POLARSSL_ERR_RSA_INVALID_PADDING );
while( *p != 0 )
{
if( p >= buf + ilen - 1 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p++;
}
p++;
break;
default:
return( POLARSSL_ERR_RSA_INVALID_PADDING );
}
if (ilen - (int)(p - buf) > output_max_len)
return( POLARSSL_ERR_RSA_OUTPUT_TO_LARGE );
*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( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}
if( nb_pad < 8 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
*p++ = 0;
*p++ = RSA_SIGN;
memset( p, 0xFF, nb_pad );
p += nb_pad;
*p++ = 0;
break;
default:
return( POLARSSL_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( POLARSSL_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( POLARSSL_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( POLARSSL_ERR_RSA_INVALID_PADDING );
while( *p != 0 )
{
if( p >= buf + siglen - 1 || *p != 0xFF )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p++;
}
p++;
break;
default:
return( POLARSSL_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( POLARSSL_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( POLARSSL_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( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
if( len == hashlen && hash_id == RSA_RAW )
{
if( memcmp( p, hash, hashlen ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
return( POLARSSL_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(POLARSSL_SELF_TEST)
#include "polarssl/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,
sizeof(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

View file

@ -1,622 +0,0 @@
/*
* FIPS-180-1 compliant SHA-1 implementation
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#include "polarssl/config.h"
#if defined(POLARSSL_SHA1_C)
#include "polarssl/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(POLARSSL_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

View file

@ -1,265 +0,0 @@
/*
* Portable interface to the CPU cycle counter
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "polarssl/config.h"
#if defined(POLARSSL_TIMING_C)
#include "polarssl/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

File diff suppressed because it is too large Load diff

View file

@ -1,93 +0,0 @@
/**
* \file base64.h
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POLARSSL_BASE64_H
#define POLARSSL_BASE64_H
#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x0010
#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x0012
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Encode a buffer into base64 format
*
* \param dst destination buffer
* \param dlen size of the buffer
* \param src source buffer
* \param slen amount of data to be encoded
*
* \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
* *dlen is always updated to reflect the amount
* of data that has (or would have) been written.
*
* \note Call this function with *dlen = 0 to obtain the
* required buffer size in *dlen
*/
int base64_encode( unsigned char *dst, int *dlen,
unsigned char *src, int slen );
/**
* \brief Decode a base64-formatted buffer
*
* \param dst destination buffer
* \param dlen size of the buffer
* \param src source buffer
* \param slen amount of data to be decoded
*
* \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or
* POLARSSL_ERR_BASE64_INVALID_DATA if the input data is not
* correct. *dlen is always updated to reflect the amount
* of data that has (or would have) been written.
*
* \note Call this function with *dlen = 0 to obtain the
* required buffer size in *dlen
*/
int base64_decode( unsigned char *dst, int *dlen,
unsigned char *src, int slen );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int base64_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* base64.h */

View file

@ -1,437 +0,0 @@
/**
* \file bignum.h
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POLARSSL_BIGNUM_H
#define POLARSSL_BIGNUM_H
#include <stdio.h>
#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002
#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004
#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006
#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008
#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A
#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C
#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E
#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
/*
* Define the base integer type, architecture-wise
*/
#if defined(POLARSSL_HAVE_INT8)
typedef unsigned char t_int;
typedef unsigned short t_dbl;
#else
#if defined(POLARSSL_HAVE_INT16)
typedef unsigned short t_int;
typedef unsigned long t_dbl;
#else
typedef unsigned long t_int;
#if defined(_MSC_VER) && defined(_M_IX86)
typedef unsigned __int64 t_dbl;
#else
#if defined(__amd64__) || defined(__x86_64__) || \
defined(__ppc64__) || defined(__powerpc64__) || \
defined(__ia64__) || defined(__alpha__)
typedef unsigned int t_dbl __attribute__((mode(TI)));
#else
typedef unsigned long long t_dbl;
#endif
#endif
#endif
#endif
/**
* \brief MPI structure
*/
typedef struct
{
int s; /*!< integer sign */
int n; /*!< total # of limbs */
t_int *p; /*!< pointer to limbs */
}
mpi;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Initialize one or more mpi
*/
void mpi_init( mpi *X, ... );
/**
* \brief Unallocate one or more mpi
*/
void mpi_free( mpi *X, ... );
/**
* \brief Enlarge to the specified number of limbs
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_grow( mpi *X, int nblimbs );
/**
* \brief Copy the contents of Y into X
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_copy( mpi *X, mpi *Y );
/**
* \brief Swap the contents of X and Y
*/
void mpi_swap( mpi *X, mpi *Y );
/**
* \brief Set value from integer
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_lset( mpi *X, int z );
/**
* \brief Return the number of least significant bits
*/
int mpi_lsb( mpi *X );
/**
* \brief Return the number of most significant bits
*/
int mpi_msb( mpi *X );
/**
* \brief Return the total size in bytes
*/
int mpi_size( mpi *X );
/**
* \brief Import from an ASCII string
*
* \param X destination mpi
* \param radix input numeric base
* \param s null-terminated string buffer
*
* \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
*/
int mpi_read_string( mpi *X, int radix, char *s );
/**
* \brief Export into an ASCII string
*
* \param X source mpi
* \param radix output numeric base
* \param s string buffer
* \param slen string buffer size
*
* \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
*
* \note Call this function with *slen = 0 to obtain the
* minimum required buffer size in *slen.
*/
int mpi_write_string( mpi *X, int radix, char *s, int *slen );
/**
* \brief Read X from an opened file
*
* \param X destination mpi
* \param radix input numeric base
* \param fin input file handle
*
* \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
*/
int mpi_read_file( mpi *X, int radix, FILE *fin );
/**
* \brief Write X into an opened file, or stdout
*
* \param p prefix, can be NULL
* \param X source mpi
* \param radix output numeric base
* \param fout output file handle
*
* \return 0 if successful, or an POLARSSL_ERR_MPI_XXX error code
*
* \note Set fout == NULL to print X on the console.
*/
int mpi_write_file( char *p, mpi *X, int radix, FILE *fout );
/**
* \brief Import X from unsigned binary data, big endian
*
* \param X destination mpi
* \param buf input buffer
* \param buflen input buffer size
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_read_binary( mpi *X, unsigned char *buf, int buflen );
/**
* \brief Export X into unsigned binary data, big endian
*
* \param X source mpi
* \param buf output buffer
* \param buflen output buffer size
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
*
* \note Call this function with *buflen = 0 to obtain the
* minimum required buffer size in *buflen.
*/
int mpi_write_binary( mpi *X, unsigned char *buf, int buflen );
/**
* \brief Left-shift: X <<= count
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_shift_l( mpi *X, int count );
/**
* \brief Right-shift: X >>= count
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_shift_r( mpi *X, int count );
/**
* \brief Compare unsigned values
*
* \return 1 if |X| is greater than |Y|,
* -1 if |X| is lesser than |Y| or
* 0 if |X| is equal to |Y|
*/
int mpi_cmp_abs( mpi *X, mpi *Y );
/**
* \brief Compare signed values
*
* \return 1 if X is greater than Y,
* -1 if X is lesser than Y or
* 0 if X is equal to Y
*/
int mpi_cmp_mpi( mpi *X, mpi *Y );
/**
* \brief Compare signed values
*
* \return 1 if X is greater than z,
* -1 if X is lesser than z or
* 0 if X is equal to z
*/
int mpi_cmp_int( mpi *X, int z );
/**
* \brief Unsigned addition: X = |A| + |B|
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_add_abs( mpi *X, mpi *A, mpi *B );
/**
* \brief Unsigned substraction: X = |A| - |B|
*
* \return 0 if successful,
* POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
*/
int mpi_sub_abs( mpi *X, mpi *A, mpi *B );
/**
* \brief Signed addition: X = A + B
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_add_mpi( mpi *X, mpi *A, mpi *B );
/**
* \brief Signed substraction: X = A - B
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_sub_mpi( mpi *X, mpi *A, mpi *B );
/**
* \brief Signed addition: X = A + b
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_add_int( mpi *X, mpi *A, int b );
/**
* \brief Signed substraction: X = A - b
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_sub_int( mpi *X, mpi *A, int b );
/**
* \brief Baseline multiplication: X = A * B
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_mul_mpi( mpi *X, mpi *A, mpi *B );
/**
* \brief Baseline multiplication: X = A * b
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_mul_int( mpi *X, mpi *A, t_int b );
/**
* \brief Division by mpi: A = Q * B + R
*
* \return 0 if successful,
* 1 if memory allocation failed,
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
*
* \note Either Q or R can be NULL.
*/
int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B );
/**
* \brief Division by int: A = Q * b + R
*
* \return 0 if successful,
* 1 if memory allocation failed,
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
*
* \note Either Q or R can be NULL.
*/
int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b );
/**
* \brief Modulo: R = A mod B
*
* \return 0 if successful,
* 1 if memory allocation failed,
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
*/
int mpi_mod_mpi( mpi *R, mpi *A, mpi *B );
/**
* \brief Modulo: r = A mod b
*
* \return 0 if successful,
* 1 if memory allocation failed,
* POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
*/
int mpi_mod_int( t_int *r, mpi *A, int b );
/**
* \brief Sliding-window exponentiation: X = A^E mod N
*
* \return 0 if successful,
* 1 if memory allocation failed,
* POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even
*
* \note _RR is used to avoid re-computing R*R mod N across
* multiple calls, which speeds up things a bit. It can
* be set to NULL if the extra performance is unneeded.
*/
int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N, mpi *_RR );
/**
* \brief Greatest common divisor: G = gcd(A, B)
*
* \return 0 if successful,
* 1 if memory allocation failed
*/
int mpi_gcd( mpi *G, mpi *A, mpi *B );
/**
* \brief Modular inverse: X = A^-1 mod N
*
* \return 0 if successful,
* 1 if memory allocation failed,
* POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
* POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
*/
int mpi_inv_mod( mpi *X, mpi *A, mpi *N );
/**
* \brief Miller-Rabin primality test
*
* \return 0 if successful (probably prime),
* 1 if memory allocation failed,
* POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
*/
int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng );
/**
* \brief Prime number generation
*
* \param X destination mpi
* \param nbits required size of X in bits
* \param dh_flag if 1, then (X-1)/2 will be prime too
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful (probably prime),
* 1 if memory allocation failed,
* POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
*/
int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
int (*f_rng)(void *), void *p_rng );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int mpi_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* bignum.h */

View file

@ -1,731 +0,0 @@
/**
* \file bn_mul.h
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Multiply source vector [s] with b, add result
* to destination vector [d] and set carry c.
*
* Currently supports:
*
* . IA-32 (386+) . AMD64 / EM64T
* . IA-32 (SSE2) . Motorola 68000
* . PowerPC, 32-bit . MicroBlaze
* . PowerPC, 64-bit . TriCore
* . SPARC v8 . ARM v3+
* . Alpha . MIPS32
* . C, longlong . C, generic
*/
#ifndef POLARSSL_BN_MUL_H
#define POLARSSL_BN_MUL_H
#include "polarssl/config.h"
#if defined(POLARSSL_HAVE_ASM)
#if defined(__GNUC__)
#if defined(__i386__)
#define MULADDC_INIT \
asm( "movl %%ebx, %0 " : "=m" (t)); \
asm( "movl %0, %%esi " :: "m" (s)); \
asm( "movl %0, %%edi " :: "m" (d)); \
asm( "movl %0, %%ecx " :: "m" (c)); \
asm( "movl %0, %%ebx " :: "m" (b));
#define MULADDC_CORE \
asm( "lodsl " ); \
asm( "mull %ebx " ); \
asm( "addl %ecx, %eax " ); \
asm( "adcl $0, %edx " ); \
asm( "addl (%edi), %eax " ); \
asm( "adcl $0, %edx " ); \
asm( "movl %edx, %ecx " ); \
asm( "stosl " );
#if defined(POLARSSL_HAVE_SSE2)
#define MULADDC_HUIT \
asm( "movd %ecx, %mm1 " ); \
asm( "movd %ebx, %mm0 " ); \
asm( "movd (%edi), %mm3 " ); \
asm( "paddq %mm3, %mm1 " ); \
asm( "movd (%esi), %mm2 " ); \
asm( "pmuludq %mm0, %mm2 " ); \
asm( "movd 4(%esi), %mm4 " ); \
asm( "pmuludq %mm0, %mm4 " ); \
asm( "movd 8(%esi), %mm6 " ); \
asm( "pmuludq %mm0, %mm6 " ); \
asm( "movd 12(%esi), %mm7 " ); \
asm( "pmuludq %mm0, %mm7 " ); \
asm( "paddq %mm2, %mm1 " ); \
asm( "movd 4(%edi), %mm3 " ); \
asm( "paddq %mm4, %mm3 " ); \
asm( "movd 8(%edi), %mm5 " ); \
asm( "paddq %mm6, %mm5 " ); \
asm( "movd 12(%edi), %mm4 " ); \
asm( "paddq %mm4, %mm7 " ); \
asm( "movd %mm1, (%edi) " ); \
asm( "movd 16(%esi), %mm2 " ); \
asm( "pmuludq %mm0, %mm2 " ); \
asm( "psrlq $32, %mm1 " ); \
asm( "movd 20(%esi), %mm4 " ); \
asm( "pmuludq %mm0, %mm4 " ); \
asm( "paddq %mm3, %mm1 " ); \
asm( "movd 24(%esi), %mm6 " ); \
asm( "pmuludq %mm0, %mm6 " ); \
asm( "movd %mm1, 4(%edi) " ); \
asm( "psrlq $32, %mm1 " ); \
asm( "movd 28(%esi), %mm3 " ); \
asm( "pmuludq %mm0, %mm3 " ); \
asm( "paddq %mm5, %mm1 " ); \
asm( "movd 16(%edi), %mm5 " ); \
asm( "paddq %mm5, %mm2 " ); \
asm( "movd %mm1, 8(%edi) " ); \
asm( "psrlq $32, %mm1 " ); \
asm( "paddq %mm7, %mm1 " ); \
asm( "movd 20(%edi), %mm5 " ); \
asm( "paddq %mm5, %mm4 " ); \
asm( "movd %mm1, 12(%edi) " ); \
asm( "psrlq $32, %mm1 " ); \
asm( "paddq %mm2, %mm1 " ); \
asm( "movd 24(%edi), %mm5 " ); \
asm( "paddq %mm5, %mm6 " ); \
asm( "movd %mm1, 16(%edi) " ); \
asm( "psrlq $32, %mm1 " ); \
asm( "paddq %mm4, %mm1 " ); \
asm( "movd 28(%edi), %mm5 " ); \
asm( "paddq %mm5, %mm3 " ); \
asm( "movd %mm1, 20(%edi) " ); \
asm( "psrlq $32, %mm1 " ); \
asm( "paddq %mm6, %mm1 " ); \
asm( "movd %mm1, 24(%edi) " ); \
asm( "psrlq $32, %mm1 " ); \
asm( "paddq %mm3, %mm1 " ); \
asm( "movd %mm1, 28(%edi) " ); \
asm( "addl $32, %edi " ); \
asm( "addl $32, %esi " ); \
asm( "psrlq $32, %mm1 " ); \
asm( "movd %mm1, %ecx " );
#define MULADDC_STOP \
asm( "emms " ); \
asm( "movl %0, %%ebx " :: "m" (t)); \
asm( "movl %%ecx, %0 " : "=m" (c)); \
asm( "movl %%edi, %0 " : "=m" (d)); \
asm( "movl %%esi, %0 " : "=m" (s) :: \
"eax", "ecx", "edx", "esi", "edi" );
#else
#define MULADDC_STOP \
asm( "movl %0, %%ebx " :: "m" (t)); \
asm( "movl %%ecx, %0 " : "=m" (c)); \
asm( "movl %%edi, %0 " : "=m" (d)); \
asm( "movl %%esi, %0 " : "=m" (s) :: \
"eax", "ecx", "edx", "esi", "edi" );
#endif /* SSE2 */
#endif /* i386 */
#if defined(__amd64__) || defined (__x86_64__)
#define MULADDC_INIT \
asm( "movq %0, %%rsi " :: "m" (s)); \
asm( "movq %0, %%rdi " :: "m" (d)); \
asm( "movq %0, %%rcx " :: "m" (c)); \
asm( "movq %0, %%rbx " :: "m" (b)); \
asm( "xorq %r8, %r8 " );
#define MULADDC_CORE \
asm( "movq (%rsi),%rax " ); \
asm( "mulq %rbx " ); \
asm( "addq $8, %rsi " ); \
asm( "addq %rcx, %rax " ); \
asm( "movq %r8, %rcx " ); \
asm( "adcq $0, %rdx " ); \
asm( "nop " ); \
asm( "addq %rax, (%rdi) " ); \
asm( "adcq %rdx, %rcx " ); \
asm( "addq $8, %rdi " );
#define MULADDC_STOP \
asm( "movq %%rcx, %0 " : "=m" (c)); \
asm( "movq %%rdi, %0 " : "=m" (d)); \
asm( "movq %%rsi, %0 " : "=m" (s) :: \
"rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
#endif /* AMD64 */
#if defined(__mc68020__) || defined(__mcpu32__)
#define MULADDC_INIT \
asm( "movl %0, %%a2 " :: "m" (s)); \
asm( "movl %0, %%a3 " :: "m" (d)); \
asm( "movl %0, %%d3 " :: "m" (c)); \
asm( "movl %0, %%d2 " :: "m" (b)); \
asm( "moveq #0, %d0 " );
#define MULADDC_CORE \
asm( "movel %a2@+, %d1 " ); \
asm( "mulul %d2, %d4:%d1 " ); \
asm( "addl %d3, %d1 " ); \
asm( "addxl %d0, %d4 " ); \
asm( "moveq #0, %d3 " ); \
asm( "addl %d1, %a3@+ " ); \
asm( "addxl %d4, %d3 " );
#define MULADDC_STOP \
asm( "movl %%d3, %0 " : "=m" (c)); \
asm( "movl %%a3, %0 " : "=m" (d)); \
asm( "movl %%a2, %0 " : "=m" (s) :: \
"d0", "d1", "d2", "d3", "d4", "a2", "a3" );
#define MULADDC_HUIT \
asm( "movel %a2@+, %d1 " ); \
asm( "mulul %d2, %d4:%d1 " ); \
asm( "addxl %d3, %d1 " ); \
asm( "addxl %d0, %d4 " ); \
asm( "addl %d1, %a3@+ " ); \
asm( "movel %a2@+, %d1 " ); \
asm( "mulul %d2, %d3:%d1 " ); \
asm( "addxl %d4, %d1 " ); \
asm( "addxl %d0, %d3 " ); \
asm( "addl %d1, %a3@+ " ); \
asm( "movel %a2@+, %d1 " ); \
asm( "mulul %d2, %d4:%d1 " ); \
asm( "addxl %d3, %d1 " ); \
asm( "addxl %d0, %d4 " ); \
asm( "addl %d1, %a3@+ " ); \
asm( "movel %a2@+, %d1 " ); \
asm( "mulul %d2, %d3:%d1 " ); \
asm( "addxl %d4, %d1 " ); \
asm( "addxl %d0, %d3 " ); \
asm( "addl %d1, %a3@+ " ); \
asm( "movel %a2@+, %d1 " ); \
asm( "mulul %d2, %d4:%d1 " ); \
asm( "addxl %d3, %d1 " ); \
asm( "addxl %d0, %d4 " ); \
asm( "addl %d1, %a3@+ " ); \
asm( "movel %a2@+, %d1 " ); \
asm( "mulul %d2, %d3:%d1 " ); \
asm( "addxl %d4, %d1 " ); \
asm( "addxl %d0, %d3 " ); \
asm( "addl %d1, %a3@+ " ); \
asm( "movel %a2@+, %d1 " ); \
asm( "mulul %d2, %d4:%d1 " ); \
asm( "addxl %d3, %d1 " ); \
asm( "addxl %d0, %d4 " ); \
asm( "addl %d1, %a3@+ " ); \
asm( "movel %a2@+, %d1 " ); \
asm( "mulul %d2, %d3:%d1 " ); \
asm( "addxl %d4, %d1 " ); \
asm( "addxl %d0, %d3 " ); \
asm( "addl %d1, %a3@+ " ); \
asm( "addxl %d0, %d3 " );
#endif /* MC68000 */
#if defined(__powerpc__) || defined(__ppc__)
#if defined(__powerpc64__) || defined(__ppc64__)
#if defined(__MACH__) && defined(__APPLE__)
#define MULADDC_INIT \
asm( "ld r3, %0 " :: "m" (s)); \
asm( "ld r4, %0 " :: "m" (d)); \
asm( "ld r5, %0 " :: "m" (c)); \
asm( "ld r6, %0 " :: "m" (b)); \
asm( "addi r3, r3, -8 " ); \
asm( "addi r4, r4, -8 " ); \
asm( "addic r5, r5, 0 " );
#define MULADDC_CORE \
asm( "ldu r7, 8(r3) " ); \
asm( "mulld r8, r7, r6 " ); \
asm( "mulhdu r9, r7, r6 " ); \
asm( "adde r8, r8, r5 " ); \
asm( "ld r7, 8(r4) " ); \
asm( "addze r5, r9 " ); \
asm( "addc r8, r8, r7 " ); \
asm( "stdu r8, 8(r4) " );
#define MULADDC_STOP \
asm( "addze r5, r5 " ); \
asm( "addi r4, r4, 8 " ); \
asm( "addi r3, r3, 8 " ); \
asm( "std r5, %0 " : "=m" (c)); \
asm( "std r4, %0 " : "=m" (d)); \
asm( "std r3, %0 " : "=m" (s) :: \
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
#else
#define MULADDC_INIT \
asm( "ld %%r3, %0 " :: "m" (s)); \
asm( "ld %%r4, %0 " :: "m" (d)); \
asm( "ld %%r5, %0 " :: "m" (c)); \
asm( "ld %%r6, %0 " :: "m" (b)); \
asm( "addi %r3, %r3, -8 " ); \
asm( "addi %r4, %r4, -8 " ); \
asm( "addic %r5, %r5, 0 " );
#define MULADDC_CORE \
asm( "ldu %r7, 8(%r3) " ); \
asm( "mulld %r8, %r7, %r6 " ); \
asm( "mulhdu %r9, %r7, %r6 " ); \
asm( "adde %r8, %r8, %r5 " ); \
asm( "ld %r7, 8(%r4) " ); \
asm( "addze %r5, %r9 " ); \
asm( "addc %r8, %r8, %r7 " ); \
asm( "stdu %r8, 8(%r4) " );
#define MULADDC_STOP \
asm( "addze %r5, %r5 " ); \
asm( "addi %r4, %r4, 8 " ); \
asm( "addi %r3, %r3, 8 " ); \
asm( "std %%r5, %0 " : "=m" (c)); \
asm( "std %%r4, %0 " : "=m" (d)); \
asm( "std %%r3, %0 " : "=m" (s) :: \
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
#endif
#else /* PPC32 */
#if defined(__MACH__) && defined(__APPLE__)
#define MULADDC_INIT \
asm( "lwz r3, %0 " :: "m" (s)); \
asm( "lwz r4, %0 " :: "m" (d)); \
asm( "lwz r5, %0 " :: "m" (c)); \
asm( "lwz r6, %0 " :: "m" (b)); \
asm( "addi r3, r3, -4 " ); \
asm( "addi r4, r4, -4 " ); \
asm( "addic r5, r5, 0 " );
#define MULADDC_CORE \
asm( "lwzu r7, 4(r3) " ); \
asm( "mullw r8, r7, r6 " ); \
asm( "mulhwu r9, r7, r6 " ); \
asm( "adde r8, r8, r5 " ); \
asm( "lwz r7, 4(r4) " ); \
asm( "addze r5, r9 " ); \
asm( "addc r8, r8, r7 " ); \
asm( "stwu r8, 4(r4) " );
#define MULADDC_STOP \
asm( "addze r5, r5 " ); \
asm( "addi r4, r4, 4 " ); \
asm( "addi r3, r3, 4 " ); \
asm( "stw r5, %0 " : "=m" (c)); \
asm( "stw r4, %0 " : "=m" (d)); \
asm( "stw r3, %0 " : "=m" (s) :: \
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
#else
#define MULADDC_INIT \
asm( "lwz %%r3, %0 " :: "m" (s)); \
asm( "lwz %%r4, %0 " :: "m" (d)); \
asm( "lwz %%r5, %0 " :: "m" (c)); \
asm( "lwz %%r6, %0 " :: "m" (b)); \
asm( "addi %r3, %r3, -4 " ); \
asm( "addi %r4, %r4, -4 " ); \
asm( "addic %r5, %r5, 0 " );
#define MULADDC_CORE \
asm( "lwzu %r7, 4(%r3) " ); \
asm( "mullw %r8, %r7, %r6 " ); \
asm( "mulhwu %r9, %r7, %r6 " ); \
asm( "adde %r8, %r8, %r5 " ); \
asm( "lwz %r7, 4(%r4) " ); \
asm( "addze %r5, %r9 " ); \
asm( "addc %r8, %r8, %r7 " ); \
asm( "stwu %r8, 4(%r4) " );
#define MULADDC_STOP \
asm( "addze %r5, %r5 " ); \
asm( "addi %r4, %r4, 4 " ); \
asm( "addi %r3, %r3, 4 " ); \
asm( "stw %%r5, %0 " : "=m" (c)); \
asm( "stw %%r4, %0 " : "=m" (d)); \
asm( "stw %%r3, %0 " : "=m" (s) :: \
"r3", "r4", "r5", "r6", "r7", "r8", "r9" );
#endif
#endif /* PPC32 */
#endif /* PPC64 */
#if defined(__sparc__)
#define MULADDC_INIT \
asm( "ld %0, %%o0 " :: "m" (s)); \
asm( "ld %0, %%o1 " :: "m" (d)); \
asm( "ld %0, %%o2 " :: "m" (c)); \
asm( "ld %0, %%o3 " :: "m" (b));
#define MULADDC_CORE \
asm( "ld [%o0], %o4 " ); \
asm( "inc 4, %o0 " ); \
asm( "ld [%o1], %o5 " ); \
asm( "umul %o3, %o4, %o4 " ); \
asm( "addcc %o4, %o2, %o4 " ); \
asm( "rd %y, %g1 " ); \
asm( "addx %g1, 0, %g1 " ); \
asm( "addcc %o4, %o5, %o4 " ); \
asm( "st %o4, [%o1] " ); \
asm( "addx %g1, 0, %o2 " ); \
asm( "inc 4, %o1 " );
#define MULADDC_STOP \
asm( "st %%o2, %0 " : "=m" (c)); \
asm( "st %%o1, %0 " : "=m" (d)); \
asm( "st %%o0, %0 " : "=m" (s) :: \
"g1", "o0", "o1", "o2", "o3", "o4", "o5" );
#endif /* SPARCv8 */
#if defined(__microblaze__) || defined(microblaze)
#define MULADDC_INIT \
asm( "lwi r3, %0 " :: "m" (s)); \
asm( "lwi r4, %0 " :: "m" (d)); \
asm( "lwi r5, %0 " :: "m" (c)); \
asm( "lwi r6, %0 " :: "m" (b)); \
asm( "andi r7, r6, 0xffff" ); \
asm( "bsrli r6, r6, 16 " );
#define MULADDC_CORE \
asm( "lhui r8, r3, 0 " ); \
asm( "addi r3, r3, 2 " ); \
asm( "lhui r9, r3, 0 " ); \
asm( "addi r3, r3, 2 " ); \
asm( "mul r10, r9, r6 " ); \
asm( "mul r11, r8, r7 " ); \
asm( "mul r12, r9, r7 " ); \
asm( "mul r13, r8, r6 " ); \
asm( "bsrli r8, r10, 16 " ); \
asm( "bsrli r9, r11, 16 " ); \
asm( "add r13, r13, r8 " ); \
asm( "add r13, r13, r9 " ); \
asm( "bslli r10, r10, 16 " ); \
asm( "bslli r11, r11, 16 " ); \
asm( "add r12, r12, r10 " ); \
asm( "addc r13, r13, r0 " ); \
asm( "add r12, r12, r11 " ); \
asm( "addc r13, r13, r0 " ); \
asm( "lwi r10, r4, 0 " ); \
asm( "add r12, r12, r10 " ); \
asm( "addc r13, r13, r0 " ); \
asm( "add r12, r12, r5 " ); \
asm( "addc r5, r13, r0 " ); \
asm( "swi r12, r4, 0 " ); \
asm( "addi r4, r4, 4 " );
#define MULADDC_STOP \
asm( "swi r5, %0 " : "=m" (c)); \
asm( "swi r4, %0 " : "=m" (d)); \
asm( "swi r3, %0 " : "=m" (s) :: \
"r3", "r4" , "r5" , "r6" , "r7" , "r8" , \
"r9", "r10", "r11", "r12", "r13" );
#endif /* MicroBlaze */
#if defined(__tricore__)
#define MULADDC_INIT \
asm( "ld.a %%a2, %0 " :: "m" (s)); \
asm( "ld.a %%a3, %0 " :: "m" (d)); \
asm( "ld.w %%d4, %0 " :: "m" (c)); \
asm( "ld.w %%d1, %0 " :: "m" (b)); \
asm( "xor %d5, %d5 " );
#define MULADDC_CORE \
asm( "ld.w %d0, [%a2+] " ); \
asm( "madd.u %e2, %e4, %d0, %d1 " ); \
asm( "ld.w %d0, [%a3] " ); \
asm( "addx %d2, %d2, %d0 " ); \
asm( "addc %d3, %d3, 0 " ); \
asm( "mov %d4, %d3 " ); \
asm( "st.w [%a3+], %d2 " );
#define MULADDC_STOP \
asm( "st.w %0, %%d4 " : "=m" (c)); \
asm( "st.a %0, %%a3 " : "=m" (d)); \
asm( "st.a %0, %%a2 " : "=m" (s) :: \
"d0", "d1", "e2", "d4", "a2", "a3" );
#endif /* TriCore */
#if defined(__arm__)
#define MULADDC_INIT \
asm( "ldr r0, %0 " :: "m" (s)); \
asm( "ldr r1, %0 " :: "m" (d)); \
asm( "ldr r2, %0 " :: "m" (c)); \
asm( "ldr r3, %0 " :: "m" (b));
#define MULADDC_CORE \
asm( "ldr r4, [r0], #4 " ); \
asm( "mov r5, #0 " ); \
asm( "ldr r6, [r1] " ); \
asm( "umlal r2, r5, r3, r4 " ); \
asm( "adds r7, r6, r2 " ); \
asm( "adc r2, r5, #0 " ); \
asm( "str r7, [r1], #4 " );
#define MULADDC_STOP \
asm( "str r2, %0 " : "=m" (c)); \
asm( "str r1, %0 " : "=m" (d)); \
asm( "str r0, %0 " : "=m" (s) :: \
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
#endif /* ARMv3 */
#if defined(__alpha__)
#define MULADDC_INIT \
asm( "ldq $1, %0 " :: "m" (s)); \
asm( "ldq $2, %0 " :: "m" (d)); \
asm( "ldq $3, %0 " :: "m" (c)); \
asm( "ldq $4, %0 " :: "m" (b));
#define MULADDC_CORE \
asm( "ldq $6, 0($1) " ); \
asm( "addq $1, 8, $1 " ); \
asm( "mulq $6, $4, $7 " ); \
asm( "umulh $6, $4, $6 " ); \
asm( "addq $7, $3, $7 " ); \
asm( "cmpult $7, $3, $3 " ); \
asm( "ldq $5, 0($2) " ); \
asm( "addq $7, $5, $7 " ); \
asm( "cmpult $7, $5, $5 " ); \
asm( "stq $7, 0($2) " ); \
asm( "addq $2, 8, $2 " ); \
asm( "addq $6, $3, $3 " ); \
asm( "addq $5, $3, $3 " );
#define MULADDC_STOP \
asm( "stq $3, %0 " : "=m" (c)); \
asm( "stq $2, %0 " : "=m" (d)); \
asm( "stq $1, %0 " : "=m" (s) :: \
"$1", "$2", "$3", "$4", "$5", "$6", "$7" );
#endif /* Alpha */
#if defined(__mips__)
#define MULADDC_INIT \
asm( "lw $10, %0 " :: "m" (s)); \
asm( "lw $11, %0 " :: "m" (d)); \
asm( "lw $12, %0 " :: "m" (c)); \
asm( "lw $13, %0 " :: "m" (b));
#define MULADDC_CORE \
asm( "lw $14, 0($10) " ); \
asm( "multu $13, $14 " ); \
asm( "addi $10, $10, 4 " ); \
asm( "mflo $14 " ); \
asm( "mfhi $9 " ); \
asm( "addu $14, $12, $14 " ); \
asm( "lw $15, 0($11) " ); \
asm( "sltu $12, $14, $12 " ); \
asm( "addu $15, $14, $15 " ); \
asm( "sltu $14, $15, $14 " ); \
asm( "addu $12, $12, $9 " ); \
asm( "sw $15, 0($11) " ); \
asm( "addu $12, $12, $14 " ); \
asm( "addi $11, $11, 4 " );
#define MULADDC_STOP \
asm( "sw $12, %0 " : "=m" (c)); \
asm( "sw $11, %0 " : "=m" (d)); \
asm( "sw $10, %0 " : "=m" (s) :: \
"$9", "$10", "$11", "$12", "$13", "$14", "$15" );
#endif /* MIPS */
#endif /* GNUC */
#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
#define MULADDC_INIT \
__asm mov esi, s \
__asm mov edi, d \
__asm mov ecx, c \
__asm mov ebx, b
#define MULADDC_CORE \
__asm lodsd \
__asm mul ebx \
__asm add eax, ecx \
__asm adc edx, 0 \
__asm add eax, [edi] \
__asm adc edx, 0 \
__asm mov ecx, edx \
__asm stosd
#if defined(POLARSSL_HAVE_SSE2)
#define EMIT __asm _emit
#define MULADDC_HUIT \
EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
EMIT 0x0F EMIT 0x6E EMIT 0x1F \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x6E EMIT 0x16 \
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
EMIT 0x0F EMIT 0x7E EMIT 0x0F \
EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x7E EMIT 0xC9
#define MULADDC_STOP \
EMIT 0x0F EMIT 0x77 \
__asm mov c, ecx \
__asm mov d, edi \
__asm mov s, esi \
#else
#define MULADDC_STOP \
__asm mov c, ecx \
__asm mov d, edi \
__asm mov s, esi \
#endif /* SSE2 */
#endif /* MSVC */
#endif /* POLARSSL_HAVE_ASM */
#if !defined(MULADDC_CORE)
#if defined(POLARSSL_HAVE_LONGLONG)
#define MULADDC_INIT \
{ \
t_dbl r; \
t_int r0, r1;
#define MULADDC_CORE \
r = *(s++) * (t_dbl) b; \
r0 = r; \
r1 = r >> biL; \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#else
#define MULADDC_INIT \
{ \
t_int s0, s1, b0, b1; \
t_int r0, r1, rx, ry; \
b0 = ( b << biH ) >> biH; \
b1 = ( b >> biH );
#define MULADDC_CORE \
s0 = ( *s << biH ) >> biH; \
s1 = ( *s >> biH ); s++; \
rx = s0 * b1; r0 = s0 * b0; \
ry = s1 * b0; r1 = s1 * b1; \
r1 += ( rx >> biH ); \
r1 += ( ry >> biH ); \
rx <<= biH; ry <<= biH; \
r0 += rx; r1 += (r0 < rx); \
r0 += ry; r1 += (r0 < ry); \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#endif /* C (generic) */
#endif /* C (longlong) */
#endif /* bn_mul.h */

View file

@ -1,329 +0,0 @@
/**
* \file config.h
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This set of compile-time options may be used to enable
* or disable features selectively, and reduce the global
* memory footprint.
*/
#ifndef POLARSSL_CONFIG_H
#define POLARSSL_CONFIG_H
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
/*
* Uncomment if native integers are 8-bit wide.
*
#define POLARSSL_HAVE_INT8
*/
/*
* Uncomment if native integers are 16-bit wide.
*
#define POLARSSL_HAVE_INT16
*/
/*
* Uncomment if the compiler supports long long.
*/
#define POLARSSL_HAVE_LONGLONG
/*
* Uncomment to enable the use of assembly code.
*/
#define POLARSSL_HAVE_ASM
/*
* Uncomment if the CPU supports SSE2 (IA-32 specific).
*
#define POLARSSL_HAVE_SSE2
*/
/*
* Enable all SSL/TLS debugging messages.
*/
#define POLARSSL_DEBUG_MSG
/*
* Enable the checkup functions (*_self_test).
*/
#define POLARSSL_SELF_TEST
/*
* Enable the prime-number generation code.
*/
#define POLARSSL_GENPRIME
/*
* Uncomment this macro to store the AES tables in ROM.
*
#define POLARSSL_AES_ROM_TABLES
*/
/*
* Module: library/aes.c
* Caller: library/ssl_tls.c
*
* This module enables the following ciphersuites:
* SSL_RSA_AES_128_SHA
* SSL_RSA_AES_256_SHA
* SSL_EDH_RSA_AES_256_SHA
*/
#define POLARSSL_AES_C
/*
* Module: library/arc4.c
* Caller: library/ssl_tls.c
*
* This module enables the following ciphersuites:
* SSL_RSA_RC4_128_MD5
* SSL_RSA_RC4_128_SHA
*/
#define POLARSSL_ARC4_C
/*
* Module: library/base64.c
* Caller: library/x509parse.c
*
* This module is required for X.509 support.
*/
#define POLARSSL_BASE64_C
/*
* Module: library/bignum.c
* Caller: library/dhm.c
* library/rsa.c
* library/ssl_tls.c
* library/x509parse.c
*
* This module is required for RSA and DHM support.
*/
#define POLARSSL_BIGNUM_C
/*
* Module: library/camellia.c
* Caller:
*
* This module enabled the following cipher suites:
*/
#define POLARSSL_CAMELLIA_C
/*
* Module: library/certs.c
* Caller:
*
* This module is used for testing (ssl_client/server).
*/
#define POLARSSL_CERTS_C
/*
* Module: library/debug.c
* Caller: library/ssl_cli.c
* library/ssl_srv.c
* library/ssl_tls.c
*
* This module provides debugging functions.
*/
#define POLARSSL_DEBUG_C
/*
* Module: library/des.c
* Caller: library/ssl_tls.c
*
* This module enables the following ciphersuites:
* SSL_RSA_DES_168_SHA
* SSL_EDH_RSA_DES_168_SHA
*/
#define POLARSSL_DES_C
/*
* Module: library/dhm.c
* Caller: library/ssl_cli.c
* library/ssl_srv.c
*
* This module enables the following ciphersuites:
* SSL_EDH_RSA_DES_168_SHA
* SSL_EDH_RSA_AES_256_SHA
*/
#define POLARSSL_DHM_C
/*
* Module: library/havege.c
* Caller:
*
* This module enables the HAVEGE random number generator.
*/
#define POLARSSL_HAVEGE_C
/*
* Module: library/md2.c
* Caller: library/x509parse.c
*
* Uncomment to enable support for (rare) MD2-signed X.509 certs.
*
#define POLARSSL_MD2_C
*/
/*
* Module: library/md4.c
* Caller: library/x509parse.c
*
* Uncomment to enable support for (rare) MD4-signed X.509 certs.
*
#define POLARSSL_MD4_C
*/
/*
* Module: library/md5.c
* Caller: library/ssl_tls.c
* library/x509parse.c
*
* This module is required for SSL/TLS and X.509.
*/
#define POLARSSL_MD5_C
/*
* Module: library/net.c
* Caller:
*
* This module provides TCP/IP networking routines.
*/
#define POLARSSL_NET_C
/*
* Module: library/padlock.c
* Caller: library/aes.c
*
* This modules adds support for the VIA PadLock on x86.
*/
#define POLARSSL_PADLOCK_C
/*
* Module: library/rsa.c
* Caller: library/ssl_cli.c
* library/ssl_srv.c
* library/ssl_tls.c
* library/x509.c
*
* This module is required for SSL/TLS and MD5-signed certificates.
*/
#define POLARSSL_RSA_C
/*
* Module: library/sha1.c
* Caller: library/ssl_cli.c
* library/ssl_srv.c
* library/ssl_tls.c
* library/x509parse.c
*
* This module is required for SSL/TLS and SHA1-signed certificates.
*/
#define POLARSSL_SHA1_C
/*
* Module: library/sha2.c
* Caller:
*
* This module adds support for SHA-224 and SHA-256.
*/
#define POLARSSL_SHA2_C
/*
* Module: library/sha4.c
* Caller:
*
* This module adds support for SHA-384 and SHA-512.
*/
#define POLARSSL_SHA4_C
/*
* Module: library/ssl_cli.c
* Caller:
*
* This module is required for SSL/TLS client support.
*/
#define POLARSSL_SSL_CLI_C
/*
* Module: library/ssl_srv.c
* Caller:
*
* This module is required for SSL/TLS server support.
*/
#define POLARSSL_SSL_SRV_C
/*
* Module: library/ssl_tls.c
* Caller: library/ssl_cli.c
* library/ssl_srv.c
*
* This module is required for SSL/TLS.
*/
#define POLARSSL_SSL_TLS_C
/*
* Module: library/timing.c
* Caller: library/havege.c
*
* This module is used by the HAVEGE random number generator.
*/
#define POLARSSL_TIMING_C
/*
* Module: library/x509parse.c
* Caller: library/ssl_cli.c
* library/ssl_srv.c
* library/ssl_tls.c
*
* This module is required for X.509 certificate parsing.
*/
#define POLARSSL_X509_PARSE_C
/*
* Module: library/x509_write.c
* Caller:
*
* This module is required for X.509 certificate writing.
*/
#define POLARSSL_X509_WRITE_C
/*
* Module: library/xtea.c
* Caller:
*/
#define POLARSSL_XTEA_C
#endif /* config.h */

View file

@ -1,75 +0,0 @@
/**
* \file havege.h
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POLARSSL_HAVEGE_H
#define POLARSSL_HAVEGE_H
#define COLLECT_SIZE 1024
/**
* \brief HAVEGE state structure
*/
typedef struct
{
int PT1, PT2, offset[2];
int pool[COLLECT_SIZE];
int WALK[8192];
}
havege_state;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief HAVEGE initialization
*
* \param hs HAVEGE state to be initialized
*/
void havege_init( havege_state *hs );
/**
* \brief HAVEGE rand function
*
* \param rng_st points to an HAVEGE state
*
* \return A random int
*/
int havege_rand( void *p_rng );
#ifdef __cplusplus
}
#endif
#endif /* havege.h */

View file

@ -1,309 +0,0 @@
/**
* \file rsa.h
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POLARSSL_RSA_H
#define POLARSSL_RSA_H
#include "polarssl/bignum.h"
#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x0400
#define POLARSSL_ERR_RSA_INVALID_PADDING -0x0410
#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x0420
#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x0430
#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x0440
#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x0450
#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x0460
#define POLARSSL_ERR_RSA_OUTPUT_TO_LARGE -0x0470
/*
* PKCS#1 constants
*/
#define RSA_RAW 0
#define RSA_MD2 2
#define RSA_MD4 3
#define RSA_MD5 4
#define RSA_SHA1 5
#define RSA_SHA256 6
#define RSA_PUBLIC 0
#define RSA_PRIVATE 1
#define RSA_PKCS_V15 0
#define RSA_PKCS_V21 1
#define RSA_SIGN 1
#define RSA_CRYPT 2
/*
* DigestInfo ::= SEQUENCE {
* digestAlgorithm DigestAlgorithmIdentifier,
* digest Digest }
*
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
*
* Digest ::= OCTET STRING
*/
#define ASN1_HASH_MDX \
"\x30\x20\x30\x0C\x06\x08\x2A\x86\x48" \
"\x86\xF7\x0D\x02\x00\x05\x00\x04\x10"
#define ASN1_HASH_SHA1 \
"\x30\x21\x30\x09\x06\x05\x2B\x0E\x03" \
"\x02\x1A\x05\x00\x04\x14"
/**
* \brief RSA context structure
*/
typedef struct
{
int ver; /*!< always 0 */
int len; /*!< size(N) in chars */
mpi N; /*!< public modulus */
mpi E; /*!< public exponent */
mpi D; /*!< private exponent */
mpi P; /*!< 1st prime factor */
mpi Q; /*!< 2nd prime factor */
mpi DP; /*!< D % (P - 1) */
mpi DQ; /*!< D % (Q - 1) */
mpi QP; /*!< 1 / (Q % P) */
mpi RN; /*!< cached R^2 mod N */
mpi RP; /*!< cached R^2 mod P */
mpi RQ; /*!< cached R^2 mod Q */
int padding; /*!< 1.5 or OAEP/PSS */
int hash_id; /*!< hash identifier */
int (*f_rng)(void *); /*!< RNG function */
void *p_rng; /*!< RNG parameter */
}
rsa_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Initialize an RSA context
*
* \param ctx RSA context to be initialized
* \param padding RSA_PKCS_V15 or RSA_PKCS_V21
* \param hash_id RSA_PKCS_V21 hash identifier
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \note The hash_id parameter is actually ignored
* when using RSA_PKCS_V15 padding.
*
* \note Currently (xyssl-0.8), RSA_PKCS_V21 padding
* is not supported.
*/
void rsa_init( rsa_context *ctx,
int padding,
int hash_id,
int (*f_rng)(void *),
void *p_rng );
/**
* \brief Generate an RSA keypair
*
* \param ctx RSA context that will hold the key
* \param nbits size of the public key in bits
* \param exponent public exponent (e.g., 65537)
*
* \note rsa_init() must be called beforehand to setup
* the RSA context (especially f_rng and p_rng).
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*/
int rsa_gen_key( rsa_context *ctx, int nbits, int exponent );
/**
* \brief Check a public RSA key
*
* \param ctx RSA context to be checked
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*/
int rsa_check_pubkey( rsa_context *ctx );
/**
* \brief Check a private RSA key
*
* \param ctx RSA context to be checked
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*/
int rsa_check_privkey( rsa_context *ctx );
/**
* \brief Do an RSA public key operation
*
* \param ctx RSA context
* \param input input buffer
* \param output output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note This function does NOT take care of message
* padding. Also, be sure to set input[0] = 0.
*
* \note The input and output buffers must be large
* enough (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_public( rsa_context *ctx,
unsigned char *input,
unsigned char *output );
/**
* \brief Do an RSA private key operation
*
* \param ctx RSA context
* \param input input buffer
* \param output output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The input and output buffers must be large
* enough (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_private( rsa_context *ctx,
unsigned char *input,
unsigned char *output );
/**
* \brief Add the message padding, then do an RSA operation
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param ilen contains the the plaintext length
* \param input buffer holding the data to be encrypted
* \param output buffer that will hold the ciphertext
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_pkcs1_encrypt( rsa_context *ctx,
int mode, int ilen,
unsigned char *input,
unsigned char *output );
/**
* \brief Do an RSA operation, then remove the message padding
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param input buffer holding the encrypted data
* \param output buffer that will hold the plaintext
* \param olen will contain the plaintext length
* \param output_max_len maximum length of the output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
* an error is thrown.
*/
int rsa_pkcs1_decrypt( rsa_context *ctx,
int mode, int *olen,
unsigned char *input,
unsigned char *output,
int output_max_len);
/**
* \brief Do a private RSA to sign a message digest
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id RSA_RAW, RSA_MD{2,4,5} or RSA_SHA{1,256}
* \param hashlen message digest length (for RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer that will hold the ciphertext
*
* \return 0 if the signing operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_pkcs1_sign( rsa_context *ctx,
int mode,
int hash_id,
int hashlen,
unsigned char *hash,
unsigned char *sig );
/**
* \brief Do a public RSA and check the message digest
*
* \param ctx points to an RSA public key
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id RSA_RAW, RSA_MD{2,4,5} or RSA_SHA{1,256}
* \param hashlen message digest length (for RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer holding the ciphertext
*
* \return 0 if the verify operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_pkcs1_verify( rsa_context *ctx,
int mode,
int hash_id,
int hashlen,
unsigned char *hash,
unsigned char *sig );
/**
* \brief Free the components of an RSA key
*/
void rsa_free( rsa_context *ctx );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int rsa_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* rsa.h */

View file

@ -1,150 +0,0 @@
/**
* \file sha1.h
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POLARSSL_SHA1_H
#define POLARSSL_SHA1_H
/**
* \brief SHA-1 context structure
*/
typedef struct
{
unsigned long total[2]; /*!< number of bytes processed */
unsigned long state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
}
sha1_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void sha1_starts( sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha1_update( sha1_context *ctx, unsigned char *input, int ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void sha1_finish( sha1_context *ctx, unsigned char output[20] );
/**
* \brief Output = SHA-1( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-1 checksum result
*/
void sha1( unsigned char *input, int ilen, unsigned char output[20] );
/**
* \brief Output = SHA-1( file contents )
*
* \param path input file name
* \param output SHA-1 checksum result
*
* \return 0 if successful, 1 if fopen failed,
* or 2 if fread failed
*/
int sha1_file( char *path, unsigned char output[20] );
/**
* \brief SHA-1 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void sha1_hmac_starts( sha1_context *ctx, unsigned char *key, int keylen );
/**
* \brief SHA-1 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha1_hmac_update( sha1_context *ctx, unsigned char *input, int ilen );
/**
* \brief SHA-1 HMAC final digest
*
* \param ctx HMAC context
* \param output SHA-1 HMAC checksum result
*/
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
/**
* \brief Output = HMAC-SHA-1( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-SHA-1 result
*/
void sha1_hmac( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[20] );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int sha1_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* sha1.h */

View file

@ -1,81 +0,0 @@
/**
* \file timing.h
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POLARSSL_TIMING_H
#define POLARSSL_TIMING_H
/**
* \brief timer structure
*/
struct hr_time
{
unsigned char opaque[32];
};
#ifdef __cplusplus
extern "C" {
#endif
extern int alarmed;
/**
* \brief Return the CPU cycle counter value
*/
unsigned long hardclock( void );
/**
* \brief Return the elapsed time in milliseconds
*
* \param val points to a timer structure
* \param reset if set to 1, the timer is restarted
*/
unsigned long get_timer( struct hr_time *val, int reset );
/**
* \brief Setup an alarm clock
*
* \param seconds delay before the "alarmed" flag is set
*/
void set_alarm( int seconds );
/**
* \brief Sleep for a certain amount of time
*/
void m_sleep( int milliseconds );
#ifdef __cplusplus
}
#endif
#endif /* timing.h */

View file

@ -1,549 +0,0 @@
/**
* \file x509.h
*
* Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
*
* Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of PolarSSL or XySSL nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POLARSSL_X509_H
#define POLARSSL_X509_H
#include "polarssl/rsa.h"
#define POLARSSL_ERR_ASN1_OUT_OF_DATA -0x0014
#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG -0x0016
#define POLARSSL_ERR_ASN1_INVALID_LENGTH -0x0018
#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH -0x001A
#define POLARSSL_ERR_ASN1_INVALID_DATA -0x001C
#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE -0x0020
#define POLARSSL_ERR_X509_CERT_INVALID_PEM -0x0040
#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT -0x0060
#define POLARSSL_ERR_X509_CERT_INVALID_VERSION -0x0080
#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL -0x00A0
#define POLARSSL_ERR_X509_CERT_INVALID_ALG -0x00C0
#define POLARSSL_ERR_X509_CERT_INVALID_NAME -0x00E0
#define POLARSSL_ERR_X509_CERT_INVALID_DATE -0x0100
#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY -0x0120
#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE -0x0140
#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS -0x0160
#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION -0x0180
#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG -0x01A0
#define POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG -0x01C0
#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH -0x01E0
#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED -0x0200
#define POLARSSL_ERR_X509_KEY_INVALID_PEM -0x0220
#define POLARSSL_ERR_X509_KEY_INVALID_VERSION -0x0240
#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT -0x0260
#define POLARSSL_ERR_X509_KEY_INVALID_ENC_IV -0x0280
#define POLARSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG -0x02A0
#define POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED -0x02C0
#define POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH -0x02E0
#define POLARSSL_ERR_X509_POINT_ERROR -0x0300
#define POLARSSL_ERR_X509_VALUE_TO_LENGTH -0x0320
#define BADCERT_EXPIRED 1
#define BADCERT_REVOKED 2
#define BADCERT_CN_MISMATCH 4
#define BADCERT_NOT_TRUSTED 8
/*
* DER constants
*/
#define ASN1_BOOLEAN 0x01
#define ASN1_INTEGER 0x02
#define ASN1_BIT_STRING 0x03
#define ASN1_OCTET_STRING 0x04
#define ASN1_NULL 0x05
#define ASN1_OID 0x06
#define ASN1_UTF8_STRING 0x0C
#define ASN1_SEQUENCE 0x10
#define ASN1_SET 0x11
#define ASN1_PRINTABLE_STRING 0x13
#define ASN1_T61_STRING 0x14
#define ASN1_IA5_STRING 0x16
#define ASN1_UTC_TIME 0x17
#define ASN1_UNIVERSAL_STRING 0x1C
#define ASN1_BMP_STRING 0x1E
#define ASN1_PRIMITIVE 0x00
#define ASN1_CONSTRUCTED 0x20
#define ASN1_CONTEXT_SPECIFIC 0x80
/*
* various object identifiers
*/
#define X520_COMMON_NAME 3
#define X520_COUNTRY 6
#define X520_LOCALITY 7
#define X520_STATE 8
#define X520_ORGANIZATION 10
#define X520_ORG_UNIT 11
#define PKCS9_EMAIL 1
#define X509_OUTPUT_DER 0x01
#define X509_OUTPUT_PEM 0x02
#define PEM_LINE_LENGTH 72
#define X509_ISSUER 0x01
#define X509_SUBJECT 0x02
#define OID_X520 "\x55\x04"
#define OID_CN "\x55\x04\x03"
#define OID_PKCS1 "\x2A\x86\x48\x86\xF7\x0D\x01\x01"
#define OID_PKCS1_RSA "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01"
#define OID_PKCS1_RSA_SHA "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05"
#define OID_PKCS9 "\x2A\x86\x48\x86\xF7\x0D\x01\x09"
#define OID_PKCS9_EMAIL "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01"
/*
* Structures for parsing X.509 certificates
*/
typedef struct _x509_buf
{
int tag;
int len;
unsigned char *p;
}
x509_buf;
typedef struct _x509_name
{
x509_buf oid;
x509_buf val;
struct _x509_name *next;
}
x509_name;
typedef struct _x509_time
{
int year, mon, day;
int hour, min, sec;
}
x509_time;
typedef struct _x509_cert
{
x509_buf raw;
x509_buf tbs;
int version;
x509_buf serial;
x509_buf sig_oid1;
x509_buf issuer_raw;
x509_buf subject_raw;
x509_name issuer;
x509_name subject;
x509_time valid_from;
x509_time valid_to;
x509_buf pk_oid;
rsa_context rsa;
x509_buf issuer_id;
x509_buf subject_id;
x509_buf v3_ext;
int ca_istrue;
int max_pathlen;
x509_buf sig_oid2;
x509_buf sig;
struct _x509_cert *next;
}
x509_cert;
/*
* Structures for writing X.509 certificates
*/
typedef struct _x509_node
{
unsigned char *data;
unsigned char *p;
unsigned char *end;
size_t len;
}
x509_node;
typedef struct _x509_raw
{
x509_node raw;
x509_node tbs;
x509_node version;
x509_node serial;
x509_node tbs_signalg;
x509_node issuer;
x509_node validity;
x509_node subject;
x509_node subpubkey;
x509_node signalg;
x509_node sign;
}
x509_raw;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Parse one or more certificates and add them
* to the chained list
*
* \param chain points to the start of the chain
* \param buf buffer holding the certificate data
* \param buflen size of the buffer
*
* \return 0 if successful, or a specific X509 error code
*/
int x509parse_crt( x509_cert *crt, unsigned char *buf, int buflen );
/**
* \brief Load one or more certificates and add them
* to the chained list
*
* \param chain points to the start of the chain
* \param path filename to read the certificates from
*
* \return 0 if successful, or a specific X509 error code
*/
int x509parse_crtfile( x509_cert *crt, char *path );
/**
* \brief Parse a private RSA key
*
* \param rsa RSA context to be initialized
* \param buf input buffer
* \param buflen size of the buffer
* \param pwd password for decryption (optional)
* \param pwdlen size of the password
*
* \return 0 if successful, or a specific X509 error code
*/
int x509parse_key( rsa_context *rsa,
unsigned char *buf, int buflen,
unsigned char *pwd, int pwdlen );
/**
* \brief Load and parse a private RSA key
*
* \param rsa RSA context to be initialized
* \param path filename to read the private key from
* \param pwd password to decrypt the file (can be NULL)
*
* \return 0 if successful, or a specific X509 error code
*/
int x509parse_keyfile( rsa_context *rsa, char *path, char *password );
/**
* \brief Store the certificate DN in printable form into buf;
* no more than (end - buf) characters will be written.
*/
int x509parse_dn_gets( char *buf, char *end, x509_name *dn );
/**
* \brief Returns an informational string about the
* certificate.
*/
char *x509parse_cert_info( char *prefix, x509_cert *crt );
/**
* \brief Return 0 if the certificate is still valid,
* or BADCERT_EXPIRED
*/
int x509parse_expired( x509_cert *crt );
/**
* \brief Verify the certificate signature
*
* \param crt a certificate to be verified
* \param trust_ca the trusted CA chain
* \param cn expected Common Name (can be set to
* NULL if the CN must not be verified)
* \param flags result of the verification
*
* \return 0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED,
* in which case *flags will have one or more of
* the following values set:
* BADCERT_EXPIRED --
* BADCERT_REVOKED --
* BADCERT_CN_MISMATCH --
* BADCERT_NOT_TRUSTED
*
* \note TODO: add two arguments, depth and crl
*/
int x509parse_verify( x509_cert *crt,
x509_cert *trust_ca,
char *cn, int *flags );
/**
* \brief Unallocate all certificate data
*/
void x509_free( x509_cert *crt );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int x509_self_test( int verbose );
/**
* \brief Write a certificate info file
*
* \param chain points to the raw certificate data
* \param path filename to write the certificate to
* \param format X509_OUTPUT_DER or X509_OUTPUT_PEM
*
* \return 0 if successful, or a specific X509 error code
*/
int x509write_crtfile( x509_raw *chain,
unsigned char *path,
int format );
/**
* \brief Write a certificate signing request message format file
*
* \param chain points to the raw certificate (with x509write_create_csr) data
* \param path filename to write the certificate to
* \param format X509_OUTPUT_DER or X509_OUTPUT_PEM
*
* \return 0 if successful, or a specific X509 error code
*/
int x509write_csrfile( x509_raw *chain,
unsigned char *path,
int format );
/*
* \brief Write a private RSA key into a file
*
* \param rsa points to an RSA key
* \param path filename to write the key to
* \param format X509_OUTPUT_DER or X509_OUTPUT_PEM
*
* \return 0 if successful, or a specific X509 error code
*/
int x509write_keyfile( rsa_context *rsa,
char *path,
int format );
/**
* \brief Add a public key to certificate
*
* \param chain points to the raw certificate data
* \param pubkey points to an RSA key
*
* \return 0 if successful, or a specific X509 error code
*/
int x509write_add_pubkey( x509_raw *chain, rsa_context *pubkey );
/**
* \brief Create x509 subject/issuer field to raw certificate
* from string or CA cert. Make string NULL if you will
* use the CA copy function or make CA NULL then used
* the string parse.
*
* \param chain points to the raw certificate data
* \param names a string that can hold (separete with ";"):
* CN=CommonName
* -- O=Organization
* -- OU=OrgUnit
* -- ST=State
* -- L=Locality
* -- R=Email
* -- C=Country
* . Make that NULL if you didn't need that.
* \param flag flag is X509_ISSUER or X509_SUBJECT that defined
* where change
* \param ca the certificate for copy data. Make that NULL if you
* didn't need that.
* \param ca_flag set the ca field from copy to crt
*
* \return 0 if successful, or a specific X509 error code
*/
int x509write_add_customize ( x509_raw *crt,
unsigned char *names,
int flag,
x509_cert *ca,
int ca_flag );
/**
* \brief Add x509 issuer field
*
* \param chain points to the raw certificate data
* \param issuer a string holding (separete with ";"):
* CN=CommonName
* -- O=Organization
* -- OU=OrgUnit
* -- ST=State
* -- L=Locality
* -- R=Email
* -- C=Country
* . Set this to NULL if not needed.
* \return 0 if successful, or a specific X509 error code
*/
int x509write_add_issuer( x509_raw *crt, unsigned char *issuer);
/**
* \brief Add x509 subject field
*
* \param chain points to the raw certificate data
* \param subject a string holding (separete with ";"):
* CN=CommonName
* -- O=Organization
* -- OU=OrgUnit
* -- ST=State
* -- L=Locality
* -- R=Email
* -- C=Country
* . Set this to NULL if not needed.
* \return 0 if successful, or a specific X509 error code
*/
int x509write_add_subject( x509_raw *crt, unsigned char *subject);
/**
* \brief Copy x509 issuer field from another certificate
*
* \param chain points to the raw certificate data
* \param from_crt the certificate whose issuer is to be copied.
* \return 0 if successful, or a specific X509 error code
*/
int x509write_copy_issuer(x509_raw *crt, x509_cert *from_crt);
/**
* \brief Copy x509 subject field from another certificate
*
* \param chain points to the raw certificate data
* \param from_crt the certificate whose subject is to be copied.
* \return 0 if successful, or a specific X509 error code
*/
int x509write_copy_subject(x509_raw *crt, x509_cert *from_crt);
/**
* \brief Copy x509 issuer field from the subject of another certificate
*
* \param chain points to the raw certificate data
* \param from_crt the certificate whose subject is to be copied.
* \return 0 if successful, or a specific X509 error code
*/
int x509write_copy_issuer_from_subject(x509_raw *crt, x509_cert *from_crt);
/**
* \brief Copy x509 subject field from the issuer of another certificate
*
* \param chain points to the raw certificate data
* \param from_crt the certificate whose issuer is to be copied.
* \return 0 if successful, or a specific X509 error code
*/
int x509write_copy_subject_from_issuer(x509_raw *crt, x509_cert *from_crt);
/**
* \brief Create x509 validity time in UTC
*
* \param chain points to the raw certificate data
* \param before valid not before in format YYYY-MM-DD hh:mm:ss
* \param after valid not after in format YYYY-MM-DD hh:mm:ss
*
* \return 0 if successful, or a specific X509 error code
*/
int x509write_add_validity( x509_raw *crt,
unsigned char *before,
unsigned char *after );
/**
* \brief Create a self-signed certificate
*
* \param chain points to the raw certificate data
* \param rsa a private key to sign the certificate
*
* \return 0 if successful, or a specific X509 error code
*/
int x509write_create_selfsign( x509_raw *crt, rsa_context *raw );
/**
* \brief Create a certificate
*
* \param chain points to the raw certificate data
* \param rsa a private key to sign the certificate
*
* \return 0 if successful, or a specific X509 error code
*/
int x509write_create_sign( x509_raw *crt, rsa_context *raw );
/**
* \brief Create a certificate signing request
*
* \param chain points to the raw certificate data. Didn't use the
* same chain that u have use for certificate.
* \param privkey a rsa private key
*
* \return 0 if successful, or a specific X509 error code
*/
int x509write_create_csr( x509_raw *chain, rsa_context *privkey );
/**
* \brief Serialize an rsa key into DER
*
* \param rsa a rsa key for output
* \param node a x509 node for write into
*
* \return 0 if successful, or a specific X509 error code
*/
int x509write_serialize_key( rsa_context *rsa, x509_node *node );
/**
* \brief Unallocate all raw certificate data
*/
void x509write_free_raw( x509_raw *crt );
/**
* \brief Allocate all raw certificate data
*/
void x509write_init_raw( x509_raw *crt );
/**
* \brief Unallocate all node certificate data
*/
void x509write_free_node( x509_node *crt_node );
/**
* \brief Allocate all node certificate data
*/
void x509write_init_node( x509_node *crt_node );
#ifdef __cplusplus
}
#endif
#endif /* x509.h */

View file

@ -1,197 +0,0 @@
/*
* px5g - Embedded x509 key and certificate generator based on PolarSSL
*
* Copyright (C) 2009 Steven Barth <steven@midlink.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1 as published by the Free Software Foundation.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "polarssl/havege.h"
#include "polarssl/bignum.h"
#include "polarssl/x509.h"
#include "polarssl/rsa.h"
#define PX5G_VERSION "0.1"
#define PX5G_COPY "Copyright (c) 2009 Steven Barth <steven@midlink.org>"
#define PX5G_LICENSE "Licensed under the GNU Lesser General Public License v2.1"
int rsakey(char **arg) {
havege_state hs;
rsa_context rsa;
unsigned int ksize = 512;
int exp = 65537;
char *path = NULL;
int flag = X509_OUTPUT_PEM;
while (*arg && **arg == '-') {
if (!strcmp(*arg, "-out") && arg[1]) {
path = arg[1];
arg++;
} else if (!strcmp(*arg, "-3")) {
exp = 3;
} else if (!strcmp(*arg, "-der")) {
flag = X509_OUTPUT_DER;
}
arg++;
}
if (*arg) {
ksize = (unsigned int)atoi(*arg);
}
havege_init(&hs);
rsa_init(&rsa, RSA_PKCS_V15, 0, havege_rand, &hs);
fprintf(stderr, "Generating RSA private key, %i bit long modulus\n", ksize);
if (rsa_gen_key(&rsa, ksize, exp)) {
fprintf(stderr, "error: key generation failed\n");
return 1;
}
if (x509write_keyfile(&rsa, path, flag)) {
fprintf(stderr, "error: I/O error\n");
return 1;
}
rsa_free(&rsa);
return 0;
}
int selfsigned(char **arg) {
havege_state hs;
rsa_context rsa;
x509_node node;
char *subject = "";
unsigned int ksize = 512;
int exp = 65537;
unsigned int days = 30;
char *keypath = NULL, *certpath = NULL;
int flag = X509_OUTPUT_PEM;
time_t from = time(NULL), to;
char fstr[20], tstr[20];
while (*arg && **arg == '-') {
if (!strcmp(*arg, "-der")) {
flag = X509_OUTPUT_DER;
} else if (!strcmp(*arg, "-newkey") && arg[1]) {
if (strncmp(arg[1], "rsa:", 4)) {
fprintf(stderr, "error: invalid algorithm");
return 1;
}
ksize = (unsigned int)atoi(arg[1] + 4);
arg++;
} else if (!strcmp(*arg, "-days") && arg[1]) {
days = (unsigned int)atoi(arg[1]);
arg++;
} else if (!strcmp(*arg, "-keyout") && arg[1]) {
keypath = arg[1];
arg++;
} else if (!strcmp(*arg, "-out") && arg[1]) {
certpath = arg[1];
arg++;
} else if (!strcmp(*arg, "-subj") && arg[1]) {
if (arg[1][0] != '/' || strchr(arg[1], ';')) {
fprintf(stderr, "error: invalid subject");
return 1;
}
subject = calloc(strlen(arg[1]) + 1, 1);
char *oldc = arg[1] + 1, *newc = subject, *delim;
do {
delim = strchr(oldc, '=');
if (!delim) {
fprintf(stderr, "error: invalid subject");
return 1;
}
memcpy(newc, oldc, delim - oldc + 1);
newc += delim - oldc + 1;
oldc = delim + 1;
delim = strchr(oldc, '/');
if (!delim) {
delim = arg[1] + strlen(arg[1]);
}
memcpy(newc, oldc, delim - oldc);
newc += delim - oldc;
*newc++ = ';';
oldc = delim + 1;
} while(*delim);
arg++;
}
arg++;
}
havege_init(&hs);
rsa_init(&rsa, RSA_PKCS_V15, 0, havege_rand, &hs);
x509write_init_node(&node);
fprintf(stderr, "Generating RSA private key, %i bit long modulus\n", ksize);
if (rsa_gen_key(&rsa, ksize, exp)) {
fprintf(stderr, "error: key generation failed\n");
return 1;
}
if (keypath) {
if (x509write_keyfile(&rsa, keypath, flag)) {
fprintf(stderr, "error: I/O error\n");
return 1;
}
}
from = (from < 1000000000) ? 1000000000 : from;
strftime(fstr, sizeof(fstr), "%F %H:%M:%S", gmtime(&from));
to = from + 60 * 60 * 24 * days;
strftime(tstr, sizeof(tstr), "%F %H:%M:%S", gmtime(&to));
x509_raw cert;
x509write_init_raw(&cert);
x509write_add_pubkey(&cert, &rsa);
x509write_add_subject(&cert, (unsigned char*)subject);
x509write_add_validity(&cert, (unsigned char*)fstr, (unsigned char*)tstr);
fprintf(stderr, "Generating selfsigned certificate with subject '%s'"
" and validity %s-%s\n", subject, fstr, tstr);
if (x509write_create_selfsign(&cert, &rsa)) {
fprintf(stderr, "error: certificate generation failed\n");
}
if (x509write_crtfile(&cert, (unsigned char*)certpath, flag)) {
fprintf(stderr, "error: I/O error\n");
return 1;
}
x509write_free_raw(&cert);
rsa_free(&rsa);
return 0;
}
int main(int argc, char *argv[]) {
if (!argv[1]) {
//Usage
} else if (!strcmp(argv[1], "rsakey")) {
return rsakey(argv+2);
} else if (!strcmp(argv[1], "selfsigned")) {
return selfsigned(argv+2);
}
fprintf(stderr,
"PX5G X.509 Certificate Generator Utility v" PX5G_VERSION "\n" PX5G_COPY
"\nbased on PolarSSL by Christophe Devine and Paul Bakker\n\n");
fprintf(stderr, "Usage: %s [rsakey|selfsigned]\n", *argv);
return 1;
}

View file

@ -1,92 +0,0 @@
#
# Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=uhttpd
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/uhttpd/default
SECTION:=net
CATEGORY:=Network
TITLE:=uHTTPd - tiny, single threaded HTTP server
endef
define Package/uhttpd
$(Package/uhttpd/default)
MENU:=1
endef
define Package/uhttpd/description
uHTTPd is a tiny single threaded HTTP server with TLS, CGI and Lua
support. It is intended as a drop-in replacement for the Busybox
HTTP daemon.
endef
define Package/uhttpd-mod-tls
$(Package/uhttpd/default)
TITLE+= (TLS plugin)
DEPENDS:=uhttpd +libcyassl
endef
define Package/uhttpd-mod-tls/description
The TLS plugin adds HTTPS support to uHTTPd.
endef
define Package/uhttpd-mod-lua
$(Package/uhttpd/default)
TITLE+= (Lua plugin)
DEPENDS:=uhttpd +liblua
endef
define Package/uhttpd-mod-lua/description
The Lua plugin adds a CGI-like Lua runtime interface to uHTTPd.
endef
# hack to use CyASSL headers
TARGET_CFLAGS += -I$(firstword $(wildcard $(BUILD_DIR)/cyassl-*/include))
MAKE_VARS += FPIC="$(FPIC)"
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Package/uhttpd/conffiles
/etc/config/uhttpd
endef
define Package/uhttpd/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/uhttpd.init $(1)/etc/init.d/uhttpd
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/uhttpd.config $(1)/etc/config/uhttpd
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd $(1)/usr/sbin/uhttpd
endef
define Package/uhttpd-mod-tls/install
$(INSTALL_DIR) $(1)/usr/lib
$(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_tls.so $(1)/usr/lib/
endef
define Package/uhttpd-mod-lua/install
$(INSTALL_DIR) $(1)/usr/lib
$(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_lua.so $(1)/usr/lib/
endef
$(eval $(call BuildPackage,uhttpd))
$(eval $(call BuildPackage,uhttpd-mod-tls))
$(eval $(call BuildPackage,uhttpd-mod-lua))

View file

@ -1,53 +0,0 @@
# Server configuration
config uhttpd main
# Server document root
option home /www
# Certificate and private key for HTTPS.
# If no listen_https addresses are given,
# the key options are ignored.
option cert /etc/uhttpd.crt
option key /etc/uhttpd.key
# CGI url prefix, will be searched in docroot.
# Default is /cgi-bin
option cgi_prefix /cgi-bin
# Lua url prefix and handler script.
# Lua support is disabled if no prefix given.
# option lua_prefix /luci
# option lua_handler /usr/lib/lua/luci/sgi/uhttpd.lua
# HTTP listen addresses, multiple allowed
list listen_http 0.0.0.0:80
# list listen_http [::]:80
# HTTPS listen addresses, multiple allowed
list listen_https 0.0.0.0:443
# list listen_https [::]:443
# Basic auth realm, defaults to local hostname
# option realm OpenWrt
# Configuration file in busybox httpd format
# option config /etc/httpd.conf
# Certificate defaults for px5g key generator
config cert px5g
# Validity time
option days 730
# RSA key size
option bits 1024
# Location
option country DE
option state Berlin
option location Berlin
# Common name
option commonname OpenWrt

View file

@ -1,115 +0,0 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2010 Jo-Philipp Wich
START=50
UHTTPD_BIN="/usr/sbin/uhttpd"
PX5G_BIN="/usr/sbin/px5g"
append_listen_http() {
append UHTTPD_ARGS "-p $1"
}
append_listen_https() {
append UHTTPD_ARGS "-s $1"
}
append_arg() {
local cfg="$1"
local var="$2"
local opt="$3"
local def="$4"
local val
config_get val "$cfg" "$var"
[ -n "$val" -o -n "$def" ] && append UHTTPD_ARGS "$opt ${val:-$def}"
}
generate_keys() {
local cfg="$1"
local key="$2"
local crt="$3"
local days bits country state location commonname
config_get days "$cfg" days
config_get bits "$cfg" bits
config_get country "$cfg" country
config_get state "$cfg" state
config_get location "$cfg" location
config_get commonname "$cfg" commonname
[ -x "$PX5G_BIN" ] && {
$PX5G_BIN selfsigned -der \
-days ${days:-730} -newkey rsa:${bits:-1024} -keyout "$UHTTPD_KEY" -out "$UHTTPD_CERT" \
-subj /C=${country:-DE}/ST=${state:-Saxony}/L=${location:-Leipzig}/CN=${commonname:-OpenWrt}
} || {
echo "WARNING: the specified certificate and key" \
"files do not exist and the px5g generator" \
"is not available, skipping SSL setup."
}
}
start_instance()
{
UHTTPD_ARGS=""
UHTTPD_CERT=""
UHTTPD_KEY=""
local cfg="$1"
local realm="$(uci get system.@system[0].hostname 2>/dev/null)"
local ssl
append_arg "$cfg" home "-h"
append_arg "$cfg" realm "-r" "${realm:-OpenWrt}"
append_arg "$cfg" config "-c"
append_arg "$cfg" cgi_prefix "-x"
append_arg "$cfg" lua_prefix "-l"
append_arg "$cfg" lua_handler "-L"
config_list_foreach "$cfg" listen_http \
append_listen_http
config_get ssl "$cfg" listen_https
config_get UHTTPD_KEY "$cfg" key /etc/uhttpd.key
config_get UHTTPD_CERT "$cfg" cert /etc/uhttpd.crt
[ -n "$ssl" ] && {
[ -f "$UHTTPD_CERT" -a -f "$UHTTPD_KEY" ] || {
config_foreach generate_keys cert
}
[ -f "$UHTTPD_CERT" -a -f "$UHTTPD_KEY" ] && {
append_arg "$cfg" cert "-C"
append_arg "$cfg" key "-K"
config_list_foreach "$cfg" listen_https \
append_listen_https
}
}
start-stop-daemon -S -x $UHTTPD_BIN \
-p /var/run/uhttpd_${cfg}.pid \
-m -b -- -f $UHTTPD_ARGS
}
stop_instance()
{
local cfg="$1"
[ -f /var/run/uhttpd_${cfg}.pid ] && {
start-stop-daemon -K -q -n ${UHTTPD_BIN##*/} \
-p /var/run/uhttpd_${cfg}.pid -s TERM
rm -f /var/run/uhttpd_${cfg}.pid
}
}
start() {
config_load uhttpd
config_foreach start_instance uhttpd
}
stop() {
config_load uhttpd
config_foreach stop_instance uhttpd
}

View file

@ -1,52 +0,0 @@
CGI_SUPPORT ?= 1
LUA_SUPPORT ?= 1
TLS_SUPPORT ?= 1
CFLAGS ?= -I./lua-5.1.4/src -I./cyassl-1.4.0/include -O0 -ggdb3
LDFLAGS ?= -L./lua-5.1.4/src -L./cyassl-1.4.0/src/.libs
CFLAGS += -Wall --std=gnu99
OBJ = uhttpd.o uhttpd-file.o uhttpd-utils.o
LIB = -Wl,--export-dynamic -lcrypt -ldl
TLSLIB =
LUALIB =
world: compile
ifeq ($(CGI_SUPPORT),1)
OBJ += uhttpd-cgi.o
CFLAGS += -DHAVE_CGI
endif
ifeq ($(LUA_SUPPORT),1)
CFLAGS += -DHAVE_LUA
LUALIB = uhttpd_lua.so
$(LUALIB): uhttpd-lua.c
$(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \
-shared -lm -llua -ldl \
-o $(LUALIB) uhttpd-lua.c
endif
ifeq ($(TLS_SUPPORT),1)
CFLAGS += -DHAVE_TLS
TLSLIB = uhttpd_tls.so
$(TLSLIB): uhttpd-tls.c
$(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \
-shared -lcyassl \
-o $(TLSLIB) uhttpd-tls.c
endif
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
compile: $(OBJ) $(TLSLIB) $(LUALIB)
$(CC) -o uhttpd $(LDFLAGS) $(LIB) $(OBJ)
clean:
rm -f *.o *.so uhttpd

View file

@ -1,561 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - CGI handler
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "uhttpd.h"
#include "uhttpd-utils.h"
#include "uhttpd-cgi.h"
static struct http_response * uh_cgi_header_parse(char *buf, int len, int *off)
{
char *bufptr = NULL;
char *hdrname = NULL;
int hdrcount = 0;
int pos = 0;
static struct http_response res;
if( ((bufptr = strfind(buf, len, "\r\n\r\n", 4)) != NULL) ||
((bufptr = strfind(buf, len, "\n\n", 2)) != NULL)
) {
*off = (int)(bufptr - buf) + ((bufptr[0] == '\r') ? 4 : 2);
memset(&res, 0, sizeof(res));
res.statuscode = 200;
res.statusmsg = "OK";
bufptr = &buf[0];
for( pos = 0; pos < len; pos++ )
{
if( !hdrname && (buf[pos] == ':') )
{
buf[pos++] = 0;
if( (pos < len) && (buf[pos] == ' ') )
pos++;
if( pos < len )
{
hdrname = bufptr;
bufptr = &buf[pos];
}
}
else if( (buf[pos] == '\r') || (buf[pos] == '\n') )
{
buf[pos++] = 0;
if( ! hdrname )
break;
if( (pos < len) && (buf[pos] == '\n') )
pos++;
if( pos < len )
{
if( (hdrcount + 1) < array_size(res.headers) )
{
if( ! strcasecmp(hdrname, "Status") )
{
res.statuscode = atoi(bufptr);
if( res.statuscode < 100 )
res.statuscode = 200;
if( ((bufptr = strchr(bufptr, ' ')) != NULL) && (&bufptr[1] != 0) )
res.statusmsg = &bufptr[1];
}
else
{
res.headers[hdrcount++] = hdrname;
res.headers[hdrcount++] = bufptr;
}
bufptr = &buf[pos];
hdrname = NULL;
}
else
{
return NULL;
}
}
}
}
return &res;
}
return NULL;
}
static char * uh_cgi_header_lookup(struct http_response *res, const char *hdrname)
{
int i;
foreach_header(i, res->headers)
{
if( ! strcasecmp(res->headers[i], hdrname) )
return res->headers[i+1];
}
return NULL;
}
static int uh_cgi_error_500(struct client *cl, struct http_request *req, const char *message)
{
if( uh_http_sendf(cl, NULL,
"HTTP/%.1f 500 Internal Server Error\r\n"
"Content-Type: text/plain\r\n%s\r\n",
req->version,
(req->version > 1.0)
? "Transfer-Encoding: chunked\r\n" : ""
) >= 0
) {
return uh_http_send(cl, req, message, -1);
}
return -1;
}
void uh_cgi_request(struct client *cl, struct http_request *req, struct path_info *pi)
{
int i, hdroff, bufoff;
int hdrlen = 0;
int buflen = 0;
int fd_max = 0;
int content_length = 0;
int header_sent = 0;
int rfd[2] = { 0, 0 };
int wfd[2] = { 0, 0 };
char buf[UH_LIMIT_MSGHEAD];
char hdr[UH_LIMIT_MSGHEAD];
pid_t child;
fd_set reader;
fd_set writer;
struct sigaction sa;
struct timeval timeout;
struct http_response *res;
/* spawn pipes for me->child, child->me */
if( (pipe(rfd) < 0) || (pipe(wfd) < 0) )
{
uh_http_sendhf(cl, 500, "Internal Server Error",
"Failed to create pipe: %s", strerror(errno));
if( rfd[0] > 0 ) close(rfd[0]);
if( rfd[1] > 0 ) close(rfd[1]);
if( wfd[0] > 0 ) close(wfd[0]);
if( wfd[1] > 0 ) close(wfd[1]);
return;
}
/* fork off child process */
switch( (child = fork()) )
{
/* oops */
case -1:
uh_http_sendhf(cl, 500, "Internal Server Error",
"Failed to fork child: %s", strerror(errno));
return;
/* exec child */
case 0:
/* restore SIGTERM */
sa.sa_flags = 0;
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
sigaction(SIGTERM, &sa, NULL);
/* close loose pipe ends */
close(rfd[0]);
close(wfd[1]);
/* patch stdout and stdin to pipes */
dup2(rfd[1], 1);
dup2(wfd[0], 0);
/* check for regular, world-executable file */
if( (pi->stat.st_mode & S_IFREG) &&
(pi->stat.st_mode & S_IXOTH)
) {
/* build environment */
clearenv();
/* common information */
setenv("GATEWAY_INTERFACE", "CGI/1.1", 1);
setenv("SERVER_SOFTWARE", "uHTTPd", 1);
setenv("PATH", "/sbin:/usr/sbin:/bin:/usr/bin", 1);
#ifdef HAVE_TLS
/* https? */
if( cl->tls )
setenv("HTTPS", "on", 1);
#endif
/* addresses */
setenv("SERVER_NAME", sa_straddr(&cl->servaddr), 1);
setenv("SERVER_ADDR", sa_straddr(&cl->servaddr), 1);
setenv("SERVER_PORT", sa_strport(&cl->servaddr), 1);
setenv("REMOTE_HOST", sa_straddr(&cl->peeraddr), 1);
setenv("REMOTE_ADDR", sa_straddr(&cl->peeraddr), 1);
setenv("REMOTE_PORT", sa_strport(&cl->peeraddr), 1);
/* path information */
setenv("SCRIPT_NAME", pi->name, 1);
setenv("SCRIPT_FILENAME", pi->phys, 1);
setenv("DOCUMENT_ROOT", pi->root, 1);
setenv("QUERY_STRING", pi->query ? pi->query : "", 1);
if( pi->info )
setenv("PATH_INFO", pi->info, 1);
/* http version */
if( req->version > 1.0 )
setenv("SERVER_PROTOCOL", "HTTP/1.1", 1);
else
setenv("SERVER_PROTOCOL", "HTTP/1.0", 1);
/* request method */
switch( req->method )
{
case UH_HTTP_MSG_GET:
setenv("REQUEST_METHOD", "GET", 1);
break;
case UH_HTTP_MSG_HEAD:
setenv("REQUEST_METHOD", "HEAD", 1);
break;
case UH_HTTP_MSG_POST:
setenv("REQUEST_METHOD", "POST", 1);
break;
}
/* request url */
setenv("REQUEST_URI", req->url, 1);
/* remote user */
if( req->realm )
setenv("REMOTE_USER", req->realm->user, 1);
/* request message headers */
foreach_header(i, req->headers)
{
if( ! strcasecmp(req->headers[i], "Accept") )
setenv("HTTP_ACCEPT", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "Accept-Charset") )
setenv("HTTP_ACCEPT_CHARSET", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "Accept-Encoding") )
setenv("HTTP_ACCEPT_ENCODING", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "Accept-Language") )
setenv("HTTP_ACCEPT_LANGUAGE", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "Authorization") )
setenv("HTTP_AUTHORIZATION", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "Connection") )
setenv("HTTP_CONNECTION", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "Cookie") )
setenv("HTTP_COOKIE", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "Host") )
setenv("HTTP_HOST", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "Referer") )
setenv("HTTP_REFERER", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "User-Agent") )
setenv("HTTP_USER_AGENT", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "Content-Type") )
setenv("CONTENT_TYPE", req->headers[i+1], 1);
else if( ! strcasecmp(req->headers[i], "Content-Length") )
setenv("CONTENT_LENGTH", req->headers[i+1], 1);
}
/* execute child code ... */
if( chdir(pi->root) )
perror("chdir()");
execl(pi->phys, pi->phys, NULL);
/* in case it fails ... */
printf(
"Status: 500 Internal Server Error\r\n\r\n"
"Unable to launch the requested CGI program:\n"
" %s: %s\n",
pi->phys, strerror(errno)
);
}
/* 403 */
else
{
printf(
"Status: 403 Forbidden\r\n\r\n"
"Access to this resource is forbidden\n"
);
}
close(wfd[0]);
close(rfd[1]);
exit(0);
break;
/* parent; handle I/O relaying */
default:
/* close unneeded pipe ends */
close(rfd[1]);
close(wfd[0]);
/* max watch fd */
fd_max = max(rfd[0], wfd[1]) + 1;
/* find content length */
if( req->method == UH_HTTP_MSG_POST )
{
foreach_header(i, req->headers)
{
if( ! strcasecmp(req->headers[i], "Content-Length") )
{
content_length = atoi(req->headers[i+1]);
break;
}
}
}
memset(hdr, 0, sizeof(hdr));
#define ensure(x) \
do { if( x < 0 ) goto out; } while(0)
/* I/O loop, watch our pipe ends and dispatch child reads/writes from/to socket */
while( 1 )
{
FD_ZERO(&reader);
FD_ZERO(&writer);
FD_SET(rfd[0], &reader);
FD_SET(wfd[1], &writer);
timeout.tv_sec = 15;
timeout.tv_usec = 0;
/* wait until we can read or write or both */
if( select(fd_max, &reader, (content_length > -1) ? &writer : NULL, NULL, &timeout) > 0 )
{
/* ready to write to cgi program */
if( FD_ISSET(wfd[1], &writer) )
{
/* there is unread post data waiting */
if( content_length > 0 )
{
/* read it from socket ... */
if( (buflen = uh_tcp_recv(cl, buf, min(content_length, sizeof(buf)))) > 0 )
{
/* ... and write it to child's stdin */
if( write(wfd[1], buf, buflen) < 0 )
perror("write()");
content_length -= buflen;
}
/* unexpected eof! */
else
{
if( write(wfd[1], "", 0) < 0 )
perror("write()");
content_length = 0;
}
}
/* there is no more post data, close pipe to child's stdin */
else if( content_length > -1 )
{
close(wfd[1]);
content_length = -1;
}
}
/* ready to read from cgi program */
if( FD_ISSET(rfd[0], &reader) )
{
/* read data from child ... */
if( (buflen = read(rfd[0], buf, sizeof(buf))) > 0 )
{
/* we have not pushed out headers yet, parse input */
if( ! header_sent )
{
/* head buffer not full and no end yet */
if( hdrlen < sizeof(hdr) )
{
bufoff = min(buflen, sizeof(hdr) - hdrlen);
memcpy(&hdr[hdrlen], buf, bufoff);
hdrlen += bufoff;
}
else
{
bufoff = 0;
}
/* try to parse header ... */
if( (res = uh_cgi_header_parse(hdr, hdrlen, &hdroff)) != NULL )
{
/* write status */
ensure(uh_http_sendf(cl, NULL,
"HTTP/%.1f %03d %s\r\n"
"Connection: close\r\n",
req->version, res->statuscode,
res->statusmsg));
/* add Content-Type if no Location or Content-Type */
if( !uh_cgi_header_lookup(res, "Location") &&
!uh_cgi_header_lookup(res, "Content-Type")
) {
ensure(uh_http_send(cl, NULL,
"Content-Type: text/plain\r\n", -1));
}
/* if request was HTTP 1.1 we'll respond chunked */
if( (req->version > 1.0) &&
!uh_cgi_header_lookup(res, "Transfer-Encoding")
) {
ensure(uh_http_send(cl, NULL,
"Transfer-Encoding: chunked\r\n", -1));
}
/* write headers from CGI program */
foreach_header(i, res->headers)
{
ensure(uh_http_sendf(cl, NULL, "%s: %s\r\n",
res->headers[i], res->headers[i+1]));
}
/* terminate header */
ensure(uh_http_send(cl, NULL, "\r\n", -1));
/* push out remaining head buffer */
if( hdroff < hdrlen )
ensure(uh_http_send(cl, req, &hdr[hdroff], hdrlen - hdroff));
}
/* ... failed and head buffer exceeded */
else if( hdrlen >= sizeof(hdr) )
{
ensure(uh_cgi_error_500(cl, req,
"The CGI program generated an invalid response:\n\n"));
ensure(uh_http_send(cl, req, hdr, hdrlen));
}
/* ... failed but free buffer space, try again */
else
{
continue;
}
/* push out remaining read buffer */
if( bufoff < buflen )
ensure(uh_http_send(cl, req, &buf[bufoff], buflen - bufoff));
header_sent = 1;
continue;
}
/* headers complete, pass through buffer to socket */
ensure(uh_http_send(cl, req, buf, buflen));
}
/* looks like eof from child */
else
{
/* cgi script did not output useful stuff at all */
if( ! header_sent )
{
/* I would do this ...
*
* uh_cgi_error_500(cl, req,
* "The CGI program generated an "
* "invalid response:\n\n");
*
* ... but in order to stay as compatible as possible,
* treat whatever we got as text/plain response and
* build the required headers here.
*/
ensure(uh_http_sendf(cl, NULL,
"HTTP/%.1f 200 OK\r\n"
"Content-Type: text/plain\r\n"
"%s\r\n",
req->version, (req->version > 1.0)
? "Transfer-Encoding: chunked\r\n" : ""
));
ensure(uh_http_send(cl, req, hdr, hdrlen));
}
/* send final chunk if we're in chunked transfer mode */
ensure(uh_http_send(cl, req, "", 0));
break;
}
}
}
/* no activity for 15 seconds... looks dead */
else
{
ensure(uh_http_sendhf(cl, 504, "Gateway Timeout",
"The CGI script took too long to produce a response"));
break;
}
}
out:
close(rfd[0]);
close(wfd[1]);
if( !kill(child, 0) )
kill(child, SIGTERM);
break;
}
}

View file

@ -1,31 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - CGI header
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _UHTTPD_CGI_
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/limits.h>
void uh_cgi_request(
struct client *cl, struct http_request *req, struct path_info *pi
);
#endif

View file

@ -1,395 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - Static file handler
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define _XOPEN_SOURCE 500 /* strptime() */
#define _BSD_SOURCE /* scandir(), timegm() */
#include "uhttpd.h"
#include "uhttpd-utils.h"
#include "uhttpd-file.h"
#include "uhttpd-mimetypes.h"
static const char * uh_file_mime_lookup(const char *path)
{
struct mimetype *m = &uh_mime_types[0];
char *p, *pd, *ps;
ps = strrchr(path, '/');
pd = strrchr(path, '.');
/* use either slash or dot as separator, whatever comes last */
p = (ps && pd && (ps > pd)) ? ps : pd;
if( (p != NULL) && (*(++p) != 0) )
{
while( m->extn )
{
if( ! strcasecmp(p, m->extn) )
return m->mime;
m++;
}
}
return "application/octet-stream";
}
static const char * uh_file_mktag(struct stat *s)
{
static char tag[128];
snprintf(tag, sizeof(tag), "\"%x-%x-%x\"",
(unsigned int) s->st_ino,
(unsigned int) s->st_size,
(unsigned int) s->st_mtime
);
return tag;
}
static time_t uh_file_date2unix(const char *date)
{
struct tm t;
memset(&t, 0, sizeof(t));
if( strptime(date, "%a, %d %b %Y %H:%M:%S %Z", &t) != NULL )
return timegm(&t);
return 0;
}
static char * uh_file_unix2date(time_t ts)
{
static char str[128];
struct tm *t = gmtime(&ts);
strftime(str, sizeof(str), "%a, %d %b %Y %H:%M:%S GMT", t);
return str;
}
static char * uh_file_header_lookup(struct http_request *req, const char *name)
{
int i;
foreach_header(i, req->headers)
{
if( ! strcasecmp(req->headers[i], name) )
return req->headers[i+1];
}
return NULL;
}
static void uh_file_response_ok_hdrs(struct client *cl, struct http_request *req, struct stat *s)
{
uh_http_sendf(cl, NULL, "Connection: close\r\n");
if( s )
{
uh_http_sendf(cl, NULL, "ETag: %s\r\n", uh_file_mktag(s));
uh_http_sendf(cl, NULL, "Last-Modified: %s\r\n", uh_file_unix2date(s->st_mtime));
}
uh_http_sendf(cl, NULL, "Date: %s\r\n", uh_file_unix2date(time(NULL)));
}
static void uh_file_response_200(struct client *cl, struct http_request *req, struct stat *s)
{
uh_http_sendf(cl, NULL, "HTTP/%.1f 200 OK\r\n", req->version);
uh_file_response_ok_hdrs(cl, req, s);
}
static void uh_file_response_304(struct client *cl, struct http_request *req, struct stat *s)
{
uh_http_sendf(cl, NULL, "HTTP/%.1f 304 Not Modified\r\n", req->version);
uh_file_response_ok_hdrs(cl, req, s);
}
static void uh_file_response_412(struct client *cl, struct http_request *req)
{
uh_http_sendf(cl, NULL,
"HTTP/%.1f 412 Precondition Failed\r\n"
"Connection: close\r\n", req->version);
}
static int uh_file_if_match(struct client *cl, struct http_request *req, struct stat *s)
{
const char *tag = uh_file_mktag(s);
char *hdr = uh_file_header_lookup(req, "If-Match");
char *p;
int i;
if( hdr )
{
p = &hdr[0];
for( i = 0; i < strlen(hdr); i++ )
{
if( (hdr[i] == ' ') || (hdr[i] == ',') )
{
hdr[i++] = 0;
p = &hdr[i];
}
else if( !strcmp(p, "*") || !strcmp(p, tag) )
{
return 1;
}
}
uh_file_response_412(cl, req);
return 0;
}
return 1;
}
static int uh_file_if_modified_since(struct client *cl, struct http_request *req, struct stat *s)
{
char *hdr = uh_file_header_lookup(req, "If-Modified-Since");
if( hdr )
{
if( uh_file_date2unix(hdr) < s->st_mtime )
{
return 1;
}
else
{
uh_file_response_304(cl, req, s);
return 0;
}
}
return 1;
}
static int uh_file_if_none_match(struct client *cl, struct http_request *req, struct stat *s)
{
const char *tag = uh_file_mktag(s);
char *hdr = uh_file_header_lookup(req, "If-None-Match");
char *p;
int i;
if( hdr )
{
p = &hdr[0];
for( i = 0; i < strlen(hdr); i++ )
{
if( (hdr[i] == ' ') || (hdr[i] == ',') )
{
hdr[i++] = 0;
p = &hdr[i];
}
else if( !strcmp(p, "*") || !strcmp(p, tag) )
{
if( (req->method == UH_HTTP_MSG_GET) ||
(req->method == UH_HTTP_MSG_HEAD) )
uh_file_response_304(cl, req, s);
else
uh_file_response_412(cl, req);
return 0;
}
}
}
return 1;
}
static int uh_file_if_range(struct client *cl, struct http_request *req, struct stat *s)
{
char *hdr = uh_file_header_lookup(req, "If-Range");
if( hdr )
{
uh_file_response_412(cl, req);
return 0;
}
return 1;
}
static int uh_file_if_unmodified_since(struct client *cl, struct http_request *req, struct stat *s)
{
char *hdr = uh_file_header_lookup(req, "If-Unmodified-Since");
if( hdr )
{
if( uh_file_date2unix(hdr) <= s->st_mtime )
{
uh_file_response_412(cl, req);
return 0;
}
}
return 1;
}
static int uh_file_scandir_filter_dir(const struct dirent *e)
{
return strcmp(e->d_name, ".") ? 1 : 0;
}
static void uh_file_dirlist(struct client *cl, struct http_request *req, struct path_info *pi)
{
int i, count;
char filename[PATH_MAX];
char *pathptr;
struct dirent **files = NULL;
struct stat s;
uh_http_sendf(cl, req,
"<html><head><title>Index of %s</title></head>"
"<body><h1>Index of %s</h1><hr /><ol>",
pi->name, pi->name
);
if( (count = scandir(pi->phys, &files, uh_file_scandir_filter_dir, alphasort)) > 0 )
{
memset(filename, 0, sizeof(filename));
memcpy(filename, pi->phys, sizeof(filename));
pathptr = &filename[strlen(filename)];
/* list subdirs */
for( i = 0; i < count; i++ )
{
strncat(filename, files[i]->d_name,
sizeof(filename) - strlen(files[i]->d_name));
if( !stat(filename, &s) && (s.st_mode & S_IFDIR) )
uh_http_sendf(cl, req,
"<li><strong><a href='%s%s'>%s</a>/</strong><br />"
"<small>modified: %s<br />directory - %.02f kbyte"
"<br /><br /></small></li>",
pi->name, files[i]->d_name, files[i]->d_name,
uh_file_unix2date(s.st_mtime), s.st_size / 1024.0
);
*pathptr = 0;
}
/* list files */
for( i = 0; i < count; i++ )
{
strncat(filename, files[i]->d_name,
sizeof(filename) - strlen(files[i]->d_name));
if( !stat(filename, &s) && !(s.st_mode & S_IFDIR) )
uh_http_sendf(cl, req,
"<li><strong><a href='%s%s'>%s</a></strong><br />"
"<small>modified: %s<br />%s - %.02f kbyte<br />"
"<br /></small></li>",
pi->name, files[i]->d_name, files[i]->d_name,
uh_file_unix2date(s.st_mtime),
uh_file_mime_lookup(filename), s.st_size / 1024.0
);
*pathptr = 0;
free(files[i]);
}
}
free(files);
uh_http_sendf(cl, req, "</ol><hr /></body></html>");
uh_http_sendf(cl, req, "");
}
void uh_file_request(struct client *cl, struct http_request *req, struct path_info *pi)
{
int fd, rlen;
char buf[UH_LIMIT_MSGHEAD];
/* we have a file */
if( (pi->stat.st_mode & S_IFREG) && ((fd = open(pi->phys, O_RDONLY)) > 0) )
{
/* test preconditions */
if(
uh_file_if_modified_since(cl, req, &pi->stat) &&
uh_file_if_match(cl, req, &pi->stat) &&
uh_file_if_range(cl, req, &pi->stat) &&
uh_file_if_unmodified_since(cl, req, &pi->stat) &&
uh_file_if_none_match(cl, req, &pi->stat)
) {
/* write status */
uh_file_response_200(cl, req, &pi->stat);
uh_http_sendf(cl, NULL, "Content-Type: %s\r\n", uh_file_mime_lookup(pi->name));
uh_http_sendf(cl, NULL, "Content-Length: %i\r\n", pi->stat.st_size);
/* if request was HTTP 1.1 we'll respond chunked */
if( (req->version > 1.0) && (req->method != UH_HTTP_MSG_HEAD) )
uh_http_send(cl, NULL, "Transfer-Encoding: chunked\r\n", -1);
/* close header */
uh_http_send(cl, NULL, "\r\n", -1);
/* send body */
if( req->method != UH_HTTP_MSG_HEAD )
{
/* pump file data */
while( (rlen = read(fd, buf, sizeof(buf))) > 0 )
{
if( uh_http_send(cl, req, buf, rlen) < 0 )
break;
}
/* send trailer in chunked mode */
uh_http_send(cl, req, "", 0);
}
}
/* one of the preconditions failed, terminate opened header and exit */
else
{
uh_http_send(cl, NULL, "\r\n", -1);
}
close(fd);
}
/* directory */
else if( pi->stat.st_mode & S_IFDIR )
{
/* write status */
uh_file_response_200(cl, req, NULL);
if( req->version > 1.0 )
uh_http_send(cl, NULL, "Transfer-Encoding: chunked\r\n", -1);
uh_http_send(cl, NULL, "Content-Type: text/html\r\n\r\n", -1);
/* content */
uh_file_dirlist(cl, req, pi);
}
/* 403 */
else
{
uh_http_sendhf(cl, 403, "Forbidden",
"Access to this resource is forbidden");
}
}

View file

@ -1,38 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - Static file header
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _UHTTPD_FILE_
#include <fcntl.h>
#include <time.h>
#include <strings.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/limits.h>
struct mimetype {
const char *extn;
const char *mime;
};
void uh_file_request(
struct client *cl, struct http_request *req, struct path_info *pi
);
#endif

View file

@ -1,541 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - Lua handler
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "uhttpd.h"
#include "uhttpd-utils.h"
#include "uhttpd-lua.h"
static int uh_lua_recv(lua_State *L)
{
size_t length;
char buffer[UH_LIMIT_MSGHEAD];
ssize_t rlen = 0;
fd_set reader;
struct timeval timeout;
length = luaL_checknumber(L, 1);
if( (length > 0) && (length <= sizeof(buffer)) )
{
FD_ZERO(&reader);
FD_SET(fileno(stdin), &reader);
/* fail after 0.1s */
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
/* check whether fd is readable */
if( select(fileno(stdin) + 1, &reader, NULL, NULL, &timeout) > 0 )
{
/* receive data */
rlen = read(fileno(stdin), buffer, length);
lua_pushnumber(L, rlen);
if( rlen > 0 )
{
lua_pushlstring(L, buffer, rlen);
return 2;
}
return 1;
}
/* no, timeout and actually no data */
lua_pushnumber(L, -2);
return 1;
}
/* parameter error */
lua_pushnumber(L, -3);
return 1;
}
static int uh_lua_send_common(lua_State *L, int chunked)
{
size_t length;
const char *buffer;
char chunk[16];
ssize_t slen = 0;
buffer = luaL_checklstring(L, 1, &length);
if( chunked )
{
if( length > 0 )
{
snprintf(chunk, sizeof(chunk), "%X\r\n", length);
slen = write(fileno(stdout), chunk, strlen(chunk));
slen += write(fileno(stdout), buffer, length);
slen += write(fileno(stdout), "\r\n", 2);
}
else
{
slen = write(fileno(stdout), "0\r\n\r\n", 5);
}
}
else
{
slen = write(fileno(stdout), buffer, length);
}
lua_pushnumber(L, slen);
return 1;
}
static int uh_lua_send(lua_State *L)
{
return uh_lua_send_common(L, 0);
}
static int uh_lua_sendc(lua_State *L)
{
return uh_lua_send_common(L, 1);
}
static int uh_lua_urldecode(lua_State *L)
{
size_t inlen, outlen;
const char *inbuf;
char outbuf[UH_LIMIT_MSGHEAD];
inbuf = luaL_checklstring(L, 1, &inlen);
outlen = uh_urldecode(outbuf, sizeof(outbuf), inbuf, inlen);
lua_pushlstring(L, outbuf, outlen);
return 1;
}
lua_State * uh_lua_init(const char *handler)
{
lua_State *L = lua_open();
const char *err_str = NULL;
/* Load standard libaries */
luaL_openlibs(L);
/* build uhttpd api table */
lua_newtable(L);
/* register global send and receive functions */
lua_pushcfunction(L, uh_lua_recv);
lua_setfield(L, -2, "recv");
lua_pushcfunction(L, uh_lua_send);
lua_setfield(L, -2, "send");
lua_pushcfunction(L, uh_lua_sendc);
lua_setfield(L, -2, "sendc");
lua_pushcfunction(L, uh_lua_urldecode);
lua_setfield(L, -2, "urldecode");
/* _G.uhttpd = { ... } */
lua_setfield(L, LUA_GLOBALSINDEX, "uhttpd");
/* load Lua handler */
switch( luaL_loadfile(L, handler) )
{
case LUA_ERRSYNTAX:
fprintf(stderr,
"Lua handler contains syntax errors, unable to continue\n");
exit(1);
case LUA_ERRMEM:
fprintf(stderr,
"Lua handler ran out of memory, unable to continue\n");
exit(1);
case LUA_ERRFILE:
fprintf(stderr,
"Lua cannot open the handler script, unable to continue\n");
exit(1);
default:
/* compile Lua handler */
switch( lua_pcall(L, 0, 0, 0) )
{
case LUA_ERRRUN:
err_str = luaL_checkstring(L, -1);
fprintf(stderr,
"Lua handler had runtime error, unable to continue\n"
"Error: %s\n", err_str
);
exit(1);
case LUA_ERRMEM:
err_str = luaL_checkstring(L, -1);
fprintf(stderr,
"Lua handler ran out of memory, unable to continue\n"
"Error: %s\n", err_str
);
exit(1);
default:
/* test handler function */
lua_getglobal(L, UH_LUA_CALLBACK);
if( ! lua_isfunction(L, -1) )
{
fprintf(stderr,
"Lua handler provides no " UH_LUA_CALLBACK "(), unable to continue\n");
exit(1);
}
lua_pop(L, 1);
break;
}
break;
}
return L;
}
void uh_lua_request(struct client *cl, struct http_request *req, lua_State *L)
{
int i, data_sent;
int content_length = 0;
int buflen = 0;
int fd_max = 0;
char *query_string;
const char *prefix = cl->server->conf->lua_prefix;
const char *err_str = NULL;
int rfd[2] = { 0, 0 };
int wfd[2] = { 0, 0 };
char buf[UH_LIMIT_MSGHEAD];
pid_t child;
fd_set reader;
fd_set writer;
struct sigaction sa;
struct timeval timeout;
/* spawn pipes for me->child, child->me */
if( (pipe(rfd) < 0) || (pipe(wfd) < 0) )
{
uh_http_sendhf(cl, 500, "Internal Server Error",
"Failed to create pipe: %s", strerror(errno));
if( rfd[0] > 0 ) close(rfd[0]);
if( rfd[1] > 0 ) close(rfd[1]);
if( wfd[0] > 0 ) close(wfd[0]);
if( wfd[1] > 0 ) close(wfd[1]);
return;
}
switch( (child = fork()) )
{
case -1:
uh_http_sendhf(cl, 500, "Internal Server Error",
"Failed to fork child: %s", strerror(errno));
break;
case 0:
/* restore SIGTERM */
sa.sa_flags = 0;
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
sigaction(SIGTERM, &sa, NULL);
/* close loose pipe ends */
close(rfd[0]);
close(wfd[1]);
/* patch stdout and stdin to pipes */
dup2(rfd[1], 1);
dup2(wfd[0], 0);
/* put handler callback on stack */
lua_getglobal(L, UH_LUA_CALLBACK);
/* build env table */
lua_newtable(L);
/* request method */
switch(req->method)
{
case UH_HTTP_MSG_GET:
lua_pushstring(L, "GET");
break;
case UH_HTTP_MSG_HEAD:
lua_pushstring(L, "HEAD");
break;
case UH_HTTP_MSG_POST:
lua_pushstring(L, "POST");
break;
}
lua_setfield(L, -2, "REQUEST_METHOD");
/* request url */
lua_pushstring(L, req->url);
lua_setfield(L, -2, "REQUEST_URI");
/* script name */
lua_pushstring(L, cl->server->conf->lua_prefix);
lua_setfield(L, -2, "SCRIPT_NAME");
/* query string, path info */
if( (query_string = strchr(req->url, '?')) != NULL )
{
lua_pushstring(L, query_string + 1);
lua_setfield(L, -2, "QUERY_STRING");
if( (int)(query_string - req->url) > strlen(prefix) )
{
lua_pushlstring(L,
&req->url[strlen(prefix)],
(int)(query_string - req->url) - strlen(prefix)
);
lua_setfield(L, -2, "PATH_INFO");
}
}
else if( strlen(req->url) > strlen(prefix) )
{
lua_pushstring(L, &req->url[strlen(prefix)]);
lua_setfield(L, -2, "PATH_INFO");
}
/* http protcol version */
lua_pushnumber(L, floor(req->version * 10) / 10);
lua_setfield(L, -2, "HTTP_VERSION");
if( req->version > 1.0 )
lua_pushstring(L, "HTTP/1.1");
else
lua_pushstring(L, "HTTP/1.0");
lua_setfield(L, -2, "SERVER_PROTOCOL");
/* address information */
lua_pushstring(L, sa_straddr(&cl->peeraddr));
lua_setfield(L, -2, "REMOTE_ADDR");
lua_pushinteger(L, sa_port(&cl->peeraddr));
lua_setfield(L, -2, "REMOTE_PORT");
lua_pushstring(L, sa_straddr(&cl->servaddr));
lua_setfield(L, -2, "SERVER_ADDR");
lua_pushinteger(L, sa_port(&cl->servaddr));
lua_setfield(L, -2, "SERVER_PORT");
/* essential env vars */
foreach_header(i, req->headers)
{
if( !strcasecmp(req->headers[i], "Content-Length") )
{
lua_pushnumber(L, atoi(req->headers[i+1]));
lua_setfield(L, -2, "CONTENT_LENGTH");
}
else if( !strcasecmp(req->headers[i], "Content-Type") )
{
lua_pushstring(L, req->headers[i+1]);
lua_setfield(L, -2, "CONTENT_TYPE");
}
}
/* misc. headers */
lua_newtable(L);
foreach_header(i, req->headers)
{
if( strcasecmp(req->headers[i], "Content-Length") &&
strcasecmp(req->headers[i], "Content-Type")
) {
lua_pushstring(L, req->headers[i+1]);
lua_setfield(L, -2, req->headers[i]);
}
}
lua_setfield(L, -2, "headers");
/* call */
switch( lua_pcall(L, 1, 0, 0) )
{
case LUA_ERRMEM:
case LUA_ERRRUN:
err_str = luaL_checkstring(L, -1);
if( ! err_str )
err_str = "Unknown error";
printf(
"HTTP/%.1f 500 Internal Server Error\r\n"
"Connection: close\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: %i\r\n\r\n"
"Lua raised a runtime error:\n %s\n",
req->version, 31 + strlen(err_str), err_str
);
break;
default:
break;
}
close(wfd[0]);
close(rfd[1]);
exit(0);
break;
/* parent; handle I/O relaying */
default:
/* close unneeded pipe ends */
close(rfd[1]);
close(wfd[0]);
/* max watch fd */
fd_max = max(rfd[0], wfd[1]) + 1;
/* find content length */
if( req->method == UH_HTTP_MSG_POST )
{
foreach_header(i, req->headers)
{
if( ! strcasecmp(req->headers[i], "Content-Length") )
{
content_length = atoi(req->headers[i+1]);
break;
}
}
}
#define ensure(x) \
do { if( x < 0 ) goto out; } while(0)
data_sent = 0;
/* I/O loop, watch our pipe ends and dispatch child reads/writes from/to socket */
while( 1 )
{
FD_ZERO(&reader);
FD_ZERO(&writer);
FD_SET(rfd[0], &reader);
FD_SET(wfd[1], &writer);
timeout.tv_sec = 15;
timeout.tv_usec = 0;
/* wait until we can read or write or both */
if( select(fd_max, &reader, (content_length > -1) ? &writer : NULL, NULL, &timeout) > 0 )
{
/* ready to write to Lua child */
if( FD_ISSET(wfd[1], &writer) )
{
/* there is unread post data waiting */
if( content_length > 0 )
{
/* read it from socket ... */
if( (buflen = uh_tcp_recv(cl, buf, min(content_length, sizeof(buf)))) > 0 )
{
/* ... and write it to child's stdin */
if( write(wfd[1], buf, buflen) < 0 )
perror("write()");
content_length -= buflen;
}
/* unexpected eof! */
else
{
if( write(wfd[1], "", 0) < 0 )
perror("write()");
content_length = 0;
}
}
/* there is no more post data, close pipe to child's stdin */
else if( content_length > -1 )
{
close(wfd[1]);
content_length = -1;
}
}
/* ready to read from Lua child */
if( FD_ISSET(rfd[0], &reader) )
{
/* read data from child ... */
if( (buflen = read(rfd[0], buf, sizeof(buf))) > 0 )
{
/* pass through buffer to socket */
ensure(uh_tcp_send(cl, buf, buflen));
data_sent = 1;
}
/* looks like eof from child */
else
{
/* error? */
if( ! data_sent )
uh_http_sendhf(cl, 500, "Internal Server Error",
"The Lua child did not produce any response");
break;
}
}
}
/* no activity for 15 seconds... looks dead */
else
{
ensure(uh_http_sendhf(cl, 504, "Gateway Timeout",
"The Lua handler took too long to produce a response"));
break;
}
}
out:
close(rfd[0]);
close(wfd[1]);
if( !kill(child, 0) )
kill(child, SIGTERM);
break;
}
}
void uh_lua_close(lua_State *L)
{
lua_close(L);
}

View file

@ -1,43 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - Lua header
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _UHTTPD_LUA_
#include <math.h> /* floor() */
#include <errno.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#define UH_LUA_CALLBACK "handle_request"
#define UH_LUA_ERR_TIMEOUT -1
#define UH_LUA_ERR_TOOBIG -2
#define UH_LUA_ERR_PARAM -3
lua_State * uh_lua_init();
void uh_lua_request(
struct client *cl, struct http_request *req, lua_State *L
);
void uh_lua_close(lua_State *L);
#endif

View file

@ -1,80 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - MIME type definitions
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _UHTTPD_MIMETYPES_
static struct mimetype uh_mime_types[] = {
{ "txt", "text/plain" },
{ "log", "text/plain" },
{ "js", "text/javascript" },
{ "css", "text/css" },
{ "htm", "text/html" },
{ "html", "text/html" },
{ "diff", "text/x-patch" },
{ "patch", "text/x-patch" },
{ "c", "text/x-csrc" },
{ "h", "text/x-chdr" },
{ "o", "text/x-object" },
{ "ko", "text/x-object" },
{ "bmp", "image/bmp" },
{ "gif", "image/gif" },
{ "png", "image/png" },
{ "jpg", "image/jpeg" },
{ "jpeg", "image/jpeg" },
{ "svg", "image/svg+xml" },
{ "zip", "application/zip" },
{ "pdf", "application/pdf" },
{ "xml", "application/xml" },
{ "xsl", "application/xml" },
{ "doc", "application/msword" },
{ "ppt", "application/vnd.ms-powerpoint" },
{ "xls", "application/vnd.ms-excel" },
{ "odt", "application/vnd.oasis.opendocument.text" },
{ "odp", "application/vnd.oasis.opendocument.presentation" },
{ "pl", "application/x-perl" },
{ "sh", "application/x-shellscript" },
{ "php", "application/x-php" },
{ "deb", "application/x-deb" },
{ "iso", "application/x-cd-image" },
{ "tgz", "application/x-compressed-tar" },
{ "gz", "application/x-gzip" },
{ "bz2", "application/x-bzip" },
{ "tar", "application/x-tar" },
{ "rar", "application/x-rar-compressed" },
{ "mp3", "audio/mpeg" },
{ "ogg", "audio/x-vorbis+ogg" },
{ "wav", "audio/x-wav" },
{ "mpg", "video/mpeg" },
{ "mpeg", "video/mpeg" },
{ "avi", "video/x-msvideo" },
{ "README", "text/plain" },
{ "log", "text/plain" },
{ "cfg", "text/plain" },
{ "conf", "text/plain" },
{ NULL, NULL }
};
#endif

View file

@ -1,82 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - TLS helper
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "uhttpd.h"
#include "uhttpd-tls.h"
#include "uhttpd-utils.h"
SSL_CTX * uh_tls_ctx_init()
{
SSL_CTX *c = NULL;
SSL_load_error_strings();
SSL_library_init();
if( (c = SSL_CTX_new(TLSv1_server_method())) != NULL )
SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
return c;
}
int uh_tls_ctx_cert(SSL_CTX *c, const char *file)
{
return SSL_CTX_use_certificate_file(c, file, SSL_FILETYPE_ASN1);
}
int uh_tls_ctx_key(SSL_CTX *c, const char *file)
{
return SSL_CTX_use_PrivateKey_file(c, file, SSL_FILETYPE_ASN1);
}
void uh_tls_ctx_free(struct listener *l)
{
SSL_CTX_free(l->tls);
}
void uh_tls_client_accept(struct client *c)
{
if( c->server && c->server->tls )
{
c->tls = SSL_new(c->server->tls);
SSL_set_fd(c->tls, c->socket);
}
}
int uh_tls_client_recv(struct client *c, void *buf, int len)
{
return SSL_read(c->tls, buf, len);
}
int uh_tls_client_send(struct client *c, void *buf, int len)
{
return SSL_write(c->tls, buf, len);
}
void uh_tls_client_close(struct client *c)
{
if( c->tls )
{
SSL_shutdown(c->tls);
SSL_free(c->tls);
c->tls = NULL;
}
}

View file

@ -1,35 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - TLS header
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _UHTTPD_TLS_
#include <openssl/ssl.h>
SSL_CTX * uh_tls_ctx_init();
int uh_tls_ctx_cert(SSL_CTX *c, const char *file);
int uh_tls_ctx_key(SSL_CTX *c, const char *file);
void uh_tls_ctx_free(struct listener *l);
void uh_tls_client_accept(struct client *c);
int uh_tls_client_recv(struct client *c, void *buf, int len);
int uh_tls_client_send(struct client *c, void *buf, int len);
void uh_tls_client_close(struct client *c);
#endif

View file

@ -1,749 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - Utility functions
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define _XOPEN_SOURCE 500 /* crypt() */
#define _BSD_SOURCE /* strcasecmp(), strncasecmp() */
#include "uhttpd.h"
#include "uhttpd-utils.h"
#ifdef HAVE_TLS
#include "uhttpd-tls.h"
#endif
static char *uh_index_files[] = {
"index.html",
"index.htm",
"default.html",
"default.htm"
};
const char * sa_straddr(void *sa)
{
static char str[INET6_ADDRSTRLEN];
struct sockaddr_in *v4 = (struct sockaddr_in *)sa;
struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)sa;
if( v4->sin_family == AF_INET )
return inet_ntop(AF_INET, &(v4->sin_addr), str, sizeof(str));
else
return inet_ntop(AF_INET6, &(v6->sin6_addr), str, sizeof(str));
}
const char * sa_strport(void *sa)
{
static char str[6];
snprintf(str, sizeof(str), "%i", sa_port(sa));
return str;
}
int sa_port(void *sa)
{
return ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
}
/* Simple strstr() like function that takes len arguments for both haystack and needle. */
char *strfind(char *haystack, int hslen, const char *needle, int ndlen)
{
int match = 0;
int i, j;
for( i = 0; i < hslen; i++ )
{
if( haystack[i] == needle[0] )
{
match = ((ndlen == 1) || ((i + ndlen) <= hslen));
for( j = 1; (j < ndlen) && ((i + j) < hslen); j++ )
{
if( haystack[i+j] != needle[j] )
{
match = 0;
break;
}
}
if( match )
return &haystack[i];
}
}
return NULL;
}
int uh_tcp_send(struct client *cl, const char *buf, int len)
{
fd_set writer;
struct timeval timeout;
FD_ZERO(&writer);
FD_SET(cl->socket, &writer);
timeout.tv_sec = 0;
timeout.tv_usec = 500000;
if( select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0 )
{
#ifdef HAVE_TLS
if( cl->tls )
return cl->server->conf->tls_send(cl, (void *)buf, len);
else
#endif
return send(cl->socket, buf, len, 0);
}
return -1;
}
int uh_tcp_peek(struct client *cl, char *buf, int len)
{
int sz = uh_tcp_recv(cl, buf, len);
/* store received data in peek buffer */
if( sz > 0 )
{
cl->peeklen = sz;
memcpy(cl->peekbuf, buf, sz);
}
return sz;
}
int uh_tcp_recv(struct client *cl, char *buf, int len)
{
int sz = 0;
int rsz = 0;
/* first serve data from peek buffer */
if( cl->peeklen > 0 )
{
sz = min(cl->peeklen, len);
len -= sz; cl->peeklen -= sz;
memcpy(buf, cl->peekbuf, sz);
memmove(cl->peekbuf, &cl->peekbuf[sz], cl->peeklen);
}
/* caller wants more */
if( len > 0 )
{
#ifdef HAVE_TLS
if( cl->tls )
rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
else
#endif
rsz = recv(cl->socket, (void *)&buf[sz], len, 0);
if( (sz == 0) || (rsz > 0) )
sz += rsz;
}
return sz;
}
#define ensure(x) \
do { if( x < 0 ) return -1; } while(0)
int uh_http_sendhf(struct client *cl, int code, const char *summary, const char *fmt, ...)
{
va_list ap;
char buffer[UH_LIMIT_MSGHEAD];
int len;
len = snprintf(buffer, sizeof(buffer),
"HTTP/1.1 %03i %s\r\n"
"Connection: close\r\n"
"Content-Type: text/plain\r\n"
"Transfer-Encoding: chunked\r\n\r\n",
code, summary
);
ensure(uh_tcp_send(cl, buffer, len));
va_start(ap, fmt);
len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
ensure(uh_http_sendc(cl, buffer, len));
ensure(uh_http_sendc(cl, NULL, 0));
return 0;
}
int uh_http_sendc(struct client *cl, const char *data, int len)
{
char chunk[8];
int clen;
if( len == -1 )
len = strlen(data);
if( len > 0 )
{
clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len);
ensure(uh_tcp_send(cl, chunk, clen));
ensure(uh_tcp_send(cl, data, len));
ensure(uh_tcp_send(cl, "\r\n", 2));
}
else
{
ensure(uh_tcp_send(cl, "0\r\n\r\n", 5));
}
return 0;
}
int uh_http_sendf(
struct client *cl, struct http_request *req, const char *fmt, ...
) {
va_list ap;
char buffer[UH_LIMIT_MSGHEAD];
int len;
va_start(ap, fmt);
len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
if( (req != NULL) && (req->version > 1.0) )
ensure(uh_http_sendc(cl, buffer, len));
else if( len > 0 )
ensure(uh_tcp_send(cl, buffer, len));
return 0;
}
int uh_http_send(
struct client *cl, struct http_request *req, const char *buf, int len
) {
if( len < 0 )
len = strlen(buf);
if( (req != NULL) && (req->version > 1.0) )
ensure(uh_http_sendc(cl, buf, len));
else if( len > 0 )
ensure(uh_tcp_send(cl, buf, len));
return 0;
}
int uh_urldecode(char *buf, int blen, const char *src, int slen)
{
int i;
int len = 0;
#define hex(x) \
(((x) <= '9') ? ((x) - '0') : \
(((x) <= 'F') ? ((x) - 'A' + 10) : \
((x) - 'a' + 10)))
for( i = 0; (i <= slen) && (i <= blen); i++ )
{
if( src[i] == '%' )
{
if( ((i+2) <= slen) && isxdigit(src[i+1]) && isxdigit(src[i+2]) )
{
buf[len++] = (char)(16 * hex(src[i+1]) + hex(src[i+2]));
i += 2;
}
else
{
buf[len++] = '%';
}
}
else
{
buf[len++] = src[i];
}
}
return len;
}
int uh_urlencode(char *buf, int blen, const char *src, int slen)
{
int i;
int len = 0;
const char hex[] = "0123456789abcdef";
for( i = 0; (i <= slen) && (i <= blen); i++ )
{
if( isalnum(src[i]) || (src[i] == '-') || (src[i] == '_') ||
(src[i] == '.') || (src[i] == '~') )
{
buf[len++] = src[i];
}
else if( (len+3) <= blen )
{
buf[len++] = '%';
buf[len++] = hex[(src[i] >> 4) & 15];
buf[len++] = hex[(src[i] & 15) & 15];
}
else
{
break;
}
}
return len;
}
int uh_b64decode(char *buf, int blen, const unsigned char *src, int slen)
{
int i = 0;
int len = 0;
unsigned int cin = 0;
unsigned int cout = 0;
for( i = 0; (i <= slen) && (src[i] != 0); i++ )
{
cin = src[i];
if( (cin >= '0') && (cin <= '9') )
cin = cin - '0' + 52;
else if( (cin >= 'A') && (cin <= 'Z') )
cin = cin - 'A';
else if( (cin >= 'a') && (cin <= 'z') )
cin = cin - 'a' + 26;
else if( cin == '+' )
cin = 62;
else if( cin == '/' )
cin = 63;
else if( cin == '=' )
cin = 0;
else
continue;
cout = (cout << 6) | cin;
if( (i % 4) == 3 )
{
if( (len + 3) < blen )
{
buf[len++] = (char)(cout >> 16);
buf[len++] = (char)(cout >> 8);
buf[len++] = (char)(cout);
}
else
{
break;
}
}
}
buf[len++] = 0;
return len;
}
struct path_info * uh_path_lookup(struct client *cl, const char *url)
{
static char path_phys[PATH_MAX];
static char path_info[PATH_MAX];
static struct path_info p;
char buffer[UH_LIMIT_MSGHEAD];
char *docroot = cl->server->conf->docroot;
char *pathptr = NULL;
int i = 0;
struct stat s;
memset(path_phys, 0, sizeof(path_phys));
memset(path_info, 0, sizeof(path_info));
memset(buffer, 0, sizeof(buffer));
memset(&p, 0, sizeof(p));
/* copy docroot */
memcpy(buffer, docroot,
min(strlen(docroot), sizeof(buffer) - 1));
/* separate query string from url */
if( (pathptr = strchr(url, '?')) != NULL )
{
p.query = pathptr[1] ? pathptr + 1 : NULL;
/* urldecode component w/o query */
if( pathptr > url )
uh_urldecode(
&buffer[strlen(docroot)],
sizeof(buffer) - strlen(docroot) - 1,
url, (int)(pathptr - url) - 1
);
}
/* no query string, decode all of url */
else
{
uh_urldecode(
&buffer[strlen(docroot)],
sizeof(buffer) - strlen(docroot) - 1,
url, strlen(url)
);
}
/* create canon path */
for( i = strlen(buffer); i >= 0; i-- )
{
if( (buffer[i] == 0) || (buffer[i] == '/') )
{
memset(path_info, 0, sizeof(path_info));
memcpy(path_info, buffer, min(i + 1, sizeof(path_info) - 1));
if( realpath(path_info, path_phys) )
{
memset(path_info, 0, sizeof(path_info));
memcpy(path_info, &buffer[i],
min(strlen(buffer) - i, sizeof(path_info) - 1));
break;
}
}
}
/* check whether found path is within docroot */
if( strncmp(path_phys, docroot, strlen(docroot)) ||
((path_phys[strlen(docroot)] != 0) &&
(path_phys[strlen(docroot)] != '/'))
) {
return NULL;
}
/* test current path */
if( ! stat(path_phys, &p.stat) )
{
/* is a regular file */
if( p.stat.st_mode & S_IFREG )
{
p.root = docroot;
p.phys = path_phys;
p.name = &path_phys[strlen(docroot)];
p.info = path_info[0] ? path_info : NULL;
}
/* is a directory */
else if( (p.stat.st_mode & S_IFDIR) && !strlen(path_info) )
{
/* ensure trailing slash */
if( path_phys[strlen(path_phys)-1] != '/' )
path_phys[strlen(path_phys)] = '/';
/* try to locate index file */
memset(buffer, 0, sizeof(buffer));
memcpy(buffer, path_phys, sizeof(buffer));
pathptr = &buffer[strlen(buffer)];
for( i = 0; i < array_size(uh_index_files); i++ )
{
strncat(buffer, uh_index_files[i], sizeof(buffer));
if( !stat(buffer, &s) && (s.st_mode & S_IFREG) )
{
memcpy(path_phys, buffer, sizeof(path_phys));
memcpy(&p.stat, &s, sizeof(p.stat));
break;
}
*pathptr = 0;
}
p.root = docroot;
p.phys = path_phys;
p.name = &path_phys[strlen(docroot)];
}
}
return p.phys ? &p : NULL;
}
static char uh_realms[UH_LIMIT_AUTHREALMS * sizeof(struct auth_realm)] = { 0 };
static int uh_realm_count = 0;
struct auth_realm * uh_auth_add(char *path, char *user, char *pass)
{
struct auth_realm *new = NULL;
struct passwd *pwd;
struct spwd *spwd;
if( uh_realm_count < UH_LIMIT_AUTHREALMS )
{
new = (struct auth_realm *)
&uh_realms[uh_realm_count * sizeof(struct auth_realm)];
memset(new, 0, sizeof(struct auth_realm));
memcpy(new->path, path,
min(strlen(path), sizeof(new->path) - 1));
memcpy(new->user, user,
min(strlen(user), sizeof(new->user) - 1));
/* given password refers to a passwd entry */
if( (strlen(pass) > 3) && !strncmp(pass, "$p$", 3) )
{
/* try to resolve shadow entry */
if( ((spwd = getspnam(&pass[3])) != NULL) && spwd->sp_pwdp )
{
memcpy(new->pass, spwd->sp_pwdp,
min(strlen(spwd->sp_pwdp), sizeof(new->pass) - 1));
}
/* try to resolve passwd entry */
else if( ((pwd = getpwnam(&pass[3])) != NULL) && pwd->pw_passwd &&
(pwd->pw_passwd[0] != '!') && (pwd->pw_passwd[0] != 0)
) {
memcpy(new->pass, pwd->pw_passwd,
min(strlen(pwd->pw_passwd), sizeof(new->pass) - 1));
}
}
/* ordinary pwd */
else
{
memcpy(new->pass, pass,
min(strlen(pass), sizeof(new->pass) - 1));
}
uh_realm_count++;
}
return new;
}
int uh_auth_check(
struct client *cl, struct http_request *req, struct path_info *pi
) {
int i, plen, rlen, protected;
char buffer[UH_LIMIT_MSGHEAD];
char *user = NULL;
char *pass = NULL;
struct auth_realm *realm = NULL;
plen = strlen(pi->name);
protected = 0;
/* check whether at least one realm covers the requested url */
for( i = 0; i < uh_realm_count; i++ )
{
realm = (struct auth_realm *)
&uh_realms[i * sizeof(struct auth_realm)];
rlen = strlen(realm->path);
if( (plen >= rlen) && !strncasecmp(pi->name, realm->path, rlen) )
{
req->realm = realm;
protected = 1;
break;
}
}
/* requested resource is covered by a realm */
if( protected )
{
/* try to get client auth info */
foreach_header(i, req->headers)
{
if( !strcasecmp(req->headers[i], "Authorization") &&
(strlen(req->headers[i+1]) > 6) &&
!strncasecmp(req->headers[i+1], "Basic ", 6)
) {
memset(buffer, 0, sizeof(buffer));
uh_b64decode(buffer, sizeof(buffer) - 1,
(unsigned char *) &req->headers[i+1][6],
strlen(req->headers[i+1]) - 6);
if( (pass = strchr(buffer, ':')) != NULL )
{
user = buffer;
*pass++ = 0;
}
break;
}
}
/* have client auth */
if( user && pass )
{
/* find matching realm */
for( i = 0, realm = NULL; i < uh_realm_count; i++ )
{
realm = (struct auth_realm *)
&uh_realms[i * sizeof(struct auth_realm)];
rlen = strlen(realm->path);
if( (plen >= rlen) &&
!strncasecmp(pi->name, realm->path, rlen) &&
!strcmp(user, realm->user)
) {
req->realm = realm;
break;
}
realm = NULL;
}
/* found a realm matching the username */
if( realm )
{
/* is a crypt passwd */
if( realm->pass[0] == '$' )
pass = crypt(pass, realm->pass);
/* check user pass */
if( !strcmp(pass, realm->pass) )
return 1;
}
}
/* 401 */
uh_http_sendf(cl, NULL,
"HTTP/%.1f 401 Authorization Required\r\n"
"WWW-Authenticate: Basic realm=\"%s\"\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 23\r\n\r\n"
"Authorization Required\n",
req->version, cl->server->conf->realm
);
return 0;
}
return 1;
}
static char uh_listeners[UH_LIMIT_LISTENERS * sizeof(struct listener)] = { 0 };
static char uh_clients[UH_LIMIT_CLIENTS * sizeof(struct client)] = { 0 };
static int uh_listener_count = 0;
static int uh_client_count = 0;
struct listener * uh_listener_add(int sock, struct config *conf)
{
struct listener *new = NULL;
socklen_t sl;
if( uh_listener_count < UH_LIMIT_LISTENERS )
{
new = (struct listener *)
&uh_listeners[uh_listener_count * sizeof(struct listener)];
new->socket = sock;
new->conf = conf;
/* get local endpoint addr */
sl = sizeof(struct sockaddr_in6);
memset(&(new->addr), 0, sl);
getsockname(sock, (struct sockaddr *) &(new->addr), &sl);
uh_listener_count++;
}
return new;
}
struct listener * uh_listener_lookup(int sock)
{
struct listener *cur = NULL;
int i;
for( i = 0; i < uh_listener_count; i++ )
{
cur = (struct listener *) &uh_listeners[i * sizeof(struct listener)];
if( cur->socket == sock )
return cur;
}
return NULL;
}
struct client * uh_client_add(int sock, struct listener *serv)
{
struct client *new = NULL;
socklen_t sl;
if( uh_client_count < UH_LIMIT_CLIENTS )
{
new = (struct client *)
&uh_clients[uh_client_count * sizeof(struct client)];
new->socket = sock;
new->server = serv;
/* get remote endpoint addr */
sl = sizeof(struct sockaddr_in6);
memset(&(new->peeraddr), 0, sl);
getpeername(sock, (struct sockaddr *) &(new->peeraddr), &sl);
/* get local endpoint addr */
sl = sizeof(struct sockaddr_in6);
memset(&(new->servaddr), 0, sl);
getsockname(sock, (struct sockaddr *) &(new->servaddr), &sl);
uh_client_count++;
}
return new;
}
struct client * uh_client_lookup(int sock)
{
struct client *cur = NULL;
int i;
for( i = 0; i < uh_client_count; i++ )
{
cur = (struct client *) &uh_clients[i * sizeof(struct client)];
if( cur->socket == sock )
return cur;
}
return NULL;
}
void uh_client_remove(int sock)
{
struct client *del = uh_client_lookup(sock);
if( del )
{
memmove(del, del + 1,
sizeof(uh_clients) - (int)((char *)del - uh_clients) - sizeof(struct client));
uh_client_count--;
}
}

View file

@ -1,98 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - Utility header
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _UHTTPD_UTILS_
#include <stdarg.h>
#include <fcntl.h>
#include <pwd.h>
#include <shadow.h>
#include <sys/stat.h>
#define min(x, y) (((x) < (y)) ? (x) : (y))
#define max(x, y) (((x) > (y)) ? (x) : (y))
#define array_size(x) \
(sizeof(x) / sizeof(x[0]))
#define foreach_header(i, h) \
for( i = 0; (i + 1) < (sizeof(h) / sizeof(h[0])) && h[i]; i += 2 )
struct path_info {
char *root;
char *phys;
char *name;
char *info;
char *query;
struct stat stat;
};
const char * sa_straddr(void *sa);
const char * sa_strport(void *sa);
int sa_port(void *sa);
char *strfind(char *haystack, int hslen, const char *needle, int ndlen);
int uh_tcp_send(struct client *cl, const char *buf, int len);
int uh_tcp_peek(struct client *cl, char *buf, int len);
int uh_tcp_recv(struct client *cl, char *buf, int len);
int uh_http_sendhf(
struct client *cl, int code, const char *summary,
const char *fmt, ...
);
#define uh_http_response(cl, code, message) \
uh_http_sendhf(cl, code, message, message)
int uh_http_sendc(struct client *cl, const char *data, int len);
int uh_http_sendf(
struct client *cl, struct http_request *req,
const char *fmt, ...
);
int uh_http_send(
struct client *cl, struct http_request *req,
const char *buf, int len
);
int uh_urldecode(char *buf, int blen, const char *src, int slen);
int uh_urlencode(char *buf, int blen, const char *src, int slen);
int uh_b64decode(char *buf, int blen, const unsigned char *src, int slen);
struct auth_realm * uh_auth_add(char *path, char *user, char *pass);
int uh_auth_check(
struct client *cl, struct http_request *req, struct path_info *pi
);
struct path_info * uh_path_lookup(struct client *cl, const char *url);
struct listener * uh_listener_add(int sock, struct config *conf);
struct listener * uh_listener_lookup(int sock);
struct client * uh_client_add(int sock, struct listener *serv);
struct client * uh_client_lookup(int sock);
void uh_client_remove(int sock);
#endif

View file

@ -1,899 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - Main component
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define _XOPEN_SOURCE 500 /* crypt() */
#include "uhttpd.h"
#include "uhttpd-utils.h"
#include "uhttpd-file.h"
#ifdef HAVE_CGI
#include "uhttpd-cgi.h"
#endif
#ifdef HAVE_LUA
#include "uhttpd-lua.h"
#endif
#ifdef HAVE_TLS
#include "uhttpd-tls.h"
#endif
static int run = 1;
static void uh_sigterm(int sig)
{
run = 0;
}
static void uh_config_parse(const char *path)
{
FILE *c;
char line[512];
char *user = NULL;
char *pass = NULL;
char *eol = NULL;
if( (c = fopen(path ? path : "/etc/httpd.conf", "r")) != NULL )
{
memset(line, 0, sizeof(line));
while( fgets(line, sizeof(line) - 1, c) )
{
if( (line[0] == '/') && (strchr(line, ':') != NULL) )
{
if( !(user = strchr(line, ':')) || (*user++ = 0) ||
!(pass = strchr(user, ':')) || (*pass++ = 0) ||
!(eol = strchr(pass, '\n')) || (*eol++ = 0) )
continue;
if( !uh_auth_add(line, user, pass) )
{
fprintf(stderr,
"Can not manage more than %i basic auth realms, "
"will skip the rest\n", UH_LIMIT_AUTHREALMS
);
break;
}
}
}
fclose(c);
}
}
static int uh_socket_bind(
fd_set *serv_fds, int *max_fd, const char *host, const char *port,
struct addrinfo *hints, int do_tls, struct config *conf
) {
int sock = -1;
int yes = 1;
int status;
int bound = 0;
struct listener *l = NULL;
struct addrinfo *addrs = NULL, *p = NULL;
if( (status = getaddrinfo(host, port, hints, &addrs)) != 0 )
{
fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(status));
}
/* try to bind a new socket to each found address */
for( p = addrs; p; p = p->ai_next )
{
/* get the socket */
if( (sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1 )
{
perror("socket()");
goto error;
}
/* "address already in use" */
if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1 )
{
perror("setsockopt()");
goto error;
}
/* required to get parallel v4 + v6 working */
if( p->ai_family == AF_INET6 )
{
if( setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) == -1 )
{
perror("setsockopt()");
goto error;
}
}
/* bind */
if( bind(sock, p->ai_addr, p->ai_addrlen) == -1 )
{
perror("bind()");
goto error;
}
/* listen */
if( listen(sock, UH_LIMIT_CLIENTS) == -1 )
{
perror("listen()");
goto error;
}
/* add listener to global list */
if( ! (l = uh_listener_add(sock, conf)) )
{
fprintf(stderr,
"uh_listener_add(): Can not create more than "
"%i listen sockets\n", UH_LIMIT_LISTENERS
);
goto error;
}
#ifdef HAVE_TLS
/* init TLS */
l->tls = do_tls ? conf->tls : NULL;
#endif
/* add socket to server fd set */
FD_SET(sock, serv_fds);
*max_fd = max(*max_fd, sock);
bound++;
continue;
error:
if( sock > 0 )
close(sock);
}
freeaddrinfo(addrs);
return bound;
}
static struct http_request * uh_http_header_parse(struct client *cl, char *buffer, int buflen)
{
char *method = &buffer[0];
char *path = NULL;
char *version = NULL;
char *headers = NULL;
char *hdrname = NULL;
char *hdrdata = NULL;
int i;
int hdrcount = 0;
static struct http_request req;
memset(&req, 0, sizeof(req));
/* terminate initial header line */
if( (headers = strfind(buffer, buflen, "\r\n", 2)) != NULL )
{
buffer[buflen-1] = 0;
*headers++ = 0;
*headers++ = 0;
/* find request path */
if( (path = strchr(buffer, ' ')) != NULL )
*path++ = 0;
/* find http version */
if( (path != NULL) && ((version = strchr(path, ' ')) != NULL) )
*version++ = 0;
/* check method */
if( strcmp(method, "GET") && strcmp(method, "HEAD") && strcmp(method, "POST") )
{
/* invalid method */
uh_http_response(cl, 405, "Method Not Allowed");
return NULL;
}
else
{
switch(method[0])
{
case 'G':
req.method = UH_HTTP_MSG_GET;
break;
case 'H':
req.method = UH_HTTP_MSG_HEAD;
break;
case 'P':
req.method = UH_HTTP_MSG_POST;
break;
}
}
/* check path */
if( !path || !strlen(path) )
{
/* malformed request */
uh_http_response(cl, 400, "Bad Request");
return NULL;
}
else
{
req.url = path;
}
/* check version */
if( strcmp(version, "HTTP/0.9") && strcmp(version, "HTTP/1.0") && strcmp(version, "HTTP/1.1") )
{
/* unsupported version */
uh_http_response(cl, 400, "Bad Request");
return NULL;
}
else
{
req.version = strtof(&version[5], NULL);
}
/* process header fields */
for( i = (int)(headers - buffer); i < buflen; i++ )
{
/* found eol and have name + value, push out header tuple */
if( hdrname && hdrdata && (buffer[i] == '\r' || buffer[i] == '\n') )
{
buffer[i] = 0;
/* store */
if( (hdrcount + 1) < array_size(req.headers) )
{
req.headers[hdrcount++] = hdrname;
req.headers[hdrcount++] = hdrdata;
hdrname = hdrdata = NULL;
}
/* too large */
else
{
uh_http_response(cl, 413, "Request Entity Too Large");
return NULL;
}
}
/* have name but no value and found a colon, start of value */
else if( hdrname && !hdrdata && ((i+2) < buflen) &&
(buffer[i] == ':') && (buffer[i+1] == ' ')
) {
buffer[i] = 0;
hdrdata = &buffer[i+2];
}
/* have no name and found [A-Z], start of name */
else if( !hdrname && isalpha(buffer[i]) && isupper(buffer[i]) )
{
hdrname = &buffer[i];
}
}
/* valid enough */
return &req;
}
/* Malformed request */
uh_http_response(cl, 400, "Bad Request");
return NULL;
}
static struct http_request * uh_http_header_recv(struct client *cl)
{
static char buffer[UH_LIMIT_MSGHEAD];
char *bufptr = &buffer[0];
char *idxptr = NULL;
struct timeval timeout;
fd_set reader;
ssize_t blen = sizeof(buffer)-1;
ssize_t rlen = 0;
memset(buffer, 0, sizeof(buffer));
while( blen > 0 )
{
FD_ZERO(&reader);
FD_SET(cl->socket, &reader);
/* fail after 0.1s */
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
/* check whether fd is readable */
if( select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0 )
{
/* receive data */
rlen = uh_tcp_peek(cl, bufptr, blen);
if( rlen > 0 )
{
if( (idxptr = strfind(buffer, sizeof(buffer), "\r\n\r\n", 4)) )
{
blen -= uh_tcp_recv(cl, bufptr, (int)(idxptr - bufptr) + 4);
/* header read complete ... */
return uh_http_header_parse(cl, buffer, sizeof(buffer) - blen - 1);
}
else
{
rlen = uh_tcp_recv(cl, bufptr, rlen);
blen -= rlen;
bufptr += rlen;
}
}
else
{
/* invalid request (unexpected eof/timeout) */
uh_http_response(cl, 408, "Request Timeout");
return NULL;
}
}
else
{
/* invalid request (unexpected eof/timeout) */
uh_http_response(cl, 408, "Request Timeout");
return NULL;
}
}
/* request entity too large */
uh_http_response(cl, 413, "Request Entity Too Large");
return NULL;
}
static int uh_path_match(const char *prefix, const char *url)
{
if( (strstr(url, prefix) == url) &&
((prefix[strlen(prefix)-1] == '/') ||
(strlen(url) == strlen(prefix)) ||
(url[strlen(prefix)] == '/'))
) {
return 1;
}
return 0;
}
int main (int argc, char **argv)
{
#ifdef HAVE_LUA
/* Lua runtime */
lua_State *L = NULL;
#endif
/* master file descriptor list */
fd_set used_fds, serv_fds, read_fds;
/* working structs */
struct addrinfo hints;
struct http_request *req;
struct path_info *pin;
struct client *cl;
struct sigaction sa;
struct config conf;
/* maximum file descriptor number */
int new_fd, cur_fd, max_fd = 0;
int tls = 0;
int keys = 0;
int bound = 0;
int nofork = 0;
/* args */
char opt;
char bind[128];
char *port = NULL;
/* library handles */
void *tls_lib;
void *lua_lib;
/* clear the master and temp sets */
FD_ZERO(&used_fds);
FD_ZERO(&serv_fds);
FD_ZERO(&read_fds);
/* handle SIGPIPE, SIGCHILD */
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
sa.sa_handler = uh_sigterm;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
/* prepare addrinfo hints */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
/* parse args */
memset(&conf, 0, sizeof(conf));
memset(bind, 0, sizeof(bind));
#ifdef HAVE_TLS
/* load TLS plugin */
if( ! (tls_lib = dlopen("uhttpd_tls.so", RTLD_LAZY | RTLD_GLOBAL)) )
{
fprintf(stderr,
"Notice: Unable to load TLS plugin - disabling SSL support! "
"(Reason: %s)\n", dlerror()
);
}
else
{
/* resolve functions */
if( !(conf.tls_init = dlsym(tls_lib, "uh_tls_ctx_init")) ||
!(conf.tls_cert = dlsym(tls_lib, "uh_tls_ctx_cert")) ||
!(conf.tls_key = dlsym(tls_lib, "uh_tls_ctx_key")) ||
!(conf.tls_free = dlsym(tls_lib, "uh_tls_ctx_free")) ||
!(conf.tls_accept = dlsym(tls_lib, "uh_tls_client_accept")) ||
!(conf.tls_close = dlsym(tls_lib, "uh_tls_client_close")) ||
!(conf.tls_recv = dlsym(tls_lib, "uh_tls_client_recv")) ||
!(conf.tls_send = dlsym(tls_lib, "uh_tls_client_send"))
) {
fprintf(stderr,
"Error: Failed to lookup required symbols "
"in TLS plugin: %s\n", dlerror()
);
exit(1);
}
/* init SSL context */
if( ! (conf.tls = conf.tls_init()) )
{
fprintf(stderr, "Error: Failed to initalize SSL context\n");
exit(1);
}
}
#endif
while( (opt = getopt(argc, argv, "fC:K:p:s:h:c:l:L:d:r:m:x:")) > 0 )
{
switch(opt)
{
/* [addr:]port */
case 'p':
case 's':
if( (port = strrchr(optarg, ':')) != NULL )
{
if( (optarg[0] == '[') && (port > optarg) && (port[-1] == ']') )
memcpy(bind, optarg + 1,
min(sizeof(bind), (int)(port - optarg) - 2));
else
memcpy(bind, optarg,
min(sizeof(bind), (int)(port - optarg)));
port++;
}
else
{
port = optarg;
}
if( opt == 's' )
{
if( !conf.tls )
{
fprintf(stderr,
"Notice: TLS support is disabled, "
"ignoring '-s %s'\n", optarg
);
continue;
}
tls = 1;
}
/* bind sockets */
bound += uh_socket_bind(
&serv_fds, &max_fd, bind[0] ? bind : NULL, port,
&hints, (opt == 's'), &conf
);
break;
#ifdef HAVE_TLS
/* certificate */
case 'C':
if( conf.tls )
{
if( conf.tls_cert(conf.tls, optarg) < 1 )
{
fprintf(stderr,
"Error: Invalid certificate file given\n");
exit(1);
}
keys++;
}
break;
/* key */
case 'K':
if( conf.tls )
{
if( conf.tls_key(conf.tls, optarg) < 1 )
{
fprintf(stderr,
"Error: Invalid private key file given\n");
exit(1);
}
keys++;
}
break;
#endif
/* docroot */
case 'h':
if( ! realpath(optarg, conf.docroot) )
{
fprintf(stderr, "Error: Invalid directory %s: %s\n",
optarg, strerror(errno));
exit(1);
}
break;
#ifdef HAVE_CGI
/* cgi prefix */
case 'x':
conf.cgi_prefix = optarg;
break;
#endif
#ifdef HAVE_LUA
/* lua prefix */
case 'l':
conf.lua_prefix = optarg;
break;
/* lua handler */
case 'L':
conf.lua_handler = optarg;
break;
#endif
/* no fork */
case 'f':
nofork = 1;
break;
/* urldecode */
case 'd':
if( (port = malloc(strlen(optarg)+1)) != NULL )
{
memset(port, 0, strlen(optarg)+1);
uh_urldecode(port, strlen(optarg), optarg, strlen(optarg));
printf("%s", port);
free(port);
exit(0);
}
break;
/* basic auth realm */
case 'r':
conf.realm = optarg;
break;
/* md5 crypt */
case 'm':
printf("%s\n", crypt(optarg, "$1$"));
exit(0);
break;
/* config file */
case 'c':
conf.file = optarg;
break;
default:
fprintf(stderr,
"Usage: %s -p [addr:]port [-h docroot]\n"
" -f Do not fork to background\n"
" -c file Configuration file, default is '/etc/httpd.conf'\n"
" -p [addr:]port Bind to specified address and port, multiple allowed\n"
#ifdef HAVE_TLS
" -s [addr:]port Like -p but provide HTTPS on this port\n"
" -C file ASN.1 server certificate file\n"
" -K file ASN.1 server private key file\n"
#endif
" -h directory Specify the document root, default is '.'\n"
#ifdef HAVE_LUA
" -l string URL prefix for Lua handler, default is '/lua'\n"
" -L file Lua handler script, omit to disable Lua\n"
#endif
#ifdef HAVE_CGI
" -x string URL prefix for CGI handler, default is '/cgi-bin'\n"
#endif
" -d string URL decode given string\n"
" -r string Specify basic auth realm\n"
" -m string MD5 crypt given string\n"
"\n", argv[0]
);
exit(1);
}
}
#ifdef HAVE_TLS
if( (tls == 1) && (keys < 2) )
{
fprintf(stderr, "Error: Missing private key or certificate file\n");
exit(1);
}
#endif
if( bound < 1 )
{
fprintf(stderr, "Error: No sockets bound, unable to continue\n");
exit(1);
}
/* default docroot */
if( !conf.docroot[0] && !realpath(".", conf.docroot) )
{
fprintf(stderr, "Error: Can not determine default document root: %s\n",
strerror(errno));
exit(1);
}
/* default realm */
if( ! conf.realm )
conf.realm = "Protected Area";
/* config file */
uh_config_parse(conf.file);
#ifdef HAVE_CGI
/* default cgi prefix */
if( ! conf.cgi_prefix )
conf.cgi_prefix = "/cgi-bin";
#endif
#ifdef HAVE_LUA
/* load Lua plugin */
if( ! (lua_lib = dlopen("uhttpd_lua.so", RTLD_LAZY | RTLD_GLOBAL)) )
{
fprintf(stderr,
"Notice: Unable to load Lua plugin - disabling Lua support! "
"(Reason: %s)\n", dlerror()
);
}
else
{
/* resolve functions */
if( !(conf.lua_init = dlsym(lua_lib, "uh_lua_init")) ||
!(conf.lua_close = dlsym(lua_lib, "uh_lua_close")) ||
!(conf.lua_request = dlsym(lua_lib, "uh_lua_request"))
) {
fprintf(stderr,
"Error: Failed to lookup required symbols "
"in Lua plugin: %s\n", dlerror()
);
exit(1);
}
/* init Lua runtime if handler is specified */
if( conf.lua_handler )
{
/* default lua prefix */
if( ! conf.lua_prefix )
conf.lua_prefix = "/lua";
L = conf.lua_init(conf.lua_handler);
}
}
#endif
/* fork (if not disabled) */
if( ! nofork )
{
switch( fork() )
{
case -1:
perror("fork()");
exit(1);
case 0:
/* daemon setup */
if( chdir("/") )
perror("chdir()");
if( (cur_fd = open("/dev/null", O_WRONLY)) > -1 )
dup2(cur_fd, 0);
if( (cur_fd = open("/dev/null", O_RDONLY)) > -1 )
dup2(cur_fd, 1);
if( (cur_fd = open("/dev/null", O_RDONLY)) > -1 )
dup2(cur_fd, 2);
break;
default:
exit(0);
}
}
/* backup server descriptor set */
used_fds = serv_fds;
/* loop */
while(run)
{
/* create a working copy of the used fd set */
read_fds = used_fds;
/* sleep until socket activity */
if( select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1 )
{
perror("select()");
exit(1);
}
/* run through the existing connections looking for data to be read */
for( cur_fd = 0; cur_fd <= max_fd; cur_fd++ )
{
/* is a socket managed by us */
if( FD_ISSET(cur_fd, &read_fds) )
{
/* is one of our listen sockets */
if( FD_ISSET(cur_fd, &serv_fds) )
{
/* handle new connections */
if( (new_fd = accept(cur_fd, NULL, 0)) != -1 )
{
/* add to global client list */
if( (cl = uh_client_add(new_fd, uh_listener_lookup(cur_fd))) != NULL )
{
#ifdef HAVE_TLS
/* setup client tls context */
if( conf.tls )
conf.tls_accept(cl);
#endif
/* add client socket to global fdset */
FD_SET(new_fd, &used_fds);
max_fd = max(max_fd, new_fd);
}
/* insufficient resources */
else
{
fprintf(stderr,
"uh_client_add(): Can not manage more than "
"%i client sockets, connection dropped\n",
UH_LIMIT_CLIENTS
);
close(new_fd);
}
}
}
/* is a client socket */
else
{
if( ! (cl = uh_client_lookup(cur_fd)) )
{
/* this should not happen! */
fprintf(stderr,
"uh_client_lookup(): No entry for fd %i!\n",
cur_fd);
goto cleanup;
}
/* parse message header */
if( (req = uh_http_header_recv(cl)) != NULL )
{
#ifdef HAVE_LUA
/* Lua request? */
if( L && uh_path_match(conf.lua_prefix, req->url) )
{
conf.lua_request(cl, req, L);
}
else
#endif
/* dispatch request */
if( (pin = uh_path_lookup(cl, req->url)) != NULL )
{
/* auth ok? */
if( uh_auth_check(cl, req, pin) )
{
#ifdef HAVE_CGI
if( uh_path_match(conf.cgi_prefix, pin->name) )
{
uh_cgi_request(cl, req, pin);
}
else
#endif
{
uh_file_request(cl, req, pin);
}
}
}
/* 404 */
else
{
uh_http_sendhf(cl, 404, "Not Found",
"No such file or directory");
}
}
/* 400 */
else
{
uh_http_sendhf(cl, 400, "Bad Request",
"Malformed request received");
}
#ifdef HAVE_TLS
/* free client tls context */
if( conf.tls )
conf.tls_close(cl);
#endif
cleanup:
/* close client socket */
close(cur_fd);
FD_CLR(cur_fd, &used_fds);
/* remove from global client list */
uh_client_remove(cur_fd);
}
}
}
}
#ifdef HAVE_LUA
/* destroy the Lua state */
if( L != NULL )
conf.lua_close(L);
#endif
return 0;
}

View file

@ -1,133 +0,0 @@
/*
* uhttpd - Tiny single-threaded httpd - Main header
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _UHTTPD_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/limits.h>
#include <netdb.h>
#include <ctype.h>
#include <dlfcn.h>
#ifdef HAVE_LUA
#include <lua.h>
#endif
#ifdef HAVE_TLS
#include <openssl/ssl.h>
#endif
#define UH_LIMIT_MSGHEAD 4096
#define UH_LIMIT_HEADERS 64
#define UH_LIMIT_LISTENERS 16
#define UH_LIMIT_CLIENTS 64
#define UH_LIMIT_AUTHREALMS 8
#define UH_HTTP_MSG_GET 0
#define UH_HTTP_MSG_HEAD 1
#define UH_HTTP_MSG_POST 2
struct listener;
struct client;
struct http_request;
struct config {
char docroot[PATH_MAX];
char *realm;
char *file;
#ifdef HAVE_CGI
char *cgi_prefix;
#endif
#ifdef HAVE_LUA
char *lua_prefix;
char *lua_handler;
lua_State * (*lua_init) (const char *handler);
void (*lua_close) (lua_State *L);
void (*lua_request) (struct client *cl, struct http_request *req, lua_State *L);
#endif
#ifdef HAVE_TLS
char *cert;
char *key;
SSL_CTX *tls;
SSL_CTX * (*tls_init) (void);
int (*tls_cert) (SSL_CTX *c, const char *file);
int (*tls_key) (SSL_CTX *c, const char *file);
void (*tls_free) (struct listener *l);
void (*tls_accept) (struct client *c);
void (*tls_close) (struct client *c);
int (*tls_recv) (struct client *c, void *buf, int len);
int (*tls_send) (struct client *c, void *buf, int len);
#endif
};
struct listener {
int socket;
struct sockaddr_in6 addr;
struct config *conf;
#ifdef HAVE_TLS
SSL_CTX *tls;
#endif
};
struct client {
int socket;
int peeklen;
char peekbuf[UH_LIMIT_MSGHEAD];
struct listener *server;
struct sockaddr_in6 servaddr;
struct sockaddr_in6 peeraddr;
#ifdef HAVE_TLS
SSL *tls;
#endif
};
struct auth_realm {
char path[PATH_MAX];
char user[32];
char pass[128];
};
struct http_request {
int method;
float version;
char *url;
char *headers[UH_LIMIT_HEADERS];
struct auth_realm *realm;
};
struct http_response {
int statuscode;
char *statusmsg;
char *headers[UH_LIMIT_HEADERS];
};
#endif