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
e905c24d
Commit
e905c24d
authored
Oct 08, 2015
by
Johny Mattsson
Browse files
Removed unsused, now incompatible SSL code.
parent
21c4e110
Changes
42
Show whitespace changes
Inline
Side-by-side
app/ssl/ssl/ssl_tls1_svr.c
deleted
100644 → 0
View file @
21c4e110
/*
* 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 @
21c4e110
/*
* 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 */
Prev
1
2
3
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