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
Hide whitespace changes
Inline
Side-by-side
app/ssl/crypto/ssl_hmac.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.
*/
/**
* HMAC implementation - This code was originally taken from RFC2104
* See http://www.ietf.org/rfc/rfc2104.txt and
* http://www.faqs.org/rfcs/rfc2202.html
*/
//#include <string.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_crypto.h"
/**
* Perform HMAC-MD5
* NOTE: does not handle keys larger than the block size.
*/
void
ICACHE_FLASH_ATTR
ssl_hmac_md5
(
const
uint8_t
*
msg
,
int
length
,
const
uint8_t
*
key
,
int
key_len
,
uint8_t
*
digest
)
{
MD5_CTX
context
;
uint8_t
k_ipad
[
64
];
uint8_t
k_opad
[
64
];
int
i
;
os_memset
(
k_ipad
,
0
,
sizeof
k_ipad
);
os_memset
(
k_opad
,
0
,
sizeof
k_opad
);
os_memcpy
(
k_ipad
,
key
,
key_len
);
os_memcpy
(
k_opad
,
key
,
key_len
);
for
(
i
=
0
;
i
<
64
;
i
++
)
{
k_ipad
[
i
]
^=
0x36
;
k_opad
[
i
]
^=
0x5c
;
}
MD5_Init
(
&
context
);
MD5_Update
(
&
context
,
k_ipad
,
64
);
MD5_Update
(
&
context
,
msg
,
length
);
MD5_Final
(
digest
,
&
context
);
MD5_Init
(
&
context
);
MD5_Update
(
&
context
,
k_opad
,
64
);
MD5_Update
(
&
context
,
digest
,
MD5_SIZE
);
MD5_Final
(
digest
,
&
context
);
}
/**
* Perform HMAC-SHA1
* NOTE: does not handle keys larger than the block size.
*/
void
ICACHE_FLASH_ATTR
ssl_hmac_sha1
(
const
uint8_t
*
msg
,
int
length
,
const
uint8_t
*
key
,
int
key_len
,
uint8_t
*
digest
)
{
SHA1_CTX
context
;
uint8_t
k_ipad
[
64
];
uint8_t
k_opad
[
64
];
int
i
;
os_memset
(
k_ipad
,
0
,
sizeof
k_ipad
);
os_memset
(
k_opad
,
0
,
sizeof
k_opad
);
os_memcpy
(
k_ipad
,
key
,
key_len
);
os_memcpy
(
k_opad
,
key
,
key_len
);
for
(
i
=
0
;
i
<
64
;
i
++
)
{
k_ipad
[
i
]
^=
0x36
;
k_opad
[
i
]
^=
0x5c
;
}
SHA1_Init
(
&
context
);
SHA1_Update
(
&
context
,
k_ipad
,
64
);
SHA1_Update
(
&
context
,
msg
,
length
);
SHA1_Final
(
digest
,
&
context
);
SHA1_Init
(
&
context
);
SHA1_Update
(
&
context
,
k_opad
,
64
);
SHA1_Update
(
&
context
,
digest
,
SHA1_SIZE
);
SHA1_Final
(
digest
,
&
context
);
}
app/ssl/crypto/ssl_md2.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.
*/
/*
* RFC 1115/1319 compliant MD2 implementation
* The MD2 algorithm was designed by Ron Rivest in 1989.
*
* http://www.ietf.org/rfc/rfc1115.txt
* http://www.ietf.org/rfc/rfc1319.txt
*/
//#include <string.h>
//#include <stdio.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_crypto.h"
//#include "os.h"
#include "lwip/mem.h"
/**
* This code is only here to enable the verification of Verisign root
* certificates. So only enable it for verification mode.
*/
#ifdef CONFIG_SSL_CERT_VERIFICATION
static
const
uint8_t
PI_SUBST
[
256
]
=
{
0x29
,
0x2E
,
0x43
,
0xC9
,
0xA2
,
0xD8
,
0x7C
,
0x01
,
0x3D
,
0x36
,
0x54
,
0xA1
,
0xEC
,
0xF0
,
0x06
,
0x13
,
0x62
,
0xA7
,
0x05
,
0xF3
,
0xC0
,
0xC7
,
0x73
,
0x8C
,
0x98
,
0x93
,
0x2B
,
0xD9
,
0xBC
,
0x4C
,
0x82
,
0xCA
,
0x1E
,
0x9B
,
0x57
,
0x3C
,
0xFD
,
0xD4
,
0xE0
,
0x16
,
0x67
,
0x42
,
0x6F
,
0x18
,
0x8A
,
0x17
,
0xE5
,
0x12
,
0xBE
,
0x4E
,
0xC4
,
0xD6
,
0xDA
,
0x9E
,
0xDE
,
0x49
,
0xA0
,
0xFB
,
0xF5
,
0x8E
,
0xBB
,
0x2F
,
0xEE
,
0x7A
,
0xA9
,
0x68
,
0x79
,
0x91
,
0x15
,
0xB2
,
0x07
,
0x3F
,
0x94
,
0xC2
,
0x10
,
0x89
,
0x0B
,
0x22
,
0x5F
,
0x21
,
0x80
,
0x7F
,
0x5D
,
0x9A
,
0x5A
,
0x90
,
0x32
,
0x27
,
0x35
,
0x3E
,
0xCC
,
0xE7
,
0xBF
,
0xF7
,
0x97
,
0x03
,
0xFF
,
0x19
,
0x30
,
0xB3
,
0x48
,
0xA5
,
0xB5
,
0xD1
,
0xD7
,
0x5E
,
0x92
,
0x2A
,
0xAC
,
0x56
,
0xAA
,
0xC6
,
0x4F
,
0xB8
,
0x38
,
0xD2
,
0x96
,
0xA4
,
0x7D
,
0xB6
,
0x76
,
0xFC
,
0x6B
,
0xE2
,
0x9C
,
0x74
,
0x04
,
0xF1
,
0x45
,
0x9D
,
0x70
,
0x59
,
0x64
,
0x71
,
0x87
,
0x20
,
0x86
,
0x5B
,
0xCF
,
0x65
,
0xE6
,
0x2D
,
0xA8
,
0x02
,
0x1B
,
0x60
,
0x25
,
0xAD
,
0xAE
,
0xB0
,
0xB9
,
0xF6
,
0x1C
,
0x46
,
0x61
,
0x69
,
0x34
,
0x40
,
0x7E
,
0x0F
,
0x55
,
0x47
,
0xA3
,
0x23
,
0xDD
,
0x51
,
0xAF
,
0x3A
,
0xC3
,
0x5C
,
0xF9
,
0xCE
,
0xBA
,
0xC5
,
0xEA
,
0x26
,
0x2C
,
0x53
,
0x0D
,
0x6E
,
0x85
,
0x28
,
0x84
,
0x09
,
0xD3
,
0xDF
,
0xCD
,
0xF4
,
0x41
,
0x81
,
0x4D
,
0x52
,
0x6A
,
0xDC
,
0x37
,
0xC8
,
0x6C
,
0xC1
,
0xAB
,
0xFA
,
0x24
,
0xE1
,
0x7B
,
0x08
,
0x0C
,
0xBD
,
0xB1
,
0x4A
,
0x78
,
0x88
,
0x95
,
0x8B
,
0xE3
,
0x63
,
0xE8
,
0x6D
,
0xE9
,
0xCB
,
0xD5
,
0xFE
,
0x3B
,
0x00
,
0x1D
,
0x39
,
0xF2
,
0xEF
,
0xB7
,
0x0E
,
0x66
,
0x58
,
0xD0
,
0xE4
,
0xA6
,
0x77
,
0x72
,
0xF8
,
0xEB
,
0x75
,
0x4B
,
0x0A
,
0x31
,
0x44
,
0x50
,
0xB4
,
0x8F
,
0xED
,
0x1F
,
0x1A
,
0xDB
,
0x99
,
0x8D
,
0x33
,
0x9F
,
0x11
,
0x83
,
0x14
};
/*
* MD2 context setup
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
MD2_Init
(
MD2_CTX
*
ctx
)
{
os_memset
(
ctx
,
0
,
sizeof
*
ctx
);
}
static
void
ICACHE_FLASH_ATTR
md2_process
(
MD2_CTX
*
ctx
)
{
int
i
,
j
;
uint8_t
t
=
0
;
for
(
i
=
0
;
i
<
16
;
i
++
)
{
ctx
->
state
[
i
+
16
]
=
ctx
->
buffer
[
i
];
ctx
->
state
[
i
+
32
]
=
ctx
->
buffer
[
i
]
^
ctx
->
state
[
i
];
}
for
(
i
=
0
;
i
<
18
;
i
++
)
{
for
(
j
=
0
;
j
<
48
;
j
++
)
t
=
(
ctx
->
state
[
j
]
^=
PI_SUBST
[
t
]);
t
=
(
t
+
i
)
&
0xFF
;
}
t
=
ctx
->
cksum
[
15
];
for
(
i
=
0
;
i
<
16
;
i
++
)
t
=
(
ctx
->
cksum
[
i
]
^=
PI_SUBST
[
ctx
->
buffer
[
i
]
^
t
]);
}
/*
* MD2 process buffer
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
MD2_Update
(
MD2_CTX
*
ctx
,
const
uint8_t
*
input
,
int
ilen
)
{
int
fill
;
while
(
ilen
>
0
)
{
if
(
ctx
->
left
+
ilen
>
16
)
fill
=
16
-
ctx
->
left
;
else
fill
=
ilen
;
os_memcpy
(
ctx
->
buffer
+
ctx
->
left
,
input
,
fill
);
ctx
->
left
+=
fill
;
input
+=
fill
;
ilen
-=
fill
;
if
(
ctx
->
left
==
16
)
{
ctx
->
left
=
0
;
md2_process
(
ctx
);
}
}
}
/*
* MD2 final digest
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
MD2_Final
(
uint8_t
*
output
,
MD2_CTX
*
ctx
)
{
int
i
;
uint8_t
x
;
x
=
(
uint8_t
)(
16
-
ctx
->
left
);
for
(
i
=
ctx
->
left
;
i
<
16
;
i
++
)
ctx
->
buffer
[
i
]
=
x
;
md2_process
(
ctx
);
os_memcpy
(
ctx
->
buffer
,
ctx
->
cksum
,
16
);
md2_process
(
ctx
);
os_memcpy
(
output
,
ctx
->
state
,
16
);
}
#endif
app/ssl/crypto/ssl_md5.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.
*/
/**
* This file implements the MD5 algorithm as defined in RFC1321
*/
//#include <string.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_crypto.h"
//#include "os.h"
#include "lwip/mem.h"
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
/* ----- static functions ----- */
static
void
MD5Transform
(
uint32_t
state
[
4
],
const
uint8_t
block
[
64
]);
static
void
Encode
(
uint8_t
*
output
,
uint32_t
*
input
,
uint32_t
len
);
static
void
Decode
(
uint32_t
*
output
,
const
uint8_t
*
input
,
uint32_t
len
);
static
const
uint8_t
PADDING
[
64
]
=
{
0x80
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation. */
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/**
* MD5 initialization - begins an MD5 operation, writing a new ctx.
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
MD5_Init
(
MD5_CTX
*
ctx
)
{
ctx
->
count
[
0
]
=
ctx
->
count
[
1
]
=
0
;
/* Load magic initialization constants.
*/
ctx
->
state
[
0
]
=
0x67452301
;
ctx
->
state
[
1
]
=
0xefcdab89
;
ctx
->
state
[
2
]
=
0x98badcfe
;
ctx
->
state
[
3
]
=
0x10325476
;
}
/**
* Accepts an array of octets as the next portion of the message.
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
MD5_Update
(
MD5_CTX
*
ctx
,
const
uint8_t
*
msg
,
int
len
)
{
uint32_t
x
;
int
i
,
partLen
;
/* Compute number of bytes mod 64 */
x
=
(
uint32_t
)((
ctx
->
count
[
0
]
>>
3
)
&
0x3F
);
/* Update number of bits */
if
((
ctx
->
count
[
0
]
+=
((
uint32_t
)
len
<<
3
))
<
((
uint32_t
)
len
<<
3
))
ctx
->
count
[
1
]
++
;
ctx
->
count
[
1
]
+=
((
uint32_t
)
len
>>
29
);
partLen
=
64
-
x
;
/* Transform as many times as possible. */
if
(
len
>=
partLen
)
{
os_memcpy
(
&
ctx
->
buffer
[
x
],
msg
,
partLen
);
MD5Transform
(
ctx
->
state
,
ctx
->
buffer
);
for
(
i
=
partLen
;
i
+
63
<
len
;
i
+=
64
)
MD5Transform
(
ctx
->
state
,
&
msg
[
i
]);
x
=
0
;
}
else
i
=
0
;
/* Buffer remaining input */
os_memcpy
(
&
ctx
->
buffer
[
x
],
&
msg
[
i
],
len
-
i
);
}
/**
* Return the 128-bit message digest into the user's array
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
MD5_Final
(
uint8_t
*
digest
,
MD5_CTX
*
ctx
)
{
uint8_t
bits
[
8
];
uint32_t
x
,
padLen
;
/* Save number of bits */
Encode
(
bits
,
ctx
->
count
,
8
);
/* Pad out to 56 mod 64.
*/
x
=
(
uint32_t
)((
ctx
->
count
[
0
]
>>
3
)
&
0x3f
);
padLen
=
(
x
<
56
)
?
(
56
-
x
)
:
(
120
-
x
);
MD5_Update
(
ctx
,
PADDING
,
padLen
);
/* Append length (before padding) */
MD5_Update
(
ctx
,
bits
,
8
);
/* Store state in digest */
Encode
(
digest
,
ctx
->
state
,
MD5_SIZE
);
}
/**
* MD5 basic transformation. Transforms state based on block.
*/
static
void
ICACHE_FLASH_ATTR
MD5Transform
(
uint32_t
state
[
4
],
const
uint8_t
block
[
64
])
{
uint32_t
a
=
state
[
0
],
b
=
state
[
1
],
c
=
state
[
2
],
d
=
state
[
3
],
x
[
MD5_SIZE
];
Decode
(
x
,
block
,
64
);
/* Round 1 */
FF
(
a
,
b
,
c
,
d
,
x
[
0
],
S11
,
0xd76aa478
);
/* 1 */
FF
(
d
,
a
,
b
,
c
,
x
[
1
],
S12
,
0xe8c7b756
);
/* 2 */
FF
(
c
,
d
,
a
,
b
,
x
[
2
],
S13
,
0x242070db
);
/* 3 */
FF
(
b
,
c
,
d
,
a
,
x
[
3
],
S14
,
0xc1bdceee
);
/* 4 */
FF
(
a
,
b
,
c
,
d
,
x
[
4
],
S11
,
0xf57c0faf
);
/* 5 */
FF
(
d
,
a
,
b
,
c
,
x
[
5
],
S12
,
0x4787c62a
);
/* 6 */
FF
(
c
,
d
,
a
,
b
,
x
[
6
],
S13
,
0xa8304613
);
/* 7 */
FF
(
b
,
c
,
d
,
a
,
x
[
7
],
S14
,
0xfd469501
);
/* 8 */
FF
(
a
,
b
,
c
,
d
,
x
[
8
],
S11
,
0x698098d8
);
/* 9 */
FF
(
d
,
a
,
b
,
c
,
x
[
9
],
S12
,
0x8b44f7af
);
/* 10 */
FF
(
c
,
d
,
a
,
b
,
x
[
10
],
S13
,
0xffff5bb1
);
/* 11 */
FF
(
b
,
c
,
d
,
a
,
x
[
11
],
S14
,
0x895cd7be
);
/* 12 */
FF
(
a
,
b
,
c
,
d
,
x
[
12
],
S11
,
0x6b901122
);
/* 13 */
FF
(
d
,
a
,
b
,
c
,
x
[
13
],
S12
,
0xfd987193
);
/* 14 */
FF
(
c
,
d
,
a
,
b
,
x
[
14
],
S13
,
0xa679438e
);
/* 15 */
FF
(
b
,
c
,
d
,
a
,
x
[
15
],
S14
,
0x49b40821
);
/* 16 */
/* Round 2 */
GG
(
a
,
b
,
c
,
d
,
x
[
1
],
S21
,
0xf61e2562
);
/* 17 */
GG
(
d
,
a
,
b
,
c
,
x
[
6
],
S22
,
0xc040b340
);
/* 18 */
GG
(
c
,
d
,
a
,
b
,
x
[
11
],
S23
,
0x265e5a51
);
/* 19 */
GG
(
b
,
c
,
d
,
a
,
x
[
0
],
S24
,
0xe9b6c7aa
);
/* 20 */
GG
(
a
,
b
,
c
,
d
,
x
[
5
],
S21
,
0xd62f105d
);
/* 21 */
GG
(
d
,
a
,
b
,
c
,
x
[
10
],
S22
,
0x2441453
);
/* 22 */
GG
(
c
,
d
,
a
,
b
,
x
[
15
],
S23
,
0xd8a1e681
);
/* 23 */
GG
(
b
,
c
,
d
,
a
,
x
[
4
],
S24
,
0xe7d3fbc8
);
/* 24 */
GG
(
a
,
b
,
c
,
d
,
x
[
9
],
S21
,
0x21e1cde6
);
/* 25 */
GG
(
d
,
a
,
b
,
c
,
x
[
14
],
S22
,
0xc33707d6
);
/* 26 */
GG
(
c
,
d
,
a
,
b
,
x
[
3
],
S23
,
0xf4d50d87
);
/* 27 */
GG
(
b
,
c
,
d
,
a
,
x
[
8
],
S24
,
0x455a14ed
);
/* 28 */
GG
(
a
,
b
,
c
,
d
,
x
[
13
],
S21
,
0xa9e3e905
);
/* 29 */
GG
(
d
,
a
,
b
,
c
,
x
[
2
],
S22
,
0xfcefa3f8
);
/* 30 */
GG
(
c
,
d
,
a
,
b
,
x
[
7
],
S23
,
0x676f02d9
);
/* 31 */
GG
(
b
,
c
,
d
,
a
,
x
[
12
],
S24
,
0x8d2a4c8a
);
/* 32 */
/* Round 3 */
HH
(
a
,
b
,
c
,
d
,
x
[
5
],
S31
,
0xfffa3942
);
/* 33 */
HH
(
d
,
a
,
b
,
c
,
x
[
8
],
S32
,
0x8771f681
);
/* 34 */
HH
(
c
,
d
,
a
,
b
,
x
[
11
],
S33
,
0x6d9d6122
);
/* 35 */
HH
(
b
,
c
,
d
,
a
,
x
[
14
],
S34
,
0xfde5380c
);
/* 36 */
HH
(
a
,
b
,
c
,
d
,
x
[
1
],
S31
,
0xa4beea44
);
/* 37 */
HH
(
d
,
a
,
b
,
c
,
x
[
4
],
S32
,
0x4bdecfa9
);
/* 38 */
HH
(
c
,
d
,
a
,
b
,
x
[
7
],
S33
,
0xf6bb4b60
);
/* 39 */
HH
(
b
,
c
,
d
,
a
,
x
[
10
],
S34
,
0xbebfbc70
);
/* 40 */
HH
(
a
,
b
,
c
,
d
,
x
[
13
],
S31
,
0x289b7ec6
);
/* 41 */
HH
(
d
,
a
,
b
,
c
,
x
[
0
],
S32
,
0xeaa127fa
);
/* 42 */
HH
(
c
,
d
,
a
,
b
,
x
[
3
],
S33
,
0xd4ef3085
);
/* 43 */
HH
(
b
,
c
,
d
,
a
,
x
[
6
],
S34
,
0x4881d05
);
/* 44 */
HH
(
a
,
b
,
c
,
d
,
x
[
9
],
S31
,
0xd9d4d039
);
/* 45 */
HH
(
d
,
a
,
b
,
c
,
x
[
12
],
S32
,
0xe6db99e5
);
/* 46 */
HH
(
c
,
d
,
a
,
b
,
x
[
15
],
S33
,
0x1fa27cf8
);
/* 47 */
HH
(
b
,
c
,
d
,
a
,
x
[
2
],
S34
,
0xc4ac5665
);
/* 48 */
/* Round 4 */
II
(
a
,
b
,
c
,
d
,
x
[
0
],
S41
,
0xf4292244
);
/* 49 */
II
(
d
,
a
,
b
,
c
,
x
[
7
],
S42
,
0x432aff97
);
/* 50 */
II
(
c
,
d
,
a
,
b
,
x
[
14
],
S43
,
0xab9423a7
);
/* 51 */
II
(
b
,
c
,
d
,
a
,
x
[
5
],
S44
,
0xfc93a039
);
/* 52 */
II
(
a
,
b
,
c
,
d
,
x
[
12
],
S41
,
0x655b59c3
);
/* 53 */
II
(
d
,
a
,
b
,
c
,
x
[
3
],
S42
,
0x8f0ccc92
);
/* 54 */
II
(
c
,
d
,
a
,
b
,
x
[
10
],
S43
,
0xffeff47d
);
/* 55 */
II
(
b
,
c
,
d
,
a
,
x
[
1
],
S44
,
0x85845dd1
);
/* 56 */
II
(
a
,
b
,
c
,
d
,
x
[
8
],
S41
,
0x6fa87e4f
);
/* 57 */
II
(
d
,
a
,
b
,
c
,
x
[
15
],
S42
,
0xfe2ce6e0
);
/* 58 */
II
(
c
,
d
,
a
,
b
,
x
[
6
],
S43
,
0xa3014314
);
/* 59 */
II
(
b
,
c
,
d
,
a
,
x
[
13
],
S44
,
0x4e0811a1
);
/* 60 */
II
(
a
,
b
,
c
,
d
,
x
[
4
],
S41
,
0xf7537e82
);
/* 61 */
II
(
d
,
a
,
b
,
c
,
x
[
11
],
S42
,
0xbd3af235
);
/* 62 */
II
(
c
,
d
,
a
,
b
,
x
[
2
],
S43
,
0x2ad7d2bb
);
/* 63 */
II
(
b
,
c
,
d
,
a
,
x
[
9
],
S44
,
0xeb86d391
);
/* 64 */
state
[
0
]
+=
a
;
state
[
1
]
+=
b
;
state
[
2
]
+=
c
;
state
[
3
]
+=
d
;
}
/**
* Encodes input (uint32_t) into output (uint8_t). Assumes len is
* a multiple of 4.
*/
static
void
ICACHE_FLASH_ATTR
Encode
(
uint8_t
*
output
,
uint32_t
*
input
,
uint32_t
len
)
{
uint32_t
i
,
j
;
for
(
i
=
0
,
j
=
0
;
j
<
len
;
i
++
,
j
+=
4
)
{
output
[
j
]
=
(
uint8_t
)(
input
[
i
]
&
0xff
);
output
[
j
+
1
]
=
(
uint8_t
)((
input
[
i
]
>>
8
)
&
0xff
);
output
[
j
+
2
]
=
(
uint8_t
)((
input
[
i
]
>>
16
)
&
0xff
);
output
[
j
+
3
]
=
(
uint8_t
)((
input
[
i
]
>>
24
)
&
0xff
);
}
}
/**
* Decodes input (uint8_t) into output (uint32_t). Assumes len is
* a multiple of 4.
*/
static
void
ICACHE_FLASH_ATTR
Decode
(
uint32_t
*
output
,
const
uint8_t
*
input
,
uint32_t
len
)
{
uint32_t
i
,
j
;
for
(
i
=
0
,
j
=
0
;
j
<
len
;
i
++
,
j
+=
4
)
output
[
i
]
=
((
uint32_t
)
input
[
j
])
|
(((
uint32_t
)
input
[
j
+
1
])
<<
8
)
|
(((
uint32_t
)
input
[
j
+
2
])
<<
16
)
|
(((
uint32_t
)
input
[
j
+
3
])
<<
24
);
}
app/ssl/crypto/ssl_rc4.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.
*/
/**
* An implementation of the RC4/ARC4 algorithm.
* Originally written by Christophe Devine.
*/
//#include <string.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_crypto.h"
/**
* Get ready for an encrypt/decrypt operation
*/
void
ICACHE_FLASH_ATTR
RC4_setup
(
RC4_CTX
*
ctx
,
const
uint8_t
*
key
,
int
length
)
{
int
i
,
j
=
0
,
k
=
0
,
a
;
uint8_t
*
m
;
ctx
->
x
=
0
;
ctx
->
y
=
0
;
m
=
ctx
->
m
;
for
(
i
=
0
;
i
<
256
;
i
++
)
m
[
i
]
=
i
;
for
(
i
=
0
;
i
<
256
;
i
++
)
{
a
=
m
[
i
];
j
=
(
uint8_t
)(
j
+
a
+
key
[
k
]);
m
[
i
]
=
m
[
j
];
m
[
j
]
=
a
;
if
(
++
k
>=
length
)
k
=
0
;
}
}
/**
* Perform the encrypt/decrypt operation (can use it for either since
* this is a stream cipher).
* NOTE: *msg and *out must be the same pointer (performance tweak)
*/
void
ICACHE_FLASH_ATTR
RC4_crypt
(
RC4_CTX
*
ctx
,
const
uint8_t
*
msg
,
uint8_t
*
out
,
int
length
)
{
int
i
;
uint8_t
*
m
,
x
,
y
,
a
,
b
;
x
=
ctx
->
x
;
y
=
ctx
->
y
;
m
=
ctx
->
m
;
for
(
i
=
0
;
i
<
length
;
i
++
)
{
a
=
m
[
++
x
];
y
+=
a
;
m
[
x
]
=
b
=
m
[
y
];
m
[
y
]
=
a
;
out
[
i
]
^=
m
[(
uint8_t
)(
a
+
b
)];
}
ctx
->
x
=
x
;
ctx
->
y
=
y
;
}
app/ssl/crypto/ssl_rsa.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.
*/
/**
* Implements the RSA public encryption algorithm. Uses the bigint library to
* perform its calculations.
*/
//#include <stdio.h>
//#include <string.h>
//#include <time.h>
//#include <stdlib.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_crypto.h"
//#include "os.h"
#include "lwip/mem.h"
void
ICACHE_FLASH_ATTR
RSA_priv_key_new
(
RSA_CTX
**
ctx
,
const
uint8_t
*
modulus
,
int
mod_len
,
const
uint8_t
*
pub_exp
,
int
pub_len
,
const
uint8_t
*
priv_exp
,
int
priv_len
#if CONFIG_BIGINT_CRT
,
const
uint8_t
*
p
,
int
p_len
,
const
uint8_t
*
q
,
int
q_len
,
const
uint8_t
*
dP
,
int
dP_len
,
const
uint8_t
*
dQ
,
int
dQ_len
,
const
uint8_t
*
qInv
,
int
qInv_len
#endif
)
{
RSA_CTX
*
rsa_ctx
;
BI_CTX
*
bi_ctx
;
RSA_pub_key_new
(
ctx
,
modulus
,
mod_len
,
pub_exp
,
pub_len
);
rsa_ctx
=
*
ctx
;
bi_ctx
=
rsa_ctx
->
bi_ctx
;
rsa_ctx
->
d
=
bi_import
(
bi_ctx
,
priv_exp
,
priv_len
);
bi_permanent
(
rsa_ctx
->
d
);
#ifdef CONFIG_BIGINT_CRT
rsa_ctx
->
p
=
bi_import
(
bi_ctx
,
p
,
p_len
);
rsa_ctx
->
q
=
bi_import
(
bi_ctx
,
q
,
q_len
);
rsa_ctx
->
dP
=
bi_import
(
bi_ctx
,
dP
,
dP_len
);
rsa_ctx
->
dQ
=
bi_import
(
bi_ctx
,
dQ
,
dQ_len
);
rsa_ctx
->
qInv
=
bi_import
(
bi_ctx
,
qInv
,
qInv_len
);
bi_permanent
(
rsa_ctx
->
dP
);
bi_permanent
(
rsa_ctx
->
dQ
);
bi_permanent
(
rsa_ctx
->
qInv
);
bi_set_mod
(
bi_ctx
,
rsa_ctx
->
p
,
BIGINT_P_OFFSET
);
bi_set_mod
(
bi_ctx
,
rsa_ctx
->
q
,
BIGINT_Q_OFFSET
);
#endif
}
void
ICACHE_FLASH_ATTR
RSA_pub_key_new
(
RSA_CTX
**
ctx
,
const
uint8_t
*
modulus
,
int
mod_len
,
const
uint8_t
*
pub_exp
,
int
pub_len
)
{
RSA_CTX
*
rsa_ctx
;
BI_CTX
*
bi_ctx
;
if
(
*
ctx
)
/* if we load multiple certs, dump the old one */
RSA_free
(
*
ctx
);
bi_ctx
=
bi_initialize
();
*
ctx
=
(
RSA_CTX
*
)
os_zalloc
(
sizeof
(
RSA_CTX
));
rsa_ctx
=
*
ctx
;
rsa_ctx
->
bi_ctx
=
bi_ctx
;
rsa_ctx
->
num_octets
=
mod_len
;
rsa_ctx
->
m
=
bi_import
(
bi_ctx
,
modulus
,
mod_len
);
bi_set_mod
(
bi_ctx
,
rsa_ctx
->
m
,
BIGINT_M_OFFSET
);
rsa_ctx
->
e
=
bi_import
(
bi_ctx
,
pub_exp
,
pub_len
);
bi_permanent
(
rsa_ctx
->
e
);
}
/**
* Free up any RSA context resources.
*/
void
ICACHE_FLASH_ATTR
RSA_free
(
RSA_CTX
*
rsa_ctx
)
{
BI_CTX
*
bi_ctx
;
if
(
rsa_ctx
==
NULL
)
/* deal with ptrs that are null */
return
;
bi_ctx
=
rsa_ctx
->
bi_ctx
;
bi_depermanent
(
rsa_ctx
->
e
);
bi_free
(
bi_ctx
,
rsa_ctx
->
e
);
bi_free_mod
(
rsa_ctx
->
bi_ctx
,
BIGINT_M_OFFSET
);
if
(
rsa_ctx
->
d
)
{
bi_depermanent
(
rsa_ctx
->
d
);
bi_free
(
bi_ctx
,
rsa_ctx
->
d
);
#ifdef CONFIG_BIGINT_CRT
bi_depermanent
(
rsa_ctx
->
dP
);
bi_depermanent
(
rsa_ctx
->
dQ
);
bi_depermanent
(
rsa_ctx
->
qInv
);
bi_free
(
bi_ctx
,
rsa_ctx
->
dP
);
bi_free
(
bi_ctx
,
rsa_ctx
->
dQ
);
bi_free
(
bi_ctx
,
rsa_ctx
->
qInv
);
bi_free_mod
(
rsa_ctx
->
bi_ctx
,
BIGINT_P_OFFSET
);
bi_free_mod
(
rsa_ctx
->
bi_ctx
,
BIGINT_Q_OFFSET
);
#endif
}
bi_terminate
(
bi_ctx
);
os_free
(
rsa_ctx
);
}
/**
* @brief Use PKCS1.5 for decryption/verification.
* @param ctx [in] The context
* @param in_data [in] The data to encrypt (must be < modulus size-11)
* @param out_data [out] The encrypted data.
* @param is_decryption [in] Decryption or verify operation.
* @return The number of bytes that were originally encrypted. -1 on error.
* @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
*/
int
ICACHE_FLASH_ATTR
RSA_decrypt
(
const
RSA_CTX
*
ctx
,
const
uint8_t
*
in_data
,
uint8_t
*
out_data
,
int
is_decryption
)
{
const
int
byte_size
=
ctx
->
num_octets
;
int
i
,
size
;
bigint
*
decrypted_bi
,
*
dat_bi
;
uint8_t
*
block
=
(
uint8_t
*
)
os_malloc
(
byte_size
);
os_memset
(
out_data
,
0
,
byte_size
);
/* initialise */
/* decrypt */
dat_bi
=
bi_import
(
ctx
->
bi_ctx
,
in_data
,
byte_size
);
#ifdef CONFIG_SSL_CERT_VERIFICATION
decrypted_bi
=
is_decryption
?
/* decrypt or verify? */
RSA_private
(
ctx
,
dat_bi
)
:
RSA_public
(
ctx
,
dat_bi
);
#else
/* always a decryption */
decrypted_bi
=
RSA_private
(
ctx
,
dat_bi
);
#endif
/* convert to a normal block */
bi_export
(
ctx
->
bi_ctx
,
decrypted_bi
,
block
,
byte_size
);
i
=
10
;
/* start at the first possible non-padded byte */
#ifdef CONFIG_SSL_CERT_VERIFICATION
if
(
is_decryption
==
0
)
/* PKCS1.5 signing pads with "0xff"s */
{
while
(
block
[
i
++
]
==
0xff
&&
i
<
byte_size
);
if
(
block
[
i
-
2
]
!=
0xff
)
i
=
byte_size
;
/*ensure size is 0 */
}
else
/* PKCS1.5 encryption padding is random */
#endif
{
while
(
block
[
i
++
]
&&
i
<
byte_size
);
}
size
=
byte_size
-
i
;
/* get only the bit we want */
if
(
size
>
0
)
os_memcpy
(
out_data
,
&
block
[
i
],
size
);
os_free
(
block
);
return
size
?
size
:
-
1
;
}
/**
* Performs m = c^d mod n
*/
bigint
*
ICACHE_FLASH_ATTR
RSA_private
(
const
RSA_CTX
*
c
,
bigint
*
bi_msg
)
{
#ifdef CONFIG_BIGINT_CRT
return
bi_crt
(
c
->
bi_ctx
,
bi_msg
,
c
->
dP
,
c
->
dQ
,
c
->
p
,
c
->
q
,
c
->
qInv
);
#else
BI_CTX
*
ctx
=
c
->
bi_ctx
;
ctx
->
mod_offset
=
BIGINT_M_OFFSET
;
return
bi_mod_power
(
ctx
,
bi_msg
,
c
->
d
);
#endif
}
#ifdef CONFIG_SSL_FULL_MODE
/**
* Used for diagnostics.
*/
void
ICACHE_FLASH_ATTR
RSA_print
(
const
RSA_CTX
*
rsa_ctx
)
{
if
(
rsa_ctx
==
NULL
)
return
;
ssl_printf
(
"----------------- RSA DEBUG ----------------
\n
"
);
ssl_printf
(
"Size:
\t
%d
\n
"
,
rsa_ctx
->
num_octets
);
bi_print
(
"Modulus"
,
rsa_ctx
->
m
);
bi_print
(
"Public Key"
,
rsa_ctx
->
e
);
bi_print
(
"Private Key"
,
rsa_ctx
->
d
);
}
#endif
#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)
/**
* Performs c = m^e mod n
*/
bigint
*
ICACHE_FLASH_ATTR
RSA_public
(
const
RSA_CTX
*
c
,
bigint
*
bi_msg
)
{
c
->
bi_ctx
->
mod_offset
=
BIGINT_M_OFFSET
;
return
bi_mod_power
(
c
->
bi_ctx
,
bi_msg
,
c
->
e
);
}
/**
* Use PKCS1.5 for encryption/signing.
* see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
*/
int
ICACHE_FLASH_ATTR
RSA_encrypt
(
const
RSA_CTX
*
ctx
,
const
uint8_t
*
in_data
,
uint16_t
in_len
,
uint8_t
*
out_data
,
int
is_signing
)
{
int
byte_size
=
ctx
->
num_octets
;
int
num_pads_needed
=
byte_size
-
in_len
-
3
;
bigint
*
dat_bi
,
*
encrypt_bi
;
/* note: in_len+11 must be > byte_size */
out_data
[
0
]
=
0
;
/* ensure encryption block is < modulus */
if
(
is_signing
)
{
out_data
[
1
]
=
1
;
/* PKCS1.5 signing pads with "0xff"'s */
os_memset
(
&
out_data
[
2
],
0xff
,
num_pads_needed
);
}
else
/* randomize the encryption padding with non-zero bytes */
{
out_data
[
1
]
=
2
;
get_random_NZ
(
num_pads_needed
,
&
out_data
[
2
]);
}
out_data
[
2
+
num_pads_needed
]
=
0
;
os_memcpy
(
&
out_data
[
3
+
num_pads_needed
],
in_data
,
in_len
);
/* now encrypt it */
dat_bi
=
bi_import
(
ctx
->
bi_ctx
,
out_data
,
byte_size
);
encrypt_bi
=
is_signing
?
RSA_private
(
ctx
,
dat_bi
)
:
RSA_public
(
ctx
,
dat_bi
);
bi_export
(
ctx
->
bi_ctx
,
encrypt_bi
,
out_data
,
byte_size
);
/* save a few bytes of memory */
bi_clear_cache
(
ctx
->
bi_ctx
);
return
byte_size
;
}
#endif
/* CONFIG_SSL_CERT_VERIFICATION */
app/ssl/crypto/ssl_sha1.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.
*/
/**
* SHA1 implementation - as defined in FIPS PUB 180-1 published April 17, 1995.
* This code was originally taken from RFC3174
*/
//#include <string.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_crypto.h"
//#include "os.h"
#include "lwip/mem.h"
/*
* Define the SHA1 circular left shift macro
*/
#define SHA1CircularShift(bits,word) \
(((word) << (bits)) | ((word) >> (32-(bits))))
/* ----- static functions ----- */
static
void
SHA1PadMessage
(
SHA1_CTX
*
ctx
);
static
void
SHA1ProcessMessageBlock
(
SHA1_CTX
*
ctx
);
/**
* Initialize the SHA1 context
*/
void
ICACHE_FLASH_ATTR
SHA1_Init
(
SHA1_CTX
*
ctx
)
{
ctx
->
Length_Low
=
0
;
ctx
->
Length_High
=
0
;
ctx
->
Message_Block_Index
=
0
;
ctx
->
Intermediate_Hash
[
0
]
=
0x67452301
;
ctx
->
Intermediate_Hash
[
1
]
=
0xEFCDAB89
;
ctx
->
Intermediate_Hash
[
2
]
=
0x98BADCFE
;
ctx
->
Intermediate_Hash
[
3
]
=
0x10325476
;
ctx
->
Intermediate_Hash
[
4
]
=
0xC3D2E1F0
;
}
/**
* Accepts an array of octets as the next portion of the message.
*/
void
ICACHE_FLASH_ATTR
SHA1_Update
(
SHA1_CTX
*
ctx
,
const
uint8_t
*
msg
,
int
len
)
{
while
(
len
--
)
{
ctx
->
Message_Block
[
ctx
->
Message_Block_Index
++
]
=
(
*
msg
&
0xFF
);
ctx
->
Length_Low
+=
8
;
if
(
ctx
->
Length_Low
==
0
)
ctx
->
Length_High
++
;
if
(
ctx
->
Message_Block_Index
==
64
)
SHA1ProcessMessageBlock
(
ctx
);
msg
++
;
}
}
/**
* Return the 160-bit message digest into the user's array
*/
void
ICACHE_FLASH_ATTR
SHA1_Final
(
uint8_t
*
digest
,
SHA1_CTX
*
ctx
)
{
int
i
;
SHA1PadMessage
(
ctx
);
os_memset
(
ctx
->
Message_Block
,
0
,
64
);
ctx
->
Length_Low
=
0
;
/* and clear length */
ctx
->
Length_High
=
0
;
for
(
i
=
0
;
i
<
SHA1_SIZE
;
i
++
)
{
digest
[
i
]
=
ctx
->
Intermediate_Hash
[
i
>>
2
]
>>
8
*
(
3
-
(
i
&
0x03
)
);
}
}
/**
* Process the next 512 bits of the message stored in the array.
*/
static
void
ICACHE_FLASH_ATTR
SHA1ProcessMessageBlock
(
SHA1_CTX
*
ctx
)
{
const
uint32_t
K
[]
=
{
/* Constants defined in SHA-1 */
0x5A827999
,
0x6ED9EBA1
,
0x8F1BBCDC
,
0xCA62C1D6
};
int
t
;
/* Loop counter */
uint32_t
temp
;
/* Temporary word value */
uint32_t
W
[
80
];
/* Word sequence */
uint32_t
A
,
B
,
C
,
D
,
E
;
/* Word buffers */
/*
* Initialize the first 16 words in the array W
*/
for
(
t
=
0
;
t
<
16
;
t
++
)
{
W
[
t
]
=
ctx
->
Message_Block
[
t
*
4
]
<<
24
;
W
[
t
]
|=
ctx
->
Message_Block
[
t
*
4
+
1
]
<<
16
;
W
[
t
]
|=
ctx
->
Message_Block
[
t
*
4
+
2
]
<<
8
;
W
[
t
]
|=
ctx
->
Message_Block
[
t
*
4
+
3
];
}
for
(
t
=
16
;
t
<
80
;
t
++
)
{
W
[
t
]
=
SHA1CircularShift
(
1
,
W
[
t
-
3
]
^
W
[
t
-
8
]
^
W
[
t
-
14
]
^
W
[
t
-
16
]);
}
A
=
ctx
->
Intermediate_Hash
[
0
];
B
=
ctx
->
Intermediate_Hash
[
1
];
C
=
ctx
->
Intermediate_Hash
[
2
];
D
=
ctx
->
Intermediate_Hash
[
3
];
E
=
ctx
->
Intermediate_Hash
[
4
];
for
(
t
=
0
;
t
<
20
;
t
++
)
{
temp
=
SHA1CircularShift
(
5
,
A
)
+
((
B
&
C
)
|
((
~
B
)
&
D
))
+
E
+
W
[
t
]
+
K
[
0
];
E
=
D
;
D
=
C
;
C
=
SHA1CircularShift
(
30
,
B
);
B
=
A
;
A
=
temp
;
}
for
(
t
=
20
;
t
<
40
;
t
++
)
{
temp
=
SHA1CircularShift
(
5
,
A
)
+
(
B
^
C
^
D
)
+
E
+
W
[
t
]
+
K
[
1
];
E
=
D
;
D
=
C
;
C
=
SHA1CircularShift
(
30
,
B
);
B
=
A
;
A
=
temp
;
}
for
(
t
=
40
;
t
<
60
;
t
++
)
{
temp
=
SHA1CircularShift
(
5
,
A
)
+
((
B
&
C
)
|
(
B
&
D
)
|
(
C
&
D
))
+
E
+
W
[
t
]
+
K
[
2
];
E
=
D
;
D
=
C
;
C
=
SHA1CircularShift
(
30
,
B
);
B
=
A
;
A
=
temp
;
}
for
(
t
=
60
;
t
<
80
;
t
++
)
{
temp
=
SHA1CircularShift
(
5
,
A
)
+
(
B
^
C
^
D
)
+
E
+
W
[
t
]
+
K
[
3
];
E
=
D
;
D
=
C
;
C
=
SHA1CircularShift
(
30
,
B
);
B
=
A
;
A
=
temp
;
}
ctx
->
Intermediate_Hash
[
0
]
+=
A
;
ctx
->
Intermediate_Hash
[
1
]
+=
B
;
ctx
->
Intermediate_Hash
[
2
]
+=
C
;
ctx
->
Intermediate_Hash
[
3
]
+=
D
;
ctx
->
Intermediate_Hash
[
4
]
+=
E
;
ctx
->
Message_Block_Index
=
0
;
}
/*
* According to the standard, the message must be padded to an even
* 512 bits. The first padding bit must be a '1'. The last 64
* bits represent the length of the original message. All bits in
* between should be 0. This function will pad the message
* according to those rules by filling the Message_Block array
* accordingly. It will also call the ProcessMessageBlock function
* provided appropriately. When it returns, it can be assumed that
* the message digest has been computed.
*
* @param ctx [in, out] The SHA1 context
*/
static
void
ICACHE_FLASH_ATTR
SHA1PadMessage
(
SHA1_CTX
*
ctx
)
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second
* block.
*/
if
(
ctx
->
Message_Block_Index
>
55
)
{
ctx
->
Message_Block
[
ctx
->
Message_Block_Index
++
]
=
0x80
;
while
(
ctx
->
Message_Block_Index
<
64
)
{
ctx
->
Message_Block
[
ctx
->
Message_Block_Index
++
]
=
0
;
}
SHA1ProcessMessageBlock
(
ctx
);
while
(
ctx
->
Message_Block_Index
<
56
)
{
ctx
->
Message_Block
[
ctx
->
Message_Block_Index
++
]
=
0
;
}
}
else
{
ctx
->
Message_Block
[
ctx
->
Message_Block_Index
++
]
=
0x80
;
while
(
ctx
->
Message_Block_Index
<
56
)
{
ctx
->
Message_Block
[
ctx
->
Message_Block_Index
++
]
=
0
;
}
}
/*
* Store the message length as the last 8 octets
*/
ctx
->
Message_Block
[
56
]
=
ctx
->
Length_High
>>
24
;
ctx
->
Message_Block
[
57
]
=
ctx
->
Length_High
>>
16
;
ctx
->
Message_Block
[
58
]
=
ctx
->
Length_High
>>
8
;
ctx
->
Message_Block
[
59
]
=
ctx
->
Length_High
;
ctx
->
Message_Block
[
60
]
=
ctx
->
Length_Low
>>
24
;
ctx
->
Message_Block
[
61
]
=
ctx
->
Length_Low
>>
16
;
ctx
->
Message_Block
[
62
]
=
ctx
->
Length_Low
>>
8
;
ctx
->
Message_Block
[
63
]
=
ctx
->
Length_Low
;
SHA1ProcessMessageBlock
(
ctx
);
}
app/ssl/ssl/ssl_asn1.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 primitive asn methods for extraction ASN.1 data.
*/
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//#include <time.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_crypto.h"
#include "ssl/ssl_crypto_misc.h"
//#include "os.h"
#include "lwip/mem.h"
struct
tm
{
int
tm_sec
;
/* Seconds. [0-60] (1 leap second) */
int
tm_min
;
/* Minutes. [0-59] */
int
tm_hour
;
/* Hours. [0-23] */
int
tm_mday
;
/* Day. [1-31] */
int
tm_mon
;
/* Month. [0-11] */
int
tm_year
;
/* Year - 1900. */
int
tm_wday
;
/* Day of week. [0-6] */
int
tm_yday
;
/* Days in year.[0-365] */
int
tm_isdst
;
/* DST. [-1/0/1]*/
#ifdef __USE_BSD
long
int
tm_gmtoff
;
/* Seconds east of UTC. */
__const
char
*
tm_zone
;
/* Timezone abbreviation. */
#else
long
int
__tm_gmtoff
;
/* Seconds east of UTC. */
__const
char
*
__tm_zone
;
/* Timezone abbreviation. */
#endif
};
#define SIG_OID_PREFIX_SIZE 8
#define SIG_IIS6_OID_SIZE 5
#define SIG_SUBJECT_ALT_NAME_SIZE 3
/* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
static
const
uint8_t
sig_oid_prefix
[
SIG_OID_PREFIX_SIZE
]
=
{
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x01
,
0x01
};
static
const
uint8_t
sig_sha1WithRSAEncrypt
[
SIG_IIS6_OID_SIZE
]
=
{
0x2b
,
0x0e
,
0x03
,
0x02
,
0x1d
};
static
const
uint8_t
sig_subject_alt_name
[
SIG_SUBJECT_ALT_NAME_SIZE
]
=
{
0x55
,
0x1d
,
0x11
};
/* CN, O, OU */
static
const
uint8_t
g_dn_types
[]
=
{
3
,
10
,
11
};
int
ICACHE_FLASH_ATTR
get_asn1_length
(
const
uint8_t
*
buf
,
int
*
offset
)
{
int
len
,
i
;
if
(
!
(
buf
[
*
offset
]
&
0x80
))
/* short form */
{
len
=
buf
[(
*
offset
)
++
];
}
else
/* long form */
{
int
length_bytes
=
buf
[(
*
offset
)
++
]
&
0x7f
;
len
=
0
;
for
(
i
=
0
;
i
<
length_bytes
;
i
++
)
{
len
<<=
8
;
len
+=
buf
[(
*
offset
)
++
];
}
}
return
len
;
}
/**
* Skip the ASN1.1 object type and its length. Get ready to read the object's
* data.
*/
int
ICACHE_FLASH_ATTR
asn1_next_obj
(
const
uint8_t
*
buf
,
int
*
offset
,
int
obj_type
)
{
if
(
buf
[
*
offset
]
!=
obj_type
)
return
X509_NOT_OK
;
(
*
offset
)
++
;
return
get_asn1_length
(
buf
,
offset
);
}
/**
* Skip over an ASN.1 object type completely. Get ready to read the next
* object.
*/
int
ICACHE_FLASH_ATTR
asn1_skip_obj
(
const
uint8_t
*
buf
,
int
*
offset
,
int
obj_type
)
{
int
len
;
if
(
buf
[
*
offset
]
!=
obj_type
)
return
X509_NOT_OK
;
(
*
offset
)
++
;
len
=
get_asn1_length
(
buf
,
offset
);
*
offset
+=
len
;
return
0
;
}
/**
* Read an integer value for ASN.1 data
* Note: This function allocates memory which must be freed by the user.
*/
int
ICACHE_FLASH_ATTR
asn1_get_int
(
const
uint8_t
*
buf
,
int
*
offset
,
uint8_t
**
object
)
{
int
len
;
if
((
len
=
asn1_next_obj
(
buf
,
offset
,
ASN1_INTEGER
))
<
0
)
goto
end_int_array
;
if
(
len
>
1
&&
buf
[
*
offset
]
==
0x00
)
/* ignore the negative byte */
{
len
--
;
(
*
offset
)
++
;
}
*
object
=
(
uint8_t
*
)
os_malloc
(
len
);
os_memcpy
(
*
object
,
&
buf
[
*
offset
],
len
);
*
offset
+=
len
;
end_int_array:
return
len
;
}
/**
* Get all the RSA private key specifics from an ASN.1 encoded file
*/
int
ICACHE_FLASH_ATTR
asn1_get_private_key
(
const
uint8_t
*
buf
,
int
len
,
RSA_CTX
**
rsa_ctx
)
{
int
offset
=
7
;
uint8_t
*
modulus
=
NULL
,
*
priv_exp
=
NULL
,
*
pub_exp
=
NULL
;
int
mod_len
,
priv_len
,
pub_len
;
#ifdef CONFIG_BIGINT_CRT
uint8_t
*
p
=
NULL
,
*
q
=
NULL
,
*
dP
=
NULL
,
*
dQ
=
NULL
,
*
qInv
=
NULL
;
int
p_len
,
q_len
,
dP_len
,
dQ_len
,
qInv_len
;
#endif
/* not in der format */
if
(
buf
[
0
]
!=
ASN1_SEQUENCE
)
/* basic sanity check */
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"Error: This is not a valid ASN.1 file
\n
"
);
#endif
return
X509_INVALID_PRIV_KEY
;
}
/* Use the private key to mix up the RNG if possible. */
RNG_custom_init
(
buf
,
len
);
mod_len
=
asn1_get_int
(
buf
,
&
offset
,
&
modulus
);
pub_len
=
asn1_get_int
(
buf
,
&
offset
,
&
pub_exp
);
priv_len
=
asn1_get_int
(
buf
,
&
offset
,
&
priv_exp
);
if
(
mod_len
<=
0
||
pub_len
<=
0
||
priv_len
<=
0
)
return
X509_INVALID_PRIV_KEY
;
#ifdef CONFIG_BIGINT_CRT
p_len
=
asn1_get_int
(
buf
,
&
offset
,
&
p
);
q_len
=
asn1_get_int
(
buf
,
&
offset
,
&
q
);
dP_len
=
asn1_get_int
(
buf
,
&
offset
,
&
dP
);
dQ_len
=
asn1_get_int
(
buf
,
&
offset
,
&
dQ
);
qInv_len
=
asn1_get_int
(
buf
,
&
offset
,
&
qInv
);
if
(
p_len
<=
0
||
q_len
<=
0
||
dP_len
<=
0
||
dQ_len
<=
0
||
qInv_len
<=
0
)
return
X509_INVALID_PRIV_KEY
;
RSA_priv_key_new
(
rsa_ctx
,
modulus
,
mod_len
,
pub_exp
,
pub_len
,
priv_exp
,
priv_len
,
p
,
p_len
,
q
,
p_len
,
dP
,
dP_len
,
dQ
,
dQ_len
,
qInv
,
qInv_len
);
os_free
(
p
);
os_free
(
q
);
os_free
(
dP
);
os_free
(
dQ
);
os_free
(
qInv
);
#else
RSA_priv_key_new
(
rsa_ctx
,
modulus
,
mod_len
,
pub_exp
,
pub_len
,
priv_exp
,
priv_len
);
#endif
os_free
(
modulus
);
os_free
(
priv_exp
);
os_free
(
pub_exp
);
return
X509_OK
;
}
/**
* Get the time of a certificate. Ignore hours/minutes/seconds.
*/
static
int
ICACHE_FLASH_ATTR
asn1_get_utc_time
(
const
uint8_t
*
buf
,
int
*
offset
,
time_t
*
t
)
{
int
ret
=
X509_NOT_OK
,
len
,
t_offset
;
struct
tm
tm
;
if
(
buf
[(
*
offset
)
++
]
!=
ASN1_UTC_TIME
)
goto
end_utc_time
;
len
=
get_asn1_length
(
buf
,
offset
);
t_offset
=
*
offset
;
os_memset
(
&
tm
,
0
,
sizeof
(
struct
tm
));
tm
.
tm_year
=
(
buf
[
t_offset
]
-
'0'
)
*
10
+
(
buf
[
t_offset
+
1
]
-
'0'
);
if
(
tm
.
tm_year
<=
50
)
/* 1951-2050 thing */
{
tm
.
tm_year
+=
100
;
}
tm
.
tm_mon
=
(
buf
[
t_offset
+
2
]
-
'0'
)
*
10
+
(
buf
[
t_offset
+
3
]
-
'0'
)
-
1
;
tm
.
tm_mday
=
(
buf
[
t_offset
+
4
]
-
'0'
)
*
10
+
(
buf
[
t_offset
+
5
]
-
'0'
);
// wujg : pass compile first
// *t = mktime(&tm);
*
offset
+=
len
;
ret
=
X509_OK
;
end_utc_time:
return
ret
;
}
/**
* Get the version type of a certificate (which we don't actually care about)
*/
int
ICACHE_FLASH_ATTR
asn1_version
(
const
uint8_t
*
cert
,
int
*
offset
,
X509_CTX
*
x509_ctx
)
{
int
ret
=
X509_NOT_OK
;
(
*
offset
)
+=
2
;
/* get past explicit tag */
if
(
asn1_skip_obj
(
cert
,
offset
,
ASN1_INTEGER
))
goto
end_version
;
ret
=
X509_OK
;
end_version:
return
ret
;
}
/**
* Retrieve the notbefore and notafter certificate times.
*/
int
ICACHE_FLASH_ATTR
asn1_validity
(
const
uint8_t
*
cert
,
int
*
offset
,
X509_CTX
*
x509_ctx
)
{
return
(
asn1_next_obj
(
cert
,
offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_get_utc_time
(
cert
,
offset
,
&
x509_ctx
->
not_before
)
||
asn1_get_utc_time
(
cert
,
offset
,
&
x509_ctx
->
not_after
));
}
/**
* Get the components of a distinguished name
*/
static
int
ICACHE_FLASH_ATTR
asn1_get_oid_x520
(
const
uint8_t
*
buf
,
int
*
offset
)
{
int
dn_type
=
0
;
int
len
;
if
((
len
=
asn1_next_obj
(
buf
,
offset
,
ASN1_OID
))
<
0
)
goto
end_oid
;
/* expect a sequence of 2.5.4.[x] where x is a one of distinguished name
components we are interested in. */
if
(
len
==
3
&&
buf
[(
*
offset
)
++
]
==
0x55
&&
buf
[(
*
offset
)
++
]
==
0x04
)
dn_type
=
buf
[(
*
offset
)
++
];
else
{
*
offset
+=
len
;
/* skip over it */
}
end_oid:
return
dn_type
;
}
/**
* Obtain an ASN.1 printable string type.
*/
static
int
ICACHE_FLASH_ATTR
asn1_get_printable_str
(
const
uint8_t
*
buf
,
int
*
offset
,
char
**
str
)
{
int
len
=
X509_NOT_OK
;
int
asn1_type
=
buf
[
*
offset
];
/* some certs have this awful crud in them for some reason */
if
(
asn1_type
!=
ASN1_PRINTABLE_STR
&&
asn1_type
!=
ASN1_PRINTABLE_STR2
&&
asn1_type
!=
ASN1_TELETEX_STR
&&
asn1_type
!=
ASN1_IA5_STR
&&
asn1_type
!=
ASN1_UNICODE_STR
)
goto
end_pnt_str
;
(
*
offset
)
++
;
len
=
get_asn1_length
(
buf
,
offset
);
if
(
asn1_type
==
ASN1_UNICODE_STR
)
{
int
i
;
*
str
=
(
char
*
)
os_malloc
(
len
/
2
+
1
);
/* allow for null */
for
(
i
=
0
;
i
<
len
;
i
+=
2
)
(
*
str
)[
i
/
2
]
=
buf
[
*
offset
+
i
+
1
];
(
*
str
)[
len
/
2
]
=
0
;
/* null terminate */
}
else
{
*
str
=
(
char
*
)
os_malloc
(
len
+
1
);
/* allow for null */
os_memcpy
(
*
str
,
&
buf
[
*
offset
],
len
);
(
*
str
)[
len
]
=
0
;
/* null terminate */
}
*
offset
+=
len
;
end_pnt_str:
return
len
;
}
/**
* Get the subject name (or the issuer) of a certificate.
*/
int
ICACHE_FLASH_ATTR
asn1_name
(
const
uint8_t
*
cert
,
int
*
offset
,
char
*
dn
[])
{
int
ret
=
X509_NOT_OK
;
int
dn_type
;
char
*
tmp
;
if
(
asn1_next_obj
(
cert
,
offset
,
ASN1_SEQUENCE
)
<
0
)
goto
end_name
;
while
(
asn1_next_obj
(
cert
,
offset
,
ASN1_SET
)
>=
0
)
{
int
i
,
found
=
0
;
if
(
asn1_next_obj
(
cert
,
offset
,
ASN1_SEQUENCE
)
<
0
||
(
dn_type
=
asn1_get_oid_x520
(
cert
,
offset
))
<
0
)
goto
end_name
;
tmp
=
NULL
;
if
(
asn1_get_printable_str
(
cert
,
offset
,
&
tmp
)
<
0
)
{
os_free
(
tmp
);
goto
end_name
;
}
/* find the distinguished named type */
for
(
i
=
0
;
i
<
X509_NUM_DN_TYPES
;
i
++
)
{
if
(
dn_type
==
g_dn_types
[
i
])
{
if
(
dn
[
i
]
==
NULL
)
{
dn
[
i
]
=
tmp
;
found
=
1
;
break
;
}
}
}
if
(
found
==
0
)
/* not found so get rid of it */
{
os_free
(
tmp
);
}
}
ret
=
X509_OK
;
end_name:
return
ret
;
}
/**
* Read the modulus and public exponent of a certificate.
*/
int
ICACHE_FLASH_ATTR
asn1_public_key
(
const
uint8_t
*
cert
,
int
*
offset
,
X509_CTX
*
x509_ctx
)
{
int
ret
=
X509_NOT_OK
,
mod_len
,
pub_len
;
uint8_t
*
modulus
=
NULL
,
*
pub_exp
=
NULL
;
if
(
asn1_next_obj
(
cert
,
offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_skip_obj
(
cert
,
offset
,
ASN1_SEQUENCE
)
||
asn1_next_obj
(
cert
,
offset
,
ASN1_BIT_STRING
)
<
0
)
goto
end_pub_key
;
(
*
offset
)
++
;
/* ignore the padding bit field */
if
(
asn1_next_obj
(
cert
,
offset
,
ASN1_SEQUENCE
)
<
0
)
goto
end_pub_key
;
mod_len
=
asn1_get_int
(
cert
,
offset
,
&
modulus
);
pub_len
=
asn1_get_int
(
cert
,
offset
,
&
pub_exp
);
RSA_pub_key_new
(
&
x509_ctx
->
rsa_ctx
,
modulus
,
mod_len
,
pub_exp
,
pub_len
);
os_free
(
modulus
);
os_free
(
pub_exp
);
ret
=
X509_OK
;
end_pub_key:
return
ret
;
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Read the signature of the certificate.
*/
int
ICACHE_FLASH_ATTR
asn1_signature
(
const
uint8_t
*
cert
,
int
*
offset
,
X509_CTX
*
x509_ctx
)
{
int
ret
=
X509_NOT_OK
;
if
(
cert
[(
*
offset
)
++
]
!=
ASN1_BIT_STRING
)
goto
end_sig
;
x509_ctx
->
sig_len
=
get_asn1_length
(
cert
,
offset
)
-
1
;
(
*
offset
)
++
;
/* ignore bit string padding bits */
x509_ctx
->
signature
=
(
uint8_t
*
)
os_malloc
(
x509_ctx
->
sig_len
);
os_memcpy
(
x509_ctx
->
signature
,
&
cert
[
*
offset
],
x509_ctx
->
sig_len
);
*
offset
+=
x509_ctx
->
sig_len
;
ret
=
X509_OK
;
end_sig:
return
ret
;
}
/*
* Compare 2 distinguished name components for equality
* @return 0 if a match
*/
static
int
ICACHE_FLASH_ATTR
asn1_compare_dn_comp
(
const
char
*
dn1
,
const
char
*
dn2
)
{
int
ret
;
if
(
dn1
==
NULL
&&
dn2
==
NULL
)
ret
=
0
;
else
ret
=
(
dn1
&&
dn2
)
?
os_strcmp
(
dn1
,
dn2
)
:
1
;
return
ret
;
}
/**
* Clean up all of the CA certificates.
*/
void
ICACHE_FLASH_ATTR
remove_ca_certs
(
CA_CERT_CTX
*
ca_cert_ctx
)
{
int
i
=
0
;
if
(
ca_cert_ctx
==
NULL
)
return
;
while
(
i
<
CONFIG_X509_MAX_CA_CERTS
&&
ca_cert_ctx
->
cert
[
i
])
{
x509_free
(
ca_cert_ctx
->
cert
[
i
]);
ca_cert_ctx
->
cert
[
i
++
]
=
NULL
;
}
os_free
(
ca_cert_ctx
);
}
/*
* Compare 2 distinguished names for equality
* @return 0 if a match
*/
int
ICACHE_FLASH_ATTR
asn1_compare_dn
(
char
*
const
dn1
[],
char
*
const
dn2
[])
{
int
i
;
for
(
i
=
0
;
i
<
X509_NUM_DN_TYPES
;
i
++
)
{
if
(
asn1_compare_dn_comp
(
dn1
[
i
],
dn2
[
i
]))
return
1
;
}
return
0
;
/* all good */
}
int
ICACHE_FLASH_ATTR
asn1_find_oid
(
const
uint8_t
*
cert
,
int
*
offset
,
const
uint8_t
*
oid
,
int
oid_length
)
{
int
seqlen
;
if
((
seqlen
=
asn1_next_obj
(
cert
,
offset
,
ASN1_SEQUENCE
))
>
0
)
{
int
end
=
*
offset
+
seqlen
;
while
(
*
offset
<
end
)
{
int
type
=
cert
[(
*
offset
)
++
];
int
length
=
get_asn1_length
(
cert
,
offset
);
int
noffset
=
*
offset
+
length
;
if
(
type
==
ASN1_SEQUENCE
)
{
type
=
cert
[(
*
offset
)
++
];
length
=
get_asn1_length
(
cert
,
offset
);
if
(
type
==
ASN1_OID
&&
length
==
oid_length
&&
os_memcmp
(
cert
+
*
offset
,
oid
,
oid_length
)
==
0
)
{
*
offset
+=
oid_length
;
return
1
;
}
}
*
offset
=
noffset
;
}
}
return
0
;
}
int
ICACHE_FLASH_ATTR
asn1_find_subjectaltname
(
const
uint8_t
*
cert
,
int
offset
)
{
if
(
asn1_find_oid
(
cert
,
&
offset
,
sig_subject_alt_name
,
SIG_SUBJECT_ALT_NAME_SIZE
))
{
return
offset
;
}
return
0
;
}
#endif
/* CONFIG_SSL_CERT_VERIFICATION */
/**
* Read the signature type of the certificate. We only support RSA-MD5 and
* RSA-SHA1 signature types.
*/
int
ICACHE_FLASH_ATTR
asn1_signature_type
(
const
uint8_t
*
cert
,
int
*
offset
,
X509_CTX
*
x509_ctx
)
{
int
ret
=
X509_NOT_OK
,
len
;
if
(
cert
[(
*
offset
)
++
]
!=
ASN1_OID
)
goto
end_check_sig
;
len
=
get_asn1_length
(
cert
,
offset
);
if
(
len
==
5
&&
os_memcmp
(
sig_sha1WithRSAEncrypt
,
&
cert
[
*
offset
],
SIG_IIS6_OID_SIZE
)
==
0
)
{
x509_ctx
->
sig_type
=
SIG_TYPE_SHA1
;
}
else
{
if
(
os_memcmp
(
sig_oid_prefix
,
&
cert
[
*
offset
],
SIG_OID_PREFIX_SIZE
))
goto
end_check_sig
;
/* unrecognised cert type */
x509_ctx
->
sig_type
=
cert
[
*
offset
+
SIG_OID_PREFIX_SIZE
];
}
*
offset
+=
len
;
asn1_skip_obj
(
cert
,
offset
,
ASN1_NULL
);
/* if it's there */
ret
=
X509_OK
;
end_check_sig:
return
ret
;
}
app/ssl/ssl/ssl_gen_cert.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.
*/
#include "ssl/ssl_config.h"
#ifdef CONFIG_SSL_GENERATE_X509_CERT
#include <string.h>
#include <stdlib.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_ssl.h"
/**
* Generate a basic X.509 certificate
*/
static
uint8_t
ICACHE_FLASH_ATTR
set_gen_length
(
int
len
,
uint8_t
*
buf
,
int
*
offset
)
{
if
(
len
<
0x80
)
/* short form */
{
buf
[(
*
offset
)
++
]
=
len
;
return
1
;
}
else
/* long form */
{
int
i
,
length_bytes
=
0
;
if
(
len
&
0x00FF0000
)
length_bytes
=
3
;
else
if
(
len
&
0x0000FF00
)
length_bytes
=
2
;
else
if
(
len
&
0x000000FF
)
length_bytes
=
1
;
buf
[(
*
offset
)
++
]
=
0x80
+
length_bytes
;
for
(
i
=
length_bytes
-
1
;
i
>=
0
;
i
--
)
{
buf
[
*
offset
+
i
]
=
len
&
0xFF
;
len
>>=
8
;
}
*
offset
+=
length_bytes
;
return
length_bytes
+
1
;
}
}
static
int
ICACHE_FLASH_ATTR
pre_adjust_with_size
(
uint8_t
type
,
int
*
seq_offset
,
uint8_t
*
buf
,
int
*
offset
)
{
buf
[(
*
offset
)
++
]
=
type
;
*
seq_offset
=
*
offset
;
*
offset
+=
4
;
/* fill in later */
return
*
offset
;
}
static
void
ICACHE_FLASH_ATTR
adjust_with_size
(
int
seq_size
,
int
seq_start
,
uint8_t
*
buf
,
int
*
offset
)
{
uint8_t
seq_byte_size
;
int
orig_seq_size
=
seq_size
;
int
orig_seq_start
=
seq_start
;
seq_size
=
*
offset
-
seq_size
;
seq_byte_size
=
set_gen_length
(
seq_size
,
buf
,
&
seq_start
);
if
(
seq_byte_size
!=
4
)
{
memmove
(
&
buf
[
orig_seq_start
+
seq_byte_size
],
&
buf
[
orig_seq_size
],
seq_size
);
*
offset
-=
4
-
seq_byte_size
;
}
}
static
void
ICACHE_FLASH_ATTR
gen_serial_number
(
uint8_t
*
buf
,
int
*
offset
)
{
static
const
uint8_t
ser_oid
[]
=
{
ASN1_INTEGER
,
1
,
0x7F
};
memcpy
(
&
buf
[
*
offset
],
ser_oid
,
sizeof
(
ser_oid
));
*
offset
+=
sizeof
(
ser_oid
);
}
static
void
ICACHE_FLASH_ATTR
gen_signature_alg
(
uint8_t
*
buf
,
int
*
offset
)
{
/* OBJECT IDENTIFIER sha1withRSAEncryption (1 2 840 113549 1 1 5) */
static
const
uint8_t
sig_oid
[]
=
{
ASN1_SEQUENCE
,
0x0d
,
ASN1_OID
,
0x09
,
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x01
,
0x01
,
0x05
,
ASN1_NULL
,
0x00
};
memcpy
(
&
buf
[
*
offset
],
sig_oid
,
sizeof
(
sig_oid
));
*
offset
+=
sizeof
(
sig_oid
);
}
static
int
ICACHE_FLASH_ATTR
gen_dn
(
const
char
*
name
,
uint8_t
dn_type
,
uint8_t
*
buf
,
int
*
offset
)
{
int
ret
=
X509_OK
;
int
name_size
=
strlen
(
name
);
if
(
name_size
>
0x70
)
/* just too big */
{
ret
=
X509_NOT_OK
;
goto
error
;
}
buf
[(
*
offset
)
++
]
=
ASN1_SET
;
set_gen_length
(
9
+
name_size
,
buf
,
offset
);
buf
[(
*
offset
)
++
]
=
ASN1_SEQUENCE
;
set_gen_length
(
7
+
name_size
,
buf
,
offset
);
buf
[(
*
offset
)
++
]
=
ASN1_OID
;
buf
[(
*
offset
)
++
]
=
3
;
buf
[(
*
offset
)
++
]
=
0x55
;
buf
[(
*
offset
)
++
]
=
0x04
;
buf
[(
*
offset
)
++
]
=
dn_type
;
buf
[(
*
offset
)
++
]
=
ASN1_PRINTABLE_STR
;
buf
[(
*
offset
)
++
]
=
name_size
;
strcpy
(
&
buf
[
*
offset
],
name
);
*
offset
+=
name_size
;
error:
return
ret
;
}
static
int
ICACHE_FLASH_ATTR
gen_issuer
(
const
char
*
dn
[],
uint8_t
*
buf
,
int
*
offset
)
{
int
ret
=
X509_OK
;
int
seq_offset
;
int
seq_size
=
pre_adjust_with_size
(
ASN1_SEQUENCE
,
&
seq_offset
,
buf
,
offset
);
char
fqdn
[
128
];
/* we need the common name, so if not configured, work out the fully
* qualified domain name */
if
(
dn
[
X509_COMMON_NAME
]
==
NULL
||
strlen
(
dn
[
X509_COMMON_NAME
])
==
0
)
{
int
fqdn_len
;
gethostname
(
fqdn
,
sizeof
(
fqdn
));
fqdn_len
=
strlen
(
fqdn
);
fqdn
[
fqdn_len
++
]
=
'.'
;
getdomainname
(
&
fqdn
[
fqdn_len
],
sizeof
(
fqdn
)
-
fqdn_len
);
fqdn_len
=
strlen
(
fqdn
);
if
(
fqdn
[
fqdn_len
-
1
]
==
'.'
)
/* ensure '.' is not last char */
fqdn
[
fqdn_len
-
1
]
=
0
;
dn
[
X509_COMMON_NAME
]
=
fqdn
;
}
if
((
ret
=
gen_dn
(
dn
[
X509_COMMON_NAME
],
3
,
buf
,
offset
)))
goto
error
;
if
(
dn
[
X509_ORGANIZATION
]
!=
NULL
&&
strlen
(
dn
[
X509_ORGANIZATION
])
>
0
)
{
if
((
ret
=
gen_dn
(
dn
[
X509_ORGANIZATION
],
10
,
buf
,
offset
)))
goto
error
;
}
if
(
dn
[
X509_ORGANIZATIONAL_UNIT
]
!=
NULL
&&
strlen
(
dn
[
X509_ORGANIZATIONAL_UNIT
])
>
0
)
{
if
((
ret
=
gen_dn
(
dn
[
X509_ORGANIZATIONAL_UNIT
],
11
,
buf
,
offset
)))
goto
error
;
}
adjust_with_size
(
seq_size
,
seq_offset
,
buf
,
offset
);
error:
return
ret
;
}
static
void
ICACHE_FLASH_ATTR
gen_utc_time
(
uint8_t
*
buf
,
int
*
offset
)
{
static
const
uint8_t
time_seq
[]
=
{
ASN1_SEQUENCE
,
30
,
ASN1_UTC_TIME
,
13
,
'0'
,
'7'
,
'0'
,
'1'
,
'0'
,
'1'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'Z'
,
ASN1_UTC_TIME
,
13
,
/* make it good for 30 or so years */
'3'
,
'8'
,
'0'
,
'1'
,
'0'
,
'1'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'0'
,
'Z'
};
/* fixed time */
memcpy
(
&
buf
[
*
offset
],
time_seq
,
sizeof
(
time_seq
));
*
offset
+=
sizeof
(
time_seq
);
}
static
void
ICACHE_FLASH_ATTR
gen_pub_key2
(
const
RSA_CTX
*
rsa_ctx
,
uint8_t
*
buf
,
int
*
offset
)
{
static
const
uint8_t
pub_key_seq
[]
=
{
ASN1_INTEGER
,
0x03
,
0x01
,
0x00
,
0x01
/* INTEGER 65537 */
};
int
seq_offset
;
int
pub_key_size
=
rsa_ctx
->
num_octets
;
uint8_t
*
block
=
(
uint8_t
*
)
alloca
(
pub_key_size
);
int
seq_size
=
pre_adjust_with_size
(
ASN1_SEQUENCE
,
&
seq_offset
,
buf
,
offset
);
buf
[(
*
offset
)
++
]
=
ASN1_INTEGER
;
bi_export
(
rsa_ctx
->
bi_ctx
,
rsa_ctx
->
m
,
block
,
pub_key_size
);
if
(
*
block
&
0x80
)
/* make integer positive */
{
set_gen_length
(
pub_key_size
+
1
,
buf
,
offset
);
buf
[(
*
offset
)
++
]
=
0
;
}
else
set_gen_length
(
pub_key_size
,
buf
,
offset
);
memcpy
(
&
buf
[
*
offset
],
block
,
pub_key_size
);
*
offset
+=
pub_key_size
;
memcpy
(
&
buf
[
*
offset
],
pub_key_seq
,
sizeof
(
pub_key_seq
));
*
offset
+=
sizeof
(
pub_key_seq
);
adjust_with_size
(
seq_size
,
seq_offset
,
buf
,
offset
);
}
static
void
ICACHE_FLASH_ATTR
gen_pub_key1
(
const
RSA_CTX
*
rsa_ctx
,
uint8_t
*
buf
,
int
*
offset
)
{
int
seq_offset
;
int
seq_size
=
pre_adjust_with_size
(
ASN1_BIT_STRING
,
&
seq_offset
,
buf
,
offset
);
buf
[(
*
offset
)
++
]
=
0
;
/* bit string is multiple of 8 */
gen_pub_key2
(
rsa_ctx
,
buf
,
offset
);
adjust_with_size
(
seq_size
,
seq_offset
,
buf
,
offset
);
}
static
void
ICACHE_FLASH_ATTR
gen_pub_key
(
const
RSA_CTX
*
rsa_ctx
,
uint8_t
*
buf
,
int
*
offset
)
{
/* OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) */
static
const
uint8_t
rsa_enc_oid
[]
=
{
ASN1_SEQUENCE
,
0x0d
,
ASN1_OID
,
0x09
,
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x01
,
0x01
,
0x01
,
ASN1_NULL
,
0x00
};
int
seq_offset
;
int
seq_size
=
pre_adjust_with_size
(
ASN1_SEQUENCE
,
&
seq_offset
,
buf
,
offset
);
memcpy
(
&
buf
[
*
offset
],
rsa_enc_oid
,
sizeof
(
rsa_enc_oid
));
*
offset
+=
sizeof
(
rsa_enc_oid
);
gen_pub_key1
(
rsa_ctx
,
buf
,
offset
);
adjust_with_size
(
seq_size
,
seq_offset
,
buf
,
offset
);
}
static
void
ICACHE_FLASH_ATTR
gen_signature
(
const
RSA_CTX
*
rsa_ctx
,
const
uint8_t
*
sha_dgst
,
uint8_t
*
buf
,
int
*
offset
)
{
static
const
uint8_t
asn1_sig
[]
=
{
ASN1_SEQUENCE
,
0x21
,
ASN1_SEQUENCE
,
0x09
,
ASN1_OID
,
0x05
,
0x2b
,
0x0e
,
0x03
,
0x02
,
0x1a
,
/* sha1 (1 3 14 3 2 26) */
ASN1_NULL
,
0x00
,
ASN1_OCTET_STRING
,
0x14
};
uint8_t
*
enc_block
=
(
uint8_t
*
)
alloca
(
rsa_ctx
->
num_octets
);
uint8_t
*
block
=
(
uint8_t
*
)
alloca
(
sizeof
(
asn1_sig
)
+
SHA1_SIZE
);
int
sig_size
;
/* add the digest as an embedded asn.1 sequence */
memcpy
(
block
,
asn1_sig
,
sizeof
(
asn1_sig
));
memcpy
(
&
block
[
sizeof
(
asn1_sig
)],
sha_dgst
,
SHA1_SIZE
);
sig_size
=
RSA_encrypt
(
rsa_ctx
,
block
,
sizeof
(
asn1_sig
)
+
SHA1_SIZE
,
enc_block
,
1
);
buf
[(
*
offset
)
++
]
=
ASN1_BIT_STRING
;
set_gen_length
(
sig_size
+
1
,
buf
,
offset
);
buf
[(
*
offset
)
++
]
=
0
;
/* bit string is multiple of 8 */
memcpy
(
&
buf
[
*
offset
],
enc_block
,
sig_size
);
*
offset
+=
sig_size
;
}
static
int
ICACHE_FLASH_ATTR
gen_tbs_cert
(
const
char
*
dn
[],
const
RSA_CTX
*
rsa_ctx
,
uint8_t
*
buf
,
int
*
offset
,
uint8_t
*
sha_dgst
)
{
int
ret
=
X509_OK
;
SHA1_CTX
sha_ctx
;
int
seq_offset
;
int
begin_tbs
=
*
offset
;
int
seq_size
=
pre_adjust_with_size
(
ASN1_SEQUENCE
,
&
seq_offset
,
buf
,
offset
);
gen_serial_number
(
buf
,
offset
);
gen_signature_alg
(
buf
,
offset
);
/* CA certicate issuer */
if
((
ret
=
gen_issuer
(
dn
,
buf
,
offset
)))
goto
error
;
gen_utc_time
(
buf
,
offset
);
/* certificate issuer */
if
((
ret
=
gen_issuer
(
dn
,
buf
,
offset
)))
goto
error
;
gen_pub_key
(
rsa_ctx
,
buf
,
offset
);
adjust_with_size
(
seq_size
,
seq_offset
,
buf
,
offset
);
SHA1_Init
(
&
sha_ctx
);
SHA1_Update
(
&
sha_ctx
,
&
buf
[
begin_tbs
],
*
offset
-
begin_tbs
);
SHA1_Final
(
sha_dgst
,
&
sha_ctx
);
error:
return
ret
;
}
/**
* Create a new certificate.
*/
EXP_FUNC
int
ICACHE_FLASH_ATTR
STDCALL
ssl_x509_create
(
SSL_CTX
*
ssl_ctx
,
uint32_t
options
,
const
char
*
dn
[],
uint8_t
**
cert_data
)
{
int
ret
=
X509_OK
,
offset
=
0
,
seq_offset
;
/* allocate enough space to load a new certificate */
uint8_t
*
buf
=
(
uint8_t
*
)
alloca
(
ssl_ctx
->
rsa_ctx
->
num_octets
*
2
+
512
);
uint8_t
sha_dgst
[
SHA1_SIZE
];
int
seq_size
=
pre_adjust_with_size
(
ASN1_SEQUENCE
,
&
seq_offset
,
buf
,
&
offset
);
if
((
ret
=
gen_tbs_cert
(
dn
,
ssl_ctx
->
rsa_ctx
,
buf
,
&
offset
,
sha_dgst
))
<
0
)
goto
error
;
gen_signature_alg
(
buf
,
&
offset
);
gen_signature
(
ssl_ctx
->
rsa_ctx
,
sha_dgst
,
buf
,
&
offset
);
adjust_with_size
(
seq_size
,
seq_offset
,
buf
,
&
offset
);
*
cert_data
=
(
uint8_t
*
)
os_malloc
(
offset
);
/* create the exact memory for it */
memcpy
(
*
cert_data
,
buf
,
offset
);
error:
return
ret
<
0
?
ret
:
offset
;
}
#endif
app/ssl/ssl/ssl_loader.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.
*/
/**
* Load certificates/keys into memory. These can be in many different formats.
* PEM support and other formats can be processed here.
*
* The PEM private keys may be optionally encrypted with AES128 or AES256.
* The encrypted PEM keys were generated with something like:
*
* openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512
*/
//#include <stdlib.h>
//#include <string.h>
//#include <stdio.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_ssl.h"
static
int
do_obj
(
SSL_CTX
*
ssl_ctx
,
int
obj_type
,
SSLObjLoader
*
ssl_obj
,
const
char
*
password
);
#ifdef CONFIG_SSL_HAS_PEM
static
int
ssl_obj_PEM_load
(
SSL_CTX
*
ssl_ctx
,
int
obj_type
,
SSLObjLoader
*
ssl_obj
,
const
char
*
password
);
#endif
/*
* Load a file into memory that is in binary DER (or ascii PEM) format.
*/
EXP_FUNC
int
STDCALL
ICACHE_FLASH_ATTR
ssl_obj_load
(
SSL_CTX
*
ssl_ctx
,
int
obj_type
,
const
char
*
filename
,
const
char
*
password
)
{
#ifndef CONFIG_SSL_SKELETON_MODE
static
const
char
*
const
begin
=
"-----BEGIN"
;
int
ret
=
SSL_OK
;
SSLObjLoader
*
ssl_obj
=
NULL
;
if
(
filename
==
NULL
)
{
ret
=
SSL_ERROR_INVALID_KEY
;
goto
error
;
}
ssl_obj
=
(
SSLObjLoader
*
)
os_zalloc
(
sizeof
(
SSLObjLoader
));
ssl_obj
->
len
=
get_file
(
filename
,
&
ssl_obj
->
buf
);
if
(
ssl_obj
->
len
<=
0
)
{
ret
=
SSL_ERROR_INVALID_KEY
;
goto
error
;
}
/* is the file a PEM file? */
if
((
char
*
)
os_strstr
((
const
char
*
)
ssl_obj
->
buf
,
begin
)
!=
NULL
)
{
#ifdef CONFIG_SSL_HAS_PEM
ret
=
ssl_obj_PEM_load
(
ssl_ctx
,
obj_type
,
ssl_obj
,
password
);
#else
ssl_printf
(
unsupported_str
);
ret
=
SSL_ERROR_NOT_SUPPORTED
;
#endif
}
else
ret
=
do_obj
(
ssl_ctx
,
obj_type
,
ssl_obj
,
password
);
error:
ssl_obj_free
(
ssl_obj
);
return
ret
;
#else
ssl_printf
(
unsupported_str
);
return
SSL_ERROR_NOT_SUPPORTED
;
#endif
/* CONFIG_SSL_SKELETON_MODE */
}
/*
* Transfer binary data into the object loader.
*/
EXP_FUNC
int
STDCALL
ICACHE_FLASH_ATTR
ssl_obj_memory_load
(
SSL_CTX
*
ssl_ctx
,
int
mem_type
,
const
uint8_t
*
data
,
int
len
,
const
char
*
password
)
{
int
ret
;
SSLObjLoader
*
ssl_obj
;
ssl_obj
=
(
SSLObjLoader
*
)
os_zalloc
(
sizeof
(
SSLObjLoader
));
ssl_obj
->
buf
=
(
uint8_t
*
)
os_malloc
(
len
);
os_memcpy
(
ssl_obj
->
buf
,
data
,
len
);
ssl_obj
->
len
=
len
;
ret
=
do_obj
(
ssl_ctx
,
mem_type
,
ssl_obj
,
password
);
ssl_obj_free
(
ssl_obj
);
return
ret
;
}
/*
* Actually work out what we are doing
*/
static
int
ICACHE_FLASH_ATTR
do_obj
(
SSL_CTX
*
ssl_ctx
,
int
obj_type
,
SSLObjLoader
*
ssl_obj
,
const
char
*
password
)
{
int
ret
=
SSL_OK
;
switch
(
obj_type
)
{
case
SSL_OBJ_RSA_KEY
:
ret
=
add_private_key
(
ssl_ctx
,
ssl_obj
);
break
;
case
SSL_OBJ_X509_CERT
:
ret
=
add_cert
(
ssl_ctx
,
ssl_obj
->
buf
,
ssl_obj
->
len
);
break
;
#ifdef CONFIG_SSL_CERT_VERIFICATION
case
SSL_OBJ_X509_CACERT
:
add_cert_auth
(
ssl_ctx
,
ssl_obj
->
buf
,
ssl_obj
->
len
);
break
;
#endif
#ifdef CONFIG_SSL_USE_PKCS12
case
SSL_OBJ_PKCS8
:
ret
=
pkcs8_decode
(
ssl_ctx
,
ssl_obj
,
password
);
break
;
case
SSL_OBJ_PKCS12
:
ret
=
pkcs12_decode
(
ssl_ctx
,
ssl_obj
,
password
);
break
;
#endif
default:
ssl_printf
(
unsupported_str
);
ret
=
SSL_ERROR_NOT_SUPPORTED
;
break
;
}
return
ret
;
}
/*
* Clean up our mess.
*/
void
ICACHE_FLASH_ATTR
ssl_obj_free
(
SSLObjLoader
*
ssl_obj
)
{
if
(
ssl_obj
)
{
os_free
(
ssl_obj
->
buf
);
os_free
(
ssl_obj
);
}
}
/*
* Support for PEM encoded keys/certificates.
*/
#ifdef CONFIG_SSL_HAS_PEM
#define NUM_PEM_TYPES 4
#define IV_SIZE 16
#define IS_RSA_PRIVATE_KEY 0
#define IS_ENCRYPTED_PRIVATE_KEY 1
#define IS_PRIVATE_KEY 2
#define IS_CERTIFICATE 3
static
const
char
*
const
begins
[
NUM_PEM_TYPES
]
=
{
"-----BEGIN RSA PRIVATE KEY-----"
,
"-----BEGIN ENCRYPTED PRIVATE KEY-----"
,
"-----BEGIN PRIVATE KEY-----"
,
"-----BEGIN CERTIFICATE-----"
,
};
static
const
char
*
const
ends
[
NUM_PEM_TYPES
]
=
{
"-----END RSA PRIVATE KEY-----"
,
"-----END ENCRYPTED PRIVATE KEY-----"
,
"-----END PRIVATE KEY-----"
,
"-----END CERTIFICATE-----"
,
};
static
const
char
*
const
aes_str
[
2
]
=
{
"DEK-Info: AES-128-CBC,"
,
"DEK-Info: AES-256-CBC,"
};
/**
* Take a base64 blob of data and decrypt it (using AES) into its
* proper ASN.1 form.
*/
static
int
ICACHE_FLASH_ATTR
pem_decrypt
(
const
char
*
where
,
const
char
*
end
,
const
char
*
password
,
SSLObjLoader
*
ssl_obj
)
{
int
ret
=
-
1
;
int
is_aes_256
=
0
;
char
*
start
=
NULL
;
uint8_t
iv
[
IV_SIZE
];
int
i
,
pem_size
;
MD5_CTX
md5_ctx
;
AES_CTX
aes_ctx
;
uint8_t
key
[
32
];
/* AES256 size */
if
(
password
==
NULL
||
os_strlen
(
password
)
==
0
)
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"Error: Need a password for this PEM file
\n
"
);
//TTY_FLUSH();
#endif
goto
error
;
}
if
((
start
=
(
char
*
)
os_strstr
((
const
char
*
)
where
,
aes_str
[
0
])))
/* AES128? */
{
start
+=
os_strlen
(
aes_str
[
0
]);
}
else
if
((
start
=
(
char
*
)
os_strstr
((
const
char
*
)
where
,
aes_str
[
1
])))
/* AES256? */
{
is_aes_256
=
1
;
start
+=
os_strlen
(
aes_str
[
1
]);
}
else
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"Error: Unsupported password cipher
\n
"
);
//TTY_FLUSH();
#endif
goto
error
;
}
/* convert from hex to binary - assumes uppercase hex */
for
(
i
=
0
;
i
<
IV_SIZE
;
i
++
)
{
char
c
=
*
start
++
-
'0'
;
iv
[
i
]
=
(
c
>
9
?
c
+
'0'
-
'A'
+
10
:
c
)
<<
4
;
c
=
*
start
++
-
'0'
;
iv
[
i
]
+=
(
c
>
9
?
c
+
'0'
-
'A'
+
10
:
c
);
}
while
(
*
start
==
'\r'
||
*
start
==
'\n'
)
start
++
;
/* turn base64 into binary */
pem_size
=
(
int
)(
end
-
start
);
if
(
base64_decode
(
start
,
pem_size
,
ssl_obj
->
buf
,
&
ssl_obj
->
len
)
!=
0
)
goto
error
;
/* work out the key */
MD5_Init
(
&
md5_ctx
);
MD5_Update
(
&
md5_ctx
,
(
const
uint8_t
*
)
password
,
os_strlen
(
password
));
MD5_Update
(
&
md5_ctx
,
iv
,
SALT_SIZE
);
MD5_Final
(
key
,
&
md5_ctx
);
if
(
is_aes_256
)
{
MD5_Init
(
&
md5_ctx
);
MD5_Update
(
&
md5_ctx
,
key
,
MD5_SIZE
);
MD5_Update
(
&
md5_ctx
,
(
const
uint8_t
*
)
password
,
os_strlen
(
password
));
MD5_Update
(
&
md5_ctx
,
iv
,
SALT_SIZE
);
MD5_Final
(
&
key
[
MD5_SIZE
],
&
md5_ctx
);
}
/* decrypt using the key/iv */
AES_set_key
(
&
aes_ctx
,
key
,
iv
,
is_aes_256
?
AES_MODE_256
:
AES_MODE_128
);
AES_convert_key
(
&
aes_ctx
);
AES_cbc_decrypt
(
&
aes_ctx
,
ssl_obj
->
buf
,
ssl_obj
->
buf
,
ssl_obj
->
len
);
ret
=
0
;
error:
return
ret
;
}
/**
* Take a base64 blob of data and turn it into its proper ASN.1 form.
*/
static
int
ICACHE_FLASH_ATTR
new_pem_obj
(
SSL_CTX
*
ssl_ctx
,
int
is_cacert
,
char
*
where
,
int
remain
,
const
char
*
password
)
{
int
ret
=
SSL_ERROR_BAD_CERTIFICATE
;
SSLObjLoader
*
ssl_obj
=
NULL
;
while
(
remain
>
0
)
{
int
i
,
pem_size
,
obj_type
;
char
*
start
=
NULL
,
*
end
=
NULL
;
for
(
i
=
0
;
i
<
NUM_PEM_TYPES
;
i
++
)
{
if
((
start
=
(
char
*
)
os_strstr
(
where
,
begins
[
i
]))
&&
(
end
=
(
char
*
)
os_strstr
(
where
,
ends
[
i
])))
{
remain
-=
(
int
)(
end
-
where
);
start
+=
os_strlen
(
begins
[
i
]);
pem_size
=
(
int
)(
end
-
start
);
ssl_obj
=
(
SSLObjLoader
*
)
os_zalloc
(
sizeof
(
SSLObjLoader
));
/* 4/3 bigger than what we need but so what */
ssl_obj
->
buf
=
(
uint8_t
*
)
os_zalloc
(
pem_size
);
ssl_obj
->
len
=
pem_size
;
if
(
i
==
IS_RSA_PRIVATE_KEY
&&
os_strstr
(
start
,
"Proc-Type:"
)
&&
os_strstr
(
start
,
"4,ENCRYPTED"
))
{
/* check for encrypted PEM file */
if
(
pem_decrypt
(
start
,
end
,
password
,
ssl_obj
)
<
0
)
{
ret
=
SSL_ERROR_BAD_CERTIFICATE
;
goto
error
;
}
}
else
{
ssl_obj
->
len
=
pem_size
;
if
(
base64_decode
(
start
,
pem_size
,
ssl_obj
->
buf
,
&
ssl_obj
->
len
)
!=
0
)
{
ret
=
SSL_ERROR_BAD_CERTIFICATE
;
goto
error
;
}
}
switch
(
i
)
{
case
IS_RSA_PRIVATE_KEY
:
obj_type
=
SSL_OBJ_RSA_KEY
;
break
;
case
IS_ENCRYPTED_PRIVATE_KEY
:
case
IS_PRIVATE_KEY
:
obj_type
=
SSL_OBJ_PKCS8
;
break
;
case
IS_CERTIFICATE
:
obj_type
=
is_cacert
?
SSL_OBJ_X509_CACERT
:
SSL_OBJ_X509_CERT
;
break
;
default:
ret
=
SSL_ERROR_BAD_CERTIFICATE
;
goto
error
;
}
/* In a format we can now understand - so process it */
if
((
ret
=
do_obj
(
ssl_ctx
,
obj_type
,
ssl_obj
,
password
)))
goto
error
;
end
+=
os_strlen
(
ends
[
i
]);
remain
-=
os_strlen
(
ends
[
i
]);
while
(
remain
>
0
&&
(
*
end
==
'\r'
||
*
end
==
'\n'
))
{
end
++
;
remain
--
;
}
where
=
end
;
break
;
}
}
ssl_obj_free
(
ssl_obj
);
ssl_obj
=
NULL
;
if
(
start
==
NULL
)
break
;
}
error:
ssl_obj_free
(
ssl_obj
);
return
ret
;
}
/*
* Load a file into memory that is in ASCII PEM format.
*/
static
int
ICACHE_FLASH_ATTR
ssl_obj_PEM_load
(
SSL_CTX
*
ssl_ctx
,
int
obj_type
,
SSLObjLoader
*
ssl_obj
,
const
char
*
password
)
{
char
*
start
;
/* add a null terminator */
ssl_obj
->
len
++
;
ssl_obj
->
buf
=
(
uint8_t
*
)
os_realloc
(
ssl_obj
->
buf
,
ssl_obj
->
len
);
ssl_obj
->
buf
[
ssl_obj
->
len
-
1
]
=
0
;
start
=
(
char
*
)
ssl_obj
->
buf
;
return
new_pem_obj
(
ssl_ctx
,
obj_type
==
SSL_OBJ_X509_CACERT
,
start
,
ssl_obj
->
len
,
password
);
}
#endif
/* CONFIG_SSL_HAS_PEM */
/**
* Load the key/certificates in memory depending on compile-time and user
* options.
*/
int
ICACHE_FLASH_ATTR
load_key_certs
(
SSL_CTX
*
ssl_ctx
)
{
int
ret
=
SSL_OK
;
uint32_t
options
=
ssl_ctx
->
options
;
#ifdef CONFIG_SSL_GENERATE_X509_CERT
uint8_t
*
cert_data
=
NULL
;
int
cert_size
;
static
const
char
*
dn
[]
=
{
CONFIG_SSL_X509_COMMON_NAME
,
CONFIG_SSL_X509_ORGANIZATION_NAME
,
CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME
};
#endif
/* do the private key first */
if
(
os_strlen
(
CONFIG_SSL_PRIVATE_KEY_LOCATION
)
>
0
)
{
if
((
ret
=
ssl_obj_load
(
ssl_ctx
,
SSL_OBJ_RSA_KEY
,
CONFIG_SSL_PRIVATE_KEY_LOCATION
,
CONFIG_SSL_PRIVATE_KEY_PASSWORD
))
<
0
)
goto
error
;
}
else
if
(
!
(
options
&
SSL_NO_DEFAULT_KEY
))
{
#if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
// static const /* saves a few more bytes */
//#include "private_key.h"
extern
unsigned
int
default_private_key_len
;
extern
unsigned
char
default_private_key
[];
ssl_obj_memory_load
(
ssl_ctx
,
SSL_OBJ_RSA_KEY
,
default_private_key
,
default_private_key_len
,
NULL
);
#endif
}
/* now load the certificate */
#ifdef CONFIG_SSL_GENERATE_X509_CERT
if
((
cert_size
=
ssl_x509_create
(
ssl_ctx
,
0
,
dn
,
&
cert_data
))
<
0
)
{
ret
=
cert_size
;
goto
error
;
}
ssl_obj_memory_load
(
ssl_ctx
,
SSL_OBJ_X509_CERT
,
cert_data
,
cert_size
,
NULL
);
os_free
(
cert_data
);
#else
if
(
os_strlen
(
CONFIG_SSL_X509_CERT_LOCATION
))
{
if
((
ret
=
ssl_obj_load
(
ssl_ctx
,
SSL_OBJ_X509_CERT
,
CONFIG_SSL_X509_CERT_LOCATION
,
NULL
))
<
0
)
goto
error
;
}
else
if
(
!
(
options
&
SSL_NO_DEFAULT_KEY
))
{
#if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
// static const /* saves a few bytes and RAM */
//#include "cert.h"
extern
unsigned
char
default_certificate
[];
extern
unsigned
int
default_certificate_len
;
ssl_obj_memory_load
(
ssl_ctx
,
SSL_OBJ_X509_CERT
,
default_certificate
,
default_certificate_len
,
NULL
);
#endif
}
#endif
error:
#ifdef CONFIG_SSL_FULL_MODE
if
(
ret
)
{
ssl_printf
(
"Error: Certificate or key not loaded
\n
"
);
//TTY_FLUSH();
}
#endif
return
ret
;
}
app/ssl/ssl/ssl_openssl.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.
*/
/*
* Enable a subset of openssl compatible functions. We don't aim to be 100%
* compatible - just to be able to do basic ports etc.
*
* Only really tested on mini_httpd, so I'm not too sure how extensive this
* port is.
*/
#include "ssl/ssl_config.h"
#ifdef CONFIG_OPENSSL_COMPATIBLE
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_ssl.h"
#define OPENSSL_CTX_ATTR ((OPENSSL_CTX *)ssl_ctx->bonus_attr)
static
char
*
key_password
=
NULL
;
void
*
SSLv23_server_method
(
void
)
{
return
NULL
;
}
void
*
SSLv3_server_method
(
void
)
{
return
NULL
;
}
void
*
TLSv1_server_method
(
void
)
{
return
NULL
;
}
void
*
SSLv23_client_method
(
void
)
{
return
NULL
;
}
void
*
SSLv3_client_method
(
void
)
{
return
NULL
;
}
void
*
TLSv1_client_method
(
void
)
{
return
NULL
;
}
typedef
void
*
(
*
ssl_func_type_t
)(
void
);
typedef
void
*
(
*
bio_func_type_t
)(
void
);
typedef
struct
{
ssl_func_type_t
ssl_func_type
;
}
OPENSSL_CTX
;
SSL_CTX
*
ICACHE_FLASH_ATTR
SSL_CTX_new
(
ssl_func_type_t
meth
)
{
SSL_CTX
*
ssl_ctx
=
ssl_ctx_new
(
0
,
5
);
ssl_ctx
->
bonus_attr
=
os_malloc
(
sizeof
(
OPENSSL_CTX
));
OPENSSL_CTX_ATTR
->
ssl_func_type
=
meth
;
return
ssl_ctx
;
}
void
ICACHE_FLASH_ATTR
SSL_CTX_free
(
SSL_CTX
*
ssl_ctx
)
{
free
(
ssl_ctx
->
bonus_attr
);
ssl_ctx_free
(
ssl_ctx
);
}
SSL
*
ICACHE_FLASH_ATTR
SSL_new
(
SSL_CTX
*
ssl_ctx
)
{
SSL
*
ssl
;
ssl_func_type_t
ssl_func_type
;
ssl
=
ssl_new
(
ssl_ctx
,
-
1
);
/* fd is set later */
ssl_func_type
=
OPENSSL_CTX_ATTR
->
ssl_func_type
;
#ifdef CONFIG_SSL_ENABLE_CLIENT
if
(
ssl_func_type
==
SSLv23_client_method
||
ssl_func_type
==
SSLv3_client_method
||
ssl_func_type
==
TLSv1_client_method
)
{
SET_SSL_FLAG
(
SSL_IS_CLIENT
);
}
else
#endif
{
ssl
->
next_state
=
HS_CLIENT_HELLO
;
}
return
ssl
;
}
int
ICACHE_FLASH_ATTR
SSL_set_fd
(
SSL
*
s
,
int
fd
)
{
s
->
client_fd
=
fd
;
return
1
;
/* always succeeds */
}
int
ICACHE_FLASH_ATTR
SSL_accept
(
SSL
*
ssl
)
{
while
(
ssl_read
(
ssl
,
NULL
)
==
SSL_OK
)
{
if
(
ssl
->
next_state
==
HS_CLIENT_HELLO
)
return
1
;
/* we're done */
}
return
-
1
;
}
#ifdef CONFIG_SSL_ENABLE_CLIENT
int
ICACHE_FLASH_ATTR
SSL_connect
(
SSL
*
ssl
)
{
return
do_client_connect
(
ssl
)
==
SSL_OK
?
1
:
-
1
;
}
#endif
void
ICACHE_FLASH_ATTR
SSL_free
(
SSL
*
ssl
)
{
ssl_free
(
ssl
);
}
int
ICACHE_FLASH_ATTR
SSL_read
(
SSL
*
ssl
,
void
*
buf
,
int
num
)
{
uint8_t
*
read_buf
;
int
ret
;
while
((
ret
=
ssl_read
(
ssl
,
&
read_buf
))
==
SSL_OK
);
if
(
ret
>
SSL_OK
)
{
os_memcpy
(
buf
,
read_buf
,
ret
>
num
?
num
:
ret
);
}
return
ret
;
}
int
ICACHE_FLASH_ATTR
SSL_write
(
SSL
*
ssl
,
const
void
*
buf
,
int
num
)
{
return
ssl_write
(
ssl
,
buf
,
num
);
}
int
ICACHE_FLASH_ATTR
SSL_CTX_use_certificate_file
(
SSL_CTX
*
ssl_ctx
,
const
char
*
file
,
int
type
)
{
return
(
ssl_obj_load
(
ssl_ctx
,
SSL_OBJ_X509_CERT
,
file
,
NULL
)
==
SSL_OK
);
}
int
ICACHE_FLASH_ATTR
SSL_CTX_use_PrivateKey_file
(
SSL_CTX
*
ssl_ctx
,
const
char
*
file
,
int
type
)
{
return
(
ssl_obj_load
(
ssl_ctx
,
SSL_OBJ_RSA_KEY
,
file
,
key_password
)
==
SSL_OK
);
}
int
ICACHE_FLASH_ATTR
SSL_CTX_use_certificate_ASN1
(
SSL_CTX
*
ssl_ctx
,
int
len
,
const
uint8_t
*
d
)
{
return
(
ssl_obj_memory_load
(
ssl_ctx
,
SSL_OBJ_X509_CERT
,
d
,
len
,
NULL
)
==
SSL_OK
);
}
int
ICACHE_FLASH_ATTR
SSL_CTX_set_session_id_context
(
SSL_CTX
*
ctx
,
const
unsigned
char
*
sid_ctx
,
unsigned
int
sid_ctx_len
)
{
return
1
;
}
int
ICACHE_FLASH_ATTR
SSL_CTX_set_default_verify_paths
(
SSL_CTX
*
ctx
)
{
return
1
;
}
int
ICACHE_FLASH_ATTR
SSL_CTX_use_certificate_chain_file
(
SSL_CTX
*
ssl_ctx
,
const
char
*
file
)
{
return
(
ssl_obj_load
(
ssl_ctx
,
SSL_OBJ_X509_CERT
,
file
,
NULL
)
==
SSL_OK
);
}
int
ICACHE_FLASH_ATTR
SSL_shutdown
(
SSL
*
ssl
)
{
return
1
;
}
/*** get/set session ***/
SSL_SESSION
*
ICACHE_FLASH_ATTR
SSL_get1_session
(
SSL
*
ssl
)
{
return
(
SSL_SESSION
*
)
ssl_get_session_id
(
ssl
);
/* note: wrong cast */
}
int
ICACHE_FLASH_ATTR
SSL_set_session
(
SSL
*
ssl
,
SSL_SESSION
*
session
)
{
os_memcpy
(
ssl
->
session_id
,
(
uint8_t
*
)
session
,
SSL_SESSION_ID_SIZE
);
return
1
;
}
void
ICACHE_FLASH_ATTR
SSL_SESSION_free
(
SSL_SESSION
*
session
)
{
}
/*** end get/set session ***/
long
ICACHE_FLASH_ATTR
SSL_CTX_ctrl
(
SSL_CTX
*
ctx
,
int
cmd
,
long
larg
,
void
*
parg
)
{
return
0
;
}
void
ICACHE_FLASH_ATTR
SSL_CTX_set_verify
(
SSL_CTX
*
ctx
,
int
mode
,
int
(
*
verify_callback
)(
int
,
void
*
))
{
}
void
ICACHE_FLASH_ATTR
SSL_CTX_set_verify_depth
(
SSL_CTX
*
ctx
,
int
depth
)
{
}
int
ICACHE_FLASH_ATTR
SSL_CTX_load_verify_locations
(
SSL_CTX
*
ctx
,
const
char
*
CAfile
,
const
char
*
CApath
)
{
return
1
;
}
void
*
ICACHE_FLASH_ATTR
SSL_load_client_CA_file
(
const
char
*
file
)
{
return
(
void
*
)
file
;
}
void
ICACHE_FLASH_ATTR
SSL_CTX_set_client_CA_list
(
SSL_CTX
*
ssl_ctx
,
void
*
file
)
{
ssl_obj_load
(
ssl_ctx
,
SSL_OBJ_X509_CERT
,
(
const
char
*
)
file
,
NULL
);
}
void
ICACHE_FLASH_ATTR
SSLv23_method
(
void
)
{
}
void
ICACHE_FLASH_ATTR
SSL_CTX_set_default_passwd_cb
(
SSL_CTX
*
ctx
,
void
*
cb
)
{
}
void
ICACHE_FLASH_ATTR
SSL_CTX_set_default_passwd_cb_userdata
(
SSL_CTX
*
ctx
,
void
*
u
)
{
key_password
=
(
char
*
)
u
;
}
int
ICACHE_FLASH_ATTR
SSL_peek
(
SSL
*
ssl
,
void
*
buf
,
int
num
)
{
os_memcpy
(
buf
,
ssl
->
bm_data
,
num
);
return
num
;
}
void
ICACHE_FLASH_ATTR
SSL_set_bio
(
SSL
*
ssl
,
void
*
rbio
,
void
*
wbio
)
{
}
long
ICACHE_FLASH_ATTR
SSL_get_verify_result
(
const
SSL
*
ssl
)
{
return
ssl_handshake_status
(
ssl
);
}
int
ICACHE_FLASH_ATTR
SSL_state
(
SSL
*
ssl
)
{
return
0x03
;
// ok state
}
/** end of could do better list */
void
*
ICACHE_FLASH_ATTR
SSL_get_peer_certificate
(
const
SSL
*
ssl
)
{
return
&
ssl
->
ssl_ctx
->
certs
[
0
];
}
int
ICACHE_FLASH_ATTR
SSL_clear
(
SSL
*
ssl
)
{
return
1
;
}
int
ICACHE_FLASH_ATTR
SSL_CTX_check_private_key
(
const
SSL_CTX
*
ctx
)
{
return
1
;
}
int
ICACHE_FLASH_ATTR
SSL_CTX_set_cipher_list
(
SSL
*
s
,
const
char
*
str
)
{
return
1
;
}
int
ICACHE_FLASH_ATTR
SSL_get_error
(
const
SSL
*
ssl
,
int
ret
)
{
ssl_display_error
(
ret
);
return
0
;
/* TODO: return proper return code */
}
void
ICACHE_FLASH_ATTR
SSL_CTX_set_options
(
SSL_CTX
*
ssl_ctx
,
int
option
)
{}
int
ICACHE_FLASH_ATTR
SSL_library_init
(
void
)
{
return
1
;
}
void
ICACHE_FLASH_ATTR
SSL_load_error_strings
(
void
)
{}
void
ICACHE_FLASH_ATTR
ERR_print_errors_fp
(
FILE
*
fp
)
{}
#ifndef CONFIG_SSL_SKELETON_MODE
long
ICACHE_FLASH_ATTR
SSL_CTX_get_timeout
(
const
SSL_CTX
*
ssl_ctx
)
{
return
CONFIG_SSL_EXPIRY_TIME
*
3600
;
}
long
ICACHE_FLASH_ATTR
SSL_CTX_set_timeout
(
SSL_CTX
*
ssl_ctx
,
long
t
)
{
return
SSL_CTX_get_timeout
(
ssl_ctx
);
}
#endif
void
ICACHE_FLASH_ATTR
BIO_printf
(
FILE
*
f
,
const
char
*
format
,
...)
{
va_list
(
ap
);
va_start
(
ap
,
format
);
vfprintf
(
f
,
format
,
ap
);
va_end
(
ap
);
}
void
*
ICACHE_FLASH_ATTR
BIO_s_null
(
void
)
{
return
NULL
;
}
FILE
*
ICACHE_FLASH_ATTR
BIO_new
(
bio_func_type_t
func
)
{
if
(
func
==
BIO_s_null
)
return
fopen
(
"/dev/null"
,
"r"
);
else
return
NULL
;
}
FILE
*
ICACHE_FLASH_ATTR
BIO_new_fp
(
FILE
*
stream
,
int
close_flag
)
{
return
stream
;
}
int
ICACHE_FLASH_ATTR
BIO_free
(
FILE
*
a
)
{
if
(
a
!=
stdout
&&
a
!=
stderr
)
fclose
(
a
);
return
1
;
}
#endif
app/ssl/ssl/ssl_os_port.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.
*/
/**
* @file os_port.c
*
* OS specific functions.
*/
//#include <time.h>
//#include <stdlib.h>
//#include <errno.h>
//#include <stdarg.h>
#include "ssl/ssl_os_port.h"
#ifdef WIN32
/**
* gettimeofday() not in Win32
*/
EXP_FUNC
void
STDCALL
gettimeofday
(
struct
timeval
*
t
,
void
*
timezone
)
{
#if defined(_WIN32_WCE)
t
->
tv_sec
=
time
(
NULL
);
t
->
tv_usec
=
0
;
/* 1sec precision only */
#else
struct
_timeb
timebuffer
;
_ftime
(
&
timebuffer
);
t
->
tv_sec
=
(
long
)
timebuffer
.
time
;
t
->
tv_usec
=
1000
*
timebuffer
.
millitm
;
/* 1ms precision */
#endif
}
/**
* strcasecmp() not in Win32
*/
EXP_FUNC
int
STDCALL
strcasecmp
(
const
char
*
s1
,
const
char
*
s2
)
{
while
(
tolower
(
*
s1
)
==
tolower
(
*
s2
++
))
{
if
(
*
s1
++
==
'\0'
)
{
return
0
;
}
}
return
*
(
unsigned
char
*
)
s1
-
*
(
unsigned
char
*
)(
s2
-
1
);
}
EXP_FUNC
int
STDCALL
getdomainname
(
char
*
buf
,
int
buf_size
)
{
HKEY
hKey
;
unsigned
long
datatype
;
unsigned
long
bufferlength
=
buf_size
;
if
(
RegOpenKeyEx
(
HKEY_LOCAL_MACHINE
,
TEXT
(
"SYSTEM
\\
CurrentControlSet
\\
Services
\\
Tcpip
\\
Parameters"
),
0
,
KEY_QUERY_VALUE
,
&
hKey
)
!=
ERROR_SUCCESS
)
return
-
1
;
RegQueryValueEx
(
hKey
,
"Domain"
,
NULL
,
&
datatype
,
buf
,
&
bufferlength
);
RegCloseKey
(
hKey
);
return
0
;
}
#endif
#if 0
#undef malloc
#undef realloc
#undef calloc
static const char * out_of_mem_str = "out of memory";
static const char * file_open_str = "Could not open file \"%s\"";
/*
* Some functions that call display some error trace and then call abort().
* This just makes life much easier on embedded systems, since we're
* suffering major trauma...
*/
EXP_FUNC void * STDCALL ax_malloc(size_t s)
{
void *x;
if ((x = malloc(s)) == NULL)
exit_now(out_of_mem_str);
return x;
}
EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s)
{
void *x;
if ((x = realloc(y, s)) == NULL)
exit_now(out_of_mem_str);
return x;
}
EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s)
{
void *x;
if ((x = calloc(n, s)) == NULL)
exit_now(out_of_mem_str);
return x;
}
EXP_FUNC int STDCALL ax_open(const char *pathname, int flags)
{
int x;
if ((x = open(pathname, flags)) < 0)
exit_now(file_open_str, pathname);
return x;
}
/**
* This is a call which will deliberately exit an application, but will
* display some information before dying.
*/
void exit_now(const char *format, ...)
{
va_list argp;
va_start(argp, format);
vfprintf(stderr, format, argp);
va_end(argp);
abort();
}
/**
* gettimeofday() not in Win32
*/
EXP_FUNC void STDCALL gettimeofday(struct timeval* t, void* timezone)
{
#if defined(_WIN32_WCE)
t->tv_sec = time(NULL);
t->tv_usec = 0; /* 1sec precision only */
#else
/* wujg : pass compile first */
t->tv_sec = 0;
t->tv_usec = 0; /* 1ms precision */
#endif
}
#endif
app/ssl/ssl/ssl_p12.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.
*/
/**
* Process PKCS#8/PKCS#12 keys.
*
* The decoding of a PKCS#12 key is fairly specific - this code was tested on a
* key generated with:
*
* openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem
* -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128
* -name "p12_withoutCA" -out axTLS.withoutCA.p12 -password pass:abcd
*
* or with a certificate chain:
*
* openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem
* -certfile axTLS.ca_x509.pem -keypbe PBE-SHA1-RC4-128 -certpbe
* PBE-SHA1-RC4-128 -name "p12_withCA" -out axTLS.withCA.p12 -password pass:abcd
*
* Note that the PBE has to be specified with PBE-SHA1-RC4-128. The
* private/public keys/certs have to use RSA encryption. Both the integrity
* and privacy passwords are the same.
*
* The PKCS#8 files were generated with something like:
*
* PEM format:
* openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -v1
* PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8
*
* DER format:
* openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -outform DER
* -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8
*/
//#include <stdlib.h>
//#include <string.h>
//#include <stdio.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_ssl.h"
/* all commented out if not used */
#ifdef CONFIG_SSL_USE_PKCS12
#define BLOCK_SIZE 64
#define PKCS12_KEY_ID 1
#define PKCS12_IV_ID 2
#define PKCS12_MAC_ID 3
static
char
*
make_uni_pass
(
const
char
*
password
,
int
*
uni_pass_len
);
static
int
p8_decrypt
(
const
char
*
uni_pass
,
int
uni_pass_len
,
const
uint8_t
*
salt
,
int
iter
,
uint8_t
*
priv_key
,
int
priv_key_len
,
int
id
);
static
int
p8_add_key
(
SSL_CTX
*
ssl_ctx
,
uint8_t
*
priv_key
);
static
int
get_pbe_params
(
uint8_t
*
buf
,
int
*
offset
,
const
uint8_t
**
salt
,
int
*
iterations
);
/*
* Take a raw pkcs8 block and then decrypt it and turn it into a normal key.
*/
int
ICACHE_FLASH_ATTR
pkcs8_decode
(
SSL_CTX
*
ssl_ctx
,
SSLObjLoader
*
ssl_obj
,
const
char
*
password
)
{
uint8_t
*
buf
=
ssl_obj
->
buf
;
int
len
,
offset
=
0
;
int
iterations
;
int
ret
=
SSL_NOT_OK
;
uint8_t
*
version
=
NULL
;
const
uint8_t
*
salt
;
uint8_t
*
priv_key
;
int
uni_pass_len
;
char
*
uni_pass
=
make_uni_pass
(
password
,
&
uni_pass_len
);
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
)
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"Error: Invalid p8 ASN.1 file
\n
"
);
#endif
goto
error
;
}
/* unencrypted key? */
if
(
asn1_get_int
(
buf
,
&
offset
,
&
version
)
>
0
&&
*
version
==
0
)
{
ret
=
p8_add_key
(
ssl_ctx
,
buf
);
goto
error
;
}
if
(
get_pbe_params
(
buf
,
&
offset
,
&
salt
,
&
iterations
)
<
0
)
goto
error
;
if
((
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OCTET_STRING
))
<
0
)
goto
error
;
priv_key
=
&
buf
[
offset
];
p8_decrypt
(
uni_pass
,
uni_pass_len
,
salt
,
iterations
,
priv_key
,
len
,
PKCS12_KEY_ID
);
ret
=
p8_add_key
(
ssl_ctx
,
priv_key
);
error:
os_free
(
version
);
os_free
(
uni_pass
);
return
ret
;
}
/*
* Take the unencrypted pkcs8 and turn it into a private key
*/
static
int
ICACHE_FLASH_ATTR
p8_add_key
(
SSL_CTX
*
ssl_ctx
,
uint8_t
*
priv_key
)
{
uint8_t
*
buf
=
priv_key
;
int
len
,
offset
=
0
;
int
ret
=
SSL_NOT_OK
;
/* Skip the preamble and go straight to the private key.
We only support rsaEncryption (1.2.840.113549.1.1.1) */
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_skip_obj
(
buf
,
&
offset
,
ASN1_INTEGER
)
<
0
||
asn1_skip_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OCTET_STRING
))
<
0
)
goto
error
;
ret
=
asn1_get_private_key
(
&
buf
[
offset
],
len
,
&
ssl_ctx
->
rsa_ctx
);
error:
return
ret
;
}
/*
* Create the unicode password
*/
static
char
*
ICACHE_FLASH_ATTR
make_uni_pass
(
const
char
*
password
,
int
*
uni_pass_len
)
{
int
pass_len
=
0
,
i
;
char
*
uni_pass
;
if
(
password
==
NULL
)
{
password
=
""
;
}
uni_pass
=
(
char
*
)
os_malloc
((
os_strlen
(
password
)
+
1
)
*
2
);
/* modify the password into a unicode version */
for
(
i
=
0
;
i
<
(
int
)
os_strlen
(
password
);
i
++
)
{
uni_pass
[
pass_len
++
]
=
0
;
uni_pass
[
pass_len
++
]
=
password
[
i
];
}
uni_pass
[
pass_len
++
]
=
0
;
/* null terminate */
uni_pass
[
pass_len
++
]
=
0
;
*
uni_pass_len
=
pass_len
;
return
uni_pass
;
}
/*
* Decrypt a pkcs8 block.
*/
static
int
ICACHE_FLASH_ATTR
p8_decrypt
(
const
char
*
uni_pass
,
int
uni_pass_len
,
const
uint8_t
*
salt
,
int
iter
,
uint8_t
*
priv_key
,
int
priv_key_len
,
int
id
)
{
uint8_t
p
[
BLOCK_SIZE
*
2
];
uint8_t
d
[
BLOCK_SIZE
];
uint8_t
Ai
[
SHA1_SIZE
];
SHA1_CTX
sha_ctx
;
RC4_CTX
rc4_ctx
;
int
i
;
for
(
i
=
0
;
i
<
BLOCK_SIZE
;
i
++
)
{
p
[
i
]
=
salt
[
i
%
SALT_SIZE
];
p
[
BLOCK_SIZE
+
i
]
=
uni_pass
[
i
%
uni_pass_len
];
d
[
i
]
=
id
;
}
/* get the key - no IV since we are using RC4 */
SHA1_Init
(
&
sha_ctx
);
SHA1_Update
(
&
sha_ctx
,
d
,
sizeof
(
d
));
SHA1_Update
(
&
sha_ctx
,
p
,
sizeof
(
p
));
SHA1_Final
(
Ai
,
&
sha_ctx
);
for
(
i
=
1
;
i
<
iter
;
i
++
)
{
SHA1_Init
(
&
sha_ctx
);
SHA1_Update
(
&
sha_ctx
,
Ai
,
SHA1_SIZE
);
SHA1_Final
(
Ai
,
&
sha_ctx
);
}
/* do the decryption */
if
(
id
==
PKCS12_KEY_ID
)
{
RC4_setup
(
&
rc4_ctx
,
Ai
,
16
);
RC4_crypt
(
&
rc4_ctx
,
priv_key
,
priv_key
,
priv_key_len
);
}
else
/* MAC */
os_memcpy
(
priv_key
,
Ai
,
SHA1_SIZE
);
return
0
;
}
/*
* Take a raw pkcs12 block and the decrypt it and turn it into a certificate(s)
* and keys.
*/
int
ICACHE_FLASH_ATTR
pkcs12_decode
(
SSL_CTX
*
ssl_ctx
,
SSLObjLoader
*
ssl_obj
,
const
char
*
password
)
{
uint8_t
*
buf
=
ssl_obj
->
buf
;
int
len
,
iterations
,
auth_safes_start
,
auth_safes_end
,
auth_safes_len
,
key_offset
,
offset
=
0
;
int
all_certs
=
0
;
uint8_t
*
version
=
NULL
,
*
auth_safes
=
NULL
,
*
cert
,
*
orig_mac
;
uint8_t
key
[
SHA1_SIZE
];
uint8_t
mac
[
SHA1_SIZE
];
const
uint8_t
*
salt
;
int
uni_pass_len
,
ret
=
SSL_OK
;
char
*
uni_pass
=
make_uni_pass
(
password
,
&
uni_pass_len
);
static
const
uint8_t
pkcs_data
[]
=
/* pkc7 data */
{
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x01
,
0x07
,
0x01
};
static
const
uint8_t
pkcs_encrypted
[]
=
/* pkc7 encrypted */
{
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x01
,
0x07
,
0x06
};
static
const
uint8_t
pkcs8_key_bag
[]
=
/* 1.2.840.113549.1.12.10.1.2 */
{
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x01
,
0x0c
,
0x0a
,
0x01
,
0x02
};
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
)
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"Error: Invalid p12 ASN.1 file
\n
"
);
#endif
goto
error
;
}
if
(
asn1_get_int
(
buf
,
&
offset
,
&
version
)
<
0
||
*
version
!=
3
)
{
ret
=
SSL_ERROR_INVALID_VERSION
;
goto
error
;
}
/* remove all the boring pcks7 bits */
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OID
))
<
0
||
len
!=
sizeof
(
pkcs_data
)
||
os_memcmp
(
&
buf
[
offset
],
pkcs_data
,
sizeof
(
pkcs_data
)))
goto
error
;
offset
+=
len
;
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_EXPLICIT_TAG
)
<
0
||
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OCTET_STRING
)
<
0
)
goto
error
;
/* work out the MAC start/end points (done on AuthSafes) */
auth_safes_start
=
offset
;
auth_safes_end
=
offset
;
if
(
asn1_skip_obj
(
buf
,
&
auth_safes_end
,
ASN1_SEQUENCE
)
<
0
)
goto
error
;
auth_safes_len
=
auth_safes_end
-
auth_safes_start
;
auth_safes
=
os_malloc
(
auth_safes_len
);
os_memcpy
(
auth_safes
,
&
buf
[
auth_safes_start
],
auth_safes_len
);
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OID
))
<
0
||
(
len
!=
sizeof
(
pkcs_encrypted
)
||
os_memcmp
(
&
buf
[
offset
],
pkcs_encrypted
,
sizeof
(
pkcs_encrypted
))))
goto
error
;
offset
+=
len
;
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_EXPLICIT_TAG
)
<
0
||
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_skip_obj
(
buf
,
&
offset
,
ASN1_INTEGER
)
<
0
||
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OID
))
<
0
||
len
!=
sizeof
(
pkcs_data
)
||
os_memcmp
(
&
buf
[
offset
],
pkcs_data
,
sizeof
(
pkcs_data
)))
goto
error
;
offset
+=
len
;
/* work out the salt for the certificate */
if
(
get_pbe_params
(
buf
,
&
offset
,
&
salt
,
&
iterations
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_IMPLICIT_TAG
))
<
0
)
goto
error
;
/* decrypt the certificate */
cert
=
&
buf
[
offset
];
if
((
ret
=
p8_decrypt
(
uni_pass
,
uni_pass_len
,
salt
,
iterations
,
cert
,
len
,
PKCS12_KEY_ID
))
<
0
)
goto
error
;
offset
+=
len
;
/* load the certificate */
key_offset
=
0
;
all_certs
=
asn1_next_obj
(
cert
,
&
key_offset
,
ASN1_SEQUENCE
);
/* keep going until all certs are loaded */
while
(
key_offset
<
all_certs
)
{
int
cert_offset
=
key_offset
;
if
(
asn1_skip_obj
(
cert
,
&
cert_offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_next_obj
(
cert
,
&
key_offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_skip_obj
(
cert
,
&
key_offset
,
ASN1_OID
)
<
0
||
asn1_next_obj
(
cert
,
&
key_offset
,
ASN1_EXPLICIT_TAG
)
<
0
||
asn1_next_obj
(
cert
,
&
key_offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_skip_obj
(
cert
,
&
key_offset
,
ASN1_OID
)
<
0
||
asn1_next_obj
(
cert
,
&
key_offset
,
ASN1_EXPLICIT_TAG
)
<
0
||
(
len
=
asn1_next_obj
(
cert
,
&
key_offset
,
ASN1_OCTET_STRING
))
<
0
)
goto
error
;
if
((
ret
=
add_cert
(
ssl_ctx
,
&
cert
[
key_offset
],
len
))
<
0
)
goto
error
;
key_offset
=
cert_offset
;
}
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OID
))
<
0
||
len
!=
sizeof
(
pkcs_data
)
||
os_memcmp
(
&
buf
[
offset
],
pkcs_data
,
sizeof
(
pkcs_data
)))
goto
error
;
offset
+=
len
;
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_EXPLICIT_TAG
)
<
0
||
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OCTET_STRING
)
<
0
||
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OID
))
<
0
||
(
len
!=
sizeof
(
pkcs8_key_bag
))
||
os_memcmp
(
&
buf
[
offset
],
pkcs8_key_bag
,
sizeof
(
pkcs8_key_bag
)))
goto
error
;
offset
+=
len
;
/* work out the salt for the private key */
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_EXPLICIT_TAG
)
<
0
||
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
get_pbe_params
(
buf
,
&
offset
,
&
salt
,
&
iterations
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OCTET_STRING
))
<
0
)
goto
error
;
/* decrypt the private key */
cert
=
&
buf
[
offset
];
if
((
ret
=
p8_decrypt
(
uni_pass
,
uni_pass_len
,
salt
,
iterations
,
cert
,
len
,
PKCS12_KEY_ID
))
<
0
)
goto
error
;
offset
+=
len
;
/* load the private key */
if
((
ret
=
p8_add_key
(
ssl_ctx
,
cert
))
<
0
)
goto
error
;
/* miss out on friendly name, local key id etc */
if
(
asn1_skip_obj
(
buf
,
&
offset
,
ASN1_SET
)
<
0
)
goto
error
;
/* work out the MAC */
if
(
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_next_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_skip_obj
(
buf
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OCTET_STRING
))
<
0
||
len
!=
SHA1_SIZE
)
goto
error
;
orig_mac
=
&
buf
[
offset
];
offset
+=
len
;
/* get the salt */
if
((
len
=
asn1_next_obj
(
buf
,
&
offset
,
ASN1_OCTET_STRING
))
<
0
||
len
!=
8
)
goto
error
;
salt
=
&
buf
[
offset
];
/* work out what the mac should be */
if
((
ret
=
p8_decrypt
(
uni_pass
,
uni_pass_len
,
salt
,
iterations
,
key
,
SHA1_SIZE
,
PKCS12_MAC_ID
))
<
0
)
goto
error
;
ssl_hmac_sha1
(
auth_safes
,
auth_safes_len
,
key
,
SHA1_SIZE
,
mac
);
if
(
os_memcmp
(
mac
,
orig_mac
,
SHA1_SIZE
))
{
ret
=
SSL_ERROR_INVALID_HMAC
;
goto
error
;
}
error:
os_free
(
version
);
os_free
(
uni_pass
);
os_free
(
auth_safes
);
return
ret
;
}
/*
* Retrieve the salt/iteration details from a PBE block.
*/
static
int
ICACHE_FLASH_ATTR
get_pbe_params
(
uint8_t
*
buf
,
int
*
offset
,
const
uint8_t
**
salt
,
int
*
iterations
)
{
static
const
uint8_t
pbeSH1RC4
[]
=
/* pbeWithSHAAnd128BitRC4 */
{
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x01
,
0x0c
,
0x01
,
0x01
};
int
i
,
len
;
uint8_t
*
iter
=
NULL
;
int
error_code
=
SSL_ERROR_NOT_SUPPORTED
;
/* Get the PBE type */
if
(
asn1_next_obj
(
buf
,
offset
,
ASN1_SEQUENCE
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
offset
,
ASN1_OID
))
<
0
)
goto
error
;
/* we expect pbeWithSHAAnd128BitRC4 (1.2.840.113549.1.12.1.1)
which is the only algorithm we support */
if
(
len
!=
sizeof
(
pbeSH1RC4
)
||
os_memcmp
(
&
buf
[
*
offset
],
pbeSH1RC4
,
sizeof
(
pbeSH1RC4
)))
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"Error: pkcs8/pkcs12 must use
\"
PBE-SHA1-RC4-128
\"\n
"
);
#endif
goto
error
;
}
*
offset
+=
len
;
if
(
asn1_next_obj
(
buf
,
offset
,
ASN1_SEQUENCE
)
<
0
||
(
len
=
asn1_next_obj
(
buf
,
offset
,
ASN1_OCTET_STRING
))
<
0
||
len
!=
8
)
goto
error
;
*
salt
=
&
buf
[
*
offset
];
*
offset
+=
len
;
if
((
len
=
asn1_get_int
(
buf
,
offset
,
&
iter
))
<
0
)
goto
error
;
*
iterations
=
0
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
(
*
iterations
)
<<=
8
;
(
*
iterations
)
+=
iter
[
i
];
}
os_free
(
iter
);
error_code
=
SSL_OK
;
/* got here - we are ok */
error:
return
error_code
;
}
#endif
app/ssl/ssl/ssl_tls1.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.
*/
/**
* Common ssl/tlsv1 code to both the client and server implementations.
*/
//#include <string.h>
//#include <stdlib.h>
//#include <stdio.h>
//#include <stdarg.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_ssl.h"
#include "lwip/tcp.h"
#include "ssl/app/espconn_ssl.h"
extern
struct
pbuf
*
psslpbuf
;
/* The session expiry time */
#define SSL_EXPIRY_TIME (CONFIG_SSL_EXPIRY_TIME*3600)
static
const
uint8_t
g_hello_request
[]
=
{
HS_HELLO_REQUEST
,
0
,
0
,
0
};
static
const
uint8_t
g_chg_cipher_spec_pkt
[]
=
{
1
};
static
const
char
*
server_finished
=
"server finished"
;
static
const
char
*
client_finished
=
"client finished"
;
static
int
do_handshake
(
SSL
*
ssl
,
uint8_t
*
buf
,
int
read_len
);
static
int
set_key_block
(
SSL
*
ssl
,
int
is_write
);
static
int
verify_digest
(
SSL
*
ssl
,
int
mode
,
const
uint8_t
*
buf
,
int
read_len
);
static
void
*
crypt_new
(
SSL
*
ssl
,
uint8_t
*
key
,
uint8_t
*
iv
,
int
is_decrypt
);
static
err_t
send_raw_packet
(
SSL
*
ssl
,
uint8_t
protocol
);
/**
* The server will pick the cipher based on the order that the order that the
* ciphers are listed. This order is defined at compile time.
*/
#ifdef CONFIG_SSL_SKELETON_MODE
const
uint8_t
ssl_prot_prefs
[
NUM_PROTOCOLS
]
=
{
SSL_RC4_128_SHA
};
#else
static
void
session_free
(
SSL_SESSION
*
ssl_sessions
[],
int
sess_index
);
const
uint8_t
ssl_prot_prefs
[
NUM_PROTOCOLS
]
=
#ifdef CONFIG_SSL_PROT_LOW
/* low security, fast speed */
{
SSL_RC4_128_SHA
,
SSL_AES128_SHA
,
SSL_AES256_SHA
,
SSL_RC4_128_MD5
};
#elif CONFIG_SSL_PROT_MEDIUM
/* medium security, medium speed */
{
SSL_AES128_SHA
,
SSL_AES256_SHA
,
SSL_RC4_128_SHA
,
SSL_RC4_128_MD5
};
#else
/* CONFIG_SSL_PROT_HIGH */
/* high security, low speed */
{
SSL_AES256_SHA
,
SSL_AES128_SHA
,
SSL_RC4_128_SHA
,
SSL_RC4_128_MD5
};
#endif
#endif
/* CONFIG_SSL_SKELETON_MODE */
/**
* The cipher map containing all the essentials for each cipher.
*/
#ifdef CONFIG_SSL_SKELETON_MODE
static
const
cipher_info_t
cipher_info
[
NUM_PROTOCOLS
]
=
{
{
/* RC4-SHA */
SSL_RC4_128_SHA
,
/* RC4-SHA */
16
,
/* key size */
0
,
/* iv size */
2
*
(
SHA1_SIZE
+
16
),
/* key block size */
0
,
/* no padding */
SHA1_SIZE
,
/* digest size */
ssl_hmac_sha1
,
/* hmac algorithm */
(
crypt_func
)
RC4_crypt
,
/* encrypt */
(
crypt_func
)
RC4_crypt
/* decrypt */
},
};
#else
static
const
cipher_info_t
cipher_info
[
NUM_PROTOCOLS
]
=
{
{
/* AES128-SHA */
SSL_AES128_SHA
,
/* AES128-SHA */
16
,
/* key size */
16
,
/* iv size */
2
*
(
SHA1_SIZE
+
16
+
16
),
/* key block size */
16
,
/* block padding size */
SHA1_SIZE
,
/* digest size */
ssl_hmac_sha1
,
/* hmac algorithm */
(
crypt_func
)
AES_cbc_encrypt
,
/* encrypt */
(
crypt_func
)
AES_cbc_decrypt
/* decrypt */
},
{
/* AES256-SHA */
SSL_AES256_SHA
,
/* AES256-SHA */
32
,
/* key size */
16
,
/* iv size */
2
*
(
SHA1_SIZE
+
32
+
16
),
/* key block size */
16
,
/* block padding size */
SHA1_SIZE
,
/* digest size */
ssl_hmac_sha1
,
/* hmac algorithm */
(
crypt_func
)
AES_cbc_encrypt
,
/* encrypt */
(
crypt_func
)
AES_cbc_decrypt
/* decrypt */
},
{
/* RC4-SHA */
SSL_RC4_128_SHA
,
/* RC4-SHA */
16
,
/* key size */
0
,
/* iv size */
2
*
(
SHA1_SIZE
+
16
),
/* key block size */
0
,
/* no padding */
SHA1_SIZE
,
/* digest size */
ssl_hmac_sha1
,
/* hmac algorithm */
(
crypt_func
)
RC4_crypt
,
/* encrypt */
(
crypt_func
)
RC4_crypt
/* decrypt */
},
/*
* This protocol is from SSLv2 days and is unlikely to be used - but was
* useful for testing different possible digest algorithms.
*/
{
/* RC4-MD5 */
SSL_RC4_128_MD5
,
/* RC4-MD5 */
16
,
/* key size */
0
,
/* iv size */
2
*
(
MD5_SIZE
+
16
),
/* key block size */
0
,
/* no padding */
MD5_SIZE
,
/* digest size */
ssl_hmac_md5
,
/* hmac algorithm */
(
crypt_func
)
RC4_crypt
,
/* encrypt */
(
crypt_func
)
RC4_crypt
/* decrypt */
},
};
#endif
static
void
prf
(
const
uint8_t
*
sec
,
int
sec_len
,
uint8_t
*
seed
,
int
seed_len
,
uint8_t
*
out
,
int
olen
);
static
const
cipher_info_t
*
get_cipher_info
(
uint8_t
cipher
);
static
void
increment_read_sequence
(
SSL
*
ssl
);
static
void
increment_write_sequence
(
SSL
*
ssl
);
static
void
add_hmac_digest
(
SSL
*
ssl
,
int
snd
,
uint8_t
*
hmac_header
,
const
uint8_t
*
buf
,
int
buf_len
,
uint8_t
*
hmac_buf
);
/* win32 VC6.0 doesn't have variadic macros */
#if defined(WIN32) && !defined(CONFIG_SSL_FULL_MODE)
void
DISPLAY_BYTES
(
SSL
*
ssl
,
const
char
*
format
,
const
uint8_t
*
data
,
int
size
,
...)
{}
#endif
/**
* Establish a new client/server context.
*/
EXP_FUNC
SSL_CTX
*
STDCALL
ICACHE_FLASH_ATTR
ssl_ctx_new
(
uint32_t
options
,
int
num_sessions
)
{
SSL_CTX
*
ssl_ctx
=
(
SSL_CTX
*
)
os_zalloc
(
sizeof
(
SSL_CTX
));
ssl_ctx
->
options
=
options
;
RNG_initialize
();
if
(
load_key_certs
(
ssl_ctx
)
<
0
)
{
os_free
(
ssl_ctx
);
/* can't load our key/certificate pair, so die */
return
NULL
;
}
#ifndef CONFIG_SSL_SKELETON_MODE
ssl_ctx
->
num_sessions
=
num_sessions
;
#endif
SSL_CTX_MUTEX_INIT
(
ssl_ctx
->
mutex
);
#ifndef CONFIG_SSL_SKELETON_MODE
if
(
num_sessions
)
{
ssl_ctx
->
ssl_sessions
=
(
SSL_SESSION
**
)
os_zalloc
(
num_sessions
*
sizeof
(
SSL_SESSION
*
));
}
#endif
return
ssl_ctx
;
}
/*
* Remove a client/server context.
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
ssl_ctx_free
(
SSL_CTX
*
ssl_ctx
)
{
SSL
*
ssl
;
int
i
;
if
(
ssl_ctx
==
NULL
)
return
;
ssl
=
ssl_ctx
->
head
;
/* clear out all the ssl entries */
while
(
ssl
)
{
SSL
*
next
=
ssl
->
next
;
ssl_free
(
ssl
);
ssl
=
next
;
}
#ifndef CONFIG_SSL_SKELETON_MODE
/* clear out all the sessions */
for
(
i
=
0
;
i
<
ssl_ctx
->
num_sessions
;
i
++
)
session_free
(
ssl_ctx
->
ssl_sessions
,
i
);
os_free
(
ssl_ctx
->
ssl_sessions
);
#endif
i
=
0
;
while
(
i
<
CONFIG_SSL_MAX_CERTS
&&
ssl_ctx
->
certs
[
i
].
buf
)
{
os_free
(
ssl_ctx
->
certs
[
i
].
buf
);
ssl_ctx
->
certs
[
i
++
].
buf
=
NULL
;
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
remove_ca_certs
(
ssl_ctx
->
ca_cert_ctx
);
#endif
ssl_ctx
->
chain_length
=
0
;
SSL_CTX_MUTEX_DESTROY
(
ssl_ctx
->
mutex
);
// ssl_printf("%s %p\n", __func__,ssl_ctx->rsa_ctx);
RSA_free
(
ssl_ctx
->
rsa_ctx
);
RNG_terminate
();
// ssl_printf("%s %p\n", __func__,ssl_ctx);
os_free
(
ssl_ctx
);
}
/*
* Free any used resources used by this connection.
*/
EXP_FUNC
void
STDCALL
ICACHE_FLASH_ATTR
ssl_free
(
SSL
*
ssl
)
{
SSL_CTX
*
ssl_ctx
;
if
(
ssl
==
NULL
)
/* just ignore null pointers */
return
;
/* only notify if we weren't notified first */
/* spec says we must notify when we are dying */
if
(
!
IS_SET_SSL_FLAG
(
SSL_SENT_CLOSE_NOTIFY
))
send_alert
(
ssl
,
SSL_ALERT_CLOSE_NOTIFY
);
// ssl_printf("%s %d\n", __func__, __LINE__);
ssl_ctx
=
ssl
->
ssl_ctx
;
SSL_CTX_LOCK
(
ssl_ctx
->
mutex
);
/* adjust the server SSL list */
if
(
ssl
->
prev
)
ssl
->
prev
->
next
=
ssl
->
next
;
else
ssl_ctx
->
head
=
ssl
->
next
;
if
(
ssl
->
next
)
ssl
->
next
->
prev
=
ssl
->
prev
;
else
ssl_ctx
->
tail
=
ssl
->
prev
;
SSL_CTX_UNLOCK
(
ssl_ctx
->
mutex
);
/* may already be free - but be sure */
os_free
(
ssl
->
encrypt_ctx
);
os_free
(
ssl
->
decrypt_ctx
);
disposable_free
(
ssl
);
#ifdef CONFIG_SSL_CERT_VERIFICATION
x509_free
(
ssl
->
x509_ctx
);
#endif
os_free
(
ssl
);
}
/*
* Read the SSL connection and send any alerts for various errors.
*/
EXP_FUNC
int
STDCALL
ICACHE_FLASH_ATTR
ssl_read
(
SSL
*
ssl
,
uint8_t
**
in_data
)
{
int
ret
=
basic_read
(
ssl
,
in_data
);
/* check for return code so we can send an alert */
if
(
ret
<
SSL_OK
&&
ret
!=
SSL_CLOSE_NOTIFY
)
{
if
(
ret
!=
SSL_ERROR_CONN_LOST
)
{
send_alert
(
ssl
,
ret
);
#ifndef CONFIG_SSL_SKELETON_MODE
/* something nasty happened, so get rid of this session */
kill_ssl_session
(
ssl
->
ssl_ctx
->
ssl_sessions
,
ssl
);
#endif
}
}
return
ret
;
}
/*
* Write application data to the client
*/
EXP_FUNC
int
STDCALL
ICACHE_FLASH_ATTR
ssl_write
(
SSL
*
ssl
,
const
uint8_t
*
out_data
,
int
out_len
)
{
int
n
=
out_len
,
nw
,
i
,
tot
=
0
;
/* maximum size of a TLS packet is around 16kB, so fragment */
do
{
nw
=
n
;
if
(
nw
>
RT_MAX_PLAIN_LENGTH
)
/* fragment if necessary */
nw
=
RT_MAX_PLAIN_LENGTH
;
if
((
i
=
send_packet
(
ssl
,
PT_APP_PROTOCOL_DATA
,
&
out_data
[
tot
],
nw
))
<=
0
)
{
out_len
=
i
;
/* an error */
break
;
}
tot
+=
i
;
n
-=
i
;
}
while
(
n
>
0
);
return
out_len
;
}
/**
* Add a certificate to the certificate chain.
*/
int
ICACHE_FLASH_ATTR
add_cert
(
SSL_CTX
*
ssl_ctx
,
const
uint8_t
*
buf
,
int
len
)
{
int
ret
=
SSL_ERROR_NO_CERT_DEFINED
,
i
=
0
;
SSL_CERT
*
ssl_cert
;
X509_CTX
*
cert
=
NULL
;
int
offset
;
while
(
ssl_ctx
->
certs
[
i
].
buf
&&
i
<
CONFIG_SSL_MAX_CERTS
)
i
++
;
if
(
i
==
CONFIG_SSL_MAX_CERTS
)
/* too many certs */
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"Error: maximum number of certs added (%d) - change of "
"compile-time configuration required
\n
"
,
CONFIG_SSL_MAX_CERTS
);
#endif
goto
error
;
}
if
((
ret
=
x509_new
(
buf
,
&
offset
,
&
cert
)))
goto
error
;
#if defined (CONFIG_SSL_FULL_MODE)
if
(
ssl_ctx
->
options
&
SSL_DISPLAY_CERTS
)
x509_print
(
cert
,
NULL
);
#endif
ssl_cert
=
&
ssl_ctx
->
certs
[
i
];
ssl_cert
->
size
=
len
;
ssl_cert
->
buf
=
(
uint8_t
*
)
os_malloc
(
len
);
os_memcpy
(
ssl_cert
->
buf
,
buf
,
len
);
ssl_ctx
->
chain_length
++
;
len
-=
offset
;
ret
=
SSL_OK
;
/* ok so far */
/* recurse? */
if
(
len
>
0
)
{
ret
=
add_cert
(
ssl_ctx
,
&
buf
[
offset
],
len
);
}
error:
x509_free
(
cert
);
/* don't need anymore */
return
ret
;
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Add a certificate authority.
*/
int
ICACHE_FLASH_ATTR
add_cert_auth
(
SSL_CTX
*
ssl_ctx
,
const
uint8_t
*
buf
,
int
len
)
{
int
ret
=
SSL_OK
;
/* ignore errors for now */
int
i
=
0
;
CA_CERT_CTX
*
ca_cert_ctx
;
if
(
ssl_ctx
->
ca_cert_ctx
==
NULL
)
ssl_ctx
->
ca_cert_ctx
=
(
CA_CERT_CTX
*
)
os_zalloc
(
sizeof
(
CA_CERT_CTX
));
ca_cert_ctx
=
ssl_ctx
->
ca_cert_ctx
;
while
(
i
<
CONFIG_X509_MAX_CA_CERTS
&&
ca_cert_ctx
->
cert
[
i
])
i
++
;
while
(
len
>
0
)
{
int
offset
;
if
(
i
>=
CONFIG_X509_MAX_CA_CERTS
)
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"Error: maximum number of CA certs added (%d) - change of "
"compile-time configuration required
\n
"
,
CONFIG_X509_MAX_CA_CERTS
);
#endif
break
;
}
/* ignore the return code */
if
(
x509_new
(
buf
,
&
offset
,
&
ca_cert_ctx
->
cert
[
i
])
==
X509_OK
)
{
#if defined (CONFIG_SSL_FULL_MODE)
if
(
ssl_ctx
->
options
&
SSL_DISPLAY_CERTS
)
x509_print
(
ca_cert_ctx
->
cert
[
i
],
NULL
);
#endif
}
i
++
;
len
-=
offset
;
}
return
ret
;
}
/*
* Retrieve an X.509 distinguished name component
*/
EXP_FUNC
const
char
*
STDCALL
ICACHE_FLASH_ATTR
ssl_get_cert_dn
(
const
SSL
*
ssl
,
int
component
)
{
if
(
ssl
->
x509_ctx
==
NULL
)
return
NULL
;
switch
(
component
)
{
case
SSL_X509_CERT_COMMON_NAME
:
return
ssl
->
x509_ctx
->
cert_dn
[
X509_COMMON_NAME
];
case
SSL_X509_CERT_ORGANIZATION
:
return
ssl
->
x509_ctx
->
cert_dn
[
X509_ORGANIZATION
];
case
SSL_X509_CERT_ORGANIZATIONAL_NAME
:
return
ssl
->
x509_ctx
->
cert_dn
[
X509_ORGANIZATIONAL_UNIT
];
case
SSL_X509_CA_CERT_COMMON_NAME
:
return
ssl
->
x509_ctx
->
ca_cert_dn
[
X509_COMMON_NAME
];
case
SSL_X509_CA_CERT_ORGANIZATION
:
return
ssl
->
x509_ctx
->
ca_cert_dn
[
X509_ORGANIZATION
];
case
SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
:
return
ssl
->
x509_ctx
->
ca_cert_dn
[
X509_ORGANIZATIONAL_UNIT
];
default:
return
NULL
;
}
}
/*
* Retrieve a "Subject Alternative Name" from a v3 certificate
*/
EXP_FUNC
const
char
*
STDCALL
ICACHE_FLASH_ATTR
ssl_get_cert_subject_alt_dnsname
(
const
SSL
*
ssl
,
int
dnsindex
)
{
int
i
;
if
(
ssl
->
x509_ctx
==
NULL
||
ssl
->
x509_ctx
->
subject_alt_dnsnames
==
NULL
)
return
NULL
;
for
(
i
=
0
;
i
<
dnsindex
;
++
i
)
{
if
(
ssl
->
x509_ctx
->
subject_alt_dnsnames
[
i
]
==
NULL
)
return
NULL
;
}
return
ssl
->
x509_ctx
->
subject_alt_dnsnames
[
dnsindex
];
}
#endif
/* CONFIG_SSL_CERT_VERIFICATION */
#if 0
/*
* Find an ssl object based on the client's file descriptor.
*/
EXP_FUNC SSL * STDCALL ICACHE_FLASH_ATTR ssl_find(SSL_CTX *ssl_ctx, int client_fd)
{
SSL *ssl;
SSL_CTX_LOCK(ssl_ctx->mutex);
ssl = ssl_ctx->head;
/* search through all the ssl entries */
while (ssl)
{
if (ssl->client_fd == client_fd)
{
SSL_CTX_UNLOCK(ssl_ctx->mutex);
return ssl;
}
ssl = ssl->next;
}
SSL_CTX_UNLOCK(ssl_ctx->mutex);
return NULL;
}
#endif
/*
* Force the client to perform its handshake again.
*/
EXP_FUNC
int
STDCALL
ICACHE_FLASH_ATTR
ssl_renegotiate
(
SSL
*
ssl
)
{
int
ret
=
SSL_OK
;
disposable_new
(
ssl
);
#ifdef CONFIG_SSL_ENABLE_CLIENT
if
(
IS_SET_SSL_FLAG
(
SSL_IS_CLIENT
))
{
ret
=
do_client_connect
(
ssl
);
}
else
#endif
{
send_packet
(
ssl
,
PT_HANDSHAKE_PROTOCOL
,
g_hello_request
,
sizeof
(
g_hello_request
));
SET_SSL_FLAG
(
SSL_NEED_RECORD
);
}
return
ret
;
}
/**
* @brief Get what we need for key info.
* @param cipher [in] The cipher information we are after
* @param key_size [out] The key size for the cipher
* @param iv_size [out] The iv size for the cipher
* @return The amount of key information we need.
*/
static
const
cipher_info_t
*
ICACHE_FLASH_ATTR
get_cipher_info
(
uint8_t
cipher
)
{
int
i
;
for
(
i
=
0
;
i
<
NUM_PROTOCOLS
;
i
++
)
{
if
(
cipher_info
[
i
].
cipher
==
cipher
)
{
return
&
cipher_info
[
i
];
}
}
return
NULL
;
/* error */
}
#if 0
/*
* Get a new ssl context for a new connection.
*/
SSL *ICACHE_FLASH_ATTR ssl_new(SSL_CTX *ssl_ctx, int client_fd)
{
SSL *ssl = (SSL *)os_zalloc(sizeof(SSL));
ssl->ssl_ctx = ssl_ctx;
ssl->need_bytes = SSL_RECORD_SIZE; /* need a record */
ssl->client_fd = client_fd;
ssl->flag = SSL_NEED_RECORD;
ssl->bm_data = ssl->bm_all_data+BM_RECORD_OFFSET; /* space at the start */
ssl->hs_status = SSL_NOT_OK; /* not connected */
#ifdef CONFIG_ENABLE_VERIFICATION
ssl->ca_cert_ctx = ssl_ctx->ca_cert_ctx;
#endif
disposable_new(ssl);
/* a bit hacky but saves a few bytes of memory */
ssl->flag |= ssl_ctx->options;
SSL_CTX_LOCK(ssl_ctx->mutex);
if (ssl_ctx->head == NULL)
{
ssl_ctx->head = ssl;
ssl_ctx->tail = ssl;
}
else
{
ssl->prev = ssl_ctx->tail;
ssl_ctx->tail->next = ssl;
ssl_ctx->tail = ssl;
}
SSL_CTX_UNLOCK(ssl_ctx->mutex);
return ssl;
}
#endif
/*
* Get a new ssl context for a new connection.(raw api)add by ives 12.12.2013
*/
SSL
*
ICACHE_FLASH_ATTR
ssl_new_context
(
SSL_CTX
*
ssl_ctx
,
struct
tcp_pcb
*
SslClient_pcb
)
{
SSL
*
ssl
=
(
SSL
*
)
os_zalloc
(
sizeof
(
SSL
));
ssl
->
ssl_ctx
=
ssl_ctx
;
ssl
->
need_bytes
=
SSL_RECORD_SIZE
;
/* need a record */
//ssl->client_fd = client_fd;annotation by ives 12.12.2013
ssl
->
SslClient_pcb
=
SslClient_pcb
;
ssl
->
ssl_pbuf
=
NULL
;
ssl
->
flag
=
SSL_NEED_RECORD
;
ssl
->
bm_data
=
ssl
->
bm_all_data
+
BM_RECORD_OFFSET
;
/* space at the start */
ssl
->
hs_status
=
SSL_NOT_OK
;
/* not connected */
#ifdef CONFIG_ENABLE_VERIFICATION
ssl
->
ca_cert_ctx
=
ssl_ctx
->
ca_cert_ctx
;
#endif
disposable_new
(
ssl
);
/* a bit hacky but saves a few bytes of memory */
ssl
->
flag
|=
ssl_ctx
->
options
;
SSL_CTX_LOCK
(
ssl_ctx
->
mutex
);
if
(
ssl_ctx
->
head
==
NULL
)
{
ssl_ctx
->
head
=
ssl
;
ssl_ctx
->
tail
=
ssl
;
}
else
{
ssl
->
prev
=
ssl_ctx
->
tail
;
ssl_ctx
->
tail
->
next
=
ssl
;
ssl_ctx
->
tail
=
ssl
;
}
SSL_CTX_UNLOCK
(
ssl_ctx
->
mutex
);
return
ssl
;
}
/*
* Add a private key to a context.
*/
int
ICACHE_FLASH_ATTR
add_private_key
(
SSL_CTX
*
ssl_ctx
,
SSLObjLoader
*
ssl_obj
)
{
int
ret
=
SSL_OK
;
/* get the private key details */
if
(
asn1_get_private_key
(
ssl_obj
->
buf
,
ssl_obj
->
len
,
&
ssl_ctx
->
rsa_ctx
))
{
ret
=
SSL_ERROR_INVALID_KEY
;
goto
error
;
}
error:
return
ret
;
}
/**
* Increment the read sequence number (as a 64 bit endian indepenent #)
*/
static
void
ICACHE_FLASH_ATTR
increment_read_sequence
(
SSL
*
ssl
)
{
int
i
;
for
(
i
=
7
;
i
>=
0
;
i
--
)
{
if
(
++
ssl
->
read_sequence
[
i
])
break
;
}
}
/**
* Increment the read sequence number (as a 64 bit endian indepenent #)
*/
static
void
ICACHE_FLASH_ATTR
increment_write_sequence
(
SSL
*
ssl
)
{
int
i
;
for
(
i
=
7
;
i
>=
0
;
i
--
)
{
if
(
++
ssl
->
write_sequence
[
i
])
break
;
}
}
/**
* Work out the HMAC digest in a packet.
*/
static
void
ICACHE_FLASH_ATTR
add_hmac_digest
(
SSL
*
ssl
,
int
mode
,
uint8_t
*
hmac_header
,
const
uint8_t
*
buf
,
int
buf_len
,
uint8_t
*
hmac_buf
)
{
int
hmac_len
=
buf_len
+
8
+
SSL_RECORD_SIZE
;
uint8_t
*
t_buf
=
(
uint8_t
*
)
os_malloc
(
hmac_len
+
10
);
os_memcpy
(
t_buf
,
(
mode
==
SSL_SERVER_WRITE
||
mode
==
SSL_CLIENT_WRITE
)
?
ssl
->
write_sequence
:
ssl
->
read_sequence
,
8
);
os_memcpy
(
&
t_buf
[
8
],
hmac_header
,
SSL_RECORD_SIZE
);
os_memcpy
(
&
t_buf
[
8
+
SSL_RECORD_SIZE
],
buf
,
buf_len
);
ssl
->
cipher_info
->
hmac
(
t_buf
,
hmac_len
,
(
mode
==
SSL_SERVER_WRITE
||
mode
==
SSL_CLIENT_READ
)
?
ssl
->
server_mac
:
ssl
->
client_mac
,
ssl
->
cipher_info
->
digest_size
,
hmac_buf
);
/* add by wujg */
os_free
(
t_buf
);
#if 0
print_blob("record", hmac_header, SSL_RECORD_SIZE);
print_blob("buf", buf, buf_len);
if (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE)
{
print_blob("write seq", ssl->write_sequence, 8);
}
else
{
print_blob("read seq", ssl->read_sequence, 8);
}
if (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ)
{
print_blob("server mac",
ssl->server_mac, ssl->cipher_info->digest_size);
}
else
{
print_blob("client mac",
ssl->client_mac, ssl->cipher_info->digest_size);
}
print_blob("hmac", hmac_buf, SHA1_SIZE);
#endif
}
/**
* Verify that the digest of a packet is correct.
*/
static
int
ICACHE_FLASH_ATTR
verify_digest
(
SSL
*
ssl
,
int
mode
,
const
uint8_t
*
buf
,
int
read_len
)
{
uint8_t
hmac_buf
[
SHA1_SIZE
];
int
hmac_offset
;
if
(
ssl
->
cipher_info
->
padding_size
)
{
int
last_blk_size
=
buf
[
read_len
-
1
],
i
;
hmac_offset
=
read_len
-
last_blk_size
-
ssl
->
cipher_info
->
digest_size
-
1
;
/* guard against a timing attack - make sure we do the digest */
if
(
hmac_offset
<
0
)
{
hmac_offset
=
0
;
}
else
{
/* already looked at last byte */
for
(
i
=
1
;
i
<
last_blk_size
;
i
++
)
{
if
(
buf
[
read_len
-
i
]
!=
last_blk_size
)
{
hmac_offset
=
0
;
break
;
}
}
}
}
else
/* stream cipher */
{
hmac_offset
=
read_len
-
ssl
->
cipher_info
->
digest_size
;
if
(
hmac_offset
<
0
)
{
hmac_offset
=
0
;
}
}
/* sanity check the offset */
ssl
->
hmac_header
[
3
]
=
hmac_offset
>>
8
;
/* insert size */
ssl
->
hmac_header
[
4
]
=
hmac_offset
&
0xff
;
add_hmac_digest
(
ssl
,
mode
,
ssl
->
hmac_header
,
buf
,
hmac_offset
,
hmac_buf
);
if
(
memcmp
(
hmac_buf
,
&
buf
[
hmac_offset
],
ssl
->
cipher_info
->
digest_size
))
{
return
SSL_ERROR_INVALID_HMAC
;
}
return
hmac_offset
;
}
/**
* Add a packet to the end of our sent and received packets, so that we may use
* it to calculate the hash at the end.
*/
void
ICACHE_FLASH_ATTR
add_packet
(
SSL
*
ssl
,
const
uint8_t
*
pkt
,
int
len
)
{
MD5_Update
(
&
ssl
->
dc
->
md5_ctx
,
pkt
,
len
);
SHA1_Update
(
&
ssl
->
dc
->
sha1_ctx
,
pkt
,
len
);
}
/**
* Work out the MD5 PRF.
*/
static
void
ICACHE_FLASH_ATTR
p_hash_md5
(
const
uint8_t
*
sec
,
int
sec_len
,
uint8_t
*
seed
,
int
seed_len
,
uint8_t
*
out
,
int
olen
)
{
uint8_t
a1
[
128
];
/* A(1) */
ssl_hmac_md5
(
seed
,
seed_len
,
sec
,
sec_len
,
a1
);
os_memcpy
(
&
a1
[
MD5_SIZE
],
seed
,
seed_len
);
ssl_hmac_md5
(
a1
,
MD5_SIZE
+
seed_len
,
sec
,
sec_len
,
out
);
while
(
olen
>
MD5_SIZE
)
{
uint8_t
a2
[
MD5_SIZE
];
out
+=
MD5_SIZE
;
olen
-=
MD5_SIZE
;
/* A(N) */
ssl_hmac_md5
(
a1
,
MD5_SIZE
,
sec
,
sec_len
,
a2
);
os_memcpy
(
a1
,
a2
,
MD5_SIZE
);
/* work out the actual hash */
ssl_hmac_md5
(
a1
,
MD5_SIZE
+
seed_len
,
sec
,
sec_len
,
out
);
}
}
/**
* Work out the SHA1 PRF.
*/
static
void
ICACHE_FLASH_ATTR
p_hash_sha1
(
const
uint8_t
*
sec
,
int
sec_len
,
uint8_t
*
seed
,
int
seed_len
,
uint8_t
*
out
,
int
olen
)
{
uint8_t
a1
[
128
];
/* A(1) */
ssl_hmac_sha1
(
seed
,
seed_len
,
sec
,
sec_len
,
a1
);
os_memcpy
(
&
a1
[
SHA1_SIZE
],
seed
,
seed_len
);
ssl_hmac_sha1
(
a1
,
SHA1_SIZE
+
seed_len
,
sec
,
sec_len
,
out
);
while
(
olen
>
SHA1_SIZE
)
{
uint8_t
a2
[
SHA1_SIZE
];
out
+=
SHA1_SIZE
;
olen
-=
SHA1_SIZE
;
/* A(N) */
ssl_hmac_sha1
(
a1
,
SHA1_SIZE
,
sec
,
sec_len
,
a2
);
os_memcpy
(
a1
,
a2
,
SHA1_SIZE
);
/* work out the actual hash */
ssl_hmac_sha1
(
a1
,
SHA1_SIZE
+
seed_len
,
sec
,
sec_len
,
out
);
}
}
/**
* Work out the PRF.
*/
static
void
ICACHE_FLASH_ATTR
prf
(
const
uint8_t
*
sec
,
int
sec_len
,
uint8_t
*
seed
,
int
seed_len
,
uint8_t
*
out
,
int
olen
)
{
int
len
,
i
;
const
uint8_t
*
S1
,
*
S2
;
uint8_t
xbuf
[
256
];
/* needs to be > the amount of key data */
uint8_t
ybuf
[
256
];
/* needs to be > the amount of key data */
len
=
sec_len
/
2
;
S1
=
sec
;
S2
=
&
sec
[
len
];
len
+=
(
sec_len
&
1
);
/* add for odd, make longer */
p_hash_md5
(
S1
,
len
,
seed
,
seed_len
,
xbuf
,
olen
);
p_hash_sha1
(
S2
,
len
,
seed
,
seed_len
,
ybuf
,
olen
);
for
(
i
=
0
;
i
<
olen
;
i
++
)
out
[
i
]
=
xbuf
[
i
]
^
ybuf
[
i
];
}
/**
* Generate a master secret based on the client/server random data and the
* premaster secret.
*/
void
ICACHE_FLASH_ATTR
generate_master_secret
(
SSL
*
ssl
,
const
uint8_t
*
premaster_secret
)
{
uint8_t
buf
[
128
];
/* needs to be > 13+32+32 in size */
os_strcpy
((
char
*
)
buf
,
"master secret"
);
os_memcpy
(
&
buf
[
13
],
ssl
->
dc
->
client_random
,
SSL_RANDOM_SIZE
);
os_memcpy
(
&
buf
[
45
],
ssl
->
dc
->
server_random
,
SSL_RANDOM_SIZE
);
prf
(
premaster_secret
,
SSL_SECRET_SIZE
,
buf
,
77
,
ssl
->
dc
->
master_secret
,
SSL_SECRET_SIZE
);
}
/**
* Generate a 'random' blob of data used for the generation of keys.
*/
static
void
ICACHE_FLASH_ATTR
generate_key_block
(
uint8_t
*
client_random
,
uint8_t
*
server_random
,
uint8_t
*
master_secret
,
uint8_t
*
key_block
,
int
key_block_size
)
{
uint8_t
buf
[
128
];
os_strcpy
((
char
*
)
buf
,
"key expansion"
);
os_memcpy
(
&
buf
[
13
],
server_random
,
SSL_RANDOM_SIZE
);
os_memcpy
(
&
buf
[
45
],
client_random
,
SSL_RANDOM_SIZE
);
prf
(
master_secret
,
SSL_SECRET_SIZE
,
buf
,
77
,
key_block
,
key_block_size
);
}
/**
* Calculate the digest used in the finished message. This function also
* doubles up as a certificate verify function.
*/
void
ICACHE_FLASH_ATTR
finished_digest
(
SSL
*
ssl
,
const
char
*
label
,
uint8_t
*
digest
)
{
uint8_t
mac_buf
[
128
];
uint8_t
*
q
=
mac_buf
;
MD5_CTX
md5_ctx
=
ssl
->
dc
->
md5_ctx
;
SHA1_CTX
sha1_ctx
=
ssl
->
dc
->
sha1_ctx
;
if
(
label
)
{
os_strcpy
((
char
*
)
q
,
label
);
q
+=
os_strlen
(
label
);
}
MD5_Final
(
q
,
&
md5_ctx
);
q
+=
MD5_SIZE
;
SHA1_Final
(
q
,
&
sha1_ctx
);
q
+=
SHA1_SIZE
;
if
(
label
)
{
prf
(
ssl
->
dc
->
master_secret
,
SSL_SECRET_SIZE
,
mac_buf
,
(
int
)(
q
-
mac_buf
),
digest
,
SSL_FINISHED_HASH_SIZE
);
}
else
/* for use in a certificate verify */
{
os_memcpy
(
digest
,
mac_buf
,
MD5_SIZE
+
SHA1_SIZE
);
}
#if 0
printf("label: %s\n", label);
print_blob("master secret", ssl->dc->master_secret, 48);
print_blob("mac_buf", mac_buf, q-mac_buf);
print_blob("finished digest", digest, SSL_FINISHED_HASH_SIZE);
#endif
}
/**
* Retrieve (and initialise) the context of a cipher.
*/
static
void
*
ICACHE_FLASH_ATTR
crypt_new
(
SSL
*
ssl
,
uint8_t
*
key
,
uint8_t
*
iv
,
int
is_decrypt
)
{
switch
(
ssl
->
cipher
)
{
#ifndef CONFIG_SSL_SKELETON_MODE
case
SSL_AES128_SHA
:
{
AES_CTX
*
aes_ctx
=
(
AES_CTX
*
)
os_malloc
(
sizeof
(
AES_CTX
));
AES_set_key
(
aes_ctx
,
key
,
iv
,
AES_MODE_128
);
if
(
is_decrypt
)
{
AES_convert_key
(
aes_ctx
);
}
return
(
void
*
)
aes_ctx
;
}
case
SSL_AES256_SHA
:
{
AES_CTX
*
aes_ctx
=
(
AES_CTX
*
)
os_malloc
(
sizeof
(
AES_CTX
));
AES_set_key
(
aes_ctx
,
key
,
iv
,
AES_MODE_256
);
if
(
is_decrypt
)
{
AES_convert_key
(
aes_ctx
);
}
return
(
void
*
)
aes_ctx
;
}
case
SSL_RC4_128_MD5
:
#endif
case
SSL_RC4_128_SHA
:
{
RC4_CTX
*
rc4_ctx
=
(
RC4_CTX
*
)
os_malloc
(
sizeof
(
RC4_CTX
));
RC4_setup
(
rc4_ctx
,
key
,
16
);
return
(
void
*
)
rc4_ctx
;
}
}
return
NULL
;
/* its all gone wrong */
}
/**
* Send a packet over the socket.
*/
static
err_t
ICACHE_FLASH_ATTR
send_raw_packet
(
SSL
*
ssl
,
uint8_t
protocol
)
{
uint8_t
*
rec_buf
=
ssl
->
bm_all_data
;
int
pkt_size
=
SSL_RECORD_SIZE
+
ssl
->
bm_index
;
int
Length
=
0
;
//int ret = SSL_OK;
err_t
Err
=
ERR_OK
;
rec_buf
[
0
]
=
protocol
;
rec_buf
[
1
]
=
0x03
;
/* version = 3.1 or higher */
rec_buf
[
2
]
=
ssl
->
version
&
0x0f
;
rec_buf
[
3
]
=
ssl
->
bm_index
>>
8
;
rec_buf
[
4
]
=
ssl
->
bm_index
&
0xff
;
//DISPLAY_BYTES(ssl, "sending %d bytes", ssl->bm_all_data,
// pkt_size, pkt_size);
ssl_printf
(
"send_raw_packet pkt_size %d
\n
"
,
pkt_size
);
if
(
tcp_sndbuf
(
ssl
->
SslClient_pcb
)
<
pkt_size
)
{
Length
=
tcp_sndbuf
(
ssl
->
SslClient_pcb
);
}
else
{
Length
=
pkt_size
;
}
if
(
Length
>
2
*
ssl
->
SslClient_pcb
->
mss
)
{
Length
=
2
*
ssl
->
SslClient_pcb
->
mss
;
}
do
{
Err
=
tcp_write
(
ssl
->
SslClient_pcb
,
&
ssl
->
bm_all_data
[
0
],
Length
,
0
);
if
(
Err
==
ERR_MEM
)
{
Length
/=
2
;
}
}
while
(
Err
==
ERR_MEM
&&
Length
>
1
);
ssl_printf
(
"send_raw_packet Length %d
\n
"
,
Length
);
if
(
Err
==
ERR_OK
)
{
Err
=
tcp_output
(
ssl
->
SslClient_pcb
);
}
SET_SSL_FLAG
(
SSL_NEED_RECORD
);
/* reset for next time */
//ssl->bm_index = 0;
if
(
protocol
!=
PT_APP_PROTOCOL_DATA
)
{
/* always return SSL_OK during handshake */
ssl
->
bm_index
=
0
;
Err
=
SSL_OK
;
}
return
Err
;
}
/**
* Send an encrypted packet with padding bytes if necessary.
*/
int
ICACHE_FLASH_ATTR
send_packet
(
SSL
*
ssl
,
uint8_t
protocol
,
const
uint8_t
*
in
,
int
length
)
{
int
ret
,
msg_length
=
0
;
/* if our state is bad, don't bother */
if
(
ssl
->
hs_status
==
SSL_ERROR_DEAD
)
return
SSL_ERROR_CONN_LOST
;
if
(
in
)
/* has the buffer already been initialised? */
{
os_memcpy
(
ssl
->
bm_data
,
in
,
length
);
}
msg_length
+=
length
;
if
(
IS_SET_SSL_FLAG
(
SSL_TX_ENCRYPTED
))
{
int
mode
=
IS_SET_SSL_FLAG
(
SSL_IS_CLIENT
)
?
SSL_CLIENT_WRITE
:
SSL_SERVER_WRITE
;
uint8_t
hmac_header
[
SSL_RECORD_SIZE
]
=
{
protocol
,
0x03
,
/* version = 3.1 or higher */
ssl
->
version
&
0x0f
,
msg_length
>>
8
,
msg_length
&
0xff
};
if
(
protocol
==
PT_HANDSHAKE_PROTOCOL
)
{
//DISPLAY_STATE(ssl, 1, ssl->bm_data[0], 0);
if
(
ssl
->
bm_data
[
0
]
!=
HS_HELLO_REQUEST
)
{
add_packet
(
ssl
,
ssl
->
bm_data
,
msg_length
);
}
}
/* add the packet digest */
add_hmac_digest
(
ssl
,
mode
,
hmac_header
,
ssl
->
bm_data
,
msg_length
,
&
ssl
->
bm_data
[
msg_length
]);
msg_length
+=
ssl
->
cipher_info
->
digest_size
;
/* add padding? */
if
(
ssl
->
cipher_info
->
padding_size
)
{
int
last_blk_size
=
msg_length
%
ssl
->
cipher_info
->
padding_size
;
int
pad_bytes
=
ssl
->
cipher_info
->
padding_size
-
last_blk_size
;
/* ensure we always have at least 1 padding byte */
if
(
pad_bytes
==
0
)
pad_bytes
+=
ssl
->
cipher_info
->
padding_size
;
os_memset
(
&
ssl
->
bm_data
[
msg_length
],
pad_bytes
-
1
,
pad_bytes
);
msg_length
+=
pad_bytes
;
}
//DISPLAY_BYTES(ssl, "unencrypted write", ssl->bm_data, msg_length);
increment_write_sequence
(
ssl
);
/* add the explicit IV for TLS1.1 */
if
(
ssl
->
version
>=
SSL_PROTOCOL_VERSION1_1
&&
ssl
->
cipher_info
->
iv_size
)
{
uint8_t
iv_size
=
ssl
->
cipher_info
->
iv_size
;
uint8_t
*
t_buf
=
(
uint8_t
*
)
os_malloc
(
msg_length
+
iv_size
);
os_memcpy
(
t_buf
+
iv_size
,
ssl
->
bm_data
,
msg_length
);
get_random
(
iv_size
,
t_buf
);
msg_length
+=
iv_size
;
os_memcpy
(
ssl
->
bm_data
,
t_buf
,
msg_length
);
os_free
(
t_buf
);
/* add by wujg */
}
/* now encrypt the packet */
ssl
->
cipher_info
->
encrypt
(
ssl
->
encrypt_ctx
,
ssl
->
bm_data
,
ssl
->
bm_data
,
msg_length
);
}
else
if
(
protocol
==
PT_HANDSHAKE_PROTOCOL
)
{
//DISPLAY_STATE(ssl, 1, ssl->bm_data[0], 0);
if
(
ssl
->
bm_data
[
0
]
!=
HS_HELLO_REQUEST
)
{
add_packet
(
ssl
,
ssl
->
bm_data
,
length
);
}
}
ssl
->
bm_index
=
msg_length
;
if
((
ret
=
send_raw_packet
(
ssl
,
protocol
))
<=
0
)
return
ret
;
return
length
;
/* just return what we wanted to send */
}
/**
* Work out the cipher keys we are going to use for this session based on the
* master secret.
*/
static
int
ICACHE_FLASH_ATTR
set_key_block
(
SSL
*
ssl
,
int
is_write
)
{
const
cipher_info_t
*
ciph_info
=
get_cipher_info
(
ssl
->
cipher
);
uint8_t
*
q
;
uint8_t
client_key
[
32
],
server_key
[
32
];
/* big enough for AES256 */
uint8_t
client_iv
[
16
],
server_iv
[
16
];
/* big enough for AES128/256 */
int
is_client
=
IS_SET_SSL_FLAG
(
SSL_IS_CLIENT
);
if
(
ciph_info
==
NULL
)
return
-
1
;
/* only do once in a handshake */
if
(
ssl
->
dc
->
key_block
==
NULL
)
{
ssl
->
dc
->
key_block
=
(
uint8_t
*
)
os_malloc
(
ciph_info
->
key_block_size
);
#if 0
print_blob("client", ssl->dc->client_random, 32);
print_blob("server", ssl->dc->server_random, 32);
print_blob("master", ssl->dc->master_secret, SSL_SECRET_SIZE);
#endif
generate_key_block
(
ssl
->
dc
->
client_random
,
ssl
->
dc
->
server_random
,
ssl
->
dc
->
master_secret
,
ssl
->
dc
->
key_block
,
ciph_info
->
key_block_size
);
#if 0
print_blob("keyblock", ssl->dc->key_block, ciph_info->key_block_size);
#endif
}
q
=
ssl
->
dc
->
key_block
;
if
((
is_client
&&
is_write
)
||
(
!
is_client
&&
!
is_write
))
{
os_memcpy
(
ssl
->
client_mac
,
q
,
ciph_info
->
digest_size
);
}
q
+=
ciph_info
->
digest_size
;
if
((
!
is_client
&&
is_write
)
||
(
is_client
&&
!
is_write
))
{
os_memcpy
(
ssl
->
server_mac
,
q
,
ciph_info
->
digest_size
);
}
q
+=
ciph_info
->
digest_size
;
os_memcpy
(
client_key
,
q
,
ciph_info
->
key_size
);
q
+=
ciph_info
->
key_size
;
os_memcpy
(
server_key
,
q
,
ciph_info
->
key_size
);
q
+=
ciph_info
->
key_size
;
#ifndef CONFIG_SSL_SKELETON_MODE
if
(
ciph_info
->
iv_size
)
/* RC4 has no IV, AES does */
{
os_memcpy
(
client_iv
,
q
,
ciph_info
->
iv_size
);
q
+=
ciph_info
->
iv_size
;
os_memcpy
(
server_iv
,
q
,
ciph_info
->
iv_size
);
q
+=
ciph_info
->
iv_size
;
}
#endif
os_free
(
is_write
?
ssl
->
encrypt_ctx
:
ssl
->
decrypt_ctx
);
/* now initialise the ciphers */
if
(
is_client
)
{
finished_digest
(
ssl
,
server_finished
,
ssl
->
dc
->
final_finish_mac
);
if
(
is_write
)
ssl
->
encrypt_ctx
=
crypt_new
(
ssl
,
client_key
,
client_iv
,
0
);
else
ssl
->
decrypt_ctx
=
crypt_new
(
ssl
,
server_key
,
server_iv
,
1
);
}
else
{
finished_digest
(
ssl
,
client_finished
,
ssl
->
dc
->
final_finish_mac
);
if
(
is_write
)
ssl
->
encrypt_ctx
=
crypt_new
(
ssl
,
server_key
,
server_iv
,
0
);
else
ssl
->
decrypt_ctx
=
crypt_new
(
ssl
,
client_key
,
client_iv
,
1
);
}
ssl
->
cipher_info
=
ciph_info
;
return
0
;
}
/**
* Read the SSL connection.
*/
int
ICACHE_FLASH_ATTR
basic_read
(
SSL
*
ssl
,
uint8_t
**
in_data
)
{
int
ret
=
SSL_OK
;
int
j
,
i
=
0
;
int
read_len
,
is_client
=
IS_SET_SSL_FLAG
(
SSL_IS_CLIENT
);
uint8_t
*
buf
=
ssl
->
bm_data
;
uint8_t
*
read_buf
=
NULL
;
uint8_t
*
pread_buf
=
NULL
;
u16_t
recvlength
=
0
;
read_buf
=
(
uint8_t
*
)
os_zalloc
(
ssl
->
ssl_pbuf
->
len
+
1
);
pread_buf
=
read_buf
;
if
(
pread_buf
!=
NULL
){
recvlength
=
pbuf_copy_partial
(
ssl
->
ssl_pbuf
,
read_buf
,
ssl
->
ssl_pbuf
->
len
,
0
);
}
if
(
recvlength
!=
0
){
do
{
// ssl_printf("basic_read ssl->bm_read_index %d\n", ssl->bm_read_index);
// ssl_printf("basic_read ssl->need_bytes %d\n", ssl->need_bytes);
// ssl_printf("basic_read ssl->got_bytes %d\n", ssl->got_bytes);
read_len
=
ssl
->
need_bytes
-
ssl
->
got_bytes
;
if
(
read_len
>=
recvlength
){
read_len
=
recvlength
;
}
os_memcpy
(
&
buf
[
ssl
->
bm_read_index
],
read_buf
,
read_len
);
// ssl_printf("basic_read read_len %d\n", read_len);
// for (i = ssl->bm_read_index; i < (ssl->bm_read_index + read_len); i ++){
// ssl_printf("%2x ",buf[i]);
// if ((i + 1) % 16 == 0)
// ssl_printf("\n");
// }
// ssl_printf("\n");
read_buf
+=
read_len
;
recvlength
-=
read_len
;
// ssl_printf("basic_read %d %d\n", __LINE__, recvlength);
/* connection has gone, so die */
if
(
read_len
<=
0
)
{
ret
=
SSL_ERROR_CONN_LOST
;
ssl
->
hs_status
=
SSL_ERROR_DEAD
;
/* make sure it stays dead */
goto
error
;
}
//DISPLAY_BYTES(ssl, "received %d bytes",
// &ssl->bm_data[ssl->bm_read_index], read_len, read_len);
ssl
->
got_bytes
+=
read_len
;
ssl
->
bm_read_index
+=
read_len
;
/* haven't quite got what we want, so try again later */
if
(
ssl
->
got_bytes
<
ssl
->
need_bytes
){
// ssl_printf("basic_read %d %p\n", __LINE__, pread_buf);
os_free
(
pread_buf
);
pread_buf
=
NULL
;
return
SSL_OK
;
}
read_len
=
ssl
->
got_bytes
;
ssl
->
got_bytes
=
0
;
if
(
IS_SET_SSL_FLAG
(
SSL_NEED_RECORD
))
{
/* check for sslv2 "client hello" */
if
(
buf
[
0
]
&
0x80
&&
buf
[
2
]
==
1
)
{
#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
uint8_t
version
=
(
buf
[
3
]
<<
4
)
+
buf
[
4
];
DISPLAY_BYTES
(
ssl
,
"ssl2 record"
,
buf
,
5
);
/* should be v3.1 (TLSv1) or better */
ssl
->
version
=
ssl
->
client_version
=
version
;
if
(
version
>
SSL_PROTOCOL_VERSION_MAX
)
{
/* use client's version */
ssl
->
version
=
SSL_PROTOCOL_VERSION_MAX
;
}
else
if
(
version
<
SSL_PROTOCOL_MIN_VERSION
)
{
ret
=
SSL_ERROR_INVALID_VERSION
;
ssl_display_error
(
ret
);
return
ret
;
}
add_packet
(
ssl
,
&
buf
[
2
],
3
);
ret
=
process_sslv23_client_hello
(
ssl
);
#else
ssl_printf
(
"Error: no SSLv23 handshaking allowed
\n
"
);
//TTY_FLUSH();
ret
=
SSL_ERROR_NOT_SUPPORTED
;
#endif
goto
error
;
/* not an error - just get out of here */
}
ssl
->
need_bytes
=
(
buf
[
3
]
<<
8
)
+
buf
[
4
];
/* do we violate the spec with the message size? */
if
(
ssl
->
need_bytes
>
RT_MAX_PLAIN_LENGTH
+
RT_EXTRA
-
BM_RECORD_OFFSET
)
{
ret
=
SSL_ERROR_INVALID_PROT_MSG
;
recvlength
=
0
;
os_printf
(
"we violate the spec with the message size
\n
"
);
goto
error
;
}
CLR_SSL_FLAG
(
SSL_NEED_RECORD
);
os_memcpy
(
ssl
->
hmac_header
,
buf
,
3
);
/* store for hmac */
ssl
->
record_type
=
buf
[
0
];
goto
error
;
/* no error, we're done */
}
/* for next time - just do it now in case of an error */
SET_SSL_FLAG
(
SSL_NEED_RECORD
);
ssl
->
need_bytes
=
SSL_RECORD_SIZE
;
/* decrypt if we need to */
if
(
IS_SET_SSL_FLAG
(
SSL_RX_ENCRYPTED
))
{
ssl
->
cipher_info
->
decrypt
(
ssl
->
decrypt_ctx
,
buf
,
buf
,
read_len
);
if
(
ssl
->
version
>=
SSL_PROTOCOL_VERSION1_1
&&
ssl
->
cipher_info
->
iv_size
)
{
buf
+=
ssl
->
cipher_info
->
iv_size
;
read_len
-=
ssl
->
cipher_info
->
iv_size
;
}
read_len
=
verify_digest
(
ssl
,
is_client
?
SSL_CLIENT_READ
:
SSL_SERVER_READ
,
buf
,
read_len
);
/* does the hmac work? */
if
(
read_len
<
0
)
{
ret
=
read_len
;
goto
error
;
}
//DISPLAY_BYTES(ssl, "decrypted", buf, read_len);
increment_read_sequence
(
ssl
);
}
/* The main part of the SSL packet */
//ssl_printf("basic_read %d %x %p\n", __LINE__, ssl->record_type, in_data);
switch
(
ssl
->
record_type
)
{
case
PT_HANDSHAKE_PROTOCOL
:
if
(
ssl
->
dc
!=
NULL
)
{
ssl
->
dc
->
bm_proc_index
=
0
;
ret
=
do_handshake
(
ssl
,
buf
,
read_len
);
}
else
/* no client renegotiation allowed */
{
ret
=
SSL_ERROR_NO_CLIENT_RENOG
;
goto
error
;
}
break
;
case
PT_CHANGE_CIPHER_SPEC
:
if
(
ssl
->
next_state
!=
HS_FINISHED
)
{
ret
=
SSL_ERROR_INVALID_HANDSHAKE
;
goto
error
;
}
/* all encrypted from now on */
SET_SSL_FLAG
(
SSL_RX_ENCRYPTED
);
if
(
set_key_block
(
ssl
,
0
)
<
0
)
{
ret
=
SSL_ERROR_INVALID_HANDSHAKE
;
goto
error
;
}
os_memset
(
ssl
->
read_sequence
,
0
,
8
);
break
;
case
PT_APP_PROTOCOL_DATA
:
if
(
in_data
)
{
*
in_data
=
buf
;
/* point to the work buffer */
(
*
in_data
)[
read_len
]
=
0
;
/* null terminate just in case */
}
ret
=
read_len
;
recvlength
=
0
;
break
;
case
PT_ALERT_PROTOCOL
:
/* return the alert # with alert bit set */
if
(
buf
[
0
]
==
SSL_ALERT_TYPE_WARNING
&&
buf
[
1
]
==
SSL_ALERT_CLOSE_NOTIFY
)
{
ret
=
SSL_CLOSE_NOTIFY
;
//send_alert(ssl, SSL_ALERT_CLOSE_NOTIFY);
SET_SSL_FLAG
(
SSL_SENT_CLOSE_NOTIFY
);
}
else
{
ret
=
-
buf
[
1
];
//DISPLAY_ALERT(ssl, buf[1]);
}
break
;
default:
ret
=
SSL_ERROR_INVALID_PROT_MSG
;
break
;
}
error:
ssl
->
bm_read_index
=
0
;
/* reset to go again */
if
(
ret
<
SSL_OK
&&
in_data
)
/* if all wrong, then clear this buffer ptr */
*
in_data
=
NULL
;
}
while
(
recvlength
!=
0
);
}
else
{
ssl_printf
(
"%s %d %d
\n
"
,
__func__
,
__LINE__
,
recvlength
);
}
os_free
(
pread_buf
);
pread_buf
=
NULL
;
return
ret
;
}
/**
* Do some basic checking of data and then perform the appropriate handshaking.
*/
static
int
ICACHE_FLASH_ATTR
do_handshake
(
SSL
*
ssl
,
uint8_t
*
buf
,
int
read_len
)
{
int
hs_len
=
(
buf
[
2
]
<<
8
)
+
buf
[
3
];
uint8_t
handshake_type
=
buf
[
0
];
int
ret
=
SSL_OK
;
int
is_client
=
IS_SET_SSL_FLAG
(
SSL_IS_CLIENT
);
/* some integrity checking on the handshake */
PARANOIA_CHECK
(
read_len
-
SSL_HS_HDR_SIZE
,
hs_len
);
if
(
handshake_type
!=
ssl
->
next_state
)
{
/* handle a special case on the client */
if
(
!
is_client
||
handshake_type
!=
HS_CERT_REQ
||
ssl
->
next_state
!=
HS_SERVER_HELLO_DONE
)
{
ret
=
SSL_ERROR_INVALID_HANDSHAKE
;
goto
error
;
}
}
hs_len
+=
SSL_HS_HDR_SIZE
;
/* adjust for when adding packets */
ssl
->
bm_index
=
hs_len
;
/* store the size and check later */
//DISPLAY_STATE(ssl, 0, handshake_type, 0);
if
(
handshake_type
!=
HS_CERT_VERIFY
&&
handshake_type
!=
HS_HELLO_REQUEST
)
add_packet
(
ssl
,
buf
,
hs_len
);
#if defined(CONFIG_SSL_ENABLE_CLIENT)
ret
=
is_client
?
do_clnt_handshake
(
ssl
,
handshake_type
,
buf
,
hs_len
)
:
do_svr_handshake
(
ssl
,
handshake_type
,
buf
,
hs_len
);
#else
ret
=
do_svr_handshake
(
ssl
,
handshake_type
,
buf
,
hs_len
);
#endif
/* just use recursion to get the rest */
if
(
hs_len
<
read_len
&&
ret
==
SSL_OK
)
ret
=
do_handshake
(
ssl
,
&
buf
[
hs_len
],
read_len
-
hs_len
);
error:
return
ret
;
}
/**
* Sends the change cipher spec message. We have just read a finished message
* from the client.
*/
int
ICACHE_FLASH_ATTR
send_change_cipher_spec
(
SSL
*
ssl
)
{
int
ret
=
send_packet
(
ssl
,
PT_CHANGE_CIPHER_SPEC
,
g_chg_cipher_spec_pkt
,
sizeof
(
g_chg_cipher_spec_pkt
));
SET_SSL_FLAG
(
SSL_TX_ENCRYPTED
);
if
(
ret
>=
0
&&
set_key_block
(
ssl
,
1
)
<
0
)
ret
=
SSL_ERROR_INVALID_HANDSHAKE
;
os_memset
(
ssl
->
write_sequence
,
0
,
8
);
return
ret
;
}
/**
* Send a "finished" message
*/
int
ICACHE_FLASH_ATTR
send_finished
(
SSL
*
ssl
)
{
uint8_t
buf
[
SSL_FINISHED_HASH_SIZE
+
4
]
=
{
HS_FINISHED
,
0
,
0
,
SSL_FINISHED_HASH_SIZE
};
/* now add the finished digest mac (12 bytes) */
finished_digest
(
ssl
,
IS_SET_SSL_FLAG
(
SSL_IS_CLIENT
)
?
client_finished
:
server_finished
,
&
buf
[
4
]);
#ifndef CONFIG_SSL_SKELETON_MODE
/* store in the session cache */
if
(
!
IS_SET_SSL_FLAG
(
SSL_SESSION_RESUME
)
&&
ssl
->
ssl_ctx
->
num_sessions
)
{
os_memcpy
(
ssl
->
session
->
master_secret
,
ssl
->
dc
->
master_secret
,
SSL_SECRET_SIZE
);
}
#endif
return
send_packet
(
ssl
,
PT_HANDSHAKE_PROTOCOL
,
buf
,
SSL_FINISHED_HASH_SIZE
+
4
);
}
/**
* Send an alert message.
* Return 1 if the alert was an "error".
*/
int
ICACHE_FLASH_ATTR
send_alert
(
SSL
*
ssl
,
int
error_code
)
{
int
alert_num
=
0
;
int
is_warning
=
0
;
uint8_t
buf
[
2
];
/* Don't bother we're already dead */
if
(
ssl
->
hs_status
==
SSL_ERROR_DEAD
)
{
return
SSL_ERROR_CONN_LOST
;
}
#ifdef CONFIG_SSL_FULL_MODE
//if (IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
//ssl_display_error(error_code);
#endif
switch
(
error_code
)
{
case
SSL_ALERT_CLOSE_NOTIFY
:
is_warning
=
1
;
alert_num
=
SSL_ALERT_CLOSE_NOTIFY
;
break
;
case
SSL_ERROR_CONN_LOST
:
/* don't send alert just yet */
is_warning
=
1
;
break
;
case
SSL_ERROR_INVALID_HANDSHAKE
:
case
SSL_ERROR_INVALID_PROT_MSG
:
alert_num
=
SSL_ALERT_HANDSHAKE_FAILURE
;
break
;
case
SSL_ERROR_INVALID_HMAC
:
case
SSL_ERROR_FINISHED_INVALID
:
alert_num
=
SSL_ALERT_BAD_RECORD_MAC
;
break
;
case
SSL_ERROR_INVALID_VERSION
:
alert_num
=
SSL_ALERT_INVALID_VERSION
;
break
;
case
SSL_ERROR_INVALID_SESSION
:
case
SSL_ERROR_NO_CIPHER
:
case
SSL_ERROR_INVALID_KEY
:
alert_num
=
SSL_ALERT_ILLEGAL_PARAMETER
;
break
;
case
SSL_ERROR_BAD_CERTIFICATE
:
alert_num
=
SSL_ALERT_BAD_CERTIFICATE
;
break
;
case
SSL_ERROR_NO_CLIENT_RENOG
:
alert_num
=
SSL_ALERT_NO_RENEGOTIATION
;
break
;
default:
/* a catch-all for any badly verified certificates */
alert_num
=
(
error_code
<=
SSL_X509_OFFSET
)
?
SSL_ALERT_BAD_CERTIFICATE
:
SSL_ALERT_UNEXPECTED_MESSAGE
;
break
;
}
buf
[
0
]
=
is_warning
?
1
:
2
;
buf
[
1
]
=
alert_num
;
send_packet
(
ssl
,
PT_ALERT_PROTOCOL
,
buf
,
sizeof
(
buf
));
//DISPLAY_ALERT(ssl, alert_num);
return
is_warning
?
0
:
1
;
}
/**
* Process a client finished message.
*/
int
ICACHE_FLASH_ATTR
process_finished
(
SSL
*
ssl
,
uint8_t
*
buf
,
int
hs_len
)
{
int
ret
=
SSL_OK
;
int
is_client
=
IS_SET_SSL_FLAG
(
SSL_IS_CLIENT
);
int
resume
=
IS_SET_SSL_FLAG
(
SSL_SESSION_RESUME
);
PARANOIA_CHECK
(
ssl
->
bm_index
,
SSL_FINISHED_HASH_SIZE
+
4
);
/* check that we all work before we continue */
if
(
os_memcmp
(
ssl
->
dc
->
final_finish_mac
,
&
buf
[
4
],
SSL_FINISHED_HASH_SIZE
))
return
SSL_ERROR_FINISHED_INVALID
;
if
((
!
is_client
&&
!
resume
)
||
(
is_client
&&
resume
))
{
if
((
ret
=
send_change_cipher_spec
(
ssl
))
==
SSL_OK
)
ret
=
send_finished
(
ssl
);
}
/* if we ever renegotiate */
ssl
->
next_state
=
is_client
?
HS_HELLO_REQUEST
:
HS_CLIENT_HELLO
;
ssl
->
hs_status
=
ret
;
/* set the final handshake status */
error:
return
ret
;
}
/**
* Send a certificate.
*/
int
ICACHE_FLASH_ATTR
send_certificate
(
SSL
*
ssl
)
{
int
i
=
0
;
uint8_t
*
buf
=
ssl
->
bm_data
;
int
offset
=
7
;
int
chain_length
;
buf
[
0
]
=
HS_CERTIFICATE
;
buf
[
1
]
=
0
;
buf
[
4
]
=
0
;
while
(
i
<
ssl
->
ssl_ctx
->
chain_length
)
{
SSL_CERT
*
cert
=
&
ssl
->
ssl_ctx
->
certs
[
i
];
buf
[
offset
++
]
=
0
;
buf
[
offset
++
]
=
cert
->
size
>>
8
;
/* cert 1 length */
buf
[
offset
++
]
=
cert
->
size
&
0xff
;
os_memcpy
(
&
buf
[
offset
],
cert
->
buf
,
cert
->
size
);
offset
+=
cert
->
size
;
i
++
;
}
chain_length
=
offset
-
7
;
buf
[
5
]
=
chain_length
>>
8
;
/* cert chain length */
buf
[
6
]
=
chain_length
&
0xff
;
chain_length
+=
3
;
buf
[
2
]
=
chain_length
>>
8
;
/* handshake length */
buf
[
3
]
=
chain_length
&
0xff
;
ssl
->
bm_index
=
offset
;
return
send_packet
(
ssl
,
PT_HANDSHAKE_PROTOCOL
,
NULL
,
offset
);
}
/**
* Create a blob of memory that we'll get rid of once the handshake is
* complete.
*/
void
ICACHE_FLASH_ATTR
disposable_new
(
SSL
*
ssl
)
{
if
(
ssl
->
dc
==
NULL
)
{
ssl
->
dc
=
(
DISPOSABLE_CTX
*
)
os_zalloc
(
sizeof
(
DISPOSABLE_CTX
));
MD5_Init
(
&
ssl
->
dc
->
md5_ctx
);
SHA1_Init
(
&
ssl
->
dc
->
sha1_ctx
);
}
}
/**
* Remove the temporary blob of memory.
*/
void
ICACHE_FLASH_ATTR
disposable_free
(
SSL
*
ssl
)
{
if
(
ssl
->
dc
)
{
os_free
(
ssl
->
dc
->
key_block
);
os_memset
(
ssl
->
dc
,
0
,
sizeof
(
DISPOSABLE_CTX
));
os_free
(
ssl
->
dc
);
ssl
->
dc
=
NULL
;
}
}
#ifndef CONFIG_SSL_SKELETON_MODE
/* no session resumption in this mode */
/**
* Find if an existing session has the same session id. If so, use the
* master secret from this session for session resumption.
*/
SSL_SESSION
*
ICACHE_FLASH_ATTR
ssl_session_update
(
int
max_sessions
,
SSL_SESSION
*
ssl_sessions
[],
SSL
*
ssl
,
const
uint8_t
*
session_id
)
{
time_t
tm
=
0
;
//time(NULL); wujg
time_t
oldest_sess_time
=
tm
;
SSL_SESSION
*
oldest_sess
=
NULL
;
int
i
;
/* no sessions? Then bail */
if
(
max_sessions
==
0
)
return
NULL
;
SSL_CTX_LOCK
(
ssl
->
ssl_ctx
->
mutex
);
if
(
session_id
)
{
for
(
i
=
0
;
i
<
max_sessions
;
i
++
)
{
if
(
ssl_sessions
[
i
])
{
/* kill off any expired sessions (including those in
the future) */
if
((
tm
>
ssl_sessions
[
i
]
->
conn_time
+
SSL_EXPIRY_TIME
)
||
(
tm
<
ssl_sessions
[
i
]
->
conn_time
))
{
session_free
(
ssl_sessions
,
i
);
continue
;
}
/* if the session id matches, it must still be less than
the expiry time */
if
(
os_memcmp
(
ssl_sessions
[
i
]
->
session_id
,
session_id
,
SSL_SESSION_ID_SIZE
)
==
0
)
{
ssl
->
session_index
=
i
;
os_memcpy
(
ssl
->
dc
->
master_secret
,
ssl_sessions
[
i
]
->
master_secret
,
SSL_SECRET_SIZE
);
SET_SSL_FLAG
(
SSL_SESSION_RESUME
);
SSL_CTX_UNLOCK
(
ssl
->
ssl_ctx
->
mutex
);
return
ssl_sessions
[
i
];
/* a session was found */
}
}
}
}
/* If we've got here, no matching session was found - so create one */
for
(
i
=
0
;
i
<
max_sessions
;
i
++
)
{
if
(
ssl_sessions
[
i
]
==
NULL
)
{
/* perfect, this will do */
ssl_sessions
[
i
]
=
(
SSL_SESSION
*
)
os_zalloc
(
sizeof
(
SSL_SESSION
));
ssl_sessions
[
i
]
->
conn_time
=
tm
;
ssl
->
session_index
=
i
;
SSL_CTX_UNLOCK
(
ssl
->
ssl_ctx
->
mutex
);
return
ssl_sessions
[
i
];
/* return the session object */
}
else
if
(
ssl_sessions
[
i
]
->
conn_time
<=
oldest_sess_time
)
{
/* find the oldest session */
oldest_sess_time
=
ssl_sessions
[
i
]
->
conn_time
;
oldest_sess
=
ssl_sessions
[
i
];
ssl
->
session_index
=
i
;
}
}
/* ok, we've used up all of our sessions. So blow the oldest session away */
oldest_sess
->
conn_time
=
tm
;
os_memset
(
oldest_sess
->
session_id
,
0
,
sizeof
(
SSL_SESSION_ID_SIZE
));
os_memset
(
oldest_sess
->
master_secret
,
0
,
sizeof
(
SSL_SECRET_SIZE
));
SSL_CTX_UNLOCK
(
ssl
->
ssl_ctx
->
mutex
);
return
oldest_sess
;
}
/**
* Free an existing session.
*/
static
void
ICACHE_FLASH_ATTR
session_free
(
SSL_SESSION
*
ssl_sessions
[],
int
sess_index
)
{
if
(
ssl_sessions
[
sess_index
])
{
os_free
(
ssl_sessions
[
sess_index
]);
ssl_sessions
[
sess_index
]
=
NULL
;
}
}
/**
* This ssl object doesn't want this session anymore.
*/
void
ICACHE_FLASH_ATTR
kill_ssl_session
(
SSL_SESSION
**
ssl_sessions
,
SSL
*
ssl
)
{
SSL_CTX_LOCK
(
ssl
->
ssl_ctx
->
mutex
);
if
(
ssl
->
ssl_ctx
->
num_sessions
)
{
session_free
(
ssl_sessions
,
ssl
->
session_index
);
ssl
->
session
=
NULL
;
}
SSL_CTX_UNLOCK
(
ssl
->
ssl_ctx
->
mutex
);
}
#endif
/* CONFIG_SSL_SKELETON_MODE */
/*
* Get the session id for a handshake. This will be a 32 byte sequence.
*/
EXP_FUNC
const
uint8_t
*
STDCALL
ICACHE_FLASH_ATTR
ssl_get_session_id
(
const
SSL
*
ssl
)
{
return
ssl
->
session_id
;
}
/*
* Get the session id size for a handshake.
*/
EXP_FUNC
uint8_t
STDCALL
ICACHE_FLASH_ATTR
ssl_get_session_id_size
(
const
SSL
*
ssl
)
{
return
ssl
->
sess_id_size
;
}
/*
* Return the cipher id (in the SSL form).
*/
EXP_FUNC
uint8_t
STDCALL
ICACHE_FLASH_ATTR
ssl_get_cipher_id
(
const
SSL
*
ssl
)
{
return
ssl
->
cipher
;
}
/*
* Return the status of the handshake.
*/
EXP_FUNC
int
STDCALL
ICACHE_FLASH_ATTR
ssl_handshake_status
(
const
SSL
*
ssl
)
{
return
ssl
->
hs_status
;
}
/*
* Retrieve various parameters about the SSL engine.
*/
EXP_FUNC
int
STDCALL
ICACHE_FLASH_ATTR
ssl_get_config
(
int
offset
)
{
switch
(
offset
)
{
/* return the appropriate build mode */
case
SSL_BUILD_MODE
:
#if defined(CONFIG_SSL_FULL_MODE)
return
SSL_BUILD_FULL_MODE
;
#elif defined(CONFIG_SSL_ENABLE_CLIENT)
return
SSL_BUILD_ENABLE_CLIENT
;
#elif defined(CONFIG_ENABLE_VERIFICATION)
return
SSL_BUILD_ENABLE_VERIFICATION
;
#elif defined(CONFIG_SSL_SERVER_ONLY )
return
SSL_BUILD_SERVER_ONLY
;
#else
return
SSL_BUILD_SKELETON_MODE
;
#endif
case
SSL_MAX_CERT_CFG_OFFSET
:
return
CONFIG_SSL_MAX_CERTS
;
#ifdef CONFIG_SSL_CERT_VERIFICATION
case
SSL_MAX_CA_CERT_CFG_OFFSET
:
return
CONFIG_X509_MAX_CA_CERTS
;
#endif
#ifdef CONFIG_SSL_HAS_PEM
case
SSL_HAS_PEM
:
return
1
;
#endif
default:
return
0
;
}
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Authenticate a received certificate.
*/
EXP_FUNC
int
STDCALL
ICACHE_FLASH_ATTR
ssl_verify_cert
(
const
SSL
*
ssl
)
{
int
ret
;
SSL_CTX_LOCK
(
ssl
->
ssl_ctx
->
mutex
);
ret
=
x509_verify
(
ssl
->
ssl_ctx
->
ca_cert_ctx
,
ssl
->
x509_ctx
);
SSL_CTX_UNLOCK
(
ssl
->
ssl_ctx
->
mutex
);
if
(
ret
)
/* modify into an SSL error type */
{
ret
=
SSL_X509_ERROR
(
ret
);
}
return
ret
;
}
/**
* Process a certificate message.
*/
int
ICACHE_FLASH_ATTR
process_certificate
(
SSL
*
ssl
,
X509_CTX
**
x509_ctx
)
{
int
ret
=
SSL_OK
;
uint8_t
*
buf
=
&
ssl
->
bm_data
[
ssl
->
dc
->
bm_proc_index
];
int
pkt_size
=
ssl
->
bm_index
;
int
cert_size
,
offset
=
5
;
int
total_cert_size
=
(
buf
[
offset
]
<<
8
)
+
buf
[
offset
+
1
];
int
is_client
=
IS_SET_SSL_FLAG
(
SSL_IS_CLIENT
);
X509_CTX
**
chain
=
x509_ctx
;
offset
+=
2
;
PARANOIA_CHECK
(
total_cert_size
,
offset
);
while
(
offset
<
total_cert_size
)
{
offset
++
;
/* skip empty char */
cert_size
=
(
buf
[
offset
]
<<
8
)
+
buf
[
offset
+
1
];
offset
+=
2
;
if
(
x509_new
(
&
buf
[
offset
],
NULL
,
chain
))
{
ret
=
SSL_ERROR_BAD_CERTIFICATE
;
goto
error
;
}
chain
=
&
((
*
chain
)
->
next
);
offset
+=
cert_size
;
}
PARANOIA_CHECK
(
pkt_size
,
offset
);
/* if we are client we can do the verify now or later */
if
(
is_client
&&
!
IS_SET_SSL_FLAG
(
SSL_SERVER_VERIFY_LATER
))
{
ret
=
ssl_verify_cert
(
ssl
);
}
ssl
->
next_state
=
is_client
?
HS_SERVER_HELLO_DONE
:
HS_CLIENT_KEY_XCHG
;
ssl
->
dc
->
bm_proc_index
+=
offset
;
error:
return
ret
;
}
#endif
/* CONFIG_SSL_CERT_VERIFICATION */
/**
* Debugging routine to display SSL handshaking stuff.
*/
#ifdef CONFIG_SSL_FULL_MODE
/**
* Debugging routine to display SSL states.
*/
#if 0
void ICACHE_FLASH_ATTR DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok)
{
const char *str;
if (!IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
return;
ssl_printf(not_ok ? "Error - invalid State:\t" : "State:\t");
ssl_printf(is_send ? "sending " : "receiving ");
switch (state)
{
case HS_HELLO_REQUEST:
str = "Hello Request (0)";
break;
case HS_CLIENT_HELLO:
str = "Client Hello (1)";
break;
case HS_SERVER_HELLO:
str = "Server Hello (2)";
break;
case HS_CERTIFICATE:
str = "Certificate (11)";
break;
case HS_SERVER_KEY_XCHG:
str = "Certificate Request (12)";
break;
case HS_CERT_REQ:
str = "Certificate Request (13)";
break;
case HS_SERVER_HELLO_DONE:
str = "Server Hello Done (14)";
break;
case HS_CERT_VERIFY:
str = "Certificate Verify (15)";
break;
case HS_CLIENT_KEY_XCHG:
str = "Client Key Exchange (16)";
break;
case HS_FINISHED:
str = "Finished (16)";
break;
default:
str = "Error (Unknown)";
break;
}
ssl_printf("%s\n", str);
//TTY_FLUSH();
}
/**
* Debugging routine to display RSA objects
*/
void ICACHE_FLASH_ATTR DISPLAY_RSA(SSL *ssl, const RSA_CTX *rsa_ctx)
{
if (!IS_SET_SSL_FLAG(SSL_DISPLAY_RSA))
return;
RSA_print(rsa_ctx);
//TTY_FLUSH();
}
/**
* Debugging routine to display SSL handshaking bytes.
*/
void ICACHE_FLASH_ATTR DISPLAY_BYTES(SSL *ssl, const char *format,
const uint8_t *data, int size, ...)
{
// wujg : pass compile first
// va_list(ap);
// if (!IS_SET_SSL_FLAG(SSL_DISPLAY_BYTES))
// return;
// va_start(ap, size);
// print_blob(format, data, size, va_arg(ap, char *));
// va_end(ap);
// TTY_FLUSH();
}
/**
* Debugging routine to display SSL handshaking errors.
*/
EXP_FUNC void STDCALL ICACHE_FLASH_ATTR ssl_display_error(int error_code)
{
if (error_code == SSL_OK)
return;
ssl_printf("Error: ");
/* X509 error? */
if (error_code < SSL_X509_OFFSET)
{
ssl_printf("%s\n", x509_display_error(error_code - SSL_X509_OFFSET));
return;
}
/* SSL alert error code */
if (error_code > SSL_ERROR_CONN_LOST)
{
ssl_printf("SSL error %d\n", -error_code);
return;
}
switch (error_code)
{
case SSL_ERROR_DEAD:
ssl_printf("connection dead");
break;
case SSL_ERROR_INVALID_HANDSHAKE:
ssl_printf("invalid handshake");
break;
case SSL_ERROR_INVALID_PROT_MSG:
ssl_printf("invalid protocol message");
break;
case SSL_ERROR_INVALID_HMAC:
ssl_printf("invalid mac");
break;
case SSL_ERROR_INVALID_VERSION:
ssl_printf("invalid version");
break;
case SSL_ERROR_INVALID_SESSION:
ssl_printf("invalid session");
break;
case SSL_ERROR_NO_CIPHER:
ssl_printf("no cipher");
break;
case SSL_ERROR_CONN_LOST:
ssl_printf("connection lost");
break;
case SSL_ERROR_BAD_CERTIFICATE:
ssl_printf("bad certificate");
break;
case SSL_ERROR_INVALID_KEY:
ssl_printf("invalid key");
break;
case SSL_ERROR_FINISHED_INVALID:
ssl_printf("finished invalid");
break;
case SSL_ERROR_NO_CERT_DEFINED:
ssl_printf("no certificate defined");
break;
case SSL_ERROR_NO_CLIENT_RENOG:
ssl_printf("client renegotiation not supported");
break;
case SSL_ERROR_NOT_SUPPORTED:
ssl_printf("Option not supported");
break;
default:
ssl_printf("undefined as yet - %d", error_code);
break;
}
ssl_printf("\n");
//TTY_FLUSH();
}
/**
* Debugging routine to display alerts.
*/
void ICACHE_FLASH_ATTR DISPLAY_ALERT(SSL *ssl, int alert)
{
if (!IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
return;
ssl_printf("Alert: ");
switch (alert)
{
case SSL_ALERT_CLOSE_NOTIFY:
ssl_printf("close notify");
break;
case SSL_ALERT_INVALID_VERSION:
ssl_printf("invalid version");
break;
case SSL_ALERT_BAD_CERTIFICATE:
ssl_printf("bad certificate");
break;
case SSL_ALERT_UNEXPECTED_MESSAGE:
ssl_printf("unexpected message");
break;
case SSL_ALERT_BAD_RECORD_MAC:
ssl_printf("bad record mac");
break;
case SSL_ALERT_HANDSHAKE_FAILURE:
ssl_printf("handshake failure");
break;
case SSL_ALERT_ILLEGAL_PARAMETER:
ssl_printf("illegal parameter");
break;
case SSL_ALERT_DECODE_ERROR:
ssl_printf("decode error");
break;
case SSL_ALERT_DECRYPT_ERROR:
ssl_printf("decrypt error");
break;
case SSL_ALERT_NO_RENEGOTIATION:
ssl_printf("no renegotiation");
break;
default:
ssl_printf("alert - (unknown %d)", alert);
break;
}
ssl_printf("\n");
//TTY_FLUSH();
}
#endif
#endif
/* CONFIG_SSL_FULL_MODE */
/**
* Return the version of this library.
*/
EXP_FUNC
const
char
*
STDCALL
ICACHE_FLASH_ATTR
ssl_version
()
{
static
const
char
*
axtls_version
=
AXTLS_VERSION
;
return
axtls_version
;
}
/**
* Enable the various language bindings to work regardless of the
* configuration - they just return an error statement and a bad return code.
*/
#if !defined(CONFIG_SSL_FULL_MODE)
EXP_FUNC
void
STDCALL
ssl_display_error
(
int
error_code
)
{}
#endif
#ifdef CONFIG_BINDINGS
#if !defined(CONFIG_SSL_ENABLE_CLIENT)
EXP_FUNC
SSL
*
STDCALL
ICACHE_FLASH_ATTR
ssl_client_new
(
SSL_CTX
*
ssl_ctx
,
int
client_fd
,
const
uint8_t
*
session_id
,
uint8_t
sess_id_size
)
{
ssl_printf
(
unsupported_str
);
return
NULL
;
}
#endif
#if !defined(CONFIG_SSL_CERT_VERIFICATION)
EXP_FUNC
int
STDCALL
ICACHE_FLASH_ATTR
ssl_verify_cert
(
const
SSL
*
ssl
)
{
ssl_printf
(
unsupported_str
);
return
-
1
;
}
EXP_FUNC
const
char
*
STDCALL
ICACHE_FLASH_ATTR
ssl_get_cert_dn
(
const
SSL
*
ssl
,
int
component
)
{
ssl_printf
(
unsupported_str
);
return
NULL
;
}
EXP_FUNC
const
char
*
STDCALL
ICACHE_FLASH_ATTR
ssl_get_cert_subject_alt_dnsname
(
const
SSL
*
ssl
,
int
index
)
{
ssl_printf
(
unsupported_str
);
return
NULL
;
}
#endif
/* CONFIG_SSL_CERT_VERIFICATION */
#endif
/* CONFIG_BINDINGS */
app/ssl/ssl/ssl_tls1_clnt.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.
*/
//#include <stdlib.h>
//#include <string.h>
//#include <time.h>
//#include <stdio.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_ssl.h"
#include "lwip/tcp.h"
#include "ssl/app/espconn_ssl.h"
#ifdef CONFIG_SSL_ENABLE_CLIENT
/* all commented out if no client */
static
int
send_client_hello
(
SSL
*
ssl
);
static
int
process_server_hello
(
SSL
*
ssl
);
static
int
process_server_hello_done
(
SSL
*
ssl
);
static
int
send_client_key_xchg
(
SSL
*
ssl
);
static
int
process_cert_req
(
SSL
*
ssl
);
static
int
send_cert_verify
(
SSL
*
ssl
);
#if 0
/*
* Establish a new SSL connection to an SSL server.
*/
EXP_FUNC SSL * STDCALL ICACHE_FLASH_ATTR ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const
uint8_t *session_id, uint8_t sess_id_size)
{
SSL *ssl = ssl_new(ssl_ctx, client_fd);
ssl->version = SSL_PROTOCOL_VERSION_MAX; /* try top version first */
if (session_id && ssl_ctx->num_sessions)
{
if (sess_id_size > SSL_SESSION_ID_SIZE) /* validity check */
{
ssl_free(ssl);
return NULL;
}
os_memcpy(ssl->session_id, session_id, sess_id_size);
ssl->sess_id_size = sess_id_size;
SET_SSL_FLAG(SSL_SESSION_RESUME); /* just flag for later */
}
SET_SSL_FLAG(SSL_IS_CLIENT);
do_client_connect(ssl);
return ssl;
}
#endif
/*
* Establish a new SSL connection to an SSL server.(raw api)add by ives 12.12.2013
*/
EXP_FUNC
SSL
*
STDCALL
ICACHE_FLASH_ATTR
SSLClient_new
(
SSL_CTX
*
ssl_ctx
,
struct
tcp_pcb
*
SslClient_pcb
,
const
uint8_t
*
session_id
,
uint8_t
sess_id_size
)
{
SSL
*
ssl
=
ssl_new_context
(
ssl_ctx
,
SslClient_pcb
);
ssl
->
version
=
SSL_PROTOCOL_VERSION_MAX
;
if
(
session_id
&&
ssl_ctx
->
num_sessions
)
{
if
(
sess_id_size
>
SSL_SESSION_ID_SIZE
)
{
ssl_free
(
ssl
);
return
NULL
;
}
os_memcpy
(
ssl
->
session_id
,
session_id
,
sess_id_size
);
ssl
->
sess_id_size
=
sess_id_size
;
SET_SSL_FLAG
(
SSL_SESSION_RESUME
);
}
SET_SSL_FLAG
(
SSL_IS_CLIENT
);
do_client_connect
(
ssl
);
return
ssl
;
}
/*
* Process the handshake record.
*/
int
ICACHE_FLASH_ATTR
do_clnt_handshake
(
SSL
*
ssl
,
int
handshake_type
,
uint8_t
*
buf
,
int
hs_len
)
{
int
ret
;
/* To get here the state must be valid */
// ssl_printf("do_clnt_handshake: %d %d\n",__LINE__, handshake_type);
switch
(
handshake_type
)
{
case
HS_SERVER_HELLO
:
ret
=
process_server_hello
(
ssl
);
break
;
case
HS_CERTIFICATE
:
ret
=
process_certificate
(
ssl
,
&
ssl
->
x509_ctx
);
break
;
case
HS_SERVER_HELLO_DONE
:
if
((
ret
=
process_server_hello_done
(
ssl
))
==
SSL_OK
)
{
if
(
IS_SET_SSL_FLAG
(
SSL_HAS_CERT_REQ
))
{
if
((
ret
=
send_certificate
(
ssl
))
==
SSL_OK
&&
(
ret
=
send_client_key_xchg
(
ssl
))
==
SSL_OK
)
{
send_cert_verify
(
ssl
);
}
}
else
{
ret
=
send_client_key_xchg
(
ssl
);
}
if
(
ret
==
SSL_OK
&&
(
ret
=
send_change_cipher_spec
(
ssl
))
==
SSL_OK
)
{
ret
=
send_finished
(
ssl
);
}
}
break
;
case
HS_CERT_REQ
:
ret
=
process_cert_req
(
ssl
);
break
;
case
HS_FINISHED
:
ret
=
process_finished
(
ssl
,
buf
,
hs_len
);
disposable_free
(
ssl
);
/* free up some memory */
/* note: client renegotiation is not allowed after this */
break
;
case
HS_HELLO_REQUEST
:
disposable_new
(
ssl
);
ret
=
do_client_connect
(
ssl
);
break
;
default:
ret
=
SSL_ERROR_INVALID_HANDSHAKE
;
break
;
}
return
ret
;
}
/*
* Do the handshaking from the beginning.
*/
int
ICACHE_FLASH_ATTR
do_client_connect
(
SSL
*
ssl
)
{
int
ret
=
SSL_OK
;
send_client_hello
(
ssl
);
/* send the client hello */
ssl
->
bm_read_index
=
0
;
ssl
->
next_state
=
HS_SERVER_HELLO
;
ssl
->
hs_status
=
SSL_NOT_OK
;
/* not connected */
#if 0
/* sit in a loop until it all looks good */
if (!IS_SET_SSL_FLAG(SSL_CONNECT_IN_PARTS))
{
while (ssl->hs_status != SSL_OK)
{
ret = ssl_read(ssl, NULL);
ssl_printf("%s %d %d\n", __func__, __LINE__,ret);
if (ret < SSL_OK)
break;
}
ssl->hs_status = ret; /* connected? */
}
#endif
return
ret
;
}
/*
* Send the initial client hello.
*/
static
int
ICACHE_FLASH_ATTR
send_client_hello
(
SSL
*
ssl
)
{
uint8_t
*
buf
=
ssl
->
bm_data
;
time_t
tm
=
0
;
//time(NULL); wujg : pass compile first
uint8_t
*
tm_ptr
=
&
buf
[
6
];
/* time will go here */
int
i
,
offset
;
buf
[
0
]
=
HS_CLIENT_HELLO
;
buf
[
1
]
=
0
;
buf
[
2
]
=
0
;
/* byte 3 is calculated later */
buf
[
4
]
=
0x03
;
buf
[
5
]
=
ssl
->
version
&
0x0f
;
/* client random value - spec says that 1st 4 bytes are big endian time */
*
tm_ptr
++
=
(
uint8_t
)(((
long
)
tm
&
0xff000000
)
>>
24
);
*
tm_ptr
++
=
(
uint8_t
)(((
long
)
tm
&
0x00ff0000
)
>>
16
);
*
tm_ptr
++
=
(
uint8_t
)(((
long
)
tm
&
0x0000ff00
)
>>
8
);
*
tm_ptr
++
=
(
uint8_t
)(((
long
)
tm
&
0x000000ff
));
get_random
(
SSL_RANDOM_SIZE
-
4
,
&
buf
[
10
]);
os_memcpy
(
ssl
->
dc
->
client_random
,
&
buf
[
6
],
SSL_RANDOM_SIZE
);
offset
=
6
+
SSL_RANDOM_SIZE
;
/* give session resumption a go */
if
(
IS_SET_SSL_FLAG
(
SSL_SESSION_RESUME
))
/* set initially by user */
{
buf
[
offset
++
]
=
ssl
->
sess_id_size
;
os_memcpy
(
&
buf
[
offset
],
ssl
->
session_id
,
ssl
->
sess_id_size
);
offset
+=
ssl
->
sess_id_size
;
CLR_SSL_FLAG
(
SSL_SESSION_RESUME
);
/* clear so we can set later */
}
else
{
/* no session id - because no session resumption just yet */
buf
[
offset
++
]
=
0
;
}
buf
[
offset
++
]
=
0
;
/* number of ciphers */
buf
[
offset
++
]
=
NUM_PROTOCOLS
*
2
;
/* number of ciphers */
/* put all our supported protocols in our request */
for
(
i
=
0
;
i
<
NUM_PROTOCOLS
;
i
++
)
{
buf
[
offset
++
]
=
0
;
/* cipher we are using */
buf
[
offset
++
]
=
ssl_prot_prefs
[
i
];
}
buf
[
offset
++
]
=
1
;
/* no compression */
buf
[
offset
++
]
=
0
;
buf
[
3
]
=
offset
-
4
;
/* handshake size */
return
send_packet
(
ssl
,
PT_HANDSHAKE_PROTOCOL
,
NULL
,
offset
);
}
/*
* Process the server hello.
*/
static
int
ICACHE_FLASH_ATTR
process_server_hello
(
SSL
*
ssl
)
{
uint8_t
*
buf
=
ssl
->
bm_data
;
int
pkt_size
=
ssl
->
bm_index
;
int
num_sessions
=
ssl
->
ssl_ctx
->
num_sessions
;
uint8_t
sess_id_size
;
int
offset
,
ret
=
SSL_OK
;
/* check that we are talking to a TLSv1 server */
uint8_t
version
=
(
buf
[
4
]
<<
4
)
+
buf
[
5
];
if
(
version
>
SSL_PROTOCOL_VERSION_MAX
)
{
version
=
SSL_PROTOCOL_VERSION_MAX
;
}
else
if
(
ssl
->
version
<
SSL_PROTOCOL_MIN_VERSION
)
{
ret
=
SSL_ERROR_INVALID_VERSION
;
//ssl_display_error(ret);
goto
error
;
}
ssl
->
version
=
version
;
/* get the server random value */
os_memcpy
(
ssl
->
dc
->
server_random
,
&
buf
[
6
],
SSL_RANDOM_SIZE
);
offset
=
6
+
SSL_RANDOM_SIZE
;
/* skip of session id size */
sess_id_size
=
buf
[
offset
++
];
if
(
sess_id_size
>
SSL_SESSION_ID_SIZE
)
{
ret
=
SSL_ERROR_INVALID_SESSION
;
goto
error
;
}
if
(
num_sessions
)
{
ssl
->
session
=
ssl_session_update
(
num_sessions
,
ssl
->
ssl_ctx
->
ssl_sessions
,
ssl
,
&
buf
[
offset
]);
os_memcpy
(
ssl
->
session
->
session_id
,
&
buf
[
offset
],
sess_id_size
);
/* pad the rest with 0's */
if
(
sess_id_size
<
SSL_SESSION_ID_SIZE
)
{
os_memset
(
&
ssl
->
session
->
session_id
[
sess_id_size
],
0
,
SSL_SESSION_ID_SIZE
-
sess_id_size
);
}
}
os_memcpy
(
ssl
->
session_id
,
&
buf
[
offset
],
sess_id_size
);
ssl
->
sess_id_size
=
sess_id_size
;
offset
+=
sess_id_size
;
/* get the real cipher we are using */
ssl
->
cipher
=
buf
[
++
offset
];
ssl
->
next_state
=
IS_SET_SSL_FLAG
(
SSL_SESSION_RESUME
)
?
HS_FINISHED
:
HS_CERTIFICATE
;
offset
++
;
// skip the compr
PARANOIA_CHECK
(
pkt_size
,
offset
);
ssl
->
dc
->
bm_proc_index
=
offset
+
1
;
error:
return
ret
;
}
/**
* Process the server hello done message.
*/
static
int
ICACHE_FLASH_ATTR
process_server_hello_done
(
SSL
*
ssl
)
{
ssl
->
next_state
=
HS_FINISHED
;
return
SSL_OK
;
}
/*
* Send a client key exchange message.
*/
static
int
ICACHE_FLASH_ATTR
send_client_key_xchg
(
SSL
*
ssl
)
{
uint8_t
*
buf
=
ssl
->
bm_data
;
uint8_t
premaster_secret
[
SSL_SECRET_SIZE
];
int
enc_secret_size
=
-
1
;
buf
[
0
]
=
HS_CLIENT_KEY_XCHG
;
buf
[
1
]
=
0
;
premaster_secret
[
0
]
=
0x03
;
/* encode the version number */
premaster_secret
[
1
]
=
SSL_PROTOCOL_MINOR_VERSION
;
/* must be TLS 1.1 */
get_random
(
SSL_SECRET_SIZE
-
2
,
&
premaster_secret
[
2
]);
//DISPLAY_RSA(ssl, ssl->x509_ctx->rsa_ctx);
/* rsa_ctx->bi_ctx is not thread-safe */
SSL_CTX_LOCK
(
ssl
->
ssl_ctx
->
mutex
);
enc_secret_size
=
RSA_encrypt
(
ssl
->
x509_ctx
->
rsa_ctx
,
premaster_secret
,
SSL_SECRET_SIZE
,
&
buf
[
6
],
0
);
SSL_CTX_UNLOCK
(
ssl
->
ssl_ctx
->
mutex
);
buf
[
2
]
=
(
enc_secret_size
+
2
)
>>
8
;
buf
[
3
]
=
(
enc_secret_size
+
2
)
&
0xff
;
buf
[
4
]
=
enc_secret_size
>>
8
;
buf
[
5
]
=
enc_secret_size
&
0xff
;
generate_master_secret
(
ssl
,
premaster_secret
);
return
send_packet
(
ssl
,
PT_HANDSHAKE_PROTOCOL
,
NULL
,
enc_secret_size
+
6
);
}
/*
* Process the certificate request.
*/
static
int
ICACHE_FLASH_ATTR
process_cert_req
(
SSL
*
ssl
)
{
uint8_t
*
buf
=
&
ssl
->
bm_data
[
ssl
->
dc
->
bm_proc_index
];
int
ret
=
SSL_OK
;
int
offset
=
(
buf
[
2
]
<<
4
)
+
buf
[
3
];
int
pkt_size
=
ssl
->
bm_index
;
/* don't do any processing - we will send back an RSA certificate anyway */
ssl
->
next_state
=
HS_SERVER_HELLO_DONE
;
SET_SSL_FLAG
(
SSL_HAS_CERT_REQ
);
ssl
->
dc
->
bm_proc_index
+=
offset
;
PARANOIA_CHECK
(
pkt_size
,
offset
);
error:
return
ret
;
}
/*
* Send a certificate verify message.
*/
static
int
ICACHE_FLASH_ATTR
send_cert_verify
(
SSL
*
ssl
)
{
uint8_t
*
buf
=
ssl
->
bm_data
;
uint8_t
dgst
[
MD5_SIZE
+
SHA1_SIZE
];
RSA_CTX
*
rsa_ctx
=
ssl
->
ssl_ctx
->
rsa_ctx
;
int
n
=
0
,
ret
;
//DISPLAY_RSA(ssl, rsa_ctx);
buf
[
0
]
=
HS_CERT_VERIFY
;
buf
[
1
]
=
0
;
finished_digest
(
ssl
,
NULL
,
dgst
);
/* calculate the digest */
/* rsa_ctx->bi_ctx is not thread-safe */
if
(
rsa_ctx
)
{
SSL_CTX_LOCK
(
ssl
->
ssl_ctx
->
mutex
);
n
=
RSA_encrypt
(
rsa_ctx
,
dgst
,
sizeof
(
dgst
),
&
buf
[
6
],
1
);
SSL_CTX_UNLOCK
(
ssl
->
ssl_ctx
->
mutex
);
if
(
n
==
0
)
{
ret
=
SSL_ERROR_INVALID_KEY
;
goto
error
;
}
}
buf
[
4
]
=
n
>>
8
;
/* add the RSA size (not officially documented) */
buf
[
5
]
=
n
&
0xff
;
n
+=
2
;
buf
[
2
]
=
n
>>
8
;
buf
[
3
]
=
n
&
0xff
;
ret
=
send_packet
(
ssl
,
PT_HANDSHAKE_PROTOCOL
,
NULL
,
n
+
4
);
error:
return
ret
;
}
#endif
/* CONFIG_SSL_ENABLE_CLIENT */
app/ssl/ssl/ssl_tls1_svr.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.
*/
//#include <stdlib.h>
//#include <string.h>
//#include <stdio.h>
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_ssl.h"
//#include "../httpd/axhttp.h"
#include "ssl/app/espconn_ssl.h"
static
const
uint8_t
g_hello_done
[]
=
{
HS_SERVER_HELLO_DONE
,
0
,
0
,
0
};
static
int
process_client_hello
(
SSL
*
ssl
);
static
int
send_server_hello_sequence
(
SSL
*
ssl
);
static
int
send_server_hello
(
SSL
*
ssl
);
static
int
send_server_hello_done
(
SSL
*
ssl
);
static
int
process_client_key_xchg
(
SSL
*
ssl
);
#ifdef CONFIG_SSL_CERT_VERIFICATION
static
int
send_certificate_request
(
SSL
*
ssl
);
static
int
process_cert_verify
(
SSL
*
ssl
);
#endif
#if 0
/*
* Establish a new SSL connection to an SSL client.
*/
EXP_FUNC SSL * STDCALL ICACHE_FLASH_ATTR ssl_server_new(SSL_CTX *ssl_ctx, int client_fd)
{
SSL *ssl;
ssl = ssl_new(ssl_ctx, client_fd);
ssl->next_state = HS_CLIENT_HELLO;
#ifdef CONFIG_SSL_FULL_MODE
if (ssl_ctx->chain_length == 0)
ssl_printf("Warning - no server certificate defined\n"); TTY_FLUSH();
#endif
return ssl;
}
#endif
/*
* Establish a new SSL connection to an SSL client.(raw api)add by ives 12.19.2013
*/
EXP_FUNC
SSL
*
STDCALL
ICACHE_FLASH_ATTR
sslserver_new
(
SSL_CTX
*
ssl_ctx
,
struct
tcp_pcb
*
client_pcb
)
{
SSL
*
ssl
;
ssl
=
ssl_new_context
(
ssl_ctx
,
client_pcb
);
ssl
->
next_state
=
HS_CLIENT_HELLO
;
#ifdef CONFIG_SSL_FULL_MODE
if
(
ssl_ctx
->
chain_length
==
0
)
ssl_printf
(
"Warning - no server certificate defined
\n
"
);
//TTY_FLUSH();
#endif
return
ssl
;
}
/*
* Process the handshake record.
*/
int
ICACHE_FLASH_ATTR
do_svr_handshake
(
SSL
*
ssl
,
int
handshake_type
,
uint8_t
*
buf
,
int
hs_len
)
{
int
ret
=
SSL_OK
;
ssl
->
hs_status
=
SSL_NOT_OK
;
/* not connected */
/* To get here the state must be valid */
// ssl_printf("%d %s %d\n",handshake_type, __func__, __LINE__);
switch
(
handshake_type
)
{
case
HS_CLIENT_HELLO
:
if
((
ret
=
process_client_hello
(
ssl
))
==
SSL_OK
)
ret
=
send_server_hello_sequence
(
ssl
);
break
;
#ifdef CONFIG_SSL_CERT_VERIFICATION
case
HS_CERTIFICATE
:
/* the client sends its cert */
ret
=
process_certificate
(
ssl
,
&
ssl
->
x509_ctx
);
if
(
ret
==
SSL_OK
)
/* verify the cert */
{
int
cert_res
;
cert_res
=
x509_verify
(
ssl
->
ssl_ctx
->
ca_cert_ctx
,
ssl
->
x509_ctx
);
ret
=
(
cert_res
==
0
)
?
SSL_OK
:
SSL_X509_ERROR
(
cert_res
);
}
break
;
case
HS_CERT_VERIFY
:
ret
=
process_cert_verify
(
ssl
);
add_packet
(
ssl
,
buf
,
hs_len
);
/* needs to be done after */
break
;
#endif
case
HS_CLIENT_KEY_XCHG
:
ret
=
process_client_key_xchg
(
ssl
);
break
;
case
HS_FINISHED
:
ret
=
process_finished
(
ssl
,
buf
,
hs_len
);
disposable_free
(
ssl
);
/* free up some memory */
break
;
}
return
ret
;
}
/*
* Process a client hello message.
*/
static
int
ICACHE_FLASH_ATTR
process_client_hello
(
SSL
*
ssl
)
{
uint8_t
*
buf
=
ssl
->
bm_data
;
uint8_t
*
record_buf
=
ssl
->
hmac_header
;
int
pkt_size
=
ssl
->
bm_index
;
int
i
,
j
,
cs_len
,
id_len
,
offset
=
6
+
SSL_RANDOM_SIZE
;
int
ret
=
SSL_OK
;
uint8_t
version
=
(
buf
[
4
]
<<
4
)
+
buf
[
5
];
ssl
->
version
=
ssl
->
client_version
=
version
;
if
(
version
>
SSL_PROTOCOL_VERSION_MAX
)
{
/* use client's version instead */
ssl
->
version
=
SSL_PROTOCOL_VERSION_MAX
;
}
else
if
(
version
<
SSL_PROTOCOL_MIN_VERSION
)
/* old version supported? */
{
ret
=
SSL_ERROR_INVALID_VERSION
;
//ssl_display_error(ret);
goto
error
;
}
os_memcpy
(
ssl
->
dc
->
client_random
,
&
buf
[
6
],
SSL_RANDOM_SIZE
);
/* process the session id */
id_len
=
buf
[
offset
++
];
if
(
id_len
>
SSL_SESSION_ID_SIZE
)
{
return
SSL_ERROR_INVALID_SESSION
;
}
#ifndef CONFIG_SSL_SKELETON_MODE
ssl
->
session
=
ssl_session_update
(
ssl
->
ssl_ctx
->
num_sessions
,
ssl
->
ssl_ctx
->
ssl_sessions
,
ssl
,
id_len
?
&
buf
[
offset
]
:
NULL
);
#endif
offset
+=
id_len
;
cs_len
=
(
buf
[
offset
]
<<
8
)
+
buf
[
offset
+
1
];
offset
+=
2
;
/* add 1 due to all cipher suites being 8 bit */
PARANOIA_CHECK
(
pkt_size
,
offset
);
/* work out what cipher suite we are going to use - client defines
the preference */
for
(
i
=
0
;
i
<
cs_len
;
i
+=
2
)
{
for
(
j
=
0
;
j
<
NUM_PROTOCOLS
;
j
++
)
{
if
(
ssl_prot_prefs
[
j
]
==
((
buf
[
offset
+
i
]
<<
8
)
+
buf
[
offset
+
i
+
1
]))
/* got a match? */
{
ssl
->
cipher
=
ssl_prot_prefs
[
j
];
goto
do_state
;
}
}
}
/* ouch! protocol is not supported */
ret
=
SSL_ERROR_NO_CIPHER
;
do_state:
error:
return
ret
;
}
#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
/*
* Some browsers use a hybrid SSLv2 "client hello"
*/
int
process_sslv23_client_hello
(
SSL
*
ssl
)
{
uint8_t
*
buf
=
ssl
->
bm_data
;
int
bytes_needed
=
((
buf
[
0
]
&
0x7f
)
<<
8
)
+
buf
[
1
];
int
ret
=
SSL_OK
;
/* we have already read 3 extra bytes so far */
// int read_len = SOCKET_READ(ssl->client_fd, buf, bytes_needed-3);
int
read_len
=
pbuf_copy_partial
(
ssl
->
ssl_pbuf
,
buf
,
bytes_needed
-
3
,
0
);
int
cs_len
=
buf
[
1
];
int
id_len
=
buf
[
3
];
int
ch_len
=
buf
[
5
];
int
i
,
j
,
offset
=
8
;
/* start at first cipher */
int
random_offset
=
0
;
DISPLAY_BYTES
(
ssl
,
"received %d bytes"
,
buf
,
read_len
,
read_len
);
add_packet
(
ssl
,
buf
,
read_len
);
/* connection has gone, so die */
if
(
bytes_needed
<
0
)
{
return
SSL_ERROR_CONN_LOST
;
}
/* now work out what cipher suite we are going to use */
for
(
j
=
0
;
j
<
NUM_PROTOCOLS
;
j
++
)
{
for
(
i
=
0
;
i
<
cs_len
;
i
+=
3
)
{
if
(
ssl_prot_prefs
[
j
]
==
buf
[
offset
+
i
])
{
ssl
->
cipher
=
ssl_prot_prefs
[
j
];
goto
server_hello
;
}
}
}
/* ouch! protocol is not supported */
ret
=
SSL_ERROR_NO_CIPHER
;
goto
error
;
server_hello:
/* get the session id */
offset
+=
cs_len
-
2
;
/* we've gone 2 bytes past the end */
#ifndef CONFIG_SSL_SKELETON_MODE
ssl
->
session
=
ssl_session_update
(
ssl
->
ssl_ctx
->
num_sessions
,
ssl
->
ssl_ctx
->
ssl_sessions
,
ssl
,
id_len
?
&
buf
[
offset
]
:
NULL
);
#endif
/* get the client random data */
offset
+=
id_len
;
/* random can be anywhere between 16 and 32 bytes long - so it is padded
* with 0's to the left */
if
(
ch_len
==
0x10
)
{
random_offset
+=
0x10
;
}
memcpy
(
&
ssl
->
dc
->
client_random
[
random_offset
],
&
buf
[
offset
],
ch_len
);
ret
=
send_server_hello_sequence
(
ssl
);
error:
return
ret
;
}
#endif
/*
* Send the entire server hello sequence
*/
static
int
ICACHE_FLASH_ATTR
send_server_hello_sequence
(
SSL
*
ssl
)
{
int
ret
;
if
((
ret
=
send_server_hello
(
ssl
))
==
SSL_OK
)
{
#ifndef CONFIG_SSL_SKELETON_MODE
/* resume handshake? */
if
(
IS_SET_SSL_FLAG
(
SSL_SESSION_RESUME
))
{
if
((
ret
=
send_change_cipher_spec
(
ssl
))
==
SSL_OK
)
{
ret
=
send_finished
(
ssl
);
ssl
->
next_state
=
HS_FINISHED
;
}
}
else
#endif
if
((
ret
=
send_certificate
(
ssl
))
==
SSL_OK
)
{
#ifdef CONFIG_SSL_CERT_VERIFICATION
/* ask the client for its certificate */
if
(
IS_SET_SSL_FLAG
(
SSL_CLIENT_AUTHENTICATION
))
{
if
((
ret
=
send_certificate_request
(
ssl
))
==
SSL_OK
)
{
ret
=
send_server_hello_done
(
ssl
);
ssl
->
next_state
=
HS_CERTIFICATE
;
}
}
else
#endif
{
ret
=
send_server_hello_done
(
ssl
);
ssl
->
next_state
=
HS_CLIENT_KEY_XCHG
;
}
}
}
return
ret
;
}
/*
* Send a server hello message.
*/
static
int
ICACHE_FLASH_ATTR
send_server_hello
(
SSL
*
ssl
)
{
uint8_t
*
buf
=
ssl
->
bm_data
;
int
offset
=
0
;
buf
[
0
]
=
HS_SERVER_HELLO
;
buf
[
1
]
=
0
;
buf
[
2
]
=
0
;
/* byte 3 is calculated later */
buf
[
4
]
=
0x03
;
buf
[
5
]
=
ssl
->
version
&
0x0f
;
/* server random value */
get_random
(
SSL_RANDOM_SIZE
,
&
buf
[
6
]);
os_memcpy
(
ssl
->
dc
->
server_random
,
&
buf
[
6
],
SSL_RANDOM_SIZE
);
offset
=
6
+
SSL_RANDOM_SIZE
;
#ifndef CONFIG_SSL_SKELETON_MODE
if
(
IS_SET_SSL_FLAG
(
SSL_SESSION_RESUME
))
{
/* retrieve id from session cache */
buf
[
offset
++
]
=
SSL_SESSION_ID_SIZE
;
os_memcpy
(
&
buf
[
offset
],
ssl
->
session
->
session_id
,
SSL_SESSION_ID_SIZE
);
os_memcpy
(
ssl
->
session_id
,
ssl
->
session
->
session_id
,
SSL_SESSION_ID_SIZE
);
ssl
->
sess_id_size
=
SSL_SESSION_ID_SIZE
;
offset
+=
SSL_SESSION_ID_SIZE
;
}
else
/* generate our own session id */
#endif
{
#ifndef CONFIG_SSL_SKELETON_MODE
buf
[
offset
++
]
=
SSL_SESSION_ID_SIZE
;
get_random
(
SSL_SESSION_ID_SIZE
,
&
buf
[
offset
]);
os_memcpy
(
ssl
->
session_id
,
&
buf
[
offset
],
SSL_SESSION_ID_SIZE
);
ssl
->
sess_id_size
=
SSL_SESSION_ID_SIZE
;
/* store id in session cache */
if
(
ssl
->
ssl_ctx
->
num_sessions
)
{
os_memcpy
(
ssl
->
session
->
session_id
,
ssl
->
session_id
,
SSL_SESSION_ID_SIZE
);
}
offset
+=
SSL_SESSION_ID_SIZE
;
#else
buf
[
offset
++
]
=
0
;
/* don't bother with session id in skelton mode */
#endif
}
buf
[
offset
++
]
=
0
;
/* cipher we are using */
buf
[
offset
++
]
=
ssl
->
cipher
;
buf
[
offset
++
]
=
0
;
/* no compression */
buf
[
3
]
=
offset
-
4
;
/* handshake size */
return
send_packet
(
ssl
,
PT_HANDSHAKE_PROTOCOL
,
NULL
,
offset
);
}
/*
* Send the server hello done message.
*/
static
int
ICACHE_FLASH_ATTR
send_server_hello_done
(
SSL
*
ssl
)
{
return
send_packet
(
ssl
,
PT_HANDSHAKE_PROTOCOL
,
g_hello_done
,
sizeof
(
g_hello_done
));
}
/*
* Pull apart a client key exchange message. Decrypt the pre-master key (using
* our RSA private key) and then work out the master key. Initialise the
* ciphers.
*/
static
int
ICACHE_FLASH_ATTR
process_client_key_xchg
(
SSL
*
ssl
)
{
uint8_t
*
buf
=
&
ssl
->
bm_data
[
ssl
->
dc
->
bm_proc_index
];
int
pkt_size
=
ssl
->
bm_index
;
int
premaster_size
,
secret_length
=
(
buf
[
2
]
<<
8
)
+
buf
[
3
];
uint8_t
premaster_secret
[
MAX_KEY_BYTE_SIZE
];
RSA_CTX
*
rsa_ctx
=
ssl
->
ssl_ctx
->
rsa_ctx
;
int
offset
=
4
;
int
ret
=
SSL_OK
;
if
(
rsa_ctx
==
NULL
)
{
ret
=
SSL_ERROR_NO_CERT_DEFINED
;
goto
error
;
}
/* is there an extra size field? */
if
((
secret_length
-
2
)
==
rsa_ctx
->
num_octets
)
offset
+=
2
;
PARANOIA_CHECK
(
pkt_size
,
rsa_ctx
->
num_octets
+
offset
);
/* rsa_ctx->bi_ctx is not thread-safe */
SSL_CTX_LOCK
(
ssl
->
ssl_ctx
->
mutex
);
premaster_size
=
RSA_decrypt
(
rsa_ctx
,
&
buf
[
offset
],
premaster_secret
,
1
);
SSL_CTX_UNLOCK
(
ssl
->
ssl_ctx
->
mutex
);
if
(
premaster_size
!=
SSL_SECRET_SIZE
||
premaster_secret
[
0
]
!=
0x03
||
/* must be the same as client
offered version */
premaster_secret
[
1
]
!=
(
ssl
->
client_version
&
0x0f
))
{
/* guard against a Bleichenbacher attack */
get_random
(
SSL_SECRET_SIZE
,
premaster_secret
);
/* and continue - will die eventually when checking the mac */
}
#if 0
print_blob("pre-master", premaster_secret, SSL_SECRET_SIZE);
#endif
generate_master_secret
(
ssl
,
premaster_secret
);
#ifdef CONFIG_SSL_CERT_VERIFICATION
ssl
->
next_state
=
IS_SET_SSL_FLAG
(
SSL_CLIENT_AUTHENTICATION
)
?
HS_CERT_VERIFY
:
HS_FINISHED
;
#else
ssl
->
next_state
=
HS_FINISHED
;
#endif
ssl
->
dc
->
bm_proc_index
+=
rsa_ctx
->
num_octets
+
offset
;
error:
return
ret
;
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
static
const
uint8_t
g_cert_request
[]
=
{
HS_CERT_REQ
,
0
,
0
,
4
,
1
,
0
,
0
,
0
};
/*
* Send the certificate request message.
*/
static
int
ICACHE_FLASH_ATTR
send_certificate_request
(
SSL
*
ssl
)
{
return
send_packet
(
ssl
,
PT_HANDSHAKE_PROTOCOL
,
g_cert_request
,
sizeof
(
g_cert_request
));
}
/*
* Ensure the client has the private key by first decrypting the packet and
* then checking the packet digests.
*/
static
int
ICACHE_FLASH_ATTR
process_cert_verify
(
SSL
*
ssl
)
{
uint8_t
*
buf
=
&
ssl
->
bm_data
[
ssl
->
dc
->
bm_proc_index
];
int
pkt_size
=
ssl
->
bm_index
;
uint8_t
dgst_buf
[
MAX_KEY_BYTE_SIZE
];
uint8_t
dgst
[
MD5_SIZE
+
SHA1_SIZE
];
X509_CTX
*
x509_ctx
=
ssl
->
x509_ctx
;
int
ret
=
SSL_OK
;
int
n
;
PARANOIA_CHECK
(
pkt_size
,
x509_ctx
->
rsa_ctx
->
num_octets
+
6
);
//DISPLAY_RSA(ssl, x509_ctx->rsa_ctx);
/* rsa_ctx->bi_ctx is not thread-safe */
SSL_CTX_LOCK
(
ssl
->
ssl_ctx
->
mutex
);
n
=
RSA_decrypt
(
x509_ctx
->
rsa_ctx
,
&
buf
[
6
],
dgst_buf
,
0
);
SSL_CTX_UNLOCK
(
ssl
->
ssl_ctx
->
mutex
);
if
(
n
!=
SHA1_SIZE
+
MD5_SIZE
)
{
ret
=
SSL_ERROR_INVALID_KEY
;
goto
end_cert_vfy
;
}
finished_digest
(
ssl
,
NULL
,
dgst
);
/* calculate the digest */
if
(
os_memcmp
(
dgst_buf
,
dgst
,
MD5_SIZE
+
SHA1_SIZE
))
{
ret
=
SSL_ERROR_INVALID_KEY
;
}
end_cert_vfy:
ssl
->
next_state
=
HS_FINISHED
;
error:
return
ret
;
}
#endif
app/ssl/ssl/ssl_x509.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.
*/
/**
* @file x509.c
*
* Certificate processing.
*/
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//#include <time.h>
#include "ssl/app/espconn_ssl.h"
#include "ssl/ssl_os_port.h"
#include "ssl/ssl_crypto_misc.h"
//#include "os.h"
#include "lwip/mem.h"
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Retrieve the signature from a certificate.
*/
static
const
uint8_t
*
ICACHE_FLASH_ATTR
get_signature
(
const
uint8_t
*
asn1_sig
,
int
*
len
)
{
int
offset
=
0
;
const
uint8_t
*
ptr
=
NULL
;
if
(
asn1_next_obj
(
asn1_sig
,
&
offset
,
ASN1_SEQUENCE
)
<
0
||
asn1_skip_obj
(
asn1_sig
,
&
offset
,
ASN1_SEQUENCE
))
goto
end_get_sig
;
if
(
asn1_sig
[
offset
++
]
!=
ASN1_OCTET_STRING
)
goto
end_get_sig
;
*
len
=
get_asn1_length
(
asn1_sig
,
&
offset
);
ptr
=
&
asn1_sig
[
offset
];
/* all ok */
end_get_sig:
return
ptr
;
}
#endif
/**
* Construct a new x509 object.
* @return 0 if ok. < 0 if there was a problem.
*/
int
ICACHE_FLASH_ATTR
x509_new
(
const
uint8_t
*
cert
,
int
*
len
,
X509_CTX
**
ctx
)
{
int
begin_tbs
,
end_tbs
;
int
ret
=
X509_NOT_OK
,
offset
=
0
,
cert_size
=
0
;
X509_CTX
*
x509_ctx
;
BI_CTX
*
bi_ctx
;
*
ctx
=
(
X509_CTX
*
)
os_zalloc
(
sizeof
(
X509_CTX
));
x509_ctx
=
*
ctx
;
/* get the certificate size */
asn1_skip_obj
(
cert
,
&
cert_size
,
ASN1_SEQUENCE
);
if
(
asn1_next_obj
(
cert
,
&
offset
,
ASN1_SEQUENCE
)
<
0
)
goto
end_cert
;
begin_tbs
=
offset
;
/* start of the tbs */
end_tbs
=
begin_tbs
;
/* work out the end of the tbs */
asn1_skip_obj
(
cert
,
&
end_tbs
,
ASN1_SEQUENCE
);
if
(
asn1_next_obj
(
cert
,
&
offset
,
ASN1_SEQUENCE
)
<
0
)
goto
end_cert
;
if
(
cert
[
offset
]
==
ASN1_EXPLICIT_TAG
)
/* optional version */
{
if
(
asn1_version
(
cert
,
&
offset
,
x509_ctx
))
goto
end_cert
;
}
if
(
asn1_skip_obj
(
cert
,
&
offset
,
ASN1_INTEGER
)
||
/* serial number */
asn1_next_obj
(
cert
,
&
offset
,
ASN1_SEQUENCE
)
<
0
)
goto
end_cert
;
/* make sure the signature is ok */
if
(
asn1_signature_type
(
cert
,
&
offset
,
x509_ctx
))
{
ret
=
X509_VFY_ERROR_UNSUPPORTED_DIGEST
;
goto
end_cert
;
}
if
(
asn1_name
(
cert
,
&
offset
,
x509_ctx
->
ca_cert_dn
)
||
asn1_validity
(
cert
,
&
offset
,
x509_ctx
)
||
asn1_name
(
cert
,
&
offset
,
x509_ctx
->
cert_dn
)
||
asn1_public_key
(
cert
,
&
offset
,
x509_ctx
))
{
goto
end_cert
;
}
bi_ctx
=
x509_ctx
->
rsa_ctx
->
bi_ctx
;
#ifdef CONFIG_SSL_CERT_VERIFICATION
/* only care if doing verification */
/* use the appropriate signature algorithm (SHA1/MD5/MD2) */
if
(
x509_ctx
->
sig_type
==
SIG_TYPE_MD5
)
{
MD5_CTX
md5_ctx
;
uint8_t
md5_dgst
[
MD5_SIZE
];
MD5_Init
(
&
md5_ctx
);
MD5_Update
(
&
md5_ctx
,
&
cert
[
begin_tbs
],
end_tbs
-
begin_tbs
);
MD5_Final
(
md5_dgst
,
&
md5_ctx
);
x509_ctx
->
digest
=
bi_import
(
bi_ctx
,
md5_dgst
,
MD5_SIZE
);
}
else
if
(
x509_ctx
->
sig_type
==
SIG_TYPE_SHA1
)
{
SHA1_CTX
sha_ctx
;
uint8_t
sha_dgst
[
SHA1_SIZE
];
SHA1_Init
(
&
sha_ctx
);
SHA1_Update
(
&
sha_ctx
,
&
cert
[
begin_tbs
],
end_tbs
-
begin_tbs
);
SHA1_Final
(
sha_dgst
,
&
sha_ctx
);
x509_ctx
->
digest
=
bi_import
(
bi_ctx
,
sha_dgst
,
SHA1_SIZE
);
}
else
if
(
x509_ctx
->
sig_type
==
SIG_TYPE_MD2
)
{
MD2_CTX
md2_ctx
;
uint8_t
md2_dgst
[
MD2_SIZE
];
MD2_Init
(
&
md2_ctx
);
MD2_Update
(
&
md2_ctx
,
&
cert
[
begin_tbs
],
end_tbs
-
begin_tbs
);
MD2_Final
(
md2_dgst
,
&
md2_ctx
);
x509_ctx
->
digest
=
bi_import
(
bi_ctx
,
md2_dgst
,
MD2_SIZE
);
}
if
(
cert
[
offset
]
==
ASN1_V3_DATA
)
{
int
suboffset
;
++
offset
;
get_asn1_length
(
cert
,
&
offset
);
if
((
suboffset
=
asn1_find_subjectaltname
(
cert
,
offset
))
>
0
)
{
if
(
asn1_next_obj
(
cert
,
&
suboffset
,
ASN1_OCTET_STRING
)
>
0
)
{
int
altlen
;
if
((
altlen
=
asn1_next_obj
(
cert
,
&
suboffset
,
ASN1_SEQUENCE
))
>
0
)
{
int
endalt
=
suboffset
+
altlen
;
int
totalnames
=
0
;
while
(
suboffset
<
endalt
)
{
int
type
=
cert
[
suboffset
++
];
int
dnslen
=
get_asn1_length
(
cert
,
&
suboffset
);
if
(
type
==
ASN1_CONTEXT_DNSNAME
)
{
x509_ctx
->
subject_alt_dnsnames
=
(
char
**
)
os_realloc
(
x509_ctx
->
subject_alt_dnsnames
,
(
totalnames
+
2
)
*
sizeof
(
char
*
));
x509_ctx
->
subject_alt_dnsnames
[
totalnames
]
=
(
char
*
)
os_malloc
(
dnslen
+
1
);
x509_ctx
->
subject_alt_dnsnames
[
totalnames
+
1
]
=
NULL
;
os_memcpy
(
x509_ctx
->
subject_alt_dnsnames
[
totalnames
],
cert
+
suboffset
,
dnslen
);
x509_ctx
->
subject_alt_dnsnames
[
totalnames
][
dnslen
]
=
0
;
++
totalnames
;
}
suboffset
+=
dnslen
;
}
}
}
}
}
offset
=
end_tbs
;
/* skip the rest of v3 data */
if
(
asn1_skip_obj
(
cert
,
&
offset
,
ASN1_SEQUENCE
)
||
asn1_signature
(
cert
,
&
offset
,
x509_ctx
))
goto
end_cert
;
#endif
ret
=
X509_OK
;
end_cert:
if
(
len
)
{
*
len
=
cert_size
;
}
if
(
ret
)
{
#ifdef CONFIG_SSL_FULL_MODE
ssl_printf
(
"Error: Invalid X509 ASN.1 file (%s)
\n
"
,
x509_display_error
(
ret
));
#endif
x509_free
(
x509_ctx
);
*
ctx
=
NULL
;
}
return
ret
;
}
/**
* Free an X.509 object's resources.
*/
void
ICACHE_FLASH_ATTR
x509_free
(
X509_CTX
*
x509_ctx
)
{
X509_CTX
*
next
;
int
i
;
if
(
x509_ctx
==
NULL
)
/* if already null, then don't bother */
return
;
for
(
i
=
0
;
i
<
X509_NUM_DN_TYPES
;
i
++
)
{
os_free
(
x509_ctx
->
ca_cert_dn
[
i
]);
os_free
(
x509_ctx
->
cert_dn
[
i
]);
}
os_free
(
x509_ctx
->
signature
);
#ifdef CONFIG_SSL_CERT_VERIFICATION
if
(
x509_ctx
->
digest
)
{
bi_free
(
x509_ctx
->
rsa_ctx
->
bi_ctx
,
x509_ctx
->
digest
);
}
if
(
x509_ctx
->
subject_alt_dnsnames
)
{
for
(
i
=
0
;
x509_ctx
->
subject_alt_dnsnames
[
i
];
++
i
)
os_free
(
x509_ctx
->
subject_alt_dnsnames
[
i
]);
os_free
(
x509_ctx
->
subject_alt_dnsnames
);
}
#endif
RSA_free
(
x509_ctx
->
rsa_ctx
);
next
=
x509_ctx
->
next
;
os_free
(
x509_ctx
);
x509_free
(
next
);
/* clear the chain */
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Take a signature and decrypt it.
*/
static
bigint
*
ICACHE_FLASH_ATTR
sig_verify
(
BI_CTX
*
ctx
,
const
uint8_t
*
sig
,
int
sig_len
,
bigint
*
modulus
,
bigint
*
pub_exp
)
{
int
i
,
size
;
bigint
*
decrypted_bi
,
*
dat_bi
;
bigint
*
bir
=
NULL
;
uint8_t
*
block
=
(
uint8_t
*
)
os_malloc
(
sig_len
);
/* decrypt */
dat_bi
=
bi_import
(
ctx
,
sig
,
sig_len
);
ctx
->
mod_offset
=
BIGINT_M_OFFSET
;
/* convert to a normal block */
decrypted_bi
=
bi_mod_power2
(
ctx
,
dat_bi
,
modulus
,
pub_exp
);
bi_export
(
ctx
,
decrypted_bi
,
block
,
sig_len
);
ctx
->
mod_offset
=
BIGINT_M_OFFSET
;
i
=
10
;
/* start at the first possible non-padded byte */
while
(
block
[
i
++
]
&&
i
<
sig_len
);
size
=
sig_len
-
i
;
/* get only the bit we want */
if
(
size
>
0
)
{
int
len
;
const
uint8_t
*
sig_ptr
=
get_signature
(
&
block
[
i
],
&
len
);
if
(
sig_ptr
)
{
bir
=
bi_import
(
ctx
,
sig_ptr
,
len
);
}
}
/* save a few bytes of memory */
bi_clear_cache
(
ctx
);
os_free
(
block
);
return
bir
;
}
/**
* Do some basic checks on the certificate chain.
*
* Certificate verification consists of a number of checks:
* - The date of the certificate is after the start date.
* - The date of the certificate is before the finish date.
* - A root certificate exists in the certificate store.
* - That the certificate(s) are not self-signed.
* - The certificate chain is valid.
* - The signature of the certificate is valid.
*/
int
ICACHE_FLASH_ATTR
x509_verify
(
const
CA_CERT_CTX
*
ca_cert_ctx
,
const
X509_CTX
*
cert
)
{
int
ret
=
X509_OK
,
i
=
0
;
bigint
*
cert_sig
;
X509_CTX
*
next_cert
=
NULL
;
BI_CTX
*
ctx
=
NULL
;
bigint
*
mod
=
NULL
,
*
expn
=
NULL
;
int
match_ca_cert
=
0
;
struct
timeval
tv
;
uint8_t
is_self_signed
=
0
;
if
(
cert
==
NULL
)
{
ret
=
X509_VFY_ERROR_NO_TRUSTED_CERT
;
goto
end_verify
;
}
/* a self-signed certificate that is not in the CA store - use this
to check the signature */
if
(
asn1_compare_dn
(
cert
->
ca_cert_dn
,
cert
->
cert_dn
)
==
0
)
{
is_self_signed
=
1
;
ctx
=
cert
->
rsa_ctx
->
bi_ctx
;
mod
=
cert
->
rsa_ctx
->
m
;
expn
=
cert
->
rsa_ctx
->
e
;
}
// gettimeofday(&tv, NULL);
/* check the not before date */
if
(
tv
.
tv_sec
<
cert
->
not_before
)
{
ret
=
X509_VFY_ERROR_NOT_YET_VALID
;
goto
end_verify
;
}
/* check the not after date */
if
(
tv
.
tv_sec
>
cert
->
not_after
)
{
ret
=
X509_VFY_ERROR_EXPIRED
;
goto
end_verify
;
}
next_cert
=
cert
->
next
;
/* last cert in the chain - look for a trusted cert */
if
(
next_cert
==
NULL
)
{
if
(
ca_cert_ctx
!=
NULL
)
{
/* go thu the CA store */
while
(
i
<
CONFIG_X509_MAX_CA_CERTS
&&
ca_cert_ctx
->
cert
[
i
])
{
if
(
asn1_compare_dn
(
cert
->
ca_cert_dn
,
ca_cert_ctx
->
cert
[
i
]
->
cert_dn
)
==
0
)
{
/* use this CA certificate for signature verification */
match_ca_cert
=
1
;
ctx
=
ca_cert_ctx
->
cert
[
i
]
->
rsa_ctx
->
bi_ctx
;
mod
=
ca_cert_ctx
->
cert
[
i
]
->
rsa_ctx
->
m
;
expn
=
ca_cert_ctx
->
cert
[
i
]
->
rsa_ctx
->
e
;
break
;
}
i
++
;
}
}
/* couldn't find a trusted cert (& let self-signed errors
be returned) */
if
(
!
match_ca_cert
&&
!
is_self_signed
)
{
ret
=
X509_VFY_ERROR_NO_TRUSTED_CERT
;
goto
end_verify
;
}
}
else
if
(
asn1_compare_dn
(
cert
->
ca_cert_dn
,
next_cert
->
cert_dn
)
!=
0
)
{
/* check the chain */
ret
=
X509_VFY_ERROR_INVALID_CHAIN
;
goto
end_verify
;
}
else
/* use the next certificate in the chain for signature verify */
{
ctx
=
next_cert
->
rsa_ctx
->
bi_ctx
;
mod
=
next_cert
->
rsa_ctx
->
m
;
expn
=
next_cert
->
rsa_ctx
->
e
;
}
/* cert is self signed */
if
(
!
match_ca_cert
&&
is_self_signed
)
{
ret
=
X509_VFY_ERROR_SELF_SIGNED
;
goto
end_verify
;
}
/* check the signature */
cert_sig
=
sig_verify
(
ctx
,
cert
->
signature
,
cert
->
sig_len
,
bi_clone
(
ctx
,
mod
),
bi_clone
(
ctx
,
expn
));
if
(
cert_sig
&&
cert
->
digest
)
{
if
(
bi_compare
(
cert_sig
,
cert
->
digest
)
!=
0
)
ret
=
X509_VFY_ERROR_BAD_SIGNATURE
;
bi_free
(
ctx
,
cert_sig
);
}
else
{
ret
=
X509_VFY_ERROR_BAD_SIGNATURE
;
}
if
(
ret
)
goto
end_verify
;
/* go down the certificate chain using recursion. */
if
(
next_cert
!=
NULL
)
{
ret
=
x509_verify
(
ca_cert_ctx
,
next_cert
);
}
end_verify:
return
ret
;
}
#endif
#if defined (CONFIG_SSL_FULL_MODE)
/**
* Used for diagnostics.
*/
static
const
char
*
not_part_of_cert
=
"<Not Part Of Certificate>"
;
void
ICACHE_FLASH_ATTR
x509_print
(
const
X509_CTX
*
cert
,
CA_CERT_CTX
*
ca_cert_ctx
)
{
if
(
cert
==
NULL
)
return
;
ssl_printf
(
"=== CERTIFICATE ISSUED TO ===
\n
"
);
ssl_printf
(
"Common Name (CN):
\t\t
"
);
ssl_printf
(
"%s
\n
"
,
cert
->
cert_dn
[
X509_COMMON_NAME
]
?
cert
->
cert_dn
[
X509_COMMON_NAME
]
:
not_part_of_cert
);
ssl_printf
(
"Organization (O):
\t\t
"
);
ssl_printf
(
"%s
\n
"
,
cert
->
cert_dn
[
X509_ORGANIZATION
]
?
cert
->
cert_dn
[
X509_ORGANIZATION
]
:
not_part_of_cert
);
ssl_printf
(
"Organizational Unit (OU):
\t
"
);
ssl_printf
(
"%s
\n
"
,
cert
->
cert_dn
[
X509_ORGANIZATIONAL_UNIT
]
?
cert
->
cert_dn
[
X509_ORGANIZATIONAL_UNIT
]
:
not_part_of_cert
);
ssl_printf
(
"=== CERTIFICATE ISSUED BY ===
\n
"
);
ssl_printf
(
"Common Name (CN):
\t\t
"
);
ssl_printf
(
"%s
\n
"
,
cert
->
ca_cert_dn
[
X509_COMMON_NAME
]
?
cert
->
ca_cert_dn
[
X509_COMMON_NAME
]
:
not_part_of_cert
);
ssl_printf
(
"Organization (O):
\t\t
"
);
ssl_printf
(
"%s
\n
"
,
cert
->
ca_cert_dn
[
X509_ORGANIZATION
]
?
cert
->
ca_cert_dn
[
X509_ORGANIZATION
]
:
not_part_of_cert
);
ssl_printf
(
"Organizational Unit (OU):
\t
"
);
ssl_printf
(
"%s
\n
"
,
cert
->
ca_cert_dn
[
X509_ORGANIZATIONAL_UNIT
]
?
cert
->
ca_cert_dn
[
X509_ORGANIZATIONAL_UNIT
]
:
not_part_of_cert
);
ssl_printf
(
"Not Before:
\t\t\t
%d
\n
"
,
cert
->
not_before
);
ssl_printf
(
"Not After:
\t\t\t
%d
\n
"
,
cert
->
not_after
);
ssl_printf
(
"RSA bitsize:
\t\t\t
%d
\n
"
,
cert
->
rsa_ctx
->
num_octets
*
8
);
ssl_printf
(
"Sig Type:
\t\t\t
"
);
switch
(
cert
->
sig_type
)
{
case
SIG_TYPE_MD5
:
ssl_printf
(
"MD5
\n
"
);
break
;
case
SIG_TYPE_SHA1
:
ssl_printf
(
"SHA1
\n
"
);
break
;
case
SIG_TYPE_MD2
:
ssl_printf
(
"MD2
\n
"
);
break
;
default:
ssl_printf
(
"Unrecognized: %d
\n
"
,
cert
->
sig_type
);
break
;
}
if
(
ca_cert_ctx
)
{
ssl_printf
(
"Verify:
\t\t\t\t
%s
\n
"
,
x509_display_error
(
x509_verify
(
ca_cert_ctx
,
cert
)));
}
#if 0
print_blob("Signature", cert->signature, cert->sig_len);
bi_print("Modulus", cert->rsa_ctx->m);
bi_print("Pub Exp", cert->rsa_ctx->e);
#endif
if
(
ca_cert_ctx
)
{
x509_print
(
cert
->
next
,
ca_cert_ctx
);
}
//TTY_FLUSH();
}
const
char
*
ICACHE_FLASH_ATTR
x509_display_error
(
int
error
)
{
switch
(
error
)
{
case
X509_OK
:
return
"Certificate verify successful"
;
case
X509_NOT_OK
:
return
"X509 not ok"
;
case
X509_VFY_ERROR_NO_TRUSTED_CERT
:
return
"No trusted cert is available"
;
case
X509_VFY_ERROR_BAD_SIGNATURE
:
return
"Bad signature"
;
case
X509_VFY_ERROR_NOT_YET_VALID
:
return
"Cert is not yet valid"
;
case
X509_VFY_ERROR_EXPIRED
:
return
"Cert has expired"
;
case
X509_VFY_ERROR_SELF_SIGNED
:
return
"Cert is self-signed"
;
case
X509_VFY_ERROR_INVALID_CHAIN
:
return
"Chain is invalid (check order of certs)"
;
case
X509_VFY_ERROR_UNSUPPORTED_DIGEST
:
return
"Unsupported digest"
;
case
X509_INVALID_PRIV_KEY
:
return
"Invalid private key"
;
default:
return
"Unknown"
;
}
}
#endif
/* CONFIG_SSL_FULL_MODE */
app/tsl2561/tsl2561.c
View file @
a33e3a4a
...
@@ -67,6 +67,7 @@
...
@@ -67,6 +67,7 @@
#include "tsl2561.h"
#include "tsl2561.h"
#include "platform.h"
#include "platform.h"
#include "user_interface.h"
#include "user_interface.h"
#include "osapi.h"
static
const
uint32_t
tsl2561_i2c_id
=
0
;
static
const
uint32_t
tsl2561_i2c_id
=
0
;
static
bool
_tsl2561Initialised
=
0
;
static
bool
_tsl2561Initialised
=
0
;
...
...
app/user/user_exceptions.c
View file @
a33e3a4a
...
@@ -104,7 +104,7 @@ die:
...
@@ -104,7 +104,7 @@ die:
* we use the linker to wrap that call and stop the SDK from shooting itself in
* we use the linker to wrap that call and stop the SDK from shooting itself in
* its proverbial foot.
* its proverbial foot.
*/
*/
exception_handler_fn
exception_handler_fn
TEXT_SECTION_ATTR
__wrap__xtos_set_exception_handler
(
uint32_t
cause
,
exception_handler_fn
fn
)
__wrap__xtos_set_exception_handler
(
uint32_t
cause
,
exception_handler_fn
fn
)
{
{
if
(
cause
!=
EXCCAUSE_LOAD_STORE_ERROR
)
if
(
cause
!=
EXCCAUSE_LOAD_STORE_ERROR
)
...
...
app/user/user_exceptions.h
View file @
a33e3a4a
#include "
c_type
s.h"
#include "
section
s.h"
#include "rom.h"
#include "rom.h"
#include <xtensa/corebits.h>
#include <xtensa/corebits.h>
...
...
app/user/user_main.c
View file @
a33e3a4a
...
@@ -28,6 +28,7 @@
...
@@ -28,6 +28,7 @@
#endif
#endif
#define SIG_LUA 0
#define SIG_LUA 0
#define SIG_UARTINPUT 1
#define TASK_QUEUE_LEN 4
#define TASK_QUEUE_LEN 4
os_event_t
*
taskQueue
;
os_event_t
*
taskQueue
;
...
@@ -58,6 +59,12 @@ void task_lua(os_event_t *e){
...
@@ -58,6 +59,12 @@ void task_lua(os_event_t *e){
NODE_DBG
(
"SIG_LUA received.
\n
"
);
NODE_DBG
(
"SIG_LUA received.
\n
"
);
lua_main
(
2
,
lua_argv
);
lua_main
(
2
,
lua_argv
);
break
;
break
;
case
SIG_UARTINPUT
:
lua_handle_input
(
false
);
break
;
case
LUA_PROCESS_LINE_SIG
:
lua_handle_input
(
true
);
break
;
default:
default:
break
;
break
;
}
}
...
@@ -139,7 +146,7 @@ void nodemcu_init(void)
...
@@ -139,7 +146,7 @@ void nodemcu_init(void)
// lua_main( 3, lua_argv );
// lua_main( 3, lua_argv );
// NODE_DBG("Flash sec num: 0x%x\n", flash_get_sec_num());
// NODE_DBG("Flash sec num: 0x%x\n", flash_get_sec_num());
task_init
();
task_init
();
system_os_post
(
USER
_TASK_PRIO
_0
,
SIG_LUA
,
's'
);
system_os_post
(
LUA
_TASK_PRIO
,
SIG_LUA
,
's'
);
}
}
/******************************************************************************
/******************************************************************************
...
@@ -158,16 +165,17 @@ void user_init(void)
...
@@ -158,16 +165,17 @@ void user_init(void)
// os_printf("Heap size::%d.\n",system_get_free_heap_size());
// os_printf("Heap size::%d.\n",system_get_free_heap_size());
// os_delay_us(50*1000); // delay 50ms before init uart
// os_delay_us(50*1000); // delay 50ms before init uart
UartBautRate
br
=
#ifdef DEVELOP_VERSION
#ifdef DEVELOP_VERSION
uart_init
(
BIT_RATE_74880
,
BIT_RATE_74880
)
;
BIT_RATE_74880
;
#else
#else
uart_init
(
BIT_RATE_9600
,
BIT_RATE_9600
)
;
BIT_RATE_9600
;
#endif
#endif
//
uart_init
(BIT_RATE_115200, BIT_RATE_115200
);
uart_init
(
br
,
br
,
USER_TASK_PRIO_0
,
SIG_UARTINPUT
);
#ifndef NODE_DEBUG
#ifndef NODE_DEBUG
system_set_os_print
(
0
);
system_set_os_print
(
0
);
#endif
#endif
system_init_done_cb
(
nodemcu_init
);
system_init_done_cb
(
nodemcu_init
);
}
}
Prev
1
2
3
4
5
6
7
8
9
10
…
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