Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
a33e3a4a
Commit
a33e3a4a
authored
Oct 17, 2015
by
Vowstar
Browse files
Merge pull request #687 from DiUS/dev140
Major upgrade to SDK 1.4.0 & open LWIP
parents
093a8959
8fba0f47
Changes
282
Show whitespace changes
Inline
Side-by-side
app/lwip/core/timers.c
View file @
a33e3a4a
...
...
@@ -57,6 +57,9 @@
#include "lwip/igmp.h"
#include "lwip/dns.h"
#ifdef MEMLEAK_DEBUG
static
const
char
mem_debug_file
[]
ICACHE_RODATA_ATTR
=
__FILE__
;
#endif
/** The one and only timeout list */
static
struct
sys_timeo
*
next_timeout
=
NULL
;
...
...
@@ -245,6 +248,7 @@ void sys_timeouts_init(void)
sys_timeout
(
ARP_TMR_INTERVAL
,
arp_timer
,
NULL
);
#endif
/* LWIP_ARP */
#if LWIP_DHCP
DHCP_MAXRTX
=
0
;
sys_timeout
(
DHCP_COARSE_TIMER_MSECS
,
dhcp_timer_coarse
,
NULL
);
sys_timeout
(
DHCP_FINE_TIMER_MSECS
,
dhcp_timer_fine
,
NULL
);
#endif
/* LWIP_DHCP */
...
...
@@ -259,8 +263,8 @@ void sys_timeouts_init(void)
#endif
/* LWIP_DNS */
#if LWIP_TCP
//
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
sys_timeout
(
TCP_TMR_INTERVAL
,
tcp_timer_coarse
,
NULL
);
sys_timeout
(
TCP_TMR_INTERVAL
,
tcpip_tcp_timer
,
NULL
);
//
sys_timeout(TCP_TMR_INTERVAL, tcp_timer_coarse, NULL);
#endif
#if NO_SYS
...
...
@@ -389,9 +393,9 @@ sys_check_timeouts(void)
if
(
next_timeout
)
{
/* this cares for wraparounds */
if
(
timer2_ms_flag
==
0
)
{
diff
=
LWIP_U32_DIFF
(
now
,
timeouts_last_time
)
/
((
CPU
_CLK_FREQ
>>
4
)
/
1000
);
diff
=
LWIP_U32_DIFF
(
now
,
timeouts_last_time
)
/
((
APB
_CLK_FREQ
>>
4
)
/
1000
);
}
else
{
diff
=
LWIP_U32_DIFF
(
now
,
timeouts_last_time
)
/
((
CPU
_CLK_FREQ
>>
8
)
/
1000
);
diff
=
LWIP_U32_DIFF
(
now
,
timeouts_last_time
)
/
((
APB
_CLK_FREQ
>>
8
)
/
1000
);
}
do
{
...
...
app/lwip/core/udp.c
View file @
a33e3a4a
...
...
@@ -64,6 +64,10 @@
#include <string.h>
#ifdef MEMLEAK_DEBUG
static
const
char
mem_debug_file
[]
ICACHE_RODATA_ATTR
=
__FILE__
;
#endif
/* The list of UDP PCBs */
/* exported in udp.h (was static) */
struct
udp_pcb
*
udp_pcbs
;
...
...
@@ -148,6 +152,15 @@ udp_input(struct pbuf *p, struct netif *inp)
pcb
=
inp
->
dhcp
->
pcb
;
}
}
}
else
if
(
dest
==
DHCP_SERVER_PORT
)
{
if
(
src
==
DHCP_CLIENT_PORT
)
{
if
(
inp
->
dhcps_pcb
!=
NULL
)
{
if
((
ip_addr_isany
(
&
inp
->
dhcps_pcb
->
local_ip
)
||
ip_addr_cmp
(
&
(
inp
->
dhcps_pcb
->
local_ip
),
&
current_iphdr_dest
)))
{
pcb
=
inp
->
dhcps_pcb
;
}
}
}
}
}
else
#endif
/* LWIP_DHCP */
...
...
@@ -935,7 +948,7 @@ udp_new(void)
* which means checksum is generated over the whole datagram per default
* (recommended as default by RFC 3828). */
/* initialize PCB to all zeroes */
memset
(
pcb
,
0
,
sizeof
(
struct
udp_pcb
));
os_
memset
(
pcb
,
0
,
sizeof
(
struct
udp_pcb
));
pcb
->
ttl
=
UDP_TTL
;
}
return
pcb
;
...
...
app/lwip/netif/Makefile
View file @
a33e3a4a
app/lwip/netif/etharp.c
View file @
a33e3a4a
...
...
@@ -62,6 +62,10 @@
#include <string.h>
#ifdef MEMLEAK_DEBUG
static
const
char
mem_debug_file
[]
ICACHE_RODATA_ATTR
=
__FILE__
;
#endif
const
struct
eth_addr
ethbroadcast
=
{{
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
}};
const
struct
eth_addr
ethzero
=
{{
0
,
0
,
0
,
0
,
0
,
0
}};
...
...
@@ -72,6 +76,9 @@ const struct eth_addr ethzero = {{0,0,0,0,0,0}};
* (240 * 5) seconds = 20 minutes.
*/
#define ARP_MAXAGE 240
/** Re-request a used ARP entry 1 minute before it would expire to prevent
* breaking a steadily used connection because the ARP entry timed out. */
#define ARP_AGE_REREQUEST_USED (ARP_MAXAGE - 12)
/** the time an ARP entry stays pending after first request,
* for ARP_TMR_INTERVAL = 5000, this is
* (2 * 5) seconds = 10 seconds.
...
...
@@ -86,7 +93,8 @@ const struct eth_addr ethzero = {{0,0,0,0,0,0}};
enum
etharp_state
{
ETHARP_STATE_EMPTY
=
0
,
ETHARP_STATE_PENDING
,
ETHARP_STATE_STABLE
ETHARP_STATE_STABLE
,
ETHARP_STATE_STABLE_REREQUESTING
};
struct
etharp_entry
{
...
...
@@ -219,10 +227,15 @@ etharp_tmr(void)
(
arp_table
[
i
].
ctime
>=
ARP_MAXPENDING
)))
{
/* pending or stable entry has become old! */
LWIP_DEBUGF
(
ETHARP_DEBUG
,
(
"etharp_timer: expired %s entry %"
U16_F
".
\n
"
,
arp_table
[
i
].
state
=
=
ETHARP_STATE_STABLE
?
"stable"
:
"pending"
,
(
u16_t
)
i
));
arp_table
[
i
].
state
>
=
ETHARP_STATE_STABLE
?
"stable"
:
"pending"
,
(
u16_t
)
i
));
/* clean up entries that have just been expired */
free_entry
(
i
);
}
else
if
(
arp_table
[
i
].
state
==
ETHARP_STATE_STABLE_REREQUESTING
)
{
/* Reset state to stable, so that the next transmitted packet will
re-send an ARP request. */
arp_table
[
i
].
state
=
ETHARP_STATE_STABLE
;
}
#if ARP_QUEUEING
/* still pending entry? (not expired) */
if
(
arp_table
[
i
].
state
==
ETHARP_STATE_PENDING
)
{
...
...
@@ -288,8 +301,8 @@ find_entry(ip_addr_t *ipaddr, u8_t flags)
/* remember first empty entry */
empty
=
i
;
}
else
if
(
state
!=
ETHARP_STATE_EMPTY
)
{
LWIP_ASSERT
(
"state == ETHARP_STATE_PENDING || state
=
= ETHARP_STATE_STABLE"
,
state
==
ETHARP_STATE_PENDING
||
state
=
=
ETHARP_STATE_STABLE
);
LWIP_ASSERT
(
"state == ETHARP_STATE_PENDING || state
>
= ETHARP_STATE_STABLE"
,
state
==
ETHARP_STATE_PENDING
||
state
>
=
ETHARP_STATE_STABLE
);
/* if given, does IP address match IP address in ARP entry? */
if
(
ipaddr
&&
ip_addr_cmp
(
ipaddr
,
&
arp_table
[
i
].
ipaddr
))
{
LWIP_DEBUGF
(
ETHARP_DEBUG
|
LWIP_DBG_TRACE
,
(
"find_entry: found matching entry %"
U16_F
"
\n
"
,
(
u16_t
)
i
));
...
...
@@ -313,7 +326,7 @@ find_entry(ip_addr_t *ipaddr, u8_t flags)
}
}
/* stable entry? */
}
else
if
(
state
=
=
ETHARP_STATE_STABLE
)
{
}
else
if
(
state
>
=
ETHARP_STATE_STABLE
)
{
#if ETHARP_SUPPORT_STATIC_ENTRIES
/* don't record old_stable for static entries since they never expire */
if
(
arp_table
[
i
].
static_entry
==
0
)
...
...
@@ -608,7 +621,7 @@ etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr,
LWIP_UNUSED_ARG
(
netif
);
i
=
find_entry
(
ipaddr
,
ETHARP_FLAG_FIND_ONLY
);
if
((
i
>=
0
)
&&
arp_table
[
i
].
state
=
=
ETHARP_STATE_STABLE
)
{
if
((
i
>=
0
)
&&
(
arp_table
[
i
].
state
>
=
ETHARP_STATE_STABLE
)
)
{
*
eth_ret
=
&
arp_table
[
i
].
ethaddr
;
*
ip_ret
=
&
arp_table
[
i
].
ipaddr
;
return
i
;
...
...
@@ -854,6 +867,28 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
pbuf_free
(
p
);
}
/** Just a small helper function that sends a pbuf to an ethernet address
* in the arp_table specified by the index 'arp_idx'.
*/
static
err_t
ICACHE_FLASH_ATTR
etharp_output_to_arp_index
(
struct
netif
*
netif
,
struct
pbuf
*
q
,
u8_t
arp_idx
)
{
LWIP_ASSERT
(
"arp_table[arp_idx].state >= ETHARP_STATE_STABLE"
,
arp_table
[
arp_idx
].
state
>=
ETHARP_STATE_STABLE
);
/* if arp table entry is about to expire: re-request it,
but only if its state is ETHARP_STATE_STABLE to prevent flooding the
network with ARP requests if this address is used frequently. */
if
((
arp_table
[
arp_idx
].
state
==
ETHARP_STATE_STABLE
)
&&
(
arp_table
[
arp_idx
].
ctime
>=
ARP_AGE_REREQUEST_USED
))
{
if
(
etharp_request
(
netif
,
&
arp_table
[
arp_idx
].
ipaddr
)
==
ERR_OK
)
{
arp_table
[
arp_idx
].
state
=
ETHARP_STATE_STABLE_REREQUESTING
;
}
}
return
etharp_send_ip
(
netif
,
q
,
(
struct
eth_addr
*
)(
netif
->
hwaddr
),
&
arp_table
[
arp_idx
].
ethaddr
);
}
/**
* Resolve and fill-in Ethernet address header for outgoing IP packet.
*
...
...
@@ -908,7 +943,9 @@ etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
dest
=
&
mcastaddr
;
/* unicast destination IP address? */
}
else
{
/* outside local network? */
s8_t
i
;
/* outside local network? if so, this can neither be a global broadcast nor
a subnet broadcast. */
if
(
!
ip_addr_netcmp
(
ipaddr
,
&
(
netif
->
ip_addr
),
&
(
netif
->
netmask
))
&&
!
ip_addr_islinklocal
(
ipaddr
))
{
#if LWIP_AUTOIP
...
...
@@ -938,17 +975,26 @@ etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
u8_t
etharp_cached_entry
=
*
(
netif
->
addr_hint
);
if
(
etharp_cached_entry
<
ARP_TABLE_SIZE
)
{
#endif
/* LWIP_NETIF_HWADDRHINT */
if
((
arp_table
[
etharp_cached_entry
].
state
=
=
ETHARP_STATE_STABLE
)
&&
if
((
arp_table
[
etharp_cached_entry
].
state
>
=
ETHARP_STATE_STABLE
)
&&
(
ip_addr_cmp
(
ipaddr
,
&
arp_table
[
etharp_cached_entry
].
ipaddr
)))
{
/* the per-pcb-cached entry is stable and the right one! */
ETHARP_STATS_INC
(
etharp
.
cachehit
);
return
etharp_send_ip
(
netif
,
q
,
(
struct
eth_addr
*
)(
netif
->
hwaddr
),
&
arp_table
[
etharp_cached_entry
].
ethaddr
);
return
etharp_output_to_arp_index
(
netif
,
q
,
etharp_cached_entry
);
}
#if LWIP_NETIF_HWADDRHINT
}
}
#endif
/* LWIP_NETIF_HWADDRHINT */
/* find stable entry: do this here since this is a critical path for
throughput and etharp_find_entry() is kind of slow */
for
(
i
=
0
;
i
<
ARP_TABLE_SIZE
;
i
++
)
{
if
((
arp_table
[
i
].
state
>=
ETHARP_STATE_STABLE
)
&&
(
ip_addr_cmp
(
ipaddr
,
&
arp_table
[
i
].
ipaddr
)))
{
/* found an existing, stable entry */
ETHARP_SET_HINT
(
netif
,
i
);
return
etharp_output_to_arp_index
(
netif
,
q
,
i
);
}
}
/* queue on destination Ethernet address belonging to ipaddr */
return
etharp_query
(
netif
,
ipaddr
,
q
);
}
...
...
@@ -1028,7 +1074,7 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
/* { i is either a STABLE or (new or existing) PENDING entry } */
LWIP_ASSERT
(
"arp_table[i].state == PENDING or STABLE"
,
((
arp_table
[
i
].
state
==
ETHARP_STATE_PENDING
)
||
(
arp_table
[
i
].
state
=
=
ETHARP_STATE_STABLE
)));
(
arp_table
[
i
].
state
>
=
ETHARP_STATE_STABLE
)));
/* do we have a pending entry? or an implicit query request? */
if
((
arp_table
[
i
].
state
==
ETHARP_STATE_PENDING
)
||
(
q
==
NULL
))
{
...
...
@@ -1048,7 +1094,7 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
/* packet given? */
LWIP_ASSERT
(
"q != NULL"
,
q
!=
NULL
);
/* stable entry? */
if
(
arp_table
[
i
].
state
=
=
ETHARP_STATE_STABLE
)
{
if
(
arp_table
[
i
].
state
>
=
ETHARP_STATE_STABLE
)
{
/* we have a valid IP->Ethernet address mapping */
ETHARP_SET_HINT
(
netif
,
i
);
/* send the packet */
...
...
@@ -1092,20 +1138,30 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
/* allocate a new arp queue entry */
new_entry
=
(
struct
etharp_q_entry
*
)
memp_malloc
(
MEMP_ARP_QUEUE
);
if
(
new_entry
!=
NULL
)
{
unsigned
int
qlen
=
0
;
new_entry
->
next
=
0
;
new_entry
->
p
=
p
;
if
(
arp_table
[
i
].
q
!=
NULL
)
{
/* queue was already existent, append the new entry to the end */
struct
etharp_q_entry
*
r
;
r
=
arp_table
[
i
].
q
;
qlen
++
;
while
(
r
->
next
!=
NULL
)
{
r
=
r
->
next
;
qlen
++
;
}
r
->
next
=
new_entry
;
}
else
{
/* queue did not exist, first item in queue */
arp_table
[
i
].
q
=
new_entry
;
}
if
(
qlen
>=
3
)
{
struct
etharp_q_entry
*
old
;
old
=
arp_table
[
i
].
q
;
arp_table
[
i
].
q
=
arp_table
[
i
].
q
->
next
;
pbuf_free
(
old
->
p
);
memp_free
(
MEM_ARP_QUEUE
,
old
);
}
LWIP_DEBUGF
(
ETHARP_DEBUG
|
LWIP_DBG_TRACE
,
(
"etharp_query: queued packet %p on ARP entry %"
S16_F
"
\n
"
,
(
void
*
)
q
,
(
s16_t
)
i
));
result
=
ERR_OK
;
}
else
{
...
...
app/modules/coap.c
View file @
a33e3a4a
...
...
@@ -12,6 +12,7 @@
#include "c_types.h"
#include "mem.h"
#include "lwip/ip_addr.h"
#include "espconn.h"
#include "driver/uart.h"
...
...
app/modules/gpio.c
View file @
a33e3a4a
...
...
@@ -64,7 +64,7 @@ static int lgpio_trig( lua_State* L )
}
else
if
(
sl
==
4
&&
c_strcmp
(
str
,
"down"
)
==
0
){
type
=
GPIO_PIN_INTR_NEGEDGE
;
}
else
if
(
sl
==
4
&&
c_strcmp
(
str
,
"both"
)
==
0
){
type
=
GPIO_PIN_INTR_ANYE
G
DE
;
type
=
GPIO_PIN_INTR_ANYED
G
E
;
}
else
if
(
sl
==
3
&&
c_strcmp
(
str
,
"low"
)
==
0
){
type
=
GPIO_PIN_INTR_LOLEVEL
;
}
else
if
(
sl
==
4
&&
c_strcmp
(
str
,
"high"
)
==
0
){
...
...
@@ -147,8 +147,8 @@ static int lgpio_write( lua_State* L )
}
#define DELAY_TABLE_MAX_LEN 256
#define noInterrupts
o
s_intr_lock
#define interrupts
o
s_intr_unlock
#define noInterrupts
et
s_intr_lock
#define interrupts
et
s_intr_unlock
#define delayMicroseconds os_delay_us
#define DIRECT_WRITE(pin, level) (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), level))
// Lua: serout( pin, firstLevel, delay_table, [repeatNum] )
...
...
app/modules/mqtt.c
View file @
a33e3a4a
...
...
@@ -12,6 +12,7 @@
#include "c_types.h"
#include "mem.h"
#include "lwip/ip_addr.h"
#include "espconn.h"
#include "mqtt_msg.h"
...
...
app/modules/net.c
View file @
a33e3a4a
...
...
@@ -12,6 +12,7 @@
#include "c_types.h"
#include "mem.h"
#include "lwip/ip_addr.h"
#include "espconn.h"
#include "lwip/dns.h"
...
...
@@ -1076,6 +1077,16 @@ static int net_send( lua_State* L, const char* mt )
luaL_unref
(
L
,
LUA_REGISTRYINDEX
,
nud
->
cb_send_ref
);
nud
->
cb_send_ref
=
luaL_ref
(
L
,
LUA_REGISTRYINDEX
);
}
// SDK 1.4.0 changed behaviour, for UDP server need to look up remote ip/port
if
(
isserver
&&
pesp_conn
->
type
==
ESPCONN_UDP
)
{
remot_info
*
pr
=
0
;
if
(
espconn_get_connection_info
(
pesp_conn
,
&
pr
,
0
)
!=
ESPCONN_OK
)
return
luaL_error
(
L
,
"remote ip/port unavailable"
);
pesp_conn
->
proto
.
udp
->
remote_port
=
pr
->
remote_port
;
os_memmove
(
pesp_conn
->
proto
.
udp
->
remote_ip
,
pr
->
remote_ip
,
4
);
// The remot_info apparently should *not* be os_free()d, fyi
}
#ifdef CLIENT_SSL_ENABLE
if
(
nud
->
secure
)
espconn_secure_sent
(
pesp_conn
,
(
unsigned
char
*
)
payload
,
l
);
...
...
app/modules/node.c
View file @
a33e3a4a
...
...
@@ -145,8 +145,58 @@ static int node_heap( lua_State* L )
static
lua_State
*
gL
=
NULL
;
#ifdef DEVKIT_VERSION_0_9
extern
int
led_high_count
;
// this is defined in lua.c
extern
int
led_low_count
;
static
int
led_high_count
=
LED_HIGH_COUNT_DEFAULT
;
static
int
led_low_count
=
LED_LOW_COUNT_DEFAULT
;
static
int
led_count
=
0
;
static
int
key_press_count
=
0
;
static
bool
key_short_pressed
=
false
;
static
bool
key_long_pressed
=
false
;
static
os_timer_t
keyled_timer
;
static
void
update_key_led
(
void
*
p
)
{
(
void
)
p
;
uint8_t
temp
=
1
,
level
=
1
;
led_count
++
;
if
(
led_count
>
led_low_count
+
led_high_count
){
led_count
=
0
;
// reset led_count, the level still high
}
else
if
(
led_count
>
led_low_count
&&
led_count
<=
led_high_count
+
led_low_count
){
level
=
1
;
// output high level
}
else
if
(
led_count
<=
led_low_count
){
level
=
0
;
// output low level
}
temp
=
platform_key_led
(
level
);
if
(
temp
==
0
){
// key is pressed
key_press_count
++
;
if
(
key_press_count
>=
KEY_LONG_COUNT
){
// key_long_press(NULL);
key_long_pressed
=
true
;
key_short_pressed
=
false
;
// key_press_count = 0;
}
else
if
(
key_press_count
>=
KEY_SHORT_COUNT
){
// < KEY_LONG_COUNT
// key_short_press(NULL);
key_short_pressed
=
true
;
}
}
else
{
// key is released
key_press_count
=
0
;
if
(
key_long_pressed
){
key_long_press
(
NULL
);
key_long_pressed
=
false
;
}
if
(
key_short_pressed
){
key_short_press
(
NULL
);
key_short_pressed
=
false
;
}
}
}
static
void
prime_keyled_timer
(
void
)
{
os_timer_disarm
(
&
keyled_timer
);
os_timer_setfn
(
&
keyled_timer
,
update_key_led
,
0
);
os_timer_arm
(
&
keyled_timer
,
KEYLED_INTERVAL
,
1
);
}
// Lua: led(low, high)
static
int
node_led
(
lua_State
*
L
)
{
...
...
@@ -171,6 +221,7 @@ static int node_led( lua_State* L )
}
led_high_count
=
(
uint32_t
)
high
/
READLINE_INTERVAL
;
led_low_count
=
(
uint32_t
)
low
/
READLINE_INTERVAL
;
prime_keyled_timer
();
return
0
;
}
...
...
@@ -246,13 +297,12 @@ static int node_key( lua_State* L )
*
ref
=
LUA_NOREF
;
}
prime_keyled_timer
();
return
0
;
}
#endif
extern
lua_Load
gLoad
;
extern
os_timer_t
lua_timer
;
extern
void
dojob
(
lua_Load
*
load
);
// Lua: input("string")
static
int
node_input
(
lua_State
*
L
)
{
...
...
@@ -269,9 +319,7 @@ static int node_input( lua_State* L )
NODE_DBG
(
"Get command:
\n
"
);
NODE_DBG
(
load
->
line
);
// buggy here
NODE_DBG
(
"
\n
Result(if any):
\n
"
);
os_timer_disarm
(
&
lua_timer
);
os_timer_setfn
(
&
lua_timer
,
(
os_timer_func_t
*
)
dojob
,
load
);
os_timer_arm
(
&
lua_timer
,
READLINE_INTERVAL
,
0
);
// no repeat
system_os_post
(
LUA_TASK_PRIO
,
LUA_PROCESS_LINE_SIG
,
0
);
}
}
return
0
;
...
...
@@ -410,10 +458,10 @@ static int node_setcpufreq(lua_State* L)
uint32_t
new_freq
=
luaL_checkinteger
(
L
,
1
);
if
(
new_freq
==
CPU160MHZ
){
REG_SET_BIT
(
0x3ff00014
,
BIT
(
0
));
o
s_update_cpu_frequency
(
CPU160MHZ
);
et
s_update_cpu_frequency
(
CPU160MHZ
);
}
else
{
REG_CLR_BIT
(
0x3ff00014
,
BIT
(
0
));
o
s_update_cpu_frequency
(
CPU80MHZ
);
et
s_update_cpu_frequency
(
CPU80MHZ
);
}
new_freq
=
ets_get_cpu_frequency
();
lua_pushinteger
(
L
,
new_freq
);
...
...
app/modules/wifi.c
View file @
a33e3a4a
...
...
@@ -28,12 +28,18 @@ static uint8 prev_wifi_status=0;
#else
static
lua_State
*
smart_L
=
NULL
;
#endif
static
void
wifi_smart_succeed_cb
(
void
*
arg
){
static
void
wifi_smart_succeed_cb
(
sc_status
status
,
void
*
pdata
){
NODE_DBG
(
"wifi_smart_succeed_cb is called.
\n
"
);
if
(
status
==
SC_STATUS_LINK_OVER
)
{
smartconfig_stop
();
return
;
}
#if defined( NODE_SMART_OLDSTYLE )
if
(
!
arg
)
if
(
status
!=
SC_STATUS_LINK
||
!
pdata
)
return
;
if
(
wifi_smart_succeed
==
LUA_NOREF
)
return
;
...
...
@@ -44,10 +50,10 @@ static void wifi_smart_succeed_cb(void *arg){
#else
if
(
!
arg
)
if
(
status
!=
SC_STATUS_LINK
||
!
pdata
)
return
;
struct
station_config
*
sta_conf
=
arg
;
struct
station_config
*
sta_conf
=
pdata
;
wifi_station_set_config
(
sta_conf
);
wifi_station_disconnect
();
wifi_station_connect
();
...
...
@@ -63,7 +69,6 @@ static void wifi_smart_succeed_cb(void *arg){
luaL_unref
(
smart_L
,
LUA_REGISTRYINDEX
,
wifi_smart_succeed
);
wifi_smart_succeed
=
LUA_NOREF
;
}
smartconfig_stop
();
#endif // defined( NODE_SMART_OLDSTYLE )
}
...
...
@@ -195,7 +200,8 @@ static int wifi_start_smart( lua_State* L )
if
(
smart_type
>
1
)
return
luaL_error
(
L
,
"wrong arg range"
);
smartconfig_start
(
smart_type
,
wifi_smart_succeed_cb
);
smartconfig_set_type
(
smart_type
);
smartconfig_start
(
wifi_smart_succeed_cb
);
#endif // defined( NODE_SMART_OLDSTYLE )
...
...
@@ -333,7 +339,7 @@ static int wifi_setmac( lua_State* L, uint8_t mode )
if
(
len
!=
17
)
return
luaL_error
(
L
,
"wrong arg type"
);
o
s_str2macaddr
(
mac
,
macaddr
);
et
s_str2macaddr
(
mac
,
macaddr
);
lua_pushboolean
(
L
,
wifi_set_macaddr
(
mode
,
(
uint8
*
)
mac
));
return
1
;
}
...
...
@@ -591,7 +597,7 @@ static int wifi_station_config( lua_State* L )
if
(
ml
!=
17
)
return
luaL_error
(
L
,
"MAC:FF:FF:FF:FF:FF:FF"
);
c_memset
(
sta_conf
.
bssid
,
0
,
6
);
o
s_str2macaddr
(
sta_conf
.
bssid
,
macaddr
);
et
s_str2macaddr
(
sta_conf
.
bssid
,
macaddr
);
sta_conf
.
bssid_set
=
1
;
}
else
...
...
@@ -743,7 +749,7 @@ static int wifi_station_listap( lua_State* L )
if
(
len
!=
17
)
return
luaL_error
(
L
,
"bssid: FF:FF:FF:FF:FF:FF"
);
c_memset
(
bssid
,
0
,
6
);
o
s_str2macaddr
(
bssid
,
macaddr
);
et
s_str2macaddr
(
bssid
,
macaddr
);
scan_cfg
.
bssid
=
bssid
;
NODE_DBG
(
MACSTR
,
MAC2STR
(
scan_cfg
.
bssid
));
NODE_DBG
(
"
\n
"
);
...
...
@@ -1229,7 +1235,7 @@ static int wifi_ap_dhcp_config( lua_State* L )
if
(
ip
==
0
)
return
luaL_error
(
L
,
"wrong arg type"
);
lease
.
start_ip
=
ip
;
lease
.
start_ip
.
addr
=
ip
;
NODE_DBG
(
IPSTR
,
IP2STR
(
&
lease
.
start_ip
));
NODE_DBG
(
"
\n
"
);
...
...
@@ -1335,9 +1341,9 @@ const LUA_REG_TYPE wifi_map[] =
{
LSTRKEY
(
"SOFTAP"
),
LNUMVAL
(
SOFTAP_MODE
)
},
{
LSTRKEY
(
"STATIONAP"
),
LNUMVAL
(
STATIONAP_MODE
)
},
{
LSTRKEY
(
"PHYMODE_B"
),
LNUMVAL
(
PHY_MODE_B
)
},
{
LSTRKEY
(
"PHYMODE_G"
),
LNUMVAL
(
PHY_MODE_G
)
},
{
LSTRKEY
(
"PHYMODE_N"
),
LNUMVAL
(
PHY_MODE_N
)
},
{
LSTRKEY
(
"PHYMODE_B"
),
LNUMVAL
(
PHY_MODE_
11
B
)
},
{
LSTRKEY
(
"PHYMODE_G"
),
LNUMVAL
(
PHY_MODE_
11
G
)
},
{
LSTRKEY
(
"PHYMODE_N"
),
LNUMVAL
(
PHY_MODE_
11
N
)
},
{
LSTRKEY
(
"NONE_SLEEP"
),
LNUMVAL
(
NONE_SLEEP_T
)
},
{
LSTRKEY
(
"LIGHT_SLEEP"
),
LNUMVAL
(
LIGHT_SLEEP_T
)
},
...
...
app/modules/ws2801.c
View file @
a33e3a4a
...
...
@@ -115,11 +115,11 @@ static int ICACHE_FLASH_ATTR ws2801_writergb(lua_State* L) {
os_delay_us
(
10
);
o
s_intr_lock
();
et
s_intr_lock
();
ws2801_strip
(
buffer
,
length
);
o
s_intr_unlock
();
et
s_intr_unlock
();
return
0
;
}
...
...
app/modules/ws2812.c
View file @
a33e3a4a
...
...
@@ -94,9 +94,9 @@ static int ICACHE_FLASH_ATTR ws2812_writergb(lua_State* L)
platform_gpio_write
(
pin
,
0
);
// Send the buffer
o
s_intr_lock
();
et
s_intr_lock
();
ws2812_write
(
pin_num
[
pin
],
(
uint8_t
*
)
buffer
,
length
);
o
s_intr_unlock
();
et
s_intr_unlock
();
c_free
(
buffer
);
...
...
@@ -120,9 +120,9 @@ static int ICACHE_FLASH_ATTR ws2812_writegrb(lua_State* L) {
platform_gpio_write
(
pin
,
0
);
// Send the buffer
o
s_intr_lock
();
et
s_intr_lock
();
ws2812_write
(
pin_num
[
pin
],
(
uint8_t
*
)
buffer
,
length
);
o
s_intr_unlock
();
et
s_intr_unlock
();
return
0
;
}
...
...
app/platform/platform.c
View file @
a33e3a4a
...
...
@@ -55,20 +55,13 @@ int platform_gpio_mode( unsigned pin, unsigned mode, unsigned pull )
switch
(
pull
){
case
PLATFORM_GPIO_PULLUP
:
PIN_PULLDWN_DIS
(
pin_mux
[
pin
]);
PIN_PULLUP_EN
(
pin_mux
[
pin
]);
break
;
case
PLATFORM_GPIO_PULLDOWN
:
PIN_PULLUP_DIS
(
pin_mux
[
pin
]);
PIN_PULLDWN_EN
(
pin_mux
[
pin
]);
break
;
case
PLATFORM_GPIO_FLOAT
:
PIN_PULLUP_DIS
(
pin_mux
[
pin
]);
PIN_PULLDWN_DIS
(
pin_mux
[
pin
]);
break
;
default:
PIN_PULLUP_DIS
(
pin_mux
[
pin
]);
PIN_PULLDWN_DIS
(
pin_mux
[
pin
]);
break
;
}
...
...
@@ -197,7 +190,6 @@ uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int pari
case
BIT_RATE_74880
:
case
BIT_RATE_115200
:
case
BIT_RATE_230400
:
case
BIT_RATE_256000
:
case
BIT_RATE_460800
:
case
BIT_RATE_921600
:
case
BIT_RATE_1843200
:
...
...
app/platform/platform.h
View file @
a33e3a4a
...
...
@@ -27,7 +27,6 @@ uint8_t platform_key_led( uint8_t level);
// GPIO subsection
#define PLATFORM_GPIO_FLOAT 0
#define PLATFORM_GPIO_PULLUP 1
#define PLATFORM_GPIO_PULLDOWN 2
#define PLATFORM_GPIO_INT 2
#define PLATFORM_GPIO_OUTPUT 1
...
...
app/spiffs/spiffs.c
View file @
a33e3a4a
...
...
@@ -46,7 +46,11 @@ The small 4KB sectors allow for greater flexibility in applications th
void
myspiffs_mount
()
{
spiffs_config
cfg
;
#ifdef SPIFFS_FIXED_LOCATION
cfg
.
phys_addr
=
SPIFFS_FIXED_LOCATION
;
#else
cfg
.
phys_addr
=
(
u32_t
)
platform_flash_get_first_free_block_address
(
NULL
);
#endif
cfg
.
phys_addr
+=
0x3000
;
cfg
.
phys_addr
&=
0xFFFFC000
;
// align to 4 sector.
cfg
.
phys_size
=
INTERNAL_FLASH_SIZE
-
(
(
u32_t
)
cfg
.
phys_addr
-
INTERNAL_FLASH_START_ADDRESS
);
...
...
@@ -85,7 +89,11 @@ int myspiffs_format( void )
{
SPIFFS_unmount
(
&
fs
);
u32_t
sect_first
,
sect_last
;
#ifdef SPIFFS_FIXED_LOCATION
sect_first
=
SPIFFS_FIXED_LOCATION
;
#else
sect_first
=
(
u32_t
)
platform_flash_get_first_free_block_address
(
NULL
);
#endif
sect_first
+=
0x3000
;
sect_first
&=
0xFFFFC000
;
// align to 4 sector.
sect_first
=
platform_flash_get_sector_of_address
(
sect_first
);
...
...
app/ssl/app/espconn_secure.c
deleted
100644 → 0
View file @
093a8959
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: espconn_encry.c
*
* Description: data encrypt interface
*
* Modification history:
* 2014/3/31, v1.0 create this file.
*******************************************************************************/
#include "lwip/netif.h"
#include "lwip/inet.h"
#include "netif/etharp.h"
#include "lwip/tcp.h"
#include "lwip/ip.h"
#include "lwip/init.h"
#include "ets_sys.h"
#include "os_type.h"
//#include "os.h"
#include "ssl/app/espconn_ssl.h"
/******************************************************************************
* FunctionName : espconn_encry_connect
* Description : The function given as the connect
* Parameters : espconn -- the espconn used to listen the connection
* Returns : none
*******************************************************************************/
sint8
ICACHE_FLASH_ATTR
espconn_secure_connect
(
struct
espconn
*
espconn
)
{
if
(
espconn
==
NULL
)
return
ESPCONN_ARG
;
return
espconn_ssl_client
(
espconn
);
}
/******************************************************************************
* FunctionName : espconn_encry_disconnect
* Description : The function given as the disconnect
* Parameters : espconn -- the espconn used to listen the connection
* Returns : none
*******************************************************************************/
sint8
ICACHE_FLASH_ATTR
espconn_secure_disconnect
(
struct
espconn
*
espconn
)
{
espconn_msg
*
pnode
=
NULL
;
bool
value
=
false
;
if
(
espconn
==
NULL
)
return
ESPCONN_ARG
;
value
=
espconn_find_connection
(
espconn
,
&
pnode
);
if
(
value
){
espconn_ssl_disconnect
(
pnode
);
return
ESPCONN_OK
;
}
else
return
ESPCONN_ARG
;
}
/******************************************************************************
* FunctionName : espconn_encry_sent
* Description : sent data for client or server
* Parameters : espconn -- espconn to set for client or server
* psent -- data to send
* length -- length of data to send
* Returns : none
*******************************************************************************/
sint8
ICACHE_FLASH_ATTR
espconn_secure_sent
(
struct
espconn
*
espconn
,
uint8
*
psent
,
uint16
length
)
{
espconn_msg
*
pnode
=
NULL
;
bool
value
=
false
;
if
(
espconn
==
NULL
)
return
ESPCONN_ARG
;
espconn
->
state
=
ESPCONN_WRITE
;
value
=
espconn_find_connection
(
espconn
,
&
pnode
);
if
(
value
){
espconn_ssl_sent
(
pnode
,
psent
,
length
);
return
ESPCONN_OK
;
}
else
return
ESPCONN_ARG
;
}
sint8
ICACHE_FLASH_ATTR
espconn_secure_accept
(
struct
espconn
*
espconn
)
{
if
(
espconn
==
NULL
)
return
ESPCONN_ARG
;
return
espconn_ssl_server
(
espconn
);
}
app/ssl/app/espconn_ssl.c
deleted
100644 → 0
View file @
093a8959
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: espconn_ssl.c
*
* Description: ssl encrypt interface
*
* Modification history:
* 2014/3/31, v1.0 create this file.
*******************************************************************************/
#include "lwip/netif.h"
#include "netif/etharp.h"
#include "lwip/tcp.h"
#include "lwip/ip.h"
#include "lwip/init.h"
#include "lwip/tcp_impl.h"
#include "ssl/ssl_os_port.h"
#include "ssl/app/espconn_ssl.h"
#include "ets_sys.h"
#include "os_type.h"
//#include "os.h"
#include "lwip/app/espconn.h"
struct
pbuf
*
psslpbuf
=
NULL
;
extern
espconn_msg
*
plink_active
;
static
err_t
espconn_ssl_crecv
(
void
*
arg
,
struct
tcp_pcb
*
pcb
,
struct
pbuf
*
p
,
err_t
err
);
static
err_t
espconn_ssl_srecv
(
void
*
arg
,
struct
tcp_pcb
*
pcb
,
struct
pbuf
*
p
,
err_t
err
);
static
void
espconn_ssl_sclose
(
void
*
arg
,
struct
tcp_pcb
*
pcb
);
static
void
espconn_ssl_cclose
(
void
*
arg
,
struct
tcp_pcb
*
pcb
);
/////////////////////////////common function///////////////////////////////////
/******************************************************************************
* FunctionName : display_session_id
* Description : Display what session id we have.
* Parameters :
* Returns :
*******************************************************************************/
static
void
ICACHE_FLASH_ATTR
display_session_id
(
SSL
*
ssl
)
{
int
i
;
const
uint8_t
*
session_id
=
ssl_get_session_id
(
ssl
);
int
sess_id_size
=
ssl_get_session_id_size
(
ssl
);
if
(
sess_id_size
>
0
)
{
ssl_printf
(
"-----BEGIN SSL SESSION PARAMETERS-----
\n
"
);
for
(
i
=
0
;
i
<
sess_id_size
;
i
++
)
{
ssl_printf
(
"%02x"
,
session_id
[
i
]);
}
ssl_printf
(
"
\n
-----END SSL SESSION PARAMETERS-----
\n
"
);
//TTY_FLUSH();
}
}
/******************************************************************************
* FunctionName : display_cipher
* Description : Display what cipher we are using
* Parameters :
* Returns :
*******************************************************************************/
static
void
ICACHE_FLASH_ATTR
display_cipher
(
SSL
*
ssl
)
{
ssl_printf
(
"CIPHER is "
);
switch
(
ssl_get_cipher_id
(
ssl
))
{
case
SSL_AES128_SHA
:
ssl_printf
(
"AES128-SHA"
);
break
;
case
SSL_AES256_SHA
:
ssl_printf
(
"AES256-SHA"
);
break
;
case
SSL_RC4_128_SHA
:
ssl_printf
(
"RC4-SHA"
);
break
;
case
SSL_RC4_128_MD5
:
ssl_printf
(
"RC4-MD5"
);
break
;
default:
ssl_printf
(
"Unknown - %d"
,
ssl_get_cipher_id
(
ssl
));
break
;
}
ssl_printf
(
"
\n
"
);
//TTY_FLUSH();
}
/******************************************************************************
* FunctionName : espconn_ssl_reconnect
* Description : reconnect with host
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
static
void
ICACHE_FLASH_ATTR
espconn_ssl_reconnect
(
void
*
arg
)
{
espconn_msg
*
pssl_recon
=
arg
;
struct
espconn
*
espconn
=
NULL
;
ssl_msg
*
pssl
=
NULL
;
sint8
ssl_reerr
=
0
;
if
(
pssl_recon
!=
NULL
)
{
espconn
=
pssl_recon
->
preverse
;
if
(
pssl_recon
->
pespconn
!=
NULL
){
if
(
espconn
!=
NULL
){
/*espconn_copy_partial(espconn, pssl_recon->pespconn);
if (pssl_recon->pespconn->proto.tcp != NULL){
os_free(pssl_recon->pespconn->proto.tcp);
pssl_recon->pespconn->proto.tcp = NULL;
}
os_free(pssl_recon->pespconn);
pssl_recon->pespconn = NULL;*/
espconn
=
pssl_recon
->
preverse
;
}
else
{
espconn
=
pssl_recon
->
pespconn
;
}
}
pssl
=
pssl_recon
->
pssl
;
ssl_reerr
=
pssl_recon
->
pcommon
.
err
;
if
(
pssl
!=
NULL
)
{
if
(
pssl
->
ssl
)
{
ssl_free
(
pssl
->
ssl
);
}
if
(
pssl
->
ssl_ctx
)
{
ssl_ctx_free
(
pssl
->
ssl_ctx
);
}
os_free
(
pssl
);
pssl
=
NULL
;
pssl_recon
->
pssl
=
pssl
;
}
os_free
(
pssl_recon
);
pssl_recon
=
NULL
;
if
(
espconn
->
proto
.
tcp
->
reconnect_callback
!=
NULL
)
{
espconn
->
proto
.
tcp
->
reconnect_callback
(
espconn
,
ssl_reerr
);
}
}
else
{
ssl_printf
(
"espconn_ssl_reconnect err
\n
"
);
}
}
/******************************************************************************
* FunctionName : espconn_ssl_dissuccessful
* Description : as
* Parameters :
* Returns :
*******************************************************************************/
static
void
ICACHE_FLASH_ATTR
espconn_ssl_dissuccessful
(
void
*
arg
)
{
espconn_msg
*
pdiscon
=
arg
;
struct
espconn
*
espconn
=
NULL
;
struct
tcp_pcb
*
pcb
=
NULL
;
ssl_msg
*
pssl
=
NULL
;
if
(
pdiscon
!=
NULL
)
{
espconn
=
pdiscon
->
preverse
;
if
(
pdiscon
->
pespconn
!=
NULL
){
if
(
espconn
!=
NULL
){
/*espconn_copy_partial(espconn, pdiscon->pespconn);
if (pdiscon->pespconn->proto.tcp != NULL){
os_free(pdiscon->pespconn->proto.tcp);
pdiscon->pespconn->proto.tcp = NULL;
}
os_free(pdiscon->pespconn);
pdiscon->pespconn = NULL;*/
espconn
=
pdiscon
->
preverse
;
}
else
{
espconn
=
pdiscon
->
pespconn
;
}
pcb
=
pdiscon
->
pcommon
.
pcb
;
tcp_arg
(
pcb
,
NULL
);
tcp_err
(
pcb
,
NULL
);
}
pssl
=
pdiscon
->
pssl
;
if
(
pssl
!=
NULL
)
{
if
(
pssl
->
ssl
)
{
ssl_free
(
pssl
->
ssl
);
}
if
(
pssl
->
ssl_ctx
)
{
ssl_ctx_free
(
pssl
->
ssl_ctx
);
}
os_free
(
pssl
);
pssl
=
NULL
;
pdiscon
->
pssl
=
pssl
;
}
os_free
(
pdiscon
);
pdiscon
=
NULL
;
if
(
espconn
->
proto
.
tcp
->
disconnect_callback
!=
NULL
)
{
espconn
->
proto
.
tcp
->
disconnect_callback
(
espconn
);
}
}
else
{
espconn_printf
(
"espconn_ssl_dissuccessful err
\n
"
);
}
}
/******************************************************************************
* FunctionName : espconn_ssl_write
* Description : sent data for client or server
* Parameters : void *arg -- client or server to send
* uint8* psent -- Data to send
* uint16 length -- Length of data to send
* Returns : none
*******************************************************************************/
void
ICACHE_FLASH_ATTR
espconn_ssl_sent
(
void
*
arg
,
uint8
*
psent
,
uint16
length
)
{
espconn_msg
*
pssl_sent
=
arg
;
struct
tcp_pcb
*
pcb
=
NULL
;
ssl_msg
*
pssl
=
NULL
;
u16_t
len
=
0
;
int
res
=
0
;
ssl_printf
(
"espconn_ssl_sent pcb %p psent %p length %d
\n
"
,
arg
,
psent
,
length
);
if
(
pssl_sent
==
NULL
||
psent
==
NULL
||
length
==
0
)
{
return
;
}
pcb
=
pssl_sent
->
pcommon
.
pcb
;
pssl
=
pssl_sent
->
pssl
;
if
(
RT_MAX_PLAIN_LENGTH
<
length
)
{
len
=
RT_MAX_PLAIN_LENGTH
;
}
else
{
len
=
length
;
}
if
(
pssl
!=
NULL
)
{
if
(
pssl
->
ssl
!=
NULL
)
{
pssl
->
ssl
->
SslClient_pcb
=
pcb
;
res
=
ssl_write
(
pssl
->
ssl
,
psent
,
len
);
pssl_sent
->
pcommon
.
ptrbuf
=
psent
+
len
;
pssl_sent
->
pcommon
.
cntr
=
length
-
len
;
}
}
}
/******************************************************************************
* FunctionName : espconn_sent_packet
* Description : sent data for client or server
* Parameters : void *arg -- client or server to send
* uint8* psent -- Data to send
* uint16 length -- Length of data to send
* Returns : none
*******************************************************************************/
void
ICACHE_FLASH_ATTR
espconn_sent_packet
(
struct
tcp_pcb
*
pcb
,
uint8
*
psent
,
uint16
length
)
{
err_t
err
=
0
;
u16_t
len
=
0
;
if
(
pcb
==
NULL
||
psent
==
NULL
||
length
==
0
)
{
return
;
}
if
(
tcp_sndbuf
(
pcb
)
<
length
)
{
len
=
tcp_sndbuf
(
pcb
);
}
else
{
len
=
length
;
}
if
(
len
>
(
2
*
pcb
->
mss
))
{
len
=
2
*
pcb
->
mss
;
}
do
{
err
=
tcp_write
(
pcb
,
psent
,
len
,
0
);
if
(
err
==
ERR_MEM
)
{
len
/=
2
;
}
}
while
(
err
==
ERR_MEM
&&
len
>
1
);
if
(
err
==
ERR_OK
)
{
err
=
tcp_output
(
pcb
);
}
}
////////////////////////////////client function////////////////////////////////
/******************************************************************************
* FunctionName : espconn_ssl_cclose_cb
* Description : as
* Parameters :
* Returns :
*******************************************************************************/
static
void
ICACHE_FLASH_ATTR
espconn_ssl_cclose_cb
(
void
*
arg
)
{
static
uint16
timecount
=
0
;
espconn_msg
*
pcclose_cb
=
arg
;
if
(
pcclose_cb
==
NULL
)
{
return
;
}
struct
tcp_pcb
*
pcb
=
pcclose_cb
->
pcommon
.
pcb
;
ssl_printf
(
"espconn_ssl_cclose_cb %d %d
\n
"
,
pcb
->
state
,
pcb
->
nrtx
);
if
(
pcb
->
state
==
TIME_WAIT
||
pcb
->
state
==
CLOSED
)
{
pcclose_cb
->
pespconn
->
state
=
ESPCONN_CLOSE
;
/*remove the node from the client's active connection list*/
espconn_list_delete
(
&
plink_active
,
pcclose_cb
);
espconn_ssl_dissuccessful
((
void
*
)
pcclose_cb
);
}
else
{
os_timer_arm
(
&
pcclose_cb
->
pcommon
.
ptimer
,
TCP_FAST_INTERVAL
,
0
);
}
}
/******************************************************************************
* FunctionName : espconn_sslclient_close
* Description : The connection shall be actively closed.
* Parameters : pcb -- Additional argument to pass to the callback function
* pcb -- the pcb to close
* Returns : none
*******************************************************************************/
static
void
ICACHE_FLASH_ATTR
espconn_ssl_cclose
(
void
*
arg
,
struct
tcp_pcb
*
pcb
)
{
espconn_msg
*
pcclose
=
arg
;
os_timer_disarm
(
&
pcclose
->
pcommon
.
ptimer
);
os_timer_setfn
(
&
pcclose
->
pcommon
.
ptimer
,
espconn_ssl_cclose_cb
,
pcclose
);
os_timer_arm
(
&
pcclose
->
pcommon
.
ptimer
,
TCP_FAST_INTERVAL
,
0
);
tcp_recv
(
pcb
,
NULL
);
pcclose
->
pcommon
.
err
=
tcp_close
(
pcb
);
ssl_printf
(
"espconn_ssl_cclose %d
\n
"
,
pcclose
->
pcommon
.
err
);
if
(
pcclose
->
pcommon
.
err
!=
ERR_OK
)
{
/* closing failed, try again later */
tcp_recv
(
pcb
,
espconn_ssl_crecv
);
}
else
{
tcp_sent
(
pcb
,
NULL
);
tcp_poll
(
pcb
,
NULL
,
0
);
}
}
/******************************************************************************
* FunctionName : espconn_sslclient_sent
* Description : Data has been sent and acknowledged by the remote host.
* This means that more data can be sent.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged
* len -- The amount of bytes acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static
err_t
ICACHE_FLASH_ATTR
espconn_ssl_csent
(
void
*
arg
,
struct
tcp_pcb
*
pcb
,
u16_t
len
)
{
espconn_msg
*
psent
=
arg
;
ssl_msg
*
pssl
=
psent
->
pssl
;
psent
->
pcommon
.
pcb
=
pcb
;
if
(
pssl
->
quiet
==
true
)
{
int
pkt_size
=
pssl
->
ssl
->
bm_index
+
SSL_RECORD_SIZE
;
u16_t
max_len
=
2
*
pcb
->
mss
;
pssl
->
pkt_length
+=
len
;
ssl_printf
(
"espconn_ssl_csent %d %d %d
\n
"
,
len
,
pssl
->
pkt_length
,
pkt_size
);
if
(
pssl
->
pkt_length
==
pkt_size
){
pssl
->
ssl
->
bm_index
=
0
;
pssl
->
pkt_length
=
0
;
if
(
psent
->
pcommon
.
cntr
==
0
)
{
psent
->
pespconn
->
state
=
ESPCONN_CONNECT
;
if
(
psent
->
pespconn
->
sent_callback
!=
NULL
)
{
psent
->
pespconn
->
sent_callback
(
psent
->
pespconn
);
}
}
else
{
espconn_ssl_sent
(
psent
,
psent
->
pcommon
.
ptrbuf
,
psent
->
pcommon
.
cntr
);
}
}
else
{
if
(
len
==
max_len
){
espconn_sent_packet
(
pcb
,
&
pssl
->
ssl
->
bm_all_data
[
pssl
->
pkt_length
],
pkt_size
-
pssl
->
pkt_length
);
}
}
}
else
{
ssl_printf
(
"espconn_ssl_csent %p %p %d
\n
"
,
pcb
,
pssl
->
ssl
->
bm_all_data
,
len
);
}
return
ERR_OK
;
}
/******************************************************************************
* FunctionName : espconn_sslclient_recv
* Description : Data has been received on this pcb.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb which received data
* p -- The received data (or NULL when the connection has been closed!)
* err -- An error code if there has been an error receiving
* Returns : ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static
err_t
ICACHE_FLASH_ATTR
espconn_ssl_crecv
(
void
*
arg
,
struct
tcp_pcb
*
pcb
,
struct
pbuf
*
p
,
err_t
err
)
{
u16_t
ret
=
0
;
espconn_msg
*
precv
=
arg
;
ssl_msg
*
pssl
=
precv
->
pssl
;
ssl_printf
(
"espconn_ssl_crecv %d %p %p
\n
"
,
__LINE__
,
pssl
->
ssl
,
p
);
if
(
p
!=
NULL
)
{
tcp_recved
(
pcb
,
p
->
tot_len
);
if
(
pssl
->
ssl
==
NULL
)
{
pbuf_free
(
p
);
}
else
{
pssl
->
ssl
->
ssl_pbuf
=
p
;
if
(
ssl_handshake_status
(
pssl
->
ssl
)
!=
SSL_OK
)
{
ret
=
ssl_read
(
pssl
->
ssl
,
NULL
);
pbuf_free
(
p
);
if
(
ret
!=
SSL_OK
){
os_printf
(
"client handshake failed
\n
"
);
espconn_ssl_cclose
(
arg
,
pcb
);
}
}
if
(
ssl_handshake_status
(
pssl
->
ssl
)
==
SSL_OK
)
{
if
(
!
pssl
->
quiet
)
{
ssl_printf
(
"client handshake need size %d
\n
"
,
system_get_free_heap_size
());
const
char
*
common_name
=
ssl_get_cert_dn
(
pssl
->
ssl
,
SSL_X509_CERT_COMMON_NAME
);
if
(
common_name
)
{
ssl_printf
(
"Common Name:
\t\t\t
%s
\n
"
,
common_name
);
}
display_session_id
(
pssl
->
ssl
);
display_cipher
(
pssl
->
ssl
);
pssl
->
quiet
=
true
;
os_printf
(
"client handshake ok!
\n
"
);
REG_CLR_BIT
(
0x3ff00014
,
BIT
(
0
));
os_update_cpu_frequency
(
80
);
precv
->
pespconn
->
state
=
ESPCONN_CONNECT
;
precv
->
pcommon
.
pcb
=
pcb
;
pbuf_free
(
p
);
if
(
precv
->
pespconn
->
proto
.
tcp
->
connect_callback
!=
NULL
)
{
precv
->
pespconn
->
proto
.
tcp
->
connect_callback
(
precv
->
pespconn
);
}
}
else
{
uint8_t
*
read_buf
=
NULL
;
ret
=
ssl_read
(
pssl
->
ssl
,
&
read_buf
);
precv
->
pespconn
->
state
=
ESPCONN_READ
;
precv
->
pcommon
.
pcb
=
pcb
;
pbuf_free
(
p
);
if
(
precv
->
pespconn
->
recv_callback
!=
NULL
&&
read_buf
!=
NULL
)
{
precv
->
pespconn
->
recv_callback
(
precv
->
pespconn
,
read_buf
,
ret
);
}
precv
->
pespconn
->
state
=
ESPCONN_CONNECT
;
}
}
}
}
if
(
err
==
ERR_OK
&&
p
==
NULL
)
{
espconn_ssl_cclose
(
precv
,
pcb
);
}
return
ERR_OK
;
}
/******************************************************************************
* FunctionName : espconn_client_err
* Description : The pcb had an error and is already deallocated.
* The argument might still be valid (if != NULL).
* Parameters : arg -- Additional argument to pass to the callback function
* err -- Error code to indicate why the pcb has been closed
* Returns : none
*******************************************************************************/
static
void
ICACHE_FLASH_ATTR
espconn_ssl_cerr
(
void
*
arg
,
err_t
err
)
{
espconn_msg
*
pssl_cerr
=
arg
;
struct
tcp_pcb
*
pcb
=
NULL
;
LWIP_UNUSED_ARG
(
err
);
if
(
pssl_cerr
!=
NULL
)
{
os_timer_disarm
(
&
pssl_cerr
->
pcommon
.
ptimer
);
pcb
=
pssl_cerr
->
pcommon
.
pcb
;
pssl_cerr
->
pespconn
->
state
=
ESPCONN_CLOSE
;
espconn_printf
(
"espconn_ssl_cerr %d %d %d
\n
"
,
pcb
->
state
,
pcb
->
nrtx
,
err
);
/*remove the node from the client's active connection list*/
espconn_list_delete
(
&
plink_active
,
pssl_cerr
);
if
(
err
==
ERR_ABRT
)
{
switch
(
pcb
->
state
)
{
case
SYN_SENT
:
if
(
pcb
->
nrtx
==
TCP_SYNMAXRTX
)
{
pssl_cerr
->
pcommon
.
err
=
ESPCONN_CONN
;
}
else
{
pssl_cerr
->
pcommon
.
err
=
err
;
}
break
;
case
ESTABLISHED
:
if
(
pcb
->
nrtx
==
TCP_MAXRTX
)
{
pssl_cerr
->
pcommon
.
err
=
ESPCONN_TIMEOUT
;
}
else
{
pssl_cerr
->
pcommon
.
err
=
err
;
}
break
;
case
FIN_WAIT_1
:
if
(
pcb
->
nrtx
==
TCP_MAXRTX
)
{
pssl_cerr
->
pcommon
.
err
=
ESPCONN_CLSD
;
}
else
{
pssl_cerr
->
pcommon
.
err
=
err
;
}
break
;
case
FIN_WAIT_2
:
pssl_cerr
->
pcommon
.
err
=
ESPCONN_CLSD
;
break
;
case
CLOSED
:
pssl_cerr
->
pcommon
.
err
=
ESPCONN_CONN
;
break
;
default
:
break
;
}
}
else
{
pssl_cerr
->
pcommon
.
err
=
err
;
}
os_timer_setfn
(
&
pssl_cerr
->
pcommon
.
ptimer
,
espconn_ssl_reconnect
,
pssl_cerr
);
os_timer_arm
(
&
pssl_cerr
->
pcommon
.
ptimer
,
10
,
0
);
}
}
#if 0
/******************************************************************************
* FunctionName : espconn_ssl_cpoll
* Description : The poll function is called every 3nd second.
* If there has been no data sent (which resets the retries) in 3 seconds, close.
* If the last portion of a file has not been sent in 3 seconds, close.
*
* This could be increased, but we don't want to waste resources for bad connections.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_ssl_cpoll(void *arg, struct tcp_pcb *pcb)
{
ssl_printf("espconn_ssl_cpoll %p %d\n", pcb, pcb->state);
struct espconn *espconn = arg;
if (arg == NULL) {
tcp_abandon(pcb, 0);
tcp_poll(pcb, NULL, 0);
return ERR_ABRT;
}
if (pcb ->state == ESTABLISHED) {
espconn->recv_check ++;
if (espconn ->recv_check == 0x05){
//tcp_poll(pcb, espconn_ssl_cpoll, 0);
espconn->recv_check = 0;
espconn_ssl_cclose(arg, pcb);
}
} else {
//tcp_poll(pcb, espconn_ssl_cpoll, 0);
espconn_ssl_cclose(arg, pcb);
}
return ERR_OK;
}
#endif
/******************************************************************************
* FunctionName : espconn_sslclient_connect
* Description : A new incoming connection has been connected.
* Parameters : arg -- Additional argument to pass to the callback function
* tpcb -- The connection pcb which is connected
* err -- An unused error code, always ERR_OK currently
* Returns : connection result
*******************************************************************************/
static
err_t
ICACHE_FLASH_ATTR
espconn_ssl_connect
(
void
*
arg
,
struct
tcp_pcb
*
tpcb
,
err_t
err
)
{
espconn_msg
*
pconnect
=
arg
;
ssl_msg
*
pssl
=
NULL
;
uint32_t
options
;
options
=
SSL_SERVER_VERIFY_LATER
|
SSL_DISPLAY_CERTS
|
SSL_NO_DEFAULT_KEY
;
ssl_printf
(
"espconn_ssl_connect %p %p %p %d
\n
"
,
tpcb
,
arg
,
pespconn
->
psecure
,
system_get_free_heap_size
());
//if (pespconn->psecure != NULL){
// return ERR_ISCONN;
//}
pconnect
->
pcommon
.
pcb
=
tpcb
;
pssl
=
(
ssl_msg
*
)
os_zalloc
(
sizeof
(
ssl_msg
));
pconnect
->
pssl
=
pssl
;
if
(
pssl
==
NULL
)
{
return
ERR_MEM
;
}
REG_SET_BIT
(
0x3ff00014
,
BIT
(
0
));
os_update_cpu_frequency
(
160
);
os_printf
(
"client handshake start.
\n
"
);
pssl
->
quiet
=
false
;
pssl
->
ssl_ctx
=
ssl_ctx_new
(
options
,
SSL_DEFAULT_CLNT_SESS
);
if
(
pssl
->
ssl_ctx
==
NULL
)
{
return
ERR_MEM
;
}
ssl_printf
(
"espconn_ssl_client ssl_ctx %p
\n
"
,
pssl
->
ssl_ctx
);
pssl
->
ssl
=
SSLClient_new
(
pssl
->
ssl_ctx
,
tpcb
,
NULL
,
0
);
if
(
pssl
->
ssl
==
NULL
)
{
return
ERR_MEM
;
}
tcp_arg
(
tpcb
,
arg
);
tcp_sent
(
tpcb
,
espconn_ssl_csent
);
tcp_recv
(
tpcb
,
espconn_ssl_crecv
);
//tcp_poll(tpcb, espconn_ssl_cpoll, 6);
return
ERR_OK
;
}
/******************************************************************************
* FunctionName : espconn_ssl_disconnect
* Description : A new incoming connection has been disconnected.
* Parameters : espconn -- the espconn used to disconnect with host
* Returns : none
*******************************************************************************/
void
ICACHE_FLASH_ATTR
espconn_ssl_disconnect
(
espconn_msg
*
pdis
)
{
if
(
pdis
!=
NULL
)
{
if
(
pdis
->
preverse
==
NULL
)
espconn_ssl_cclose
(
pdis
,
pdis
->
pcommon
.
pcb
);
else
espconn_ssl_sclose
(
pdis
,
pdis
->
pcommon
.
pcb
);
}
else
{
ssl_printf
(
"espconn_ssl_disconnect err.
\n
"
);
}
}
/******************************************************************************
* FunctionName : espconn_ssl_client
* Description : Initialize the client: set up a connect PCB and bind it to
* the defined port
* Parameters : espconn -- the espconn used to build client
* Returns : none
*******************************************************************************/
sint8
ICACHE_FLASH_ATTR
espconn_ssl_client
(
struct
espconn
*
espconn
)
{
struct
tcp_pcb
*
pcb
;
struct
ip_addr
ipaddr
;
espconn_msg
*
pclient
=
NULL
;
pclient
=
plink_active
;
while
(
pclient
!=
NULL
){
if
(
pclient
->
pssl
!=
NULL
)
return
ESPCONN_ISCONN
;
pclient
=
pclient
->
pnext
;
}
pclient
=
(
espconn_msg
*
)
os_zalloc
(
sizeof
(
espconn_msg
));
if
(
pclient
==
NULL
){
return
ESPCONN_MEM
;
}
IP4_ADDR
(
&
ipaddr
,
espconn
->
proto
.
tcp
->
remote_ip
[
0
],
espconn
->
proto
.
tcp
->
remote_ip
[
1
],
espconn
->
proto
.
tcp
->
remote_ip
[
2
],
espconn
->
proto
.
tcp
->
remote_ip
[
3
]);
pcb
=
tcp_new
();
if
(
pcb
==
NULL
)
{
espconn
->
state
=
ESPCONN_NONE
;
os_free
(
pclient
);
pclient
=
NULL
;
return
ESPCONN_MEM
;
}
else
{
/*insert the node to the active connection list*/
espconn_list_creat
(
&
plink_active
,
pclient
);
tcp_arg
(
pcb
,
(
void
*
)
pclient
);
tcp_err
(
pcb
,
espconn_ssl_cerr
);
pclient
->
preverse
=
NULL
;
pclient
->
pespconn
=
espconn
;
pclient
->
pespconn
->
state
=
ESPCONN_WAIT
;
pclient
->
pcommon
.
pcb
=
pcb
;
tcp_bind
(
pcb
,
IP_ADDR_ANY
,
pclient
->
pespconn
->
proto
.
tcp
->
local_port
);
pclient
->
pcommon
.
err
=
tcp_connect
(
pcb
,
&
ipaddr
,
pclient
->
pespconn
->
proto
.
tcp
->
remote_port
,
espconn_ssl_connect
);
return
ESPCONN_OK
;
}
}
/////////////////////////////server's function/////////////////////////////////
/******************************************************************************
* FunctionName : espconn_ssl_sclose_cb
* Description : as
* Parameters :
* Returns :
*******************************************************************************/
static
void
ICACHE_FLASH_ATTR
espconn_ssl_sclose_cb
(
void
*
arg
)
{
static
uint16
timecount
=
0
;
espconn_msg
*
psclose_cb
=
arg
;
if
(
psclose_cb
==
NULL
)
{
return
;
}
struct
tcp_pcb
*
pcb
=
psclose_cb
->
pcommon
.
pcb
;
ssl_printf
(
"espconn_ssl_sclose_cb %d %d
\n
"
,
pcb
->
state
,
pcb
->
nrtx
);
if
(
pcb
->
state
==
CLOSED
||
pcb
->
state
==
TIME_WAIT
)
{
psclose_cb
->
pespconn
->
state
=
ESPCONN_CLOSE
;
psclose_cb
->
pespconn
->
link_cnt
--
;
/*remove the node from the server's active connection list*/
espconn_list_delete
(
&
plink_active
,
psclose_cb
);
espconn_ssl_dissuccessful
((
void
*
)
psclose_cb
);
}
else
{
os_timer_arm
(
&
psclose_cb
->
pcommon
.
ptimer
,
TCP_FAST_INTERVAL
,
0
);
}
}
/******************************************************************************
* FunctionName : espconn_sslclient_close
* Description : The connection shall be actively closed.
* Parameters : pcb -- Additional argument to pass to the callback function
* pcb -- the pcb to close
* Returns : none
*******************************************************************************/
static
void
ICACHE_FLASH_ATTR
espconn_ssl_sclose
(
void
*
arg
,
struct
tcp_pcb
*
pcb
)
{
espconn_msg
*
psclose
=
arg
;
os_timer_disarm
(
&
psclose
->
pcommon
.
ptimer
);
os_timer_setfn
(
&
psclose
->
pcommon
.
ptimer
,
espconn_ssl_sclose_cb
,
psclose
);
os_timer_arm
(
&
psclose
->
pcommon
.
ptimer
,
TCP_FAST_INTERVAL
,
0
);
tcp_recv
(
pcb
,
NULL
);
psclose
->
pcommon
.
err
=
tcp_close
(
pcb
);
if
(
psclose
->
pcommon
.
err
!=
ERR_OK
)
{
/* closing failed, try again later */
tcp_recv
(
pcb
,
espconn_ssl_srecv
);
}
else
{
tcp_sent
(
pcb
,
NULL
);
tcp_poll
(
pcb
,
NULL
,
0
);
}
}
/******************************************************************************
* FunctionName : espconn_sslclient_sent
* Description : Data has been sent and acknowledged by the remote host.
* This means that more data can be sent.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged
* len -- The amount of bytes acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static
err_t
ICACHE_FLASH_ATTR
espconn_ssl_ssent
(
void
*
arg
,
struct
tcp_pcb
*
pcb
,
u16_t
len
)
{
espconn_msg
*
psent
=
arg
;
ssl_msg
*
pssl
=
psent
->
pssl
;
psent
->
pcommon
.
pcb
=
pcb
;
psent
->
pcommon
.
recv_check
=
0
;
if
(
ssl_handshake_status
(
pssl
->
ssl
)
==
SSL_OK
)
{
if
(
!
pssl
->
quiet
)
{
ssl_printf
(
"espconn_ssl_ssent %p %d
\n
"
,
pcb
,
system_get_free_heap_size
());
const
char
*
common_name
=
ssl_get_cert_dn
(
pssl
->
ssl
,
SSL_X509_CERT_COMMON_NAME
);
if
(
common_name
)
{
ssl_printf
(
"Common Name:
\t\t\t
%s
\n
"
,
common_name
);
}
display_session_id
(
pssl
->
ssl
);
display_cipher
(
pssl
->
ssl
);
pssl
->
quiet
=
true
;
os_printf
(
"server handshake ok!
\n
"
);
REG_CLR_BIT
(
0x3ff00014
,
BIT
(
0
));
os_update_cpu_frequency
(
80
);
psent
->
pespconn
->
state
=
ESPCONN_CONNECT
;
if
(
psent
->
pespconn
->
proto
.
tcp
->
connect_callback
!=
NULL
)
{
psent
->
pespconn
->
proto
.
tcp
->
connect_callback
(
psent
->
pespconn
);
}
}
else
{
int
pkt_size
=
pssl
->
ssl
->
bm_index
+
SSL_RECORD_SIZE
;
u16_t
max_len
=
2
*
pcb
->
mss
;
pssl
->
pkt_length
+=
len
;
ssl_printf
(
"espconn_ssl_ssent %d %d %d
\n
"
,
len
,
pssl
->
pkt_length
,
pkt_size
);
if
(
pssl
->
pkt_length
==
pkt_size
){
pssl
->
ssl
->
bm_index
=
0
;
pssl
->
pkt_length
=
0
;
if
(
psent
->
pcommon
.
cntr
==
0
)
{
psent
->
pespconn
->
state
=
ESPCONN_CONNECT
;
if
(
psent
->
pespconn
->
sent_callback
!=
NULL
)
{
psent
->
pespconn
->
sent_callback
(
psent
->
pespconn
);
}
}
else
{
espconn_ssl_sent
(
psent
,
psent
->
pcommon
.
ptrbuf
,
psent
->
pcommon
.
cntr
);
}
}
else
{
if
(
len
==
max_len
){
espconn_sent_packet
(
pcb
,
&
pssl
->
ssl
->
bm_all_data
[
pssl
->
pkt_length
],
pkt_size
-
pssl
->
pkt_length
);
}
}
}
}
else
{
ssl_printf
(
"espconn_ssl_ssent %p %p %d
\n
"
,
pcb
,
pssl
->
ssl
->
bm_all_data
,
len
);
}
return
ERR_OK
;
}
/******************************************************************************
* FunctionName : espconn_sslclient_recv
* Description : Data has been received on this pcb.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb which received data
* p -- The received data (or NULL when the connection has been closed!)
* err -- An error code if there has been an error receiving
* Returns : ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static
err_t
ICACHE_FLASH_ATTR
espconn_ssl_srecv
(
void
*
arg
,
struct
tcp_pcb
*
pcb
,
struct
pbuf
*
p
,
err_t
err
)
{
u16_t
ret
=
0
;
espconn_msg
*
precv
=
arg
;
ssl_msg
*
pssl
=
precv
->
pssl
;
ssl_printf
(
"espconn_ssl_srecv %d %p %p
\n
"
,
__LINE__
,
pcb
,
p
);
if
(
p
!=
NULL
)
{
tcp_recved
(
pcb
,
p
->
tot_len
);
precv
->
pcommon
.
recv_check
=
0
;
if
(
pssl
->
ssl
==
NULL
)
{
pbuf_free
(
p
);
}
else
{
pssl
->
ssl
->
ssl_pbuf
=
p
;
if
(
ssl_handshake_status
(
pssl
->
ssl
)
!=
SSL_OK
)
{
ret
=
ssl_read
(
pssl
->
ssl
,
NULL
);
pbuf_free
(
p
);
if
(
ret
!=
SSL_OK
){
os_printf
(
"server handshake failed.
\n
"
);
espconn_ssl_sclose
(
arg
,
pcb
);
}
}
else
{
uint8_t
*
read_buf
=
NULL
;
ret
=
ssl_read
(
pssl
->
ssl
,
&
read_buf
);
precv
->
pespconn
->
state
=
ESPCONN_READ
;
precv
->
pcommon
.
pcb
=
pcb
;
pbuf_free
(
p
);
if
(
precv
->
pespconn
->
recv_callback
!=
NULL
&&
read_buf
!=
NULL
)
{
precv
->
pespconn
->
recv_callback
(
precv
->
pespconn
,
read_buf
,
ret
);
}
precv
->
pespconn
->
state
=
ESPCONN_CONNECT
;
}
}
}
if
(
err
==
ERR_OK
&&
p
==
NULL
)
{
espconn_ssl_sclose
(
precv
,
pcb
);
}
return
ERR_OK
;
}
/******************************************************************************
* FunctionName : espconn_server_poll
* Description : The poll function is called every 3nd second.
* If there has been no data sent (which resets the retries) in 3 seconds, close.
* If the last portion of a file has not been sent in 3 seconds, close.
*
* This could be increased, but we don't want to waste resources for bad connections.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static
err_t
ICACHE_FLASH_ATTR
espconn_ssl_spoll
(
void
*
arg
,
struct
tcp_pcb
*
pcb
)
{
ssl_printf
(
"espconn_ssl_spoll %p %d
\n
"
,
pcb
,
pcb
->
state
);
espconn_msg
*
pspoll
=
arg
;
if
(
arg
==
NULL
)
{
tcp_abandon
(
pcb
,
0
);
tcp_poll
(
pcb
,
NULL
,
0
);
return
ERR_ABRT
;
}
if
(
pcb
->
state
==
ESTABLISHED
)
{
pspoll
->
pcommon
.
recv_check
++
;
if
(
pspoll
->
pcommon
.
recv_check
==
pspoll
->
pcommon
.
timeout
){
tcp_poll
(
pcb
,
NULL
,
0
);
pspoll
->
pcommon
.
recv_check
=
0
;
espconn_ssl_sclose
(
arg
,
pcb
);
}
}
else
{
tcp_poll
(
pcb
,
NULL
,
0
);
espconn_ssl_sclose
(
arg
,
pcb
);
}
return
ERR_OK
;
}
/******************************************************************************
* FunctionName : esponn_server_err
* Description : The pcb had an error and is already deallocated.
* The argument might still be valid (if != NULL).
* Parameters : arg -- Additional argument to pass to the callback function
* err -- Error code to indicate why the pcb has been closed
* Returns : none
*******************************************************************************/
static
void
ICACHE_FLASH_ATTR
espconn_ssl_serr
(
void
*
arg
,
err_t
err
)
{
espconn_msg
*
pserr
=
arg
;
struct
tcp_pcb
*
pcb
=
NULL
;
LWIP_UNUSED_ARG
(
err
);
if
(
pserr
!=
NULL
)
{
os_timer_disarm
(
&
pserr
->
pcommon
.
ptimer
);
pcb
=
pserr
->
pcommon
.
pcb
;
pserr
->
pespconn
->
state
=
ESPCONN_CLOSE
;
/*remove the node from the server's active connection list*/
espconn_list_delete
(
&
plink_active
,
pserr
);
if
(
err
==
ERR_ABRT
)
{
switch
(
pcb
->
state
)
{
case
SYN_RCVD
:
if
(
pcb
->
nrtx
==
TCP_SYNMAXRTX
)
{
pserr
->
pcommon
.
err
=
ESPCONN_CONN
;
}
else
{
pserr
->
pcommon
.
err
=
err
;
}
break
;
case
ESTABLISHED
:
if
(
pcb
->
nrtx
==
TCP_MAXRTX
)
{
pserr
->
pcommon
.
err
=
ESPCONN_TIMEOUT
;
}
else
{
pserr
->
pcommon
.
err
=
err
;
}
break
;
case
CLOSE_WAIT
:
if
(
pcb
->
nrtx
==
TCP_MAXRTX
)
{
pserr
->
pcommon
.
err
=
ESPCONN_CLSD
;
}
else
{
pserr
->
pcommon
.
err
=
err
;
}
break
;
case
LAST_ACK
:
pserr
->
pcommon
.
err
=
ESPCONN_CLSD
;
break
;
case
CLOSED
:
pserr
->
pcommon
.
err
=
ESPCONN_CONN
;
break
;
default
:
break
;
}
}
else
{
pserr
->
pcommon
.
err
=
err
;
}
os_timer_setfn
(
&
pserr
->
pcommon
.
ptimer
,
espconn_ssl_reconnect
,
pserr
);
os_timer_arm
(
&
pserr
->
pcommon
.
ptimer
,
10
,
0
);
}
}
/******************************************************************************
* FunctionName : espconn_tcp_accept
* Description : A new incoming connection has been accepted.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb which is accepted
* err -- An unused error code, always ERR_OK currently
* Returns : acception result
*******************************************************************************/
static
err_t
ICACHE_FLASH_ATTR
espconn_ssl_accept
(
void
*
arg
,
struct
tcp_pcb
*
pcb
,
err_t
err
)
{
struct
espconn
*
espconn
=
arg
;
ssl_msg
*
pssl
=
NULL
;
espconn_msg
*
paccept
=
NULL
;
remot_info
*
pinfo
=
NULL
;
ssl_printf
(
"espconn_ssl_accept %p %p %p %d
\n
"
,
pcb
,
arg
,
espconn
->
psecure
,
system_get_free_heap_size
());
LWIP_UNUSED_ARG
(
err
);
paccept
=
(
espconn_msg
*
)
os_zalloc
(
sizeof
(
espconn_msg
));
tcp_arg
(
pcb
,
paccept
);
tcp_err
(
pcb
,
espconn_ssl_serr
);
if
(
paccept
==
NULL
)
return
ERR_MEM
;
/*insert the node to the active connection list*/
espconn_list_creat
(
&
plink_active
,
paccept
);
paccept
->
preverse
=
espconn
;
paccept
->
pespconn
=
espconn
;
paccept
->
pcommon
.
timeout
=
0x0a
;
paccept
->
pcommon
.
pcb
=
pcb
;
paccept
->
pcommon
.
remote_port
=
pcb
->
remote_port
;
paccept
->
pcommon
.
remote_ip
[
0
]
=
ip4_addr1_16
(
&
pcb
->
remote_ip
);
paccept
->
pcommon
.
remote_ip
[
1
]
=
ip4_addr2_16
(
&
pcb
->
remote_ip
);
paccept
->
pcommon
.
remote_ip
[
2
]
=
ip4_addr3_16
(
&
pcb
->
remote_ip
);
paccept
->
pcommon
.
remote_ip
[
3
]
=
ip4_addr4_16
(
&
pcb
->
remote_ip
);
os_memcpy
(
espconn
->
proto
.
tcp
->
remote_ip
,
paccept
->
pcommon
.
remote_ip
,
4
);
espconn
->
proto
.
tcp
->
remote_port
=
pcb
->
remote_port
;
espconn_get_connection_info
(
espconn
,
&
pinfo
,
ESPCONN_SSL
);
if
(
espconn
->
link_cnt
==
0x01
)
return
ERR_ISCONN
;
pssl
=
(
ssl_msg
*
)
os_zalloc
(
sizeof
(
ssl_msg
));
paccept
->
pssl
=
pssl
;
if
(
pssl
==
NULL
)
{
return
ERR_MEM
;
}
REG_SET_BIT
(
0x3ff00014
,
BIT
(
0
));
os_update_cpu_frequency
(
160
);
os_printf
(
"server handshake start.
\n
"
);
pssl
->
quiet
=
false
;
pssl
->
ssl_ctx
=
ssl_ctx_new
(
SSL_DISPLAY_CERTS
,
SSL_DEFAULT_SVR_SESS
);
if
(
pssl
->
ssl_ctx
==
NULL
)
{
ssl_printf
(
"Error: Server context is invalid
\n
"
);
return
ERR_MEM
;
}
ssl_printf
(
"Server context %p
\n
"
,
pssl
->
ssl_ctx
);
pssl
->
ssl
=
sslserver_new
(
pssl
->
ssl_ctx
,
pcb
);
if
(
pssl
->
ssl
==
NULL
)
{
ssl_printf
(
"Error: Server ssl connection is invalid
\n
"
);
return
ERR_MEM
;
}
tcp_sent
(
pcb
,
espconn_ssl_ssent
);
tcp_recv
(
pcb
,
espconn_ssl_srecv
);
tcp_poll
(
pcb
,
espconn_ssl_spoll
,
2
);
return
ERR_OK
;
}
/******************************************************************************
* FunctionName : espconn_ssl_server
* Description : as
* Parameters :
* Returns :
*******************************************************************************/
sint8
ICACHE_FLASH_ATTR
espconn_ssl_server
(
struct
espconn
*
espconn
)
{
struct
tcp_pcb
*
pcb
;
pcb
=
tcp_new
();
if
(
pcb
==
NULL
)
{
espconn
->
state
=
ESPCONN_NONE
;
return
ESPCONN_MEM
;
}
else
{
tcp_bind
(
pcb
,
IP_ADDR_ANY
,
espconn
->
proto
.
tcp
->
local_port
);
pcb
=
tcp_listen
(
pcb
);
if
(
pcb
!=
NULL
)
{
espconn
->
state
=
ESPCONN_LISTEN
;
tcp_arg
(
pcb
,
(
void
*
)
espconn
);
tcp_accept
(
pcb
,
espconn_ssl_accept
);
return
ESPCONN_OK
;
}
else
{
espconn
->
state
=
ESPCONN_NONE
;
return
ESPCONN_MEM
;
}
}
}
app/ssl/crypto/ssl_aes.c
deleted
100644 → 0
View file @
093a8959
/*
* Copyright (c) 2007, Cameron Rich
*
* 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 name of the axTLS project 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.
*/
/**
* AES implementation - this is a small code version. There are much faster
* versions around but they are much larger in size (i.e. they use large
* submix tables).
*/
//#include <string.h>
#include "lwip/opt.h"
#include "lwip/def.h"
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_crypto.h"
/* all commented out in skeleton mode */
#ifndef CONFIG_SSL_SKELETON_MODE
#define rot1(x) (((x) << 24) | ((x) >> 8))
#define rot2(x) (((x) << 16) | ((x) >> 16))
#define rot3(x) (((x) << 8) | ((x) >> 24))
/*
* This cute trick does 4 'mul by two' at once. Stolen from
* Dr B. R. Gladman <brg@gladman.uk.net> but I'm sure the u-(u>>7) is
* a standard graphics trick
* The key to this is that we need to xor with 0x1b if the top bit is set.
* a 1xxx xxxx 0xxx 0xxx First we mask the 7bit,
* b 1000 0000 0000 0000 then we shift right by 7 putting the 7bit in 0bit,
* c 0000 0001 0000 0000 we then subtract (c) from (b)
* d 0111 1111 0000 0000 and now we and with our mask
* e 0001 1011 0000 0000
*/
#define mt 0x80808080
#define ml 0x7f7f7f7f
#define mh 0xfefefefe
#define mm 0x1b1b1b1b
#define mul2(x,t) ((t)=((x)&mt), \
((((x)+(x))&mh)^(((t)-((t)>>7))&mm)))
#define inv_mix_col(x,f2,f4,f8,f9) (\
(f2)=mul2(x,f2), \
(f4)=mul2(f2,f4), \
(f8)=mul2(f4,f8), \
(f9)=(x)^(f8), \
(f8)=((f2)^(f4)^(f8)), \
(f2)^=(f9), \
(f4)^=(f9), \
(f8)^=rot3(f2), \
(f8)^=rot2(f4), \
(f8)^rot1(f9))
/*
* AES S-box
*/
static
const
uint8_t
aes_sbox
[
256
]
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
{
0x63
,
0x7C
,
0x77
,
0x7B
,
0xF2
,
0x6B
,
0x6F
,
0xC5
,
0x30
,
0x01
,
0x67
,
0x2B
,
0xFE
,
0xD7
,
0xAB
,
0x76
,
0xCA
,
0x82
,
0xC9
,
0x7D
,
0xFA
,
0x59
,
0x47
,
0xF0
,
0xAD
,
0xD4
,
0xA2
,
0xAF
,
0x9C
,
0xA4
,
0x72
,
0xC0
,
0xB7
,
0xFD
,
0x93
,
0x26
,
0x36
,
0x3F
,
0xF7
,
0xCC
,
0x34
,
0xA5
,
0xE5
,
0xF1
,
0x71
,
0xD8
,
0x31
,
0x15
,
0x04
,
0xC7
,
0x23
,
0xC3
,
0x18
,
0x96
,
0x05
,
0x9A
,
0x07
,
0x12
,
0x80
,
0xE2
,
0xEB
,
0x27
,
0xB2
,
0x75
,
0x09
,
0x83
,
0x2C
,
0x1A
,
0x1B
,
0x6E
,
0x5A
,
0xA0
,
0x52
,
0x3B
,
0xD6
,
0xB3
,
0x29
,
0xE3
,
0x2F
,
0x84
,
0x53
,
0xD1
,
0x00
,
0xED
,
0x20
,
0xFC
,
0xB1
,
0x5B
,
0x6A
,
0xCB
,
0xBE
,
0x39
,
0x4A
,
0x4C
,
0x58
,
0xCF
,
0xD0
,
0xEF
,
0xAA
,
0xFB
,
0x43
,
0x4D
,
0x33
,
0x85
,
0x45
,
0xF9
,
0x02
,
0x7F
,
0x50
,
0x3C
,
0x9F
,
0xA8
,
0x51
,
0xA3
,
0x40
,
0x8F
,
0x92
,
0x9D
,
0x38
,
0xF5
,
0xBC
,
0xB6
,
0xDA
,
0x21
,
0x10
,
0xFF
,
0xF3
,
0xD2
,
0xCD
,
0x0C
,
0x13
,
0xEC
,
0x5F
,
0x97
,
0x44
,
0x17
,
0xC4
,
0xA7
,
0x7E
,
0x3D
,
0x64
,
0x5D
,
0x19
,
0x73
,
0x60
,
0x81
,
0x4F
,
0xDC
,
0x22
,
0x2A
,
0x90
,
0x88
,
0x46
,
0xEE
,
0xB8
,
0x14
,
0xDE
,
0x5E
,
0x0B
,
0xDB
,
0xE0
,
0x32
,
0x3A
,
0x0A
,
0x49
,
0x06
,
0x24
,
0x5C
,
0xC2
,
0xD3
,
0xAC
,
0x62
,
0x91
,
0x95
,
0xE4
,
0x79
,
0xE7
,
0xC8
,
0x37
,
0x6D
,
0x8D
,
0xD5
,
0x4E
,
0xA9
,
0x6C
,
0x56
,
0xF4
,
0xEA
,
0x65
,
0x7A
,
0xAE
,
0x08
,
0xBA
,
0x78
,
0x25
,
0x2E
,
0x1C
,
0xA6
,
0xB4
,
0xC6
,
0xE8
,
0xDD
,
0x74
,
0x1F
,
0x4B
,
0xBD
,
0x8B
,
0x8A
,
0x70
,
0x3E
,
0xB5
,
0x66
,
0x48
,
0x03
,
0xF6
,
0x0E
,
0x61
,
0x35
,
0x57
,
0xB9
,
0x86
,
0xC1
,
0x1D
,
0x9E
,
0xE1
,
0xF8
,
0x98
,
0x11
,
0x69
,
0xD9
,
0x8E
,
0x94
,
0x9B
,
0x1E
,
0x87
,
0xE9
,
0xCE
,
0x55
,
0x28
,
0xDF
,
0x8C
,
0xA1
,
0x89
,
0x0D
,
0xBF
,
0xE6
,
0x42
,
0x68
,
0x41
,
0x99
,
0x2D
,
0x0F
,
0xB0
,
0x54
,
0xBB
,
0x16
,
};
/*
* AES is-box
*/
static
const
uint8_t
aes_isbox
[
256
]
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
{
0x52
,
0x09
,
0x6a
,
0xd5
,
0x30
,
0x36
,
0xa5
,
0x38
,
0xbf
,
0x40
,
0xa3
,
0x9e
,
0x81
,
0xf3
,
0xd7
,
0xfb
,
0x7c
,
0xe3
,
0x39
,
0x82
,
0x9b
,
0x2f
,
0xff
,
0x87
,
0x34
,
0x8e
,
0x43
,
0x44
,
0xc4
,
0xde
,
0xe9
,
0xcb
,
0x54
,
0x7b
,
0x94
,
0x32
,
0xa6
,
0xc2
,
0x23
,
0x3d
,
0xee
,
0x4c
,
0x95
,
0x0b
,
0x42
,
0xfa
,
0xc3
,
0x4e
,
0x08
,
0x2e
,
0xa1
,
0x66
,
0x28
,
0xd9
,
0x24
,
0xb2
,
0x76
,
0x5b
,
0xa2
,
0x49
,
0x6d
,
0x8b
,
0xd1
,
0x25
,
0x72
,
0xf8
,
0xf6
,
0x64
,
0x86
,
0x68
,
0x98
,
0x16
,
0xd4
,
0xa4
,
0x5c
,
0xcc
,
0x5d
,
0x65
,
0xb6
,
0x92
,
0x6c
,
0x70
,
0x48
,
0x50
,
0xfd
,
0xed
,
0xb9
,
0xda
,
0x5e
,
0x15
,
0x46
,
0x57
,
0xa7
,
0x8d
,
0x9d
,
0x84
,
0x90
,
0xd8
,
0xab
,
0x00
,
0x8c
,
0xbc
,
0xd3
,
0x0a
,
0xf7
,
0xe4
,
0x58
,
0x05
,
0xb8
,
0xb3
,
0x45
,
0x06
,
0xd0
,
0x2c
,
0x1e
,
0x8f
,
0xca
,
0x3f
,
0x0f
,
0x02
,
0xc1
,
0xaf
,
0xbd
,
0x03
,
0x01
,
0x13
,
0x8a
,
0x6b
,
0x3a
,
0x91
,
0x11
,
0x41
,
0x4f
,
0x67
,
0xdc
,
0xea
,
0x97
,
0xf2
,
0xcf
,
0xce
,
0xf0
,
0xb4
,
0xe6
,
0x73
,
0x96
,
0xac
,
0x74
,
0x22
,
0xe7
,
0xad
,
0x35
,
0x85
,
0xe2
,
0xf9
,
0x37
,
0xe8
,
0x1c
,
0x75
,
0xdf
,
0x6e
,
0x47
,
0xf1
,
0x1a
,
0x71
,
0x1d
,
0x29
,
0xc5
,
0x89
,
0x6f
,
0xb7
,
0x62
,
0x0e
,
0xaa
,
0x18
,
0xbe
,
0x1b
,
0xfc
,
0x56
,
0x3e
,
0x4b
,
0xc6
,
0xd2
,
0x79
,
0x20
,
0x9a
,
0xdb
,
0xc0
,
0xfe
,
0x78
,
0xcd
,
0x5a
,
0xf4
,
0x1f
,
0xdd
,
0xa8
,
0x33
,
0x88
,
0x07
,
0xc7
,
0x31
,
0xb1
,
0x12
,
0x10
,
0x59
,
0x27
,
0x80
,
0xec
,
0x5f
,
0x60
,
0x51
,
0x7f
,
0xa9
,
0x19
,
0xb5
,
0x4a
,
0x0d
,
0x2d
,
0xe5
,
0x7a
,
0x9f
,
0x93
,
0xc9
,
0x9c
,
0xef
,
0xa0
,
0xe0
,
0x3b
,
0x4d
,
0xae
,
0x2a
,
0xf5
,
0xb0
,
0xc8
,
0xeb
,
0xbb
,
0x3c
,
0x83
,
0x53
,
0x99
,
0x61
,
0x17
,
0x2b
,
0x04
,
0x7e
,
0xba
,
0x77
,
0xd6
,
0x26
,
0xe1
,
0x69
,
0x14
,
0x63
,
0x55
,
0x21
,
0x0c
,
0x7d
};
static
const
unsigned
char
Rcon
[
30
]
=
{
0x01
,
0x02
,
0x04
,
0x08
,
0x10
,
0x20
,
0x40
,
0x80
,
0x1b
,
0x36
,
0x6c
,
0xd8
,
0xab
,
0x4d
,
0x9a
,
0x2f
,
0x5e
,
0xbc
,
0x63
,
0xc6
,
0x97
,
0x35
,
0x6a
,
0xd4
,
0xb3
,
0x7d
,
0xfa
,
0xef
,
0xc5
,
0x91
,
};
/* ----- static functions ----- */
static
void
AES_encrypt
(
const
AES_CTX
*
ctx
,
uint32_t
*
data
);
static
void
AES_decrypt
(
const
AES_CTX
*
ctx
,
uint32_t
*
data
);
/* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial
x^8+x^4+x^3+x+1 */
static
unsigned
char
ICACHE_FLASH_ATTR
AES_xtime
(
uint32_t
x
)
{
return
(
x
&
0x80
)
?
(
x
<<
1
)
^
0x1b
:
x
<<
1
;
}
/**
* Set up AES with the key/iv and cipher size.
*/
void
ICACHE_FLASH_ATTR
AES_set_key
(
AES_CTX
*
ctx
,
const
uint8_t
*
key
,
const
uint8_t
*
iv
,
AES_MODE
mode
)
{
int
i
,
ii
;
uint32_t
*
W
,
tmp
,
tmp2
;
const
unsigned
char
*
ip
;
int
words
;
switch
(
mode
)
{
case
AES_MODE_128
:
i
=
10
;
words
=
4
;
break
;
case
AES_MODE_256
:
i
=
14
;
words
=
8
;
break
;
default:
/* fail silently */
return
;
}
ctx
->
rounds
=
i
;
ctx
->
key_size
=
words
;
W
=
ctx
->
ks
;
for
(
i
=
0
;
i
<
words
;
i
+=
2
)
{
W
[
i
+
0
]
=
((
uint32_t
)
key
[
0
]
<<
24
)
|
((
uint32_t
)
key
[
1
]
<<
16
)
|
((
uint32_t
)
key
[
2
]
<<
8
)
|
((
uint32_t
)
key
[
3
]
);
W
[
i
+
1
]
=
((
uint32_t
)
key
[
4
]
<<
24
)
|
((
uint32_t
)
key
[
5
]
<<
16
)
|
((
uint32_t
)
key
[
6
]
<<
8
)
|
((
uint32_t
)
key
[
7
]
);
key
+=
8
;
}
ip
=
Rcon
;
ii
=
4
*
(
ctx
->
rounds
+
1
);
for
(
i
=
words
;
i
<
ii
;
i
++
)
{
tmp
=
W
[
i
-
1
];
if
((
i
%
words
)
==
0
)
{
// tmp2 =(uint32_t)aes_sbox[(tmp )&0xff]<< 8;
// tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<<16;
// tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<24;
// tmp2|=(uint32_t)aes_sbox[(tmp>>24) ];
tmp2
=
((
uint32_t
)
byte_of_aligned_array
(
aes_sbox
,(
tmp
)
&
0xff
))
<<
8
;
tmp2
|=
((
uint32_t
)
byte_of_aligned_array
(
aes_sbox
,(
tmp
>>
8
)
&
0xff
))
<<
16
;
tmp2
|=
((
uint32_t
)
byte_of_aligned_array
(
aes_sbox
,(
tmp
>>
16
)
&
0xff
))
<<
24
;
tmp2
|=
((
uint32_t
)
byte_of_aligned_array
(
aes_sbox
,(
tmp
>>
24
)
));
tmp
=
tmp2
^
(((
unsigned
int
)
*
ip
)
<<
24
);
ip
++
;
}
if
((
words
==
8
)
&&
((
i
%
words
)
==
4
))
{
// tmp2 =(uint32_t)aes_sbox[(tmp )&0xff] ;
// tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<< 8;
// tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<16;
// tmp2|=(uint32_t)aes_sbox[(tmp>>24) ]<<24;
tmp2
=
((
uint32_t
)
byte_of_aligned_array
(
aes_sbox
,(
tmp
)
&
0xff
))
;
tmp2
|=
((
uint32_t
)
byte_of_aligned_array
(
aes_sbox
,(
tmp
>>
8
)
&
0xff
))
<<
8
;
tmp2
|=
((
uint32_t
)
byte_of_aligned_array
(
aes_sbox
,(
tmp
>>
16
)
&
0xff
))
<<
16
;
tmp2
|=
((
uint32_t
)
byte_of_aligned_array
(
aes_sbox
,(
tmp
>>
24
)
))
<<
24
;
tmp
=
tmp2
;
}
W
[
i
]
=
W
[
i
-
words
]
^
tmp
;
}
/* copy the iv across */
os_memcpy
(
ctx
->
iv
,
iv
,
16
);
}
/**
* Change a key for decryption.
*/
void
ICACHE_FLASH_ATTR
AES_convert_key
(
AES_CTX
*
ctx
)
{
int
i
;
uint32_t
*
k
,
w
,
t1
,
t2
,
t3
,
t4
;
k
=
ctx
->
ks
;
k
+=
4
;
for
(
i
=
ctx
->
rounds
*
4
;
i
>
4
;
i
--
)
{
w
=
*
k
;
w
=
inv_mix_col
(
w
,
t1
,
t2
,
t3
,
t4
);
*
k
++
=
w
;
}
}
/**
* Encrypt a byte sequence (with a block size 16) using the AES cipher.
*/
void
ICACHE_FLASH_ATTR
AES_cbc_encrypt
(
AES_CTX
*
ctx
,
const
uint8_t
*
msg
,
uint8_t
*
out
,
int
length
)
{
int
i
;
uint32_t
tin
[
4
],
tout
[
4
],
iv
[
4
];
os_memcpy
(
iv
,
ctx
->
iv
,
AES_IV_SIZE
);
for
(
i
=
0
;
i
<
4
;
i
++
)
tout
[
i
]
=
ntohl
(
iv
[
i
]);
for
(
length
-=
AES_BLOCKSIZE
;
length
>=
0
;
length
-=
AES_BLOCKSIZE
)
{
uint32_t
msg_32
[
4
];
uint32_t
out_32
[
4
];
os_memcpy
(
msg_32
,
msg
,
AES_BLOCKSIZE
);
msg
+=
AES_BLOCKSIZE
;
for
(
i
=
0
;
i
<
4
;
i
++
)
tin
[
i
]
=
ntohl
(
msg_32
[
i
])
^
tout
[
i
];
AES_encrypt
(
ctx
,
tin
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
tout
[
i
]
=
tin
[
i
];
out_32
[
i
]
=
htonl
(
tout
[
i
]);
}
os_memcpy
(
out
,
out_32
,
AES_BLOCKSIZE
);
out
+=
AES_BLOCKSIZE
;
}
for
(
i
=
0
;
i
<
4
;
i
++
)
iv
[
i
]
=
htonl
(
tout
[
i
]);
os_memcpy
(
ctx
->
iv
,
iv
,
AES_IV_SIZE
);
}
/**
* Decrypt a byte sequence (with a block size 16) using the AES cipher.
*/
void
ICACHE_FLASH_ATTR
AES_cbc_decrypt
(
AES_CTX
*
ctx
,
const
uint8_t
*
msg
,
uint8_t
*
out
,
int
length
)
{
int
i
;
uint32_t
tin
[
4
],
xor
[
4
],
tout
[
4
],
data
[
4
],
iv
[
4
];
os_memcpy
(
iv
,
ctx
->
iv
,
AES_IV_SIZE
);
for
(
i
=
0
;
i
<
4
;
i
++
)
xor
[
i
]
=
ntohl
(
iv
[
i
]);
for
(
length
-=
16
;
length
>=
0
;
length
-=
16
)
{
uint32_t
msg_32
[
4
];
uint32_t
out_32
[
4
];
os_memcpy
(
msg_32
,
msg
,
AES_BLOCKSIZE
);
msg
+=
AES_BLOCKSIZE
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
tin
[
i
]
=
ntohl
(
msg_32
[
i
]);
data
[
i
]
=
tin
[
i
];
}
AES_decrypt
(
ctx
,
data
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
tout
[
i
]
=
data
[
i
]
^
xor
[
i
];
xor
[
i
]
=
tin
[
i
];
out_32
[
i
]
=
htonl
(
tout
[
i
]);
}
os_memcpy
(
out
,
out_32
,
AES_BLOCKSIZE
);
out
+=
AES_BLOCKSIZE
;
}
for
(
i
=
0
;
i
<
4
;
i
++
)
iv
[
i
]
=
htonl
(
xor
[
i
]);
os_memcpy
(
ctx
->
iv
,
iv
,
AES_IV_SIZE
);
}
/**
* Encrypt a single block (16 bytes) of data
*/
static
void
ICACHE_FLASH_ATTR
AES_encrypt
(
const
AES_CTX
*
ctx
,
uint32_t
*
data
)
{
/* To make this code smaller, generate the sbox entries on the fly.
* This will have a really heavy effect upon performance.
*/
uint32_t
tmp
[
4
];
uint32_t
tmp1
,
old_a0
,
a0
,
a1
,
a2
,
a3
,
row
;
int
curr_rnd
;
int
rounds
=
ctx
->
rounds
;
const
uint32_t
*
k
=
ctx
->
ks
;
/* Pre-round key addition */
for
(
row
=
0
;
row
<
4
;
row
++
)
data
[
row
]
^=
*
(
k
++
);
/* Encrypt one block. */
for
(
curr_rnd
=
0
;
curr_rnd
<
rounds
;
curr_rnd
++
)
{
/* Perform ByteSub and ShiftRow operations together */
for
(
row
=
0
;
row
<
4
;
row
++
)
{
// a0 = (uint32_t)aes_sbox[(data[row%4]>>24)&0xFF];
// a1 = (uint32_t)aes_sbox[(data[(row+1)%4]>>16)&0xFF];
// a2 = (uint32_t)aes_sbox[(data[(row+2)%4]>>8)&0xFF];
// a3 = (uint32_t)aes_sbox[(data[(row+3)%4])&0xFF];
a0
=
(
uint32_t
)(
byte_of_aligned_array
(
aes_sbox
,(
data
[
row
%
4
]
>>
24
)
&
0xFF
));
a1
=
(
uint32_t
)(
byte_of_aligned_array
(
aes_sbox
,(
data
[(
row
+
1
)
%
4
]
>>
16
)
&
0xFF
));
a2
=
(
uint32_t
)(
byte_of_aligned_array
(
aes_sbox
,(
data
[(
row
+
2
)
%
4
]
>>
8
)
&
0xFF
));
a3
=
(
uint32_t
)(
byte_of_aligned_array
(
aes_sbox
,(
data
[(
row
+
3
)
%
4
])
&
0xFF
));
/* Perform MixColumn iff not last round */
if
(
curr_rnd
<
(
rounds
-
1
))
{
tmp1
=
a0
^
a1
^
a2
^
a3
;
old_a0
=
a0
;
a0
^=
tmp1
^
AES_xtime
(
a0
^
a1
);
a1
^=
tmp1
^
AES_xtime
(
a1
^
a2
);
a2
^=
tmp1
^
AES_xtime
(
a2
^
a3
);
a3
^=
tmp1
^
AES_xtime
(
a3
^
old_a0
);
}
tmp
[
row
]
=
((
a0
<<
24
)
|
(
a1
<<
16
)
|
(
a2
<<
8
)
|
a3
);
}
/* KeyAddition - note that it is vital that this loop is separate from
the MixColumn operation, which must be atomic...*/
for
(
row
=
0
;
row
<
4
;
row
++
)
data
[
row
]
=
tmp
[
row
]
^
*
(
k
++
);
}
}
/**
* Decrypt a single block (16 bytes) of data
*/
static
void
ICACHE_FLASH_ATTR
AES_decrypt
(
const
AES_CTX
*
ctx
,
uint32_t
*
data
)
{
uint32_t
tmp
[
4
];
uint32_t
xt0
,
xt1
,
xt2
,
xt3
,
xt4
,
xt5
,
xt6
;
uint32_t
a0
,
a1
,
a2
,
a3
,
row
;
int
curr_rnd
;
int
rounds
=
ctx
->
rounds
;
const
uint32_t
*
k
=
ctx
->
ks
+
((
rounds
+
1
)
*
4
);
/* pre-round key addition */
for
(
row
=
4
;
row
>
0
;
row
--
)
data
[
row
-
1
]
^=
*
(
--
k
);
/* Decrypt one block */
for
(
curr_rnd
=
0
;
curr_rnd
<
rounds
;
curr_rnd
++
)
{
/* Perform ByteSub and ShiftRow operations together */
for
(
row
=
4
;
row
>
0
;
row
--
)
{
// a0 = aes_isbox[(data[(row+3)%4]>>24)&0xFF];
// a1 = aes_isbox[(data[(row+2)%4]>>16)&0xFF];
// a2 = aes_isbox[(data[(row+1)%4]>>8)&0xFF];
// a3 = aes_isbox[(data[row%4])&0xFF];
a0
=
byte_of_aligned_array
(
aes_isbox
,(
data
[(
row
+
3
)
%
4
]
>>
24
)
&
0xFF
);
a1
=
byte_of_aligned_array
(
aes_isbox
,(
data
[(
row
+
2
)
%
4
]
>>
16
)
&
0xFF
);
a2
=
byte_of_aligned_array
(
aes_isbox
,(
data
[(
row
+
1
)
%
4
]
>>
8
)
&
0xFF
);
a3
=
byte_of_aligned_array
(
aes_isbox
,(
data
[
row
%
4
])
&
0xFF
);
/* Perform MixColumn iff not last round */
if
(
curr_rnd
<
(
rounds
-
1
))
{
/* The MDS cofefficients (0x09, 0x0B, 0x0D, 0x0E)
are quite large compared to encryption; this
operation slows decryption down noticeably. */
xt0
=
AES_xtime
(
a0
^
a1
);
xt1
=
AES_xtime
(
a1
^
a2
);
xt2
=
AES_xtime
(
a2
^
a3
);
xt3
=
AES_xtime
(
a3
^
a0
);
xt4
=
AES_xtime
(
xt0
^
xt1
);
xt5
=
AES_xtime
(
xt1
^
xt2
);
xt6
=
AES_xtime
(
xt4
^
xt5
);
xt0
^=
a1
^
a2
^
a3
^
xt4
^
xt6
;
xt1
^=
a0
^
a2
^
a3
^
xt5
^
xt6
;
xt2
^=
a0
^
a1
^
a3
^
xt4
^
xt6
;
xt3
^=
a0
^
a1
^
a2
^
xt5
^
xt6
;
tmp
[
row
-
1
]
=
((
xt0
<<
24
)
|
(
xt1
<<
16
)
|
(
xt2
<<
8
)
|
xt3
);
}
else
tmp
[
row
-
1
]
=
((
a0
<<
24
)
|
(
a1
<<
16
)
|
(
a2
<<
8
)
|
a3
);
}
for
(
row
=
4
;
row
>
0
;
row
--
)
data
[
row
-
1
]
=
tmp
[
row
-
1
]
^
*
(
--
k
);
}
}
#endif
app/ssl/crypto/ssl_bigint.c
deleted
100644 → 0
View file @
093a8959
/*
* Copyright (c) 2007, Cameron Rich
*
* 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 name of the axTLS project 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.
*/
/**
* @defgroup bigint_api Big Integer API
* @brief The bigint implementation as used by the axTLS project.
*
* The bigint library is for RSA encryption/decryption as well as signing.
* This code tries to minimise use of malloc/free by maintaining a small
* cache. A bigint context may maintain state by being made "permanent".
* It be be later released with a bi_depermanent() and bi_free() call.
*
* It supports the following reduction techniques:
* - Classical
* - Barrett
* - Montgomery
*
* It also implements the following:
* - Karatsuba multiplication
* - Squaring
* - Sliding window exponentiation
* - Chinese Remainder Theorem (implemented in rsa.c).
*
* All the algorithms used are pretty standard, and designed for different
* data bus sizes. Negative numbers are not dealt with at all, so a subtraction
* may need to be tested for negativity.
*
* This library steals some ideas from Jef Poskanzer
* <http://cs.marlboro.edu/term/cs-fall02/algorithms/crypto/RSA/bigint>
* and GMP <http://www.swox.com/gmp>. It gets most of its implementation
* detail from "The Handbook of Applied Cryptography"
* <http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf>
* @{
*/
//#include <stdlib.h>
//#include <limits.h>
//#include <string.h>
//#include <stdio.h>
//#include <time.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_bigint.h"
//#include "os.h"
#include "lwip/mem.h"
#define V1 v->comps[v->size-1]
/**< v1 for division */
#define V2 v->comps[v->size-2]
/**< v2 for division */
#define U(j) tmp_u->comps[tmp_u->size-j-1]
/**< uj for division */
#define Q(j) quotient->comps[quotient->size-j-1]
/**< qj for division */
static
bigint
*
bi_int_multiply
(
BI_CTX
*
ctx
,
bigint
*
bi
,
comp
i
);
static
bigint
*
bi_int_divide
(
BI_CTX
*
ctx
,
bigint
*
biR
,
comp
denom
);
static
bigint
*
alloc
(
BI_CTX
*
ctx
,
int
size
);
static
bigint
*
trim
(
bigint
*
bi
);
static
void
more_comps
(
bigint
*
bi
,
int
n
);
#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
defined(CONFIG_BIGINT_MONTGOMERY)
static
bigint
*
comp_right_shift
(
bigint
*
biR
,
int
num_shifts
);
static
bigint
*
comp_left_shift
(
bigint
*
biR
,
int
num_shifts
);
#endif
#ifdef CONFIG_BIGINT_CHECK_ON
static
void
check
(
const
bigint
*
bi
);
#else
#define check(A)
/**< disappears in normal production mode */
#endif
/**
* @brief Start a new bigint context.
* @return A bigint context.
*/
BI_CTX
*
ICACHE_FLASH_ATTR
bi_initialize
(
void
)
{
/* calloc() sets everything to zero */
BI_CTX
*
ctx
=
(
BI_CTX
*
)
os_zalloc
(
sizeof
(
BI_CTX
));
/* the radix */
ctx
->
bi_radix
=
alloc
(
ctx
,
2
);
ctx
->
bi_radix
->
comps
[
0
]
=
0
;
ctx
->
bi_radix
->
comps
[
1
]
=
1
;
bi_permanent
(
ctx
->
bi_radix
);
return
ctx
;
}
/**
* @brief Close the bigint context and free any resources.
*
* Free up any used memory - a check is done if all objects were not
* properly freed.
* @param ctx [in] The bigint session context.
*/
void
ICACHE_FLASH_ATTR
bi_terminate
(
BI_CTX
*
ctx
)
{
bi_depermanent
(
ctx
->
bi_radix
);
bi_free
(
ctx
,
ctx
->
bi_radix
);
if
(
ctx
->
active_count
!=
0
)
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"bi_terminate: there were %d un-freed bigints
\n
"
,
ctx
->
active_count
);
#endif
return
;
/* wujg : org ---> abort(); */
}
bi_clear_cache
(
ctx
);
os_free
(
ctx
);
}
/**
*@brief Clear the memory cache.
*/
void
ICACHE_FLASH_ATTR
bi_clear_cache
(
BI_CTX
*
ctx
)
{
bigint
*
p
,
*
pn
;
if
(
ctx
->
free_list
==
NULL
)
return
;
for
(
p
=
ctx
->
free_list
;
p
!=
NULL
;
p
=
pn
)
{
pn
=
p
->
next
;
os_free
(
p
->
comps
);
os_free
(
p
);
}
ctx
->
free_count
=
0
;
ctx
->
free_list
=
NULL
;
}
/**
* @brief Increment the number of references to this object.
* It does not do a full copy.
* @param bi [in] The bigint to copy.
* @return A reference to the same bigint.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_copy
(
bigint
*
bi
)
{
check
(
bi
);
if
(
bi
->
refs
!=
PERMANENT
)
bi
->
refs
++
;
return
bi
;
}
/**
* @brief Simply make a bigint object "unfreeable" if bi_free() is called on it.
*
* For this object to be freed, bi_depermanent() must be called.
* @param bi [in] The bigint to be made permanent.
*/
void
ICACHE_FLASH_ATTR
bi_permanent
(
bigint
*
bi
)
{
check
(
bi
);
if
(
bi
->
refs
!=
1
)
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"bi_permanent: refs was not 1
\n
"
);
#endif
return
;
/* wujg : org ----> abort(); */
}
bi
->
refs
=
PERMANENT
;
}
/**
* @brief Take a permanent object and make it eligible for freedom.
* @param bi [in] The bigint to be made back to temporary.
*/
void
ICACHE_FLASH_ATTR
bi_depermanent
(
bigint
*
bi
)
{
check
(
bi
);
if
(
bi
->
refs
!=
PERMANENT
)
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"bi_depermanent: bigint was not permanent
\n
"
);
#endif
return
;
/* wujg : org ----> abort(); */
}
bi
->
refs
=
1
;
}
/**
* @brief Free a bigint object so it can be used again.
*
* The memory itself it not actually freed, just tagged as being available
* @param ctx [in] The bigint session context.
* @param bi [in] The bigint to be freed.
*/
void
ICACHE_FLASH_ATTR
bi_free
(
BI_CTX
*
ctx
,
bigint
*
bi
)
{
check
(
bi
);
if
(
bi
->
refs
==
PERMANENT
)
{
return
;
}
if
(
--
bi
->
refs
>
0
)
{
return
;
}
bi
->
next
=
ctx
->
free_list
;
ctx
->
free_list
=
bi
;
ctx
->
free_count
++
;
if
(
--
ctx
->
active_count
<
0
)
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"bi_free: active_count went negative "
"- double-freed bigint?
\n
"
);
#endif
return
;
/* wujg : org ----> abort(); */
}
}
/**
* @brief Convert an (unsigned) integer into a bigint.
* @param ctx [in] The bigint session context.
* @param i [in] The (unsigned) integer to be converted.
*
*/
bigint
*
ICACHE_FLASH_ATTR
int_to_bi
(
BI_CTX
*
ctx
,
comp
i
)
{
bigint
*
biR
=
alloc
(
ctx
,
1
);
biR
->
comps
[
0
]
=
i
;
return
biR
;
}
/**
* @brief Do a full copy of the bigint object.
* @param ctx [in] The bigint session context.
* @param bi [in] The bigint object to be copied.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_clone
(
BI_CTX
*
ctx
,
const
bigint
*
bi
)
{
bigint
*
biR
=
alloc
(
ctx
,
bi
->
size
);
check
(
bi
);
os_memcpy
(
biR
->
comps
,
bi
->
comps
,
bi
->
size
*
COMP_BYTE_SIZE
);
return
biR
;
}
/**
* @brief Perform an addition operation between two bigints.
* @param ctx [in] The bigint session context.
* @param bia [in] A bigint.
* @param bib [in] Another bigint.
* @return The result of the addition.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_add
(
BI_CTX
*
ctx
,
bigint
*
bia
,
bigint
*
bib
)
{
int
n
;
comp
carry
=
0
;
comp
*
pa
,
*
pb
;
check
(
bia
);
check
(
bib
);
n
=
max
(
bia
->
size
,
bib
->
size
);
more_comps
(
bia
,
n
+
1
);
more_comps
(
bib
,
n
);
pa
=
bia
->
comps
;
pb
=
bib
->
comps
;
do
{
comp
sl
,
rl
,
cy1
;
sl
=
*
pa
+
*
pb
++
;
rl
=
sl
+
carry
;
cy1
=
sl
<
*
pa
;
carry
=
cy1
|
(
rl
<
sl
);
*
pa
++
=
rl
;
}
while
(
--
n
!=
0
);
*
pa
=
carry
;
/* do overflow */
bi_free
(
ctx
,
bib
);
return
trim
(
bia
);
}
/**
* @brief Perform a subtraction operation between two bigints.
* @param ctx [in] The bigint session context.
* @param bia [in] A bigint.
* @param bib [in] Another bigint.
* @param is_negative [out] If defined, indicates that the result was negative.
* is_negative may be null.
* @return The result of the subtraction. The result is always positive.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_subtract
(
BI_CTX
*
ctx
,
bigint
*
bia
,
bigint
*
bib
,
int
*
is_negative
)
{
int
n
=
bia
->
size
;
comp
*
pa
,
*
pb
,
carry
=
0
;
check
(
bia
);
check
(
bib
);
more_comps
(
bib
,
n
);
pa
=
bia
->
comps
;
pb
=
bib
->
comps
;
do
{
comp
sl
,
rl
,
cy1
;
sl
=
*
pa
-
*
pb
++
;
rl
=
sl
-
carry
;
cy1
=
sl
>
*
pa
;
carry
=
cy1
|
(
rl
>
sl
);
*
pa
++
=
rl
;
}
while
(
--
n
!=
0
);
if
(
is_negative
)
/* indicate a negative result */
{
*
is_negative
=
carry
;
}
bi_free
(
ctx
,
trim
(
bib
));
/* put bib back to the way it was */
return
trim
(
bia
);
}
/**
* Perform a multiply between a bigint an an (unsigned) integer
*/
static
bigint
*
ICACHE_FLASH_ATTR
bi_int_multiply
(
BI_CTX
*
ctx
,
bigint
*
bia
,
comp
b
)
{
int
j
=
0
,
n
=
bia
->
size
;
bigint
*
biR
=
alloc
(
ctx
,
n
+
1
);
comp
carry
=
0
;
comp
*
r
=
biR
->
comps
;
comp
*
a
=
bia
->
comps
;
check
(
bia
);
/* clear things to start with */
os_memset
(
r
,
0
,
((
n
+
1
)
*
COMP_BYTE_SIZE
));
do
{
long_comp
tmp
=
*
r
+
(
long_comp
)
a
[
j
]
*
b
+
carry
;
*
r
++
=
(
comp
)
tmp
;
/* downsize */
carry
=
(
comp
)(
tmp
>>
COMP_BIT_SIZE
);
}
while
(
++
j
<
n
);
*
r
=
carry
;
bi_free
(
ctx
,
bia
);
return
trim
(
biR
);
}
/**
* @brief Does both division and modulo calculations.
*
* Used extensively when doing classical reduction.
* @param ctx [in] The bigint session context.
* @param u [in] A bigint which is the numerator.
* @param v [in] Either the denominator or the modulus depending on the mode.
* @param is_mod [n] Determines if this is a normal division (0) or a reduction
* (1).
* @return The result of the division/reduction.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_divide
(
BI_CTX
*
ctx
,
bigint
*
u
,
bigint
*
v
,
int
is_mod
)
{
int
n
=
v
->
size
,
m
=
u
->
size
-
n
;
int
j
=
0
,
orig_u_size
=
u
->
size
;
uint8_t
mod_offset
=
ctx
->
mod_offset
;
comp
d
;
bigint
*
quotient
,
*
tmp_u
;
comp
q_dash
;
check
(
u
);
check
(
v
);
/* if doing reduction and we are < mod, then return mod */
if
(
is_mod
&&
bi_compare
(
v
,
u
)
>
0
)
{
bi_free
(
ctx
,
v
);
return
u
;
}
quotient
=
alloc
(
ctx
,
m
+
1
);
tmp_u
=
alloc
(
ctx
,
n
+
1
);
v
=
trim
(
v
);
/* make sure we have no leading 0's */
d
=
(
comp
)((
long_comp
)
COMP_RADIX
/
(
V1
+
1
));
/* clear things to start with */
os_memset
(
quotient
->
comps
,
0
,
((
quotient
->
size
)
*
COMP_BYTE_SIZE
));
/* normalise */
if
(
d
>
1
)
{
u
=
bi_int_multiply
(
ctx
,
u
,
d
);
if
(
is_mod
)
{
v
=
ctx
->
bi_normalised_mod
[
mod_offset
];
}
else
{
v
=
bi_int_multiply
(
ctx
,
v
,
d
);
}
}
if
(
orig_u_size
==
u
->
size
)
/* new digit position u0 */
{
more_comps
(
u
,
orig_u_size
+
1
);
}
do
{
/* get a temporary short version of u */
os_memcpy
(
tmp_u
->
comps
,
&
u
->
comps
[
u
->
size
-
n
-
1
-
j
],
(
n
+
1
)
*
COMP_BYTE_SIZE
);
/* calculate q' */
if
(
U
(
0
)
==
V1
)
{
q_dash
=
COMP_RADIX
-
1
;
}
else
{
q_dash
=
(
comp
)(((
long_comp
)
U
(
0
)
*
COMP_RADIX
+
U
(
1
))
/
V1
);
if
(
v
->
size
>
1
&&
V2
)
{
/* we are implementing the following:
if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) -
q_dash*V1)*COMP_RADIX) + U(2))) ... */
comp
inner
=
(
comp
)((
long_comp
)
COMP_RADIX
*
U
(
0
)
+
U
(
1
)
-
(
long_comp
)
q_dash
*
V1
);
if
((
long_comp
)
V2
*
q_dash
>
(
long_comp
)
inner
*
COMP_RADIX
+
U
(
2
))
{
q_dash
--
;
}
}
}
/* multiply and subtract */
if
(
q_dash
)
{
int
is_negative
;
tmp_u
=
bi_subtract
(
ctx
,
tmp_u
,
bi_int_multiply
(
ctx
,
bi_copy
(
v
),
q_dash
),
&
is_negative
);
more_comps
(
tmp_u
,
n
+
1
);
Q
(
j
)
=
q_dash
;
/* add back */
if
(
is_negative
)
{
Q
(
j
)
--
;
tmp_u
=
bi_add
(
ctx
,
tmp_u
,
bi_copy
(
v
));
/* lop off the carry */
tmp_u
->
size
--
;
v
->
size
--
;
}
}
else
{
Q
(
j
)
=
0
;
}
/* copy back to u */
os_memcpy
(
&
u
->
comps
[
u
->
size
-
n
-
1
-
j
],
tmp_u
->
comps
,
(
n
+
1
)
*
COMP_BYTE_SIZE
);
}
while
(
++
j
<=
m
);
bi_free
(
ctx
,
tmp_u
);
bi_free
(
ctx
,
v
);
if
(
is_mod
)
/* get the remainder */
{
bi_free
(
ctx
,
quotient
);
return
bi_int_divide
(
ctx
,
trim
(
u
),
d
);
}
else
/* get the quotient */
{
bi_free
(
ctx
,
u
);
return
trim
(
quotient
);
}
}
/*
* Perform an integer divide on a bigint.
*/
static
bigint
*
ICACHE_FLASH_ATTR
bi_int_divide
(
BI_CTX
*
ctx
,
bigint
*
biR
,
comp
denom
)
{
int
i
=
biR
->
size
-
1
;
long_comp
r
=
0
;
check
(
biR
);
do
{
r
=
(
r
<<
COMP_BIT_SIZE
)
+
biR
->
comps
[
i
];
biR
->
comps
[
i
]
=
(
comp
)(
r
/
denom
);
r
%=
denom
;
}
while
(
--
i
>=
0
);
return
trim
(
biR
);
}
#ifdef CONFIG_BIGINT_MONTGOMERY
/**
* There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1,
* where B^-1(B-1) mod N=1. Actually, only the least significant part of
* N' is needed, hence the definition N0'=N' mod b. We reproduce below the
* simple algorithm from an article by Dusse and Kaliski to efficiently
* find N0' from N0 and b */
static
comp
ICACHE_FLASH_ATTR
modular_inverse
(
bigint
*
bim
)
{
int
i
;
comp
t
=
1
;
comp
two_2_i_minus_1
=
2
;
/* 2^(i-1) */
long_comp
two_2_i
=
4
;
/* 2^i */
comp
N
=
bim
->
comps
[
0
];
for
(
i
=
2
;
i
<=
COMP_BIT_SIZE
;
i
++
)
{
if
((
long_comp
)
N
*
t
%
two_2_i
>=
two_2_i_minus_1
)
{
t
+=
two_2_i_minus_1
;
}
two_2_i_minus_1
<<=
1
;
two_2_i
<<=
1
;
}
return
(
comp
)(
COMP_RADIX
-
t
);
}
#endif
#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
defined(CONFIG_BIGINT_MONTGOMERY)
/**
* Take each component and shift down (in terms of components)
*/
static
bigint
*
ICACHE_FLASH_ATTR
comp_right_shift
(
bigint
*
biR
,
int
num_shifts
)
{
int
i
=
biR
->
size
-
num_shifts
;
comp
*
x
=
biR
->
comps
;
comp
*
y
=
&
biR
->
comps
[
num_shifts
];
check
(
biR
);
if
(
i
<=
0
)
/* have we completely right shifted? */
{
biR
->
comps
[
0
]
=
0
;
/* return 0 */
biR
->
size
=
1
;
return
biR
;
}
do
{
*
x
++
=
*
y
++
;
}
while
(
--
i
>
0
);
biR
->
size
-=
num_shifts
;
return
biR
;
}
/**
* Take each component and shift it up (in terms of components)
*/
static
bigint
*
ICACHE_FLASH_ATTR
comp_left_shift
(
bigint
*
biR
,
int
num_shifts
)
{
int
i
=
biR
->
size
-
1
;
comp
*
x
,
*
y
;
check
(
biR
);
if
(
num_shifts
<=
0
)
{
return
biR
;
}
more_comps
(
biR
,
biR
->
size
+
num_shifts
);
x
=
&
biR
->
comps
[
i
+
num_shifts
];
y
=
&
biR
->
comps
[
i
];
do
{
*
x
--
=
*
y
--
;
}
while
(
i
--
);
os_memset
(
biR
->
comps
,
0
,
num_shifts
*
COMP_BYTE_SIZE
);
/* zero LS comps */
return
biR
;
}
#endif
/**
* @brief Allow a binary sequence to be imported as a bigint.
* @param ctx [in] The bigint session context.
* @param data [in] The data to be converted.
* @param size [in] The number of bytes of data.
* @return A bigint representing this data.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_import
(
BI_CTX
*
ctx
,
const
uint8_t
*
data
,
int
size
)
{
bigint
*
biR
=
alloc
(
ctx
,
(
size
+
COMP_BYTE_SIZE
-
1
)
/
COMP_BYTE_SIZE
);
int
i
,
j
=
0
,
offset
=
0
;
os_memset
(
biR
->
comps
,
0
,
biR
->
size
*
COMP_BYTE_SIZE
);
for
(
i
=
size
-
1
;
i
>=
0
;
i
--
)
{
biR
->
comps
[
offset
]
+=
data
[
i
]
<<
(
j
*
8
);
if
(
++
j
==
COMP_BYTE_SIZE
)
{
j
=
0
;
offset
++
;
}
}
return
trim
(
biR
);
}
#ifdef CONFIG_SSL_FULL_MODE
/**
* @brief The testharness uses this code to import text hex-streams and
* convert them into bigints.
* @param ctx [in] The bigint session context.
* @param data [in] A string consisting of hex characters. The characters must
* be in upper case.
* @return A bigint representing this data.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_str_import
(
BI_CTX
*
ctx
,
const
char
*
data
)
{
int
size
=
os_strlen
(
data
);
bigint
*
biR
=
alloc
(
ctx
,
(
size
+
COMP_NUM_NIBBLES
-
1
)
/
COMP_NUM_NIBBLES
);
int
i
,
j
=
0
,
offset
=
0
;
os_memset
(
biR
->
comps
,
0
,
biR
->
size
*
COMP_BYTE_SIZE
);
for
(
i
=
size
-
1
;
i
>=
0
;
i
--
)
{
int
num
=
(
data
[
i
]
<=
'9'
)
?
(
data
[
i
]
-
'0'
)
:
(
data
[
i
]
-
'A'
+
10
);
biR
->
comps
[
offset
]
+=
num
<<
(
j
*
4
);
if
(
++
j
==
COMP_NUM_NIBBLES
)
{
j
=
0
;
offset
++
;
}
}
return
biR
;
}
void
ICACHE_FLASH_ATTR
bi_print
(
const
char
*
label
,
bigint
*
x
)
{
int
i
,
j
;
if
(
x
==
NULL
)
{
ssl_printf
(
"%s: (null)
\n
"
,
label
);
return
;
}
ssl_printf
(
"%s: (size %d)
\n
"
,
label
,
x
->
size
);
for
(
i
=
x
->
size
-
1
;
i
>=
0
;
i
--
)
{
for
(
j
=
COMP_NUM_NIBBLES
-
1
;
j
>=
0
;
j
--
)
{
comp
mask
=
0x0f
<<
(
j
*
4
);
comp
num
=
(
x
->
comps
[
i
]
&
mask
)
>>
(
j
*
4
);
os_putc
((
num
<=
9
)
?
(
num
+
'0'
)
:
(
num
+
'A'
-
10
));
}
}
ssl_printf
(
"
\n
"
);
}
#endif
/**
* @brief Take a bigint and convert it into a byte sequence.
*
* This is useful after a decrypt operation.
* @param ctx [in] The bigint session context.
* @param x [in] The bigint to be converted.
* @param data [out] The converted data as a byte stream.
* @param size [in] The maximum size of the byte stream. Unused bytes will be
* zeroed.
*/
void
ICACHE_FLASH_ATTR
bi_export
(
BI_CTX
*
ctx
,
bigint
*
x
,
uint8_t
*
data
,
int
size
)
{
int
i
,
j
,
k
=
size
-
1
;
check
(
x
);
os_memset
(
data
,
0
,
size
);
/* ensure all leading 0's are cleared */
for
(
i
=
0
;
i
<
x
->
size
;
i
++
)
{
for
(
j
=
0
;
j
<
COMP_BYTE_SIZE
;
j
++
)
{
comp
mask
=
0xff
<<
(
j
*
8
);
int
num
=
(
x
->
comps
[
i
]
&
mask
)
>>
(
j
*
8
);
data
[
k
--
]
=
num
;
if
(
k
<
0
)
{
goto
buf_done
;
}
}
}
buf_done:
bi_free
(
ctx
,
x
);
}
/**
* @brief Pre-calculate some of the expensive steps in reduction.
*
* This function should only be called once (normally when a session starts).
* When the session is over, bi_free_mod() should be called. bi_mod_power()
* relies on this function being called.
* @param ctx [in] The bigint session context.
* @param bim [in] The bigint modulus that will be used.
* @param mod_offset [in] There are three moduluii that can be stored - the
* standard modulus, and its two primes p and q. This offset refers to which
* modulus we are referring to.
* @see bi_free_mod(), bi_mod_power().
*/
void
ICACHE_FLASH_ATTR
bi_set_mod
(
BI_CTX
*
ctx
,
bigint
*
bim
,
int
mod_offset
)
{
int
k
=
bim
->
size
;
comp
d
=
(
comp
)((
long_comp
)
COMP_RADIX
/
(
bim
->
comps
[
k
-
1
]
+
1
));
#ifdef CONFIG_BIGINT_MONTGOMERY
bigint
*
R
,
*
R2
;
#endif
ctx
->
bi_mod
[
mod_offset
]
=
bim
;
bi_permanent
(
ctx
->
bi_mod
[
mod_offset
]);
ctx
->
bi_normalised_mod
[
mod_offset
]
=
bi_int_multiply
(
ctx
,
bim
,
d
);
bi_permanent
(
ctx
->
bi_normalised_mod
[
mod_offset
]);
#if defined(CONFIG_BIGINT_MONTGOMERY)
/* set montgomery variables */
R
=
comp_left_shift
(
bi_clone
(
ctx
,
ctx
->
bi_radix
),
k
-
1
);
/* R */
R2
=
comp_left_shift
(
bi_clone
(
ctx
,
ctx
->
bi_radix
),
k
*
2
-
1
);
/* R^2 */
ctx
->
bi_RR_mod_m
[
mod_offset
]
=
bi_mod
(
ctx
,
R2
);
/* R^2 mod m */
ctx
->
bi_R_mod_m
[
mod_offset
]
=
bi_mod
(
ctx
,
R
);
/* R mod m */
bi_permanent
(
ctx
->
bi_RR_mod_m
[
mod_offset
]);
bi_permanent
(
ctx
->
bi_R_mod_m
[
mod_offset
]);
ctx
->
N0_dash
[
mod_offset
]
=
modular_inverse
(
ctx
->
bi_mod
[
mod_offset
]);
#elif defined (CONFIG_BIGINT_BARRETT)
ctx
->
bi_mu
[
mod_offset
]
=
bi_divide
(
ctx
,
comp_left_shift
(
bi_clone
(
ctx
,
ctx
->
bi_radix
),
k
*
2
-
1
),
ctx
->
bi_mod
[
mod_offset
],
0
);
bi_permanent
(
ctx
->
bi_mu
[
mod_offset
]);
#endif
}
/**
* @brief Used when cleaning various bigints at the end of a session.
* @param ctx [in] The bigint session context.
* @param mod_offset [in] The offset to use.
* @see bi_set_mod().
*/
void
ICACHE_FLASH_ATTR
bi_free_mod
(
BI_CTX
*
ctx
,
int
mod_offset
)
{
bi_depermanent
(
ctx
->
bi_mod
[
mod_offset
]);
bi_free
(
ctx
,
ctx
->
bi_mod
[
mod_offset
]);
#if defined (CONFIG_BIGINT_MONTGOMERY)
bi_depermanent
(
ctx
->
bi_RR_mod_m
[
mod_offset
]);
bi_depermanent
(
ctx
->
bi_R_mod_m
[
mod_offset
]);
bi_free
(
ctx
,
ctx
->
bi_RR_mod_m
[
mod_offset
]);
bi_free
(
ctx
,
ctx
->
bi_R_mod_m
[
mod_offset
]);
#elif defined(CONFIG_BIGINT_BARRETT)
bi_depermanent
(
ctx
->
bi_mu
[
mod_offset
]);
bi_free
(
ctx
,
ctx
->
bi_mu
[
mod_offset
]);
#endif
bi_depermanent
(
ctx
->
bi_normalised_mod
[
mod_offset
]);
bi_free
(
ctx
,
ctx
->
bi_normalised_mod
[
mod_offset
]);
}
/**
* Perform a standard multiplication between two bigints.
*
* Barrett reduction has no need for some parts of the product, so ignore bits
* of the multiply. This routine gives Barrett its big performance
* improvements over Classical/Montgomery reduction methods.
*/
static
bigint
*
ICACHE_FLASH_ATTR
regular_multiply
(
BI_CTX
*
ctx
,
bigint
*
bia
,
bigint
*
bib
,
int
inner_partial
,
int
outer_partial
)
{
int
i
=
0
,
j
;
int
n
=
bia
->
size
;
int
t
=
bib
->
size
;
bigint
*
biR
=
alloc
(
ctx
,
n
+
t
);
comp
*
sr
=
biR
->
comps
;
comp
*
sa
=
bia
->
comps
;
comp
*
sb
=
bib
->
comps
;
check
(
bia
);
check
(
bib
);
/* clear things to start with */
os_memset
(
biR
->
comps
,
0
,
((
n
+
t
)
*
COMP_BYTE_SIZE
));
do
{
long_comp
tmp
;
comp
carry
=
0
;
int
r_index
=
i
;
j
=
0
;
if
(
outer_partial
&&
outer_partial
-
i
>
0
&&
outer_partial
<
n
)
{
r_index
=
outer_partial
-
1
;
j
=
outer_partial
-
i
-
1
;
}
do
{
if
(
inner_partial
&&
r_index
>=
inner_partial
)
{
break
;
}
tmp
=
sr
[
r_index
]
+
((
long_comp
)
sa
[
j
])
*
sb
[
i
]
+
carry
;
sr
[
r_index
++
]
=
(
comp
)
tmp
;
/* downsize */
carry
=
tmp
>>
COMP_BIT_SIZE
;
}
while
(
++
j
<
n
);
sr
[
r_index
]
=
carry
;
}
while
(
++
i
<
t
);
bi_free
(
ctx
,
bia
);
bi_free
(
ctx
,
bib
);
return
trim
(
biR
);
}
#ifdef CONFIG_BIGINT_KARATSUBA
/*
* Karatsuba improves on regular multiplication due to only 3 multiplications
* being done instead of 4. The additional additions/subtractions are O(N)
* rather than O(N^2) and so for big numbers it saves on a few operations
*/
static
bigint
*
ICACHE_FLASH_ATTR
karatsuba
(
BI_CTX
*
ctx
,
bigint
*
bia
,
bigint
*
bib
,
int
is_square
)
{
bigint
*
x0
,
*
x1
;
bigint
*
p0
,
*
p1
,
*
p2
;
int
m
;
if
(
is_square
)
{
m
=
(
bia
->
size
+
1
)
/
2
;
}
else
{
m
=
(
max
(
bia
->
size
,
bib
->
size
)
+
1
)
/
2
;
}
x0
=
bi_clone
(
ctx
,
bia
);
x0
->
size
=
m
;
x1
=
bi_clone
(
ctx
,
bia
);
comp_right_shift
(
x1
,
m
);
bi_free
(
ctx
,
bia
);
/* work out the 3 partial products */
if
(
is_square
)
{
p0
=
bi_square
(
ctx
,
bi_copy
(
x0
));
p2
=
bi_square
(
ctx
,
bi_copy
(
x1
));
p1
=
bi_square
(
ctx
,
bi_add
(
ctx
,
x0
,
x1
));
}
else
/* normal multiply */
{
bigint
*
y0
,
*
y1
;
y0
=
bi_clone
(
ctx
,
bib
);
y0
->
size
=
m
;
y1
=
bi_clone
(
ctx
,
bib
);
comp_right_shift
(
y1
,
m
);
bi_free
(
ctx
,
bib
);
p0
=
bi_multiply
(
ctx
,
bi_copy
(
x0
),
bi_copy
(
y0
));
p2
=
bi_multiply
(
ctx
,
bi_copy
(
x1
),
bi_copy
(
y1
));
p1
=
bi_multiply
(
ctx
,
bi_add
(
ctx
,
x0
,
x1
),
bi_add
(
ctx
,
y0
,
y1
));
}
p1
=
bi_subtract
(
ctx
,
bi_subtract
(
ctx
,
p1
,
bi_copy
(
p2
),
NULL
),
bi_copy
(
p0
),
NULL
);
comp_left_shift
(
p1
,
m
);
comp_left_shift
(
p2
,
2
*
m
);
return
bi_add
(
ctx
,
p1
,
bi_add
(
ctx
,
p0
,
p2
));
}
#endif
/**
* @brief Perform a multiplication operation between two bigints.
* @param ctx [in] The bigint session context.
* @param bia [in] A bigint.
* @param bib [in] Another bigint.
* @return The result of the multiplication.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_multiply
(
BI_CTX
*
ctx
,
bigint
*
bia
,
bigint
*
bib
)
{
check
(
bia
);
check
(
bib
);
#ifdef CONFIG_BIGINT_KARATSUBA
if
(
min
(
bia
->
size
,
bib
->
size
)
<
MUL_KARATSUBA_THRESH
)
{
return
regular_multiply
(
ctx
,
bia
,
bib
,
0
,
0
);
}
return
karatsuba
(
ctx
,
bia
,
bib
,
0
);
#else
return
regular_multiply
(
ctx
,
bia
,
bib
,
0
,
0
);
#endif
}
#ifdef CONFIG_BIGINT_SQUARE
/*
* Perform the actual square operion. It takes into account overflow.
*/
static
bigint
*
ICACHE_FLASH_ATTR
regular_square
(
BI_CTX
*
ctx
,
bigint
*
bi
)
{
int
t
=
bi
->
size
;
int
i
=
0
,
j
;
bigint
*
biR
=
alloc
(
ctx
,
t
*
2
+
1
);
comp
*
w
=
biR
->
comps
;
comp
*
x
=
bi
->
comps
;
long_comp
carry
;
os_memset
(
w
,
0
,
biR
->
size
*
COMP_BYTE_SIZE
);
do
{
long_comp
tmp
=
w
[
2
*
i
]
+
(
long_comp
)
x
[
i
]
*
x
[
i
];
w
[
2
*
i
]
=
(
comp
)
tmp
;
carry
=
tmp
>>
COMP_BIT_SIZE
;
for
(
j
=
i
+
1
;
j
<
t
;
j
++
)
{
uint8_t
c
=
0
;
long_comp
xx
=
(
long_comp
)
x
[
i
]
*
x
[
j
];
if
((
COMP_MAX
-
xx
)
<
xx
)
c
=
1
;
tmp
=
(
xx
<<
1
);
if
((
COMP_MAX
-
tmp
)
<
w
[
i
+
j
])
c
=
1
;
tmp
+=
w
[
i
+
j
];
if
((
COMP_MAX
-
tmp
)
<
carry
)
c
=
1
;
tmp
+=
carry
;
w
[
i
+
j
]
=
(
comp
)
tmp
;
carry
=
tmp
>>
COMP_BIT_SIZE
;
if
(
c
)
carry
+=
COMP_RADIX
;
}
tmp
=
w
[
i
+
t
]
+
carry
;
w
[
i
+
t
]
=
(
comp
)
tmp
;
w
[
i
+
t
+
1
]
=
tmp
>>
COMP_BIT_SIZE
;
}
while
(
++
i
<
t
);
bi_free
(
ctx
,
bi
);
return
trim
(
biR
);
}
/**
* @brief Perform a square operation on a bigint.
* @param ctx [in] The bigint session context.
* @param bia [in] A bigint.
* @return The result of the multiplication.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_square
(
BI_CTX
*
ctx
,
bigint
*
bia
)
{
check
(
bia
);
#ifdef CONFIG_BIGINT_KARATSUBA
if
(
bia
->
size
<
SQU_KARATSUBA_THRESH
)
{
return
regular_square
(
ctx
,
bia
);
}
return
karatsuba
(
ctx
,
bia
,
NULL
,
1
);
#else
return
regular_square
(
ctx
,
bia
);
#endif
}
#endif
/**
* @brief Compare two bigints.
* @param bia [in] A bigint.
* @param bib [in] Another bigint.
* @return -1 if smaller, 1 if larger and 0 if equal.
*/
int
ICACHE_FLASH_ATTR
bi_compare
(
bigint
*
bia
,
bigint
*
bib
)
{
int
r
,
i
;
check
(
bia
);
check
(
bib
);
if
(
bia
->
size
>
bib
->
size
)
r
=
1
;
else
if
(
bia
->
size
<
bib
->
size
)
r
=
-
1
;
else
{
comp
*
a
=
bia
->
comps
;
comp
*
b
=
bib
->
comps
;
/* Same number of components. Compare starting from the high end
* and working down. */
r
=
0
;
i
=
bia
->
size
-
1
;
do
{
if
(
a
[
i
]
>
b
[
i
])
{
r
=
1
;
break
;
}
else
if
(
a
[
i
]
<
b
[
i
])
{
r
=
-
1
;
break
;
}
}
while
(
--
i
>=
0
);
}
return
r
;
}
/*
* Allocate and zero more components. Does not consume bi.
*/
static
void
ICACHE_FLASH_ATTR
more_comps
(
bigint
*
bi
,
int
n
)
{
if
(
n
>
bi
->
max_comps
)
{
bi
->
max_comps
=
max
(
bi
->
max_comps
*
2
,
n
);
bi
->
comps
=
(
comp
*
)
os_realloc
(
bi
->
comps
,
bi
->
max_comps
*
COMP_BYTE_SIZE
);
}
if
(
n
>
bi
->
size
)
{
os_memset
(
&
bi
->
comps
[
bi
->
size
],
0
,
(
n
-
bi
->
size
)
*
COMP_BYTE_SIZE
);
}
bi
->
size
=
n
;
}
/*
* Make a new empty bigint. It may just use an old one if one is available.
* Otherwise get one off the heap.
*/
static
bigint
*
ICACHE_FLASH_ATTR
alloc
(
BI_CTX
*
ctx
,
int
size
)
{
bigint
*
biR
;
/* Can we recycle an old bigint? */
if
(
ctx
->
free_list
!=
NULL
)
{
biR
=
ctx
->
free_list
;
ctx
->
free_list
=
biR
->
next
;
ctx
->
free_count
--
;
if
(
biR
->
refs
!=
0
)
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"alloc: refs was not 0
\n
"
);
#endif
return
;
/* wujg : org ----> abort(); */
}
more_comps
(
biR
,
size
);
}
else
{
/* No free bigints available - create a new one. */
biR
=
(
bigint
*
)
os_malloc
(
sizeof
(
bigint
));
biR
->
comps
=
(
comp
*
)
os_malloc
(
size
*
COMP_BYTE_SIZE
);
biR
->
max_comps
=
size
;
/* give some space to spare */
}
biR
->
size
=
size
;
biR
->
refs
=
1
;
biR
->
next
=
NULL
;
ctx
->
active_count
++
;
return
biR
;
}
/*
* Work out the highest '1' bit in an exponent. Used when doing sliding-window
* exponentiation.
*/
static
int
ICACHE_FLASH_ATTR
find_max_exp_index
(
bigint
*
biexp
)
{
int
i
=
COMP_BIT_SIZE
-
1
;
comp
shift
=
COMP_RADIX
/
2
;
comp
test
=
biexp
->
comps
[
biexp
->
size
-
1
];
/* assume no leading zeroes */
check
(
biexp
);
do
{
if
(
test
&
shift
)
{
return
i
+
(
biexp
->
size
-
1
)
*
COMP_BIT_SIZE
;
}
shift
>>=
1
;
}
while
(
i
--
!=
0
);
return
-
1
;
/* error - must have been a leading 0 */
}
/*
* Is a particular bit is an exponent 1 or 0? Used when doing sliding-window
* exponentiation.
*/
static
int
ICACHE_FLASH_ATTR
exp_bit_is_one
(
bigint
*
biexp
,
int
offset
)
{
comp
test
=
biexp
->
comps
[
offset
/
COMP_BIT_SIZE
];
int
num_shifts
=
offset
%
COMP_BIT_SIZE
;
comp
shift
=
1
;
int
i
;
check
(
biexp
);
for
(
i
=
0
;
i
<
num_shifts
;
i
++
)
{
shift
<<=
1
;
}
return
(
test
&
shift
)
!=
0
;
}
#ifdef CONFIG_BIGINT_CHECK_ON
/*
* Perform a sanity check on bi.
*/
static
void
ICACHE_FLASH_ATTR
check
(
const
bigint
*
bi
)
{
if
(
bi
->
refs
<=
0
)
{
ssl_printf
(
"check: zero or negative refs in bigint
\n
"
);
return
;
/* wujg : org ----> abort(); */
}
if
(
bi
->
next
!=
NULL
)
{
ssl_printf
(
"check: attempt to use a bigint from "
"the free list
\n
"
);
return
;
/* wujg : org ----> abort(); */
}
}
#endif
/*
* Delete any leading 0's (and allow for 0).
*/
static
bigint
*
ICACHE_FLASH_ATTR
trim
(
bigint
*
bi
)
{
check
(
bi
);
while
(
bi
->
comps
[
bi
->
size
-
1
]
==
0
&&
bi
->
size
>
1
)
{
bi
->
size
--
;
}
return
bi
;
}
#if defined(CONFIG_BIGINT_MONTGOMERY)
/**
* @brief Perform a single montgomery reduction.
* @param ctx [in] The bigint session context.
* @param bixy [in] A bigint.
* @return The result of the montgomery reduction.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_mont
(
BI_CTX
*
ctx
,
bigint
*
bixy
)
{
int
i
=
0
,
n
;
uint8_t
mod_offset
=
ctx
->
mod_offset
;
bigint
*
bim
=
ctx
->
bi_mod
[
mod_offset
];
comp
mod_inv
=
ctx
->
N0_dash
[
mod_offset
];
check
(
bixy
);
if
(
ctx
->
use_classical
)
/* just use classical instead */
{
return
bi_mod
(
ctx
,
bixy
);
}
n
=
bim
->
size
;
do
{
bixy
=
bi_add
(
ctx
,
bixy
,
comp_left_shift
(
bi_int_multiply
(
ctx
,
bim
,
bixy
->
comps
[
i
]
*
mod_inv
),
i
));
}
while
(
++
i
<
n
);
comp_right_shift
(
bixy
,
n
);
if
(
bi_compare
(
bixy
,
bim
)
>=
0
)
{
bixy
=
bi_subtract
(
ctx
,
bixy
,
bim
,
NULL
);
}
return
bixy
;
}
#elif defined(CONFIG_BIGINT_BARRETT)
/*
* Stomp on the most significant components to give the illusion of a "mod base
* radix" operation
*/
static
bigint
*
ICACHE_FLASH_ATTR
comp_mod
(
bigint
*
bi
,
int
mod
)
{
check
(
bi
);
if
(
bi
->
size
>
mod
)
{
bi
->
size
=
mod
;
}
return
bi
;
}
/**
* @brief Perform a single Barrett reduction.
* @param ctx [in] The bigint session context.
* @param bi [in] A bigint.
* @return The result of the Barrett reduction.
*/
bigint
*
ICACHE_FLASH_ATTR
bi_barrett
(
BI_CTX
*
ctx
,
bigint
*
bi
)
{
bigint
*
q1
,
*
q2
,
*
q3
,
*
r1
,
*
r2
,
*
r
;
uint8_t
mod_offset
=
ctx
->
mod_offset
;
bigint
*
bim
=
ctx
->
bi_mod
[
mod_offset
];
int
k
=
bim
->
size
;
check
(
bi
);
check
(
bim
);
/* use Classical method instead - Barrett cannot help here */
if
(
bi
->
size
>
k
*
2
)
{
return
bi_mod
(
ctx
,
bi
);
}
q1
=
comp_right_shift
(
bi_clone
(
ctx
,
bi
),
k
-
1
);
/* do outer partial multiply */
q2
=
regular_multiply
(
ctx
,
q1
,
ctx
->
bi_mu
[
mod_offset
],
0
,
k
-
1
);
q3
=
comp_right_shift
(
q2
,
k
+
1
);
r1
=
comp_mod
(
bi
,
k
+
1
);
/* do inner partial multiply */
r2
=
comp_mod
(
regular_multiply
(
ctx
,
q3
,
bim
,
k
+
1
,
0
),
k
+
1
);
r
=
bi_subtract
(
ctx
,
r1
,
r2
,
NULL
);
/* if (r >= m) r = r - m; */
if
(
bi_compare
(
r
,
bim
)
>=
0
)
{
r
=
bi_subtract
(
ctx
,
r
,
bim
,
NULL
);
}
return
r
;
}
#endif
/* CONFIG_BIGINT_BARRETT */
#ifdef CONFIG_BIGINT_SLIDING_WINDOW
/*
* Work out g1, g3, g5, g7... etc for the sliding-window algorithm
*/
static
void
ICACHE_FLASH_ATTR
precompute_slide_window
(
BI_CTX
*
ctx
,
int
window
,
bigint
*
g1
)
{
int
k
=
1
,
i
;
bigint
*
g2
;
for
(
i
=
0
;
i
<
window
-
1
;
i
++
)
/* compute 2^(window-1) */
{
k
<<=
1
;
}
ctx
->
g
=
(
bigint
**
)
os_malloc
(
k
*
sizeof
(
bigint
*
));
ctx
->
g
[
0
]
=
bi_clone
(
ctx
,
g1
);
bi_permanent
(
ctx
->
g
[
0
]);
g2
=
bi_residue
(
ctx
,
bi_square
(
ctx
,
ctx
->
g
[
0
]));
/* g^2 */
for
(
i
=
1
;
i
<
k
;
i
++
)
{
ctx
->
g
[
i
]
=
bi_residue
(
ctx
,
bi_multiply
(
ctx
,
ctx
->
g
[
i
-
1
],
bi_copy
(
g2
)));
bi_permanent
(
ctx
->
g
[
i
]);
}
bi_free
(
ctx
,
g2
);
ctx
->
window
=
k
;
}
#endif
/**
* @brief Perform a modular exponentiation.
*
* This function requires bi_set_mod() to have been called previously. This is
* one of the optimisations used for performance.
* @param ctx [in] The bigint session context.
* @param bi [in] The bigint on which to perform the mod power operation.
* @param biexp [in] The bigint exponent.
* @return The result of the mod exponentiation operation
* @see bi_set_mod().
*/
bigint
*
ICACHE_FLASH_ATTR
bi_mod_power
(
BI_CTX
*
ctx
,
bigint
*
bi
,
bigint
*
biexp
)
{
int
i
=
find_max_exp_index
(
biexp
),
j
,
window_size
=
1
;
bigint
*
biR
=
int_to_bi
(
ctx
,
1
);
#if defined(CONFIG_BIGINT_MONTGOMERY)
uint8_t
mod_offset
=
ctx
->
mod_offset
;
if
(
!
ctx
->
use_classical
)
{
/* preconvert */
bi
=
bi_mont
(
ctx
,
bi_multiply
(
ctx
,
bi
,
ctx
->
bi_RR_mod_m
[
mod_offset
]));
/* x' */
bi_free
(
ctx
,
biR
);
biR
=
ctx
->
bi_R_mod_m
[
mod_offset
];
/* A */
}
#endif
check
(
bi
);
check
(
biexp
);
#ifdef CONFIG_BIGINT_SLIDING_WINDOW
for
(
j
=
i
;
j
>
32
;
j
/=
5
)
/* work out an optimum size */
window_size
++
;
/* work out the slide constants */
precompute_slide_window
(
ctx
,
window_size
,
bi
);
#else
/* just one constant */
ctx
->
g
=
(
bigint
**
)
os_malloc
(
sizeof
(
bigint
*
));
ctx
->
g
[
0
]
=
bi_clone
(
ctx
,
bi
);
ctx
->
window
=
1
;
bi_permanent
(
ctx
->
g
[
0
]);
#endif
/* if sliding-window is off, then only one bit will be done at a time and
* will reduce to standard left-to-right exponentiation */
do
{
if
(
exp_bit_is_one
(
biexp
,
i
))
{
int
l
=
i
-
window_size
+
1
;
int
part_exp
=
0
;
if
(
l
<
0
)
/* LSB of exponent will always be 1 */
l
=
0
;
else
{
while
(
exp_bit_is_one
(
biexp
,
l
)
==
0
)
l
++
;
/* go back up */
}
/* build up the section of the exponent */
for
(
j
=
i
;
j
>=
l
;
j
--
)
{
biR
=
bi_residue
(
ctx
,
bi_square
(
ctx
,
biR
));
if
(
exp_bit_is_one
(
biexp
,
j
))
part_exp
++
;
if
(
j
!=
l
)
part_exp
<<=
1
;
}
part_exp
=
(
part_exp
-
1
)
/
2
;
/* adjust for array */
biR
=
bi_residue
(
ctx
,
bi_multiply
(
ctx
,
biR
,
ctx
->
g
[
part_exp
]));
i
=
l
-
1
;
}
else
/* square it */
{
biR
=
bi_residue
(
ctx
,
bi_square
(
ctx
,
biR
));
i
--
;
}
}
while
(
i
>=
0
);
/* cleanup */
for
(
i
=
0
;
i
<
ctx
->
window
;
i
++
)
{
bi_depermanent
(
ctx
->
g
[
i
]);
bi_free
(
ctx
,
ctx
->
g
[
i
]);
}
os_free
(
ctx
->
g
);
bi_free
(
ctx
,
bi
);
bi_free
(
ctx
,
biexp
);
#if defined CONFIG_BIGINT_MONTGOMERY
return
ctx
->
use_classical
?
biR
:
bi_mont
(
ctx
,
biR
);
/* convert back */
#else
/* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */
return
biR
;
#endif
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* @brief Perform a modular exponentiation using a temporary modulus.
*
* We need this function to check the signatures of certificates. The modulus
* of this function is temporary as it's just used for authentication.
* @param ctx [in] The bigint session context.
* @param bi [in] The bigint to perform the exp/mod.
* @param bim [in] The temporary modulus.
* @param biexp [in] The bigint exponent.
* @return The result of the mod exponentiation operation
* @see bi_set_mod().
*/
bigint
*
ICACHE_FLASH_ATTR
bi_mod_power2
(
BI_CTX
*
ctx
,
bigint
*
bi
,
bigint
*
bim
,
bigint
*
biexp
)
{
bigint
*
biR
,
*
tmp_biR
;
/* Set up a temporary bigint context and transfer what we need between
* them. We need to do this since we want to keep the original modulus
* which is already in this context. This operation is only called when
* doing peer verification, and so is not expensive :-) */
BI_CTX
*
tmp_ctx
=
bi_initialize
();
bi_set_mod
(
tmp_ctx
,
bi_clone
(
tmp_ctx
,
bim
),
BIGINT_M_OFFSET
);
tmp_biR
=
bi_mod_power
(
tmp_ctx
,
bi_clone
(
tmp_ctx
,
bi
),
bi_clone
(
tmp_ctx
,
biexp
));
biR
=
bi_clone
(
ctx
,
tmp_biR
);
bi_free
(
tmp_ctx
,
tmp_biR
);
bi_free_mod
(
tmp_ctx
,
BIGINT_M_OFFSET
);
bi_terminate
(
tmp_ctx
);
bi_free
(
ctx
,
bi
);
bi_free
(
ctx
,
bim
);
bi_free
(
ctx
,
biexp
);
return
biR
;
}
#endif
#ifdef CONFIG_BIGINT_CRT
/**
* @brief Use the Chinese Remainder Theorem to quickly perform RSA decrypts.
*
* @param ctx [in] The bigint session context.
* @param bi [in] The bigint to perform the exp/mod.
* @param dP [in] CRT's dP bigint
* @param dQ [in] CRT's dQ bigint
* @param p [in] CRT's p bigint
* @param q [in] CRT's q bigint
* @param qInv [in] CRT's qInv bigint
* @return The result of the CRT operation
*/
bigint
*
ICACHE_FLASH_ATTR
bi_crt
(
BI_CTX
*
ctx
,
bigint
*
bi
,
bigint
*
dP
,
bigint
*
dQ
,
bigint
*
p
,
bigint
*
q
,
bigint
*
qInv
)
{
bigint
*
m1
,
*
m2
,
*
h
;
/* Montgomery has a condition the 0 < x, y < m and these products violate
* that condition. So disable Montgomery when using CRT */
#if defined(CONFIG_BIGINT_MONTGOMERY)
ctx
->
use_classical
=
1
;
#endif
ctx
->
mod_offset
=
BIGINT_P_OFFSET
;
m1
=
bi_mod_power
(
ctx
,
bi_copy
(
bi
),
dP
);
ctx
->
mod_offset
=
BIGINT_Q_OFFSET
;
m2
=
bi_mod_power
(
ctx
,
bi
,
dQ
);
h
=
bi_subtract
(
ctx
,
bi_add
(
ctx
,
m1
,
p
),
bi_copy
(
m2
),
NULL
);
h
=
bi_multiply
(
ctx
,
h
,
qInv
);
ctx
->
mod_offset
=
BIGINT_P_OFFSET
;
h
=
bi_residue
(
ctx
,
h
);
#if defined(CONFIG_BIGINT_MONTGOMERY)
ctx
->
use_classical
=
0
;
/* reset for any further operation */
#endif
return
bi_add
(
ctx
,
m2
,
bi_multiply
(
ctx
,
q
,
h
));
}
#endif
/** @} */
app/ssl/crypto/ssl_crypto_misc.c
deleted
100644 → 0
View file @
093a8959
/*
* Copyright (c) 2007, Cameron Rich
*
* 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 name of the axTLS project 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.
*/
/**
* Some misc. routines to help things out
*/
#include <stdlib.h>
//#include <string.h>
//#include <stdarg.h>
//#include <stdio.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_crypto_misc.h"
#ifdef CONFIG_WIN32_USE_CRYPTO_LIB
#include "wincrypt.h"
#endif
#ifndef WIN32
static
int
rng_fd
=
-
1
;
#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
static
HCRYPTPROV
gCryptProv
;
#endif
#if (!defined(CONFIG_USE_DEV_URANDOM) && !defined(CONFIG_WIN32_USE_CRYPTO_LIB))
/* change to processor registers as appropriate */
#define ENTROPY_POOL_SIZE 32
#define ENTROPY_COUNTER1 ((((uint64_t)tv.tv_sec)<<32) | tv.tv_usec)
#define ENTROPY_COUNTER2 rand()
static
uint8_t
entropy_pool
[
ENTROPY_POOL_SIZE
];
#endif
const
char
*
const
unsupported_str
=
"Error: Feature not supported
\n
"
;
#ifndef CONFIG_SSL_SKELETON_MODE
/**
* Retrieve a file and put it into memory
* @return The size of the file, or -1 on failure.
*/
int
get_file
(
const
char
*
filename
,
uint8_t
**
buf
)
{
#if 0
int total_bytes = 0;
int bytes_read = 0;
int filesize;
FILE *stream = fopen(filename, "rb");
if (stream == NULL)
{
#ifdef CONFIG_SSL_FULL_MODE
printf("file '%s' does not exist\n", filename); //TTY_FLUSH();
#endif
return -1;
}
/* Win CE doesn't support stat() */
fseek(stream, 0, SEEK_END);
filesize = ftell(stream);
*buf = (uint8_t *)os_malloc(filesize);
fseek(stream, 0, SEEK_SET);
do
{
bytes_read = fread(*buf+total_bytes, 1, filesize-total_bytes, stream);
total_bytes += bytes_read;
} while (total_bytes < filesize && bytes_read > 0);
fclose(stream);
return filesize;
#endif
return
0
;
}
#endif
/**
* Initialise the Random Number Generator engine.
* - On Win32 use the platform SDK's crypto engine.
* - On Linux use /dev/urandom
* - If none of these work then use a custom RNG.
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
RNG_initialize
()
{
#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
rng_fd
=
ax_open
(
"/dev/urandom"
,
O_RDONLY
);
#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
if
(
!
CryptAcquireContext
(
&
gCryptProv
,
NULL
,
NULL
,
PROV_RSA_FULL
,
0
))
{
if
(
GetLastError
()
==
NTE_BAD_KEYSET
&&
!
CryptAcquireContext
(
&
gCryptProv
,
NULL
,
NULL
,
PROV_RSA_FULL
,
CRYPT_NEWKEYSET
))
{
printf
(
"CryptoLib: %x
\n
"
,
unsupported_str
,
GetLastError
());
exit
(
1
);
}
}
#else
/* start of with a stack to copy across */
int
i
;
os_memcpy
(
entropy_pool
,
&
i
,
ENTROPY_POOL_SIZE
);
srand
((
unsigned
int
)
&
i
);
#endif
}
/**
* If no /dev/urandom, then initialise the RNG with something interesting.
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
RNG_custom_init
(
const
uint8_t
*
seed_buf
,
int
size
)
{
#if defined(WIN32) || defined(CONFIG_WIN32_USE_CRYPTO_LIB)
int
i
;
for
(
i
=
0
;
i
<
ENTROPY_POOL_SIZE
&&
i
<
size
;
i
++
)
entropy_pool
[
i
]
^=
seed_buf
[
i
];
#endif
}
/**
* Terminate the RNG engine.
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
RNG_terminate
(
void
)
{
#ifndef WIN32
// close(rng_fd);
#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
CryptReleaseContext
(
gCryptProv
,
0
);
#endif
}
/**
* Set a series of bytes with a random number. Individual bytes can be 0
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
get_random
(
int
num_rand_bytes
,
uint8_t
*
rand_data
)
{
#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
/* use the Linux default */
read
(
rng_fd
,
rand_data
,
num_rand_bytes
);
/* read from /dev/urandom */
#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
/* use Microsoft Crypto Libraries */
CryptGenRandom
(
gCryptProv
,
num_rand_bytes
,
rand_data
);
#else
/* nothing else to use, so use a custom RNG */
/* The method we use when we've got nothing better. Use RC4, time
and a couple of random seeds to generate a random sequence */
RC4_CTX
rng_ctx
;
struct
timeval
tv
;
MD5_CTX
rng_digest_ctx
;
uint8_t
digest
[
MD5_SIZE
];
uint64_t
*
ep
;
int
i
;
/* A proper implementation would use counters etc for entropy */
// gettimeofday(&tv, NULL);
ep
=
(
uint64_t
*
)
entropy_pool
;
ep
[
0
]
^=
ENTROPY_COUNTER1
;
ep
[
1
]
^=
ENTROPY_COUNTER2
;
/* use a digested version of the entropy pool as a key */
MD5_Init
(
&
rng_digest_ctx
);
MD5_Update
(
&
rng_digest_ctx
,
entropy_pool
,
ENTROPY_POOL_SIZE
);
MD5_Final
(
digest
,
&
rng_digest_ctx
);
/* come up with the random sequence */
RC4_setup
(
&
rng_ctx
,
digest
,
MD5_SIZE
);
/* use as a key */
os_memcpy
(
rand_data
,
entropy_pool
,
num_rand_bytes
<
ENTROPY_POOL_SIZE
?
num_rand_bytes
:
ENTROPY_POOL_SIZE
);
RC4_crypt
(
&
rng_ctx
,
rand_data
,
rand_data
,
num_rand_bytes
);
/* move things along */
for
(
i
=
ENTROPY_POOL_SIZE
-
1
;
i
>=
MD5_SIZE
;
i
--
)
entropy_pool
[
i
]
=
entropy_pool
[
i
-
MD5_SIZE
];
/* insert the digest at the start of the entropy pool */
os_memcpy
(
entropy_pool
,
digest
,
MD5_SIZE
);
#endif
}
/**
* Set a series of bytes with a random number. Individual bytes are not zero.
*/
void
ICACHE_FLASH_ATTR
get_random_NZ
(
int
num_rand_bytes
,
uint8_t
*
rand_data
)
{
int
i
;
get_random
(
num_rand_bytes
,
rand_data
);
for
(
i
=
0
;
i
<
num_rand_bytes
;
i
++
)
{
while
(
rand_data
[
i
]
==
0
)
/* can't be 0 */
rand_data
[
i
]
=
(
uint8_t
)(
rand
());
}
}
/**
* Some useful diagnostic routines
*/
#if defined(CONFIG_SSL_FULL_MODE) || defined(CONFIG_DEBUG)
int
hex_finish
;
int
hex_index
;
static
void
ICACHE_FLASH_ATTR
print_hex_init
(
int
finish
)
{
hex_finish
=
finish
;
hex_index
=
0
;
}
static
void
ICACHE_FLASH_ATTR
print_hex
(
uint8_t
hex
)
{
static
int
column
;
if
(
hex_index
==
0
)
{
column
=
0
;
}
ssl_printf
(
"%02x "
,
hex
);
if
(
++
column
==
8
)
{
ssl_printf
(
": "
);
}
else
if
(
column
>=
16
)
{
ssl_printf
(
"
\n
"
);
column
=
0
;
}
if
(
++
hex_index
>=
hex_finish
&&
column
>
0
)
{
ssl_printf
(
"
\n
"
);
}
}
/**
* Spit out a blob of data for diagnostics. The data is is a nice column format
* for easy reading.
*
* @param format [in] The string (with possible embedded format characters)
* @param size [in] The number of numbers to print
* @param data [in] The start of data to use
* @param ... [in] Any additional arguments
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
print_blob
(
const
char
*
format
,
const
uint8_t
*
data
,
int
size
,
...)
{
// int i;
// char tmp[80];
// va_list(ap);
// va_start(ap, size);
// sprintf(tmp, "%s\n", format);
// vprintf(tmp, ap);
// print_hex_init(size);
// for (i = 0; i < size; i++)
// {
// print_hex(data[i]);
// }
// va_end(ap);
// TTY_FLUSH();
}
#elif defined(WIN32)
/* VC6.0 doesn't handle variadic macros */
EXP_FUNC
void
STDCALL
print_blob
(
const
char
*
format
,
const
unsigned
char
*
data
,
int
size
,
...)
{}
#endif
#if defined(CONFIG_SSL_HAS_PEM) || defined(CONFIG_HTTP_HAS_AUTHORIZATION)
/* base64 to binary lookup table */
static
const
uint8_t
map
[
128
]
=
{
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
62
,
255
,
255
,
255
,
63
,
52
,
53
,
54
,
55
,
56
,
57
,
58
,
59
,
60
,
61
,
255
,
255
,
255
,
254
,
255
,
255
,
255
,
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
,
255
,
255
,
255
,
255
,
255
,
255
,
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
,
255
,
255
,
255
,
255
,
255
};
EXP_FUNC
int
STDCALL
ICACHE_FLASH_ATTR
base64_decode
(
const
char
*
in
,
int
len
,
uint8_t
*
out
,
int
*
outlen
)
{
int
g
,
t
,
x
,
y
,
z
;
uint8_t
c
;
int
ret
=
-
1
;
g
=
3
;
for
(
x
=
y
=
z
=
t
=
0
;
x
<
len
;
x
++
)
{
if
((
c
=
map
[
in
[
x
]
&
0x7F
])
==
0xff
)
continue
;
if
(
c
==
254
)
/* this is the end... */
{
c
=
0
;
if
(
--
g
<
0
)
goto
error
;
}
else
if
(
g
!=
3
)
/* only allow = at end */
goto
error
;
t
=
(
t
<<
6
)
|
c
;
if
(
++
y
==
4
)
{
out
[
z
++
]
=
(
uint8_t
)((
t
>>
16
)
&
255
);
if
(
g
>
1
)
out
[
z
++
]
=
(
uint8_t
)((
t
>>
8
)
&
255
);
if
(
g
>
2
)
out
[
z
++
]
=
(
uint8_t
)(
t
&
255
);
y
=
t
=
0
;
}
/* check that we don't go past the output buffer */
if
(
z
>
*
outlen
)
goto
error
;
}
if
(
y
!=
0
)
goto
error
;
*
outlen
=
z
;
ret
=
0
;
error:
#ifdef CONFIG_SSL_FULL_MODE
if
(
ret
<
0
)
ssl_printf
(
"Error: Invalid base64
\n
"
);
//TTY_FLUSH();
#endif
//TTY_FLUSH();
return
ret
;
}
#endif
Prev
1
2
3
4
5
6
7
8
9
…
15
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment