contrib/package: remove px5g, uhttpd - moved to OpenWrt core packages
This commit is contained in:
parent
e47ac7cabc
commit
11527683bf
36 changed files with 0 additions and 12327 deletions
|
@ -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))
|
|
@ -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)
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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))
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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--;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
Loading…
Reference in a new issue