Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DODO�
arduino-esp32
提交
00f96243
A
arduino-esp32
项目概览
DODO�
/
arduino-esp32
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
arduino-esp32
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
00f96243
编写于
5月 14, 2018
作者:
C
chemicstry
提交者:
Me No Dev
5月 14, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Port SSL fingerprint checking from ESP8266 WiFiClientSecure to ESP32 (#1397)
上级
0ea9ea44
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
157 addition
and
0 deletion
+157
-0
libraries/WiFiClientSecure/src/WiFiClientSecure.cpp
libraries/WiFiClientSecure/src/WiFiClientSecure.cpp
+8
-0
libraries/WiFiClientSecure/src/WiFiClientSecure.h
libraries/WiFiClientSecure/src/WiFiClientSecure.h
+1
-0
libraries/WiFiClientSecure/src/ssl_client.cpp
libraries/WiFiClientSecure/src/ssl_client.cpp
+146
-0
libraries/WiFiClientSecure/src/ssl_client.h
libraries/WiFiClientSecure/src/ssl_client.h
+2
-0
未找到文件。
libraries/WiFiClientSecure/src/WiFiClientSecure.cpp
浏览文件 @
00f96243
...
...
@@ -210,6 +210,14 @@ void WiFiClientSecure::setPrivateKey (const char *private_key)
_private_key
=
private_key
;
}
bool
WiFiClientSecure
::
verify
(
const
char
*
fp
,
const
char
*
domain_name
)
{
if
(
!
sslclient
)
return
false
;
return
verify_ssl_fingerprint
(
sslclient
,
fp
,
domain_name
);
}
int
WiFiClientSecure
::
lastError
(
char
*
buf
,
const
size_t
size
)
{
if
(
!
_lastError
)
{
...
...
libraries/WiFiClientSecure/src/WiFiClientSecure.h
浏览文件 @
00f96243
...
...
@@ -58,6 +58,7 @@ public:
void
setCACert
(
const
char
*
rootCA
);
void
setCertificate
(
const
char
*
client_ca
);
void
setPrivateKey
(
const
char
*
private_key
);
bool
verify
(
const
char
*
fingerprint
,
const
char
*
domain_name
);
operator
bool
()
{
...
...
libraries/WiFiClientSecure/src/ssl_client.cpp
浏览文件 @
00f96243
...
...
@@ -12,6 +12,10 @@
#include <lwip/sockets.h>
#include <lwip/sys.h>
#include <lwip/netdb.h>
#include <mbedtls/sha256.h>
#include <mbedtls/oid.h>
#include <algorithm>
#include <string>
#include "ssl_client.h"
...
...
@@ -262,3 +266,145 @@ int get_ssl_receive(sslclient_context *ssl_client, uint8_t *data, int length)
//log_v( "%d bytes read", ret); //for low level debug
return
ret
;
}
static
bool
parseHexNibble
(
char
pb
,
uint8_t
*
res
)
{
if
(
pb
>=
'0'
&&
pb
<=
'9'
)
{
*
res
=
(
uint8_t
)
(
pb
-
'0'
);
return
true
;
}
else
if
(
pb
>=
'a'
&&
pb
<=
'f'
)
{
*
res
=
(
uint8_t
)
(
pb
-
'a'
+
10
);
return
true
;
}
else
if
(
pb
>=
'A'
&&
pb
<=
'F'
)
{
*
res
=
(
uint8_t
)
(
pb
-
'A'
+
10
);
return
true
;
}
return
false
;
}
// Compare a name from certificate and domain name, return true if they match
static
bool
matchName
(
const
std
::
string
&
name
,
const
std
::
string
&
domainName
)
{
size_t
wildcardPos
=
name
.
find
(
'*'
);
if
(
wildcardPos
==
std
::
string
::
npos
)
{
// Not a wildcard, expect an exact match
return
name
==
domainName
;
}
size_t
firstDotPos
=
name
.
find
(
'.'
);
if
(
wildcardPos
>
firstDotPos
)
{
// Wildcard is not part of leftmost component of domain name
// Do not attempt to match (rfc6125 6.4.3.1)
return
false
;
}
if
(
wildcardPos
!=
0
||
firstDotPos
!=
1
)
{
// Matching of wildcards such as baz*.example.com and b*z.example.com
// is optional. Maybe implement this in the future?
return
false
;
}
size_t
domainNameFirstDotPos
=
domainName
.
find
(
'.'
);
if
(
domainNameFirstDotPos
==
std
::
string
::
npos
)
{
return
false
;
}
return
domainName
.
substr
(
domainNameFirstDotPos
)
==
name
.
substr
(
firstDotPos
);
}
// Verifies certificate provided by the peer to match specified SHA256 fingerprint
bool
verify_ssl_fingerprint
(
sslclient_context
*
ssl_client
,
const
char
*
fp
,
const
char
*
domain_name
)
{
// Convert hex string to byte array
uint8_t
fingerprint_local
[
32
];
int
len
=
strlen
(
fp
);
int
pos
=
0
;
for
(
size_t
i
=
0
;
i
<
sizeof
(
fingerprint_local
);
++
i
)
{
while
(
pos
<
len
&&
((
fp
[
pos
]
==
' '
)
||
(
fp
[
pos
]
==
':'
)))
{
++
pos
;
}
if
(
pos
>
len
-
2
)
{
log_d
(
"pos:%d len:%d fingerprint too short"
,
pos
,
len
);
return
false
;
}
uint8_t
high
,
low
;
if
(
!
parseHexNibble
(
fp
[
pos
],
&
high
)
||
!
parseHexNibble
(
fp
[
pos
+
1
],
&
low
))
{
log_d
(
"pos:%d len:%d invalid hex sequence: %c%c"
,
pos
,
len
,
fp
[
pos
],
fp
[
pos
+
1
]);
return
false
;
}
pos
+=
2
;
fingerprint_local
[
i
]
=
low
|
(
high
<<
4
);
}
// Get certificate provided by the peer
const
mbedtls_x509_crt
*
crt
=
mbedtls_ssl_get_peer_cert
(
&
ssl_client
->
ssl_ctx
);
if
(
!
crt
)
{
log_d
(
"could not fetch peer certificate"
);
return
false
;
}
// Calculate certificate's SHA256 fingerprint
uint8_t
fingerprint_remote
[
32
];
mbedtls_sha256_context
sha256_ctx
;
mbedtls_sha256_init
(
&
sha256_ctx
);
mbedtls_sha256_starts
(
&
sha256_ctx
,
false
);
mbedtls_sha256_update
(
&
sha256_ctx
,
crt
->
raw
.
p
,
crt
->
raw
.
len
);
mbedtls_sha256_finish
(
&
sha256_ctx
,
fingerprint_remote
);
// Check if fingerprints match
if
(
memcmp
(
fingerprint_local
,
fingerprint_remote
,
32
))
{
log_d
(
"fingerprint doesn't match"
);
return
false
;
}
// Additionally check if certificate has domain name if provided
if
(
domain_name
)
return
verify_ssl_dn
(
ssl_client
,
domain_name
);
else
return
true
;
}
// Checks if peer certificate has specified domain in CN or SANs
bool
verify_ssl_dn
(
sslclient_context
*
ssl_client
,
const
char
*
domain_name
)
{
log_d
(
"domain name: '%s'"
,
(
domain_name
)
?
domain_name
:
"(null)"
);
std
::
string
domain_name_str
(
domain_name
);
std
::
transform
(
domain_name_str
.
begin
(),
domain_name_str
.
end
(),
domain_name_str
.
begin
(),
::
tolower
);
// Get certificate provided by the peer
const
mbedtls_x509_crt
*
crt
=
mbedtls_ssl_get_peer_cert
(
&
ssl_client
->
ssl_ctx
);
// Check for domain name in SANs
const
mbedtls_x509_sequence
*
san
=
&
crt
->
subject_alt_names
;
while
(
san
!=
nullptr
)
{
std
::
string
san_str
((
const
char
*
)
san
->
buf
.
p
,
san
->
buf
.
len
);
std
::
transform
(
san_str
.
begin
(),
san_str
.
end
(),
san_str
.
begin
(),
::
tolower
);
if
(
matchName
(
san_str
,
domain_name_str
))
return
true
;
log_d
(
"SAN '%s': no match"
,
san_str
.
c_str
());
// Fetch next SAN
san
=
san
->
next
;
}
// Check for domain name in CN
const
mbedtls_asn1_named_data
*
common_name
=
&
crt
->
subject
;
while
(
common_name
!=
nullptr
)
{
// While iterating through DN objects, check for CN object
if
(
!
MBEDTLS_OID_CMP
(
MBEDTLS_OID_AT_CN
,
&
common_name
->
oid
))
{
std
::
string
common_name_str
((
const
char
*
)
common_name
->
val
.
p
,
common_name
->
val
.
len
);
if
(
matchName
(
common_name_str
,
domain_name_str
))
return
true
;
log_d
(
"CN '%s': not match"
,
common_name_str
.
c_str
());
}
// Fetch next DN object
common_name
=
common_name
->
next
;
}
return
false
;
}
libraries/WiFiClientSecure/src/ssl_client.h
浏览文件 @
00f96243
...
...
@@ -32,5 +32,7 @@ void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, cons
int
data_to_read
(
sslclient_context
*
ssl_client
);
int
send_ssl_data
(
sslclient_context
*
ssl_client
,
const
uint8_t
*
data
,
uint16_t
len
);
int
get_ssl_receive
(
sslclient_context
*
ssl_client
,
uint8_t
*
data
,
int
length
);
bool
verify_ssl_fingerprint
(
sslclient_context
*
ssl_client
,
const
char
*
fp
,
const
char
*
domain_name
);
bool
verify_ssl_dn
(
sslclient_context
*
ssl_client
,
const
char
*
domain_name
);
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录