mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-02 14:49:04 +00:00
add auto generated test folder to components:
1. add test cases and related scripts 2. add CI config files read README.md for detail
This commit is contained in:
90
components/test/TestCaseScript/SSLTest/Capability.py
Executable file
90
components/test/TestCaseScript/SSLTest/Capability.py
Executable file
@@ -0,0 +1,90 @@
|
||||
|
||||
|
||||
class SSLCapability(object):
|
||||
CAPABILITY_TYPE = ["version", "cipher_suite", "fragment_size", # for hello capability negotiation
|
||||
"verify_server", "verify_client", # if support verify server/client
|
||||
"key_algorithm", "key_encoding", "pem_encryption", # what kind of private it supports
|
||||
"certificate_encoding", "certificate_digest", # what kind of certificate it supports
|
||||
]
|
||||
SSL_TYPE = ("TargetClient", "TargetServer", "PCClient", "PCServer")
|
||||
|
||||
def __init__(self, typ, **kwargs):
|
||||
assert typ in self.SSL_TYPE
|
||||
self.type = typ
|
||||
self.capability = dict.fromkeys(self.CAPABILITY_TYPE, None)
|
||||
for kw in kwargs:
|
||||
self.capability[kw] = kwargs[kw]
|
||||
for kw in self.capability:
|
||||
assert self.capability[kw] is not None
|
||||
pass
|
||||
|
||||
def get(self, kw):
|
||||
return self.capability[kw]
|
||||
|
||||
def set(self, **kwargs):
|
||||
for kw in kwargs:
|
||||
self.capability[kw] = kwargs[kw]
|
||||
pass
|
||||
|
||||
|
||||
class TargetSSLCapability(SSLCapability):
|
||||
DEFAULT_CAPABILITY = {
|
||||
"version": ["SSLv23_2"],
|
||||
"cipher_suite": ["TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_RSA_WITH_RC4_128_SHA",
|
||||
"TLS_RSA_WITH_RC4_128_MD5"],
|
||||
"fragment_size": [2048, 4096, 8192],
|
||||
"verify_server": True,
|
||||
"verify_client": False,
|
||||
"key_algorithm": ["RSA512", "RSA1024", "RSA2048", "RSA4096"],
|
||||
"key_encoding": ["PEM", "DER"],
|
||||
"pem_encryption": [None, "aes128", "aes256"],
|
||||
"certificate_encoding": ["PEM", "DER"],
|
||||
"certificate_digest": ["md5", "sha1", "sha256", "sha384", "sha512"],
|
||||
}
|
||||
|
||||
def __init__(self, typ, **kwargs):
|
||||
assert typ == "TargetClient" or typ == "TargetServer"
|
||||
capability = dict(self.DEFAULT_CAPABILITY)
|
||||
for kw in kwargs:
|
||||
capability[kw] = kwargs[kw]
|
||||
SSLCapability.__init__(self, typ, **capability)
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
class PCSSLCapability(SSLCapability):
|
||||
DEFAULT_CAPABILITY = {
|
||||
"version": ["SSLv23", "SSLv20", "SSLv30", "TLSv10", "TLSv11", "TLSv12"],
|
||||
"cipher_suite": ["TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_RSA_WITH_RC4_128_SHA",
|
||||
"TLS_RSA_WITH_RC4_128_MD5",
|
||||
"TLS_DH_DSS_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"],
|
||||
"fragment_size": [16384],
|
||||
"verify_server": True,
|
||||
"verify_client": True,
|
||||
"key_algorithm": ["RSA512", "RSA1024", "RSA2048", "RSA4096"],
|
||||
"key_encoding": ["PEM"],
|
||||
"pem_encryption": [None],
|
||||
"certificate_encoding": ["PEM"],
|
||||
"certificate_digest": ["md5", "sha1", "sha256", "sha384", "sha512"],
|
||||
}
|
||||
|
||||
def __init__(self, typ):
|
||||
assert typ == "PCClient" or typ == "PCServer"
|
||||
SSLCapability.__init__(self, typ, **self.DEFAULT_CAPABILITY)
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
pc = PCSSLCapability("PCClient")
|
||||
target = TargetSSLCapability("TargetClient")
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
333
components/test/TestCaseScript/SSLTest/ConfigUtility.py
Executable file
333
components/test/TestCaseScript/SSLTest/ConfigUtility.py
Executable file
@@ -0,0 +1,333 @@
|
||||
from PKI import PKIDict, PKIItem
|
||||
import Parameter
|
||||
|
||||
|
||||
def multiply_2_lists(list1, list2):
|
||||
def make_list(li):
|
||||
if not isinstance(li, list):
|
||||
li = [li]
|
||||
return li
|
||||
list1 = make_list(list1)
|
||||
list2 = make_list(list2)
|
||||
ret = []
|
||||
for a in list1:
|
||||
for b in list2:
|
||||
ret.append(make_list(a) + make_list(b))
|
||||
return ret
|
||||
|
||||
|
||||
def list_multiply(list1, *args):
|
||||
ret = list1
|
||||
for arg in args:
|
||||
ret = multiply_2_lists(ret, arg)
|
||||
return ret
|
||||
|
||||
|
||||
def list_and(list1, list2):
|
||||
ret = []
|
||||
for item in list1:
|
||||
if item in list2:
|
||||
ret.append(item)
|
||||
return ret
|
||||
|
||||
|
||||
class ComputeResult(object):
|
||||
NEGOTIATION_CONFIG = ["client_version", "client_cipher_suite", "client_fragment_size",
|
||||
"server_version", "server_cipher_suite", "server_fragment_size"]
|
||||
CERT_KEY_CONFIG = ["verify_server", "verify_client",
|
||||
"client_trust_anchor", "client_certificate", "client_key",
|
||||
"server_trust_anchor", "server_certificate", "server_key"]
|
||||
|
||||
TYPE_CONTEXT = "context"
|
||||
TYPE_NEGOTIATION = "negotiation"
|
||||
TYPE_CERT_KEY = "cert_key"
|
||||
TYPE_SEND_PARAM = "send_param"
|
||||
|
||||
# results
|
||||
SUCCEED = 0
|
||||
CREATE_CONTEXT_FAIL = 1
|
||||
HANDSHAKE_FAIL = 2
|
||||
CERT_KEY_FAIL = 3
|
||||
|
||||
def __init__(self, client_capability, server_capability):
|
||||
self.client_capability = client_capability
|
||||
self.server_capability = server_capability
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def __check_cert(cert, capability, check_encoding=True):
|
||||
ret = True
|
||||
if cert.name is not None:
|
||||
if check_encoding is True:
|
||||
if cert.digest not in capability.get("certificate_digest") \
|
||||
or cert.key_algorithm not in capability.get("key_algorithm") \
|
||||
or cert.file_encoding not in capability.get("certificate_encoding"):
|
||||
ret = False
|
||||
else:
|
||||
if cert.digest not in capability.get("certificate_digest") \
|
||||
or cert.key_algorithm not in capability.get("key_algorithm"):
|
||||
ret = False
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def __check_key(key, capability, check_encoding=True):
|
||||
ret = True
|
||||
if key.name is not None:
|
||||
if check_encoding is True:
|
||||
if key.algorithm not in capability.get("key_algorithm") \
|
||||
or key.file_encoding not in capability.get("key_encoding") \
|
||||
or key.file_encryption not in capability.get("pem_encryption"):
|
||||
ret = False
|
||||
else:
|
||||
if key.algorithm not in capability.get("key_algorithm") \
|
||||
or key.file_encryption not in capability.get("pem_encryption"):
|
||||
ret = False
|
||||
return ret
|
||||
|
||||
# compute result functions
|
||||
def check_context(self, config):
|
||||
result = self.SUCCEED
|
||||
check_list = [(self.__check_cert, PKIItem.Certificate(config["client_trust_anchor"]),
|
||||
self.client_capability),
|
||||
(self.__check_cert, PKIItem.Certificate(config["client_certificate"]),
|
||||
self.client_capability),
|
||||
(self.__check_key, PKIItem.PrivateKey(config["client_key"]),
|
||||
self.client_capability),
|
||||
(self.__check_cert, PKIItem.Certificate(config["server_trust_anchor"]),
|
||||
self.server_capability),
|
||||
(self.__check_cert, PKIItem.Certificate(config["server_certificate"]),
|
||||
self.server_capability),
|
||||
(self.__check_key, PKIItem.PrivateKey(config["server_key"]),
|
||||
self.server_capability)]
|
||||
for _check in check_list:
|
||||
if _check[0](_check[1], _check[2]) is False:
|
||||
result = self.CREATE_CONTEXT_FAIL
|
||||
break
|
||||
return result
|
||||
|
||||
def check_negotiation_param(self, config):
|
||||
result = self.SUCCEED
|
||||
# first check version
|
||||
while True:
|
||||
if Parameter.VERSION[config["client_version"]]\
|
||||
& Parameter.VERSION[config["server_version"]] == 0:
|
||||
result = self.HANDSHAKE_FAIL
|
||||
break
|
||||
# check cipher suite
|
||||
supported_cipher_suite = list_and(self.client_capability.get("cipher_suite"),
|
||||
self.server_capability.get("cipher_suite"))
|
||||
if config["client_cipher_suite"] not in supported_cipher_suite\
|
||||
or config["server_cipher_suite"] not in supported_cipher_suite\
|
||||
or config["client_cipher_suite"] != config["server_cipher_suite"]:
|
||||
result = self.HANDSHAKE_FAIL
|
||||
break
|
||||
break
|
||||
return result
|
||||
|
||||
# check cert key, if it can be supported by both client and server, if it matches
|
||||
def __check_cert_key_content(self, cert, key):
|
||||
if self.__check_cert(cert, self.client_capability, check_encoding=False) is True\
|
||||
and self.__check_cert(cert, self.server_capability, check_encoding=False) is True \
|
||||
and self.__check_key(key, self.client_capability, check_encoding=False) is True \
|
||||
and self.__check_key(key, self.server_capability, check_encoding=False) is True \
|
||||
and key.name.find(cert.private_key) != -1:
|
||||
result = True
|
||||
else:
|
||||
result = False
|
||||
return result
|
||||
|
||||
def __verify_ca(self, ca, cert, capability):
|
||||
result = True
|
||||
while True:
|
||||
# if ca supported
|
||||
if self.__check_cert(ca, capability) is False:
|
||||
result = False
|
||||
break
|
||||
# check if ca in cert chain
|
||||
try:
|
||||
index = cert.cert_chain.index(ca.name)
|
||||
except StandardError:
|
||||
result = False
|
||||
break
|
||||
|
||||
# for pem cert, it contains cert chain to issuer, any cert in chain works
|
||||
# der cert do not contain cert chain
|
||||
# only der root cert verify L1 cert and root cert works
|
||||
if cert.file_encoding == "DER":
|
||||
if len(cert.cert_chain) > 2 and index != len(cert.cert_chain) - 1:
|
||||
result = False
|
||||
break
|
||||
# check if all certs in before trust anchor supported
|
||||
for cert_name in cert.cert_chain[1:index]:
|
||||
_cert = PKIItem.Certificate(cert_name + ".pem")
|
||||
if self.__check_cert(_cert, capability) is False:
|
||||
result = False
|
||||
break
|
||||
break
|
||||
return result
|
||||
|
||||
def __check_verify_client(self, client_cert, client_key, server_ca):
|
||||
result = self.__check_cert_key_content(client_cert, client_key)
|
||||
if result is True:
|
||||
result = self.__verify_ca(server_ca, client_cert, self.server_capability)
|
||||
return result
|
||||
|
||||
def __check_verify_server(self, client_ca, server_cert):
|
||||
return self.__verify_ca(client_ca, server_cert, self.client_capability)
|
||||
|
||||
def check_cert_key(self, config):
|
||||
result = self.SUCCEED
|
||||
while True: # break if when anything failed
|
||||
if (config["verify_server"] is True and self.client_capability.get("verify_server") is False) \
|
||||
or (config["verify_client"] is True and
|
||||
(self.server_capability.get("verify_client") is False or
|
||||
self.client_capability.get("verify_client") is False)):
|
||||
result = self.CERT_KEY_FAIL
|
||||
break
|
||||
|
||||
server_cert = PKIItem.Certificate(config["server_certificate"])
|
||||
server_key = PKIItem.PrivateKey(config["server_key"])
|
||||
server_ca = PKIItem.Certificate(config["server_trust_anchor"])
|
||||
client_cert = PKIItem.Certificate(config["client_certificate"])
|
||||
client_key = PKIItem.PrivateKey(config["client_key"])
|
||||
client_ca = PKIItem.Certificate(config["client_trust_anchor"])
|
||||
# always check server cert key
|
||||
if self.__check_cert_key_content(server_cert, server_key) is False:
|
||||
result = self.CERT_KEY_FAIL
|
||||
break
|
||||
# if require to verify server
|
||||
if config["verify_server"] is True:
|
||||
if self.__check_verify_server(client_ca, server_cert) is False:
|
||||
result = self.CERT_KEY_FAIL
|
||||
break
|
||||
# if require to verify client
|
||||
if config["verify_client"] is True:
|
||||
if self.__check_verify_client(client_cert, client_key, server_ca) is False:
|
||||
result = self.CERT_KEY_FAIL
|
||||
break
|
||||
break
|
||||
return result
|
||||
|
||||
CHECK_FUNC = {
|
||||
TYPE_CONTEXT: check_context,
|
||||
TYPE_NEGOTIATION: check_negotiation_param,
|
||||
TYPE_CERT_KEY: check_cert_key,
|
||||
}
|
||||
CONFIG_KEY = {
|
||||
TYPE_CONTEXT: CERT_KEY_CONFIG,
|
||||
TYPE_NEGOTIATION: NEGOTIATION_CONFIG,
|
||||
TYPE_CERT_KEY: CERT_KEY_CONFIG,
|
||||
}
|
||||
|
||||
def compute_result(self, typ, config_list):
|
||||
succeed_list = []
|
||||
fail_list = []
|
||||
for config in config_list:
|
||||
if self.CHECK_FUNC[typ](self, dict(zip(self.CONFIG_KEY[typ], config))) != self.SUCCEED:
|
||||
fail_list.append(config)
|
||||
else:
|
||||
succeed_list.append(config)
|
||||
return succeed_list, fail_list
|
||||
pass
|
||||
|
||||
|
||||
class GenerateTestConfig(ComputeResult):
|
||||
TEST_CONFIG = ComputeResult.NEGOTIATION_CONFIG + \
|
||||
ComputeResult.CERT_KEY_CONFIG
|
||||
|
||||
def __init__(self, client_capability, server_capability):
|
||||
ComputeResult.__init__(self, client_capability, server_capability)
|
||||
self.key_dict = PKIDict.PKIDict.KEY_DICT
|
||||
self.cert_dict = PKIDict.PKIDict.CERT_DICT
|
||||
pass
|
||||
|
||||
def generate_negotiation_config(self):
|
||||
_config = list_multiply(self.client_capability.get("version"),
|
||||
self.client_capability.get("cipher_suite"),
|
||||
self.client_capability.get("fragment_size"),
|
||||
self.server_capability.get("version"),
|
||||
self.server_capability.get("cipher_suite"),
|
||||
self.server_capability.get("fragment_size"))
|
||||
return self.compute_result(self.TYPE_NEGOTIATION, _config)
|
||||
|
||||
def __choose_cert_key(self, verify_server, verify_client,
|
||||
client_ca_opt, client_cert_key_opt,
|
||||
server_ca_opt, server_cert_key_opt):
|
||||
pass
|
||||
|
||||
# CERT_KEY_CONFIG = ["verify_server", "verify_client",
|
||||
# "client_trust_anchor", "client_certificate", "client_key",
|
||||
# "server_trust_anchor", "server_certificate", "server_key"]
|
||||
def generate_cert_key_config(self):
|
||||
# first handle not verify certificate case
|
||||
_config_list = []
|
||||
for cert in PKIDict.PKIDict.CERT_DICT:
|
||||
for key in PKIDict.PKIDict.KEY_DICT:
|
||||
_config_list.append([False, False, None, None, None, None, cert, key])
|
||||
cert_key_succeed, context_fail = self.compute_result(self.TYPE_CONTEXT, _config_list)
|
||||
cert_key_succeed, cert_key_fail = self.compute_result(self.TYPE_CERT_KEY, cert_key_succeed)
|
||||
key_cert_pair = [[x[6], x[7]] for x in cert_key_succeed]
|
||||
# for succeed config, do server cert verify
|
||||
_config_list = []
|
||||
for _config in cert_key_succeed:
|
||||
for cert in PKIDict.PKIDict.CERT_DICT:
|
||||
_config_list.append([True, False, cert, None, None,
|
||||
None, _config[6], _config[7]])
|
||||
_cert_key_succeed, _context_fail = self.compute_result(self.TYPE_CONTEXT, _config_list)
|
||||
context_fail += _context_fail
|
||||
_cert_key_succeed, _cert_key_fail = self.compute_result(self.TYPE_CERT_KEY, _cert_key_succeed)
|
||||
cert_key_fail += _cert_key_fail
|
||||
cert_key_succeed += _cert_key_succeed
|
||||
# for succeed config, do client verify
|
||||
_config_list = []
|
||||
for _config in _cert_key_succeed:
|
||||
for key_cert in key_cert_pair:
|
||||
_config_list.append([True, True, _config[2], key_cert[0], key_cert[1],
|
||||
key_cert[0], _config[6], _config[7]])
|
||||
_cert_key_succeed, _context_fail = self.compute_result(self.TYPE_CONTEXT, _config_list)
|
||||
context_fail += _context_fail
|
||||
_cert_key_succeed, _cert_key_fail = self.compute_result(self.TYPE_CERT_KEY, _cert_key_succeed)
|
||||
cert_key_fail += _cert_key_fail
|
||||
cert_key_succeed += _cert_key_succeed
|
||||
# only verify client not verify server
|
||||
_config_list = []
|
||||
for _config in _cert_key_succeed:
|
||||
_config_list.append([False, True, None,
|
||||
_config[3], _config[4], _config[5], _config[6], _config[7]])
|
||||
_cert_key_succeed, _context_fail = self.compute_result(self.TYPE_CONTEXT, _config_list)
|
||||
context_fail += _context_fail
|
||||
_cert_key_succeed, _cert_key_fail = self.compute_result(self.TYPE_CERT_KEY, _cert_key_succeed)
|
||||
cert_key_fail += _cert_key_fail
|
||||
cert_key_succeed += _cert_key_succeed
|
||||
return cert_key_succeed, context_fail, cert_key_fail
|
||||
|
||||
|
||||
class ConfigUtility(GenerateTestConfig):
|
||||
# test config
|
||||
_TEST_CONFIG_DICT_KEY = ("config", "result")
|
||||
|
||||
def __init__(self, client_capability, server_capability):
|
||||
GenerateTestConfig.__init__(self, client_capability, server_capability)
|
||||
pass
|
||||
|
||||
def get_all_test_config(self):
|
||||
negotiation_succeed, negotiation_fail = self.generate_negotiation_config()
|
||||
cert_key_succeed, context_fail, cert_key_fail = self.generate_cert_key_config()
|
||||
succeed_config = list_multiply(negotiation_succeed, cert_key_succeed)
|
||||
context_fail_config = list_multiply([negotiation_succeed[0]], context_fail)
|
||||
negotiation_fail_config = list_multiply(negotiation_fail, [cert_key_succeed[0]])
|
||||
cert_key_fail_config = list_multiply([negotiation_succeed[0]], cert_key_fail)
|
||||
return dict(zip(["succeed", "context_fail", "negotiation_fail", "cert_key_fail"],
|
||||
[[dict(zip(self.TEST_CONFIG, x)) for x in succeed_config],
|
||||
[dict(zip(self.TEST_CONFIG, x)) for x in context_fail_config],
|
||||
[dict(zip(self.TEST_CONFIG, x)) for x in negotiation_fail_config],
|
||||
[dict(zip(self.TEST_CONFIG, x)) for x in cert_key_fail_config]]))
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
56
components/test/TestCaseScript/SSLTest/Parameter.py
Executable file
56
components/test/TestCaseScript/SSLTest/Parameter.py
Executable file
@@ -0,0 +1,56 @@
|
||||
|
||||
|
||||
VERSION = {
|
||||
"SSLv23": 0x1F,
|
||||
"SSLv23_2": 0x1C, # current target ssl implementation do not support SSLv20 and TLSv12
|
||||
"SSLv20": 0x01,
|
||||
"SSLv30": 0x02,
|
||||
"TLSv10": 0x04,
|
||||
"TLSv11": 0x08,
|
||||
"TLSv12": 0x10,
|
||||
}
|
||||
|
||||
|
||||
CIPHER_SUITE = {
|
||||
# supported algorithm
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA": "AES128-SHA",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA": "AES256-SHA",
|
||||
"TLS_RSA_WITH_RC4_128_SHA": "RC4-SHA",
|
||||
"TLS_RSA_WITH_RC4_128_MD5": "RC4-MD5",
|
||||
"TLS_DH_DSS_WITH_AES_128_CBC_SHA": "DH-DSS-AES128-SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": "ECDHE-RSA-AES128-GCM-SHA256",
|
||||
}
|
||||
|
||||
|
||||
FRAGMENT_SIZE = {
|
||||
"SIZE_DEFAULT": 0,
|
||||
"SIZE_512": 512,
|
||||
"SIZE_1024": 1024,
|
||||
"SIZE_2048": 2048,
|
||||
"SIZE_4096": 4096,
|
||||
"SIZE_8192": 8192,
|
||||
}
|
||||
|
||||
|
||||
VERIFY_OPTION = {
|
||||
"NOT_VERIFY": "NOT_VERIFY",
|
||||
"VERIFY": "VERIFY",
|
||||
}
|
||||
|
||||
|
||||
SEND_OPTION = {
|
||||
"MAX_SEND_SIZE_512": 512,
|
||||
"MAX_SEND_SIZE_1K": 1024,
|
||||
"MAX_SEND_SIZE_2K": 2048,
|
||||
"MAX_SEND_SIZE_4K": 4096,
|
||||
"MAX_SEND_SIZE_8K": 8192,
|
||||
"MAX_SEND_SIZE_16K": 16384,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
498
components/test/TestCaseScript/SSLTest/SSLHandler.py
Normal file
498
components/test/TestCaseScript/SSLTest/SSLHandler.py
Normal file
@@ -0,0 +1,498 @@
|
||||
import socket
|
||||
import ssl
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import threading
|
||||
|
||||
import Parameter
|
||||
from PKI import PKIDict
|
||||
from PKI import PKIItem
|
||||
from NativeLog import NativeLog
|
||||
|
||||
|
||||
class SerialPortCheckFail(StandardError):
|
||||
pass
|
||||
|
||||
|
||||
class SSLHandlerFail(StandardError):
|
||||
pass
|
||||
|
||||
|
||||
class PCFail(StandardError):
|
||||
pass
|
||||
|
||||
|
||||
class TargetFail(StandardError):
|
||||
pass
|
||||
|
||||
|
||||
def ssl_handler_wrapper(handler_type):
|
||||
if handler_type == "PC":
|
||||
exception_type = PCFail
|
||||
elif handler_type == "Target":
|
||||
exception_type = TargetFail
|
||||
else:
|
||||
exception_type = None
|
||||
|
||||
def _handle_func(func):
|
||||
def _handle_args(*args, **kwargs):
|
||||
try:
|
||||
ret = func(*args, **kwargs)
|
||||
except StandardError, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
raise exception_type(str(e))
|
||||
return ret
|
||||
return _handle_args
|
||||
return _handle_func
|
||||
|
||||
|
||||
class SerialPort(object):
|
||||
def __init__(self, tc_action, port_name):
|
||||
self.tc_action = tc_action
|
||||
self.port_name = port_name
|
||||
|
||||
def flush(self):
|
||||
self.tc_action.flush_data(self.port_name)
|
||||
|
||||
def write_line(self, data):
|
||||
self.tc_action.serial_write_line(self.port_name, data)
|
||||
|
||||
def check(self, condition, timeout=10):
|
||||
if self.tc_action.check_response(self.port_name, condition, timeout) is False:
|
||||
raise SerialPortCheckFail("serial port check fail, condition is %s" % condition)
|
||||
|
||||
def read_data(self):
|
||||
return self.tc_action.serial_read_data(self.port_name)
|
||||
pass
|
||||
|
||||
|
||||
class SSLHandler(object):
|
||||
# ssl operation timeout is 30 seconds
|
||||
TIMEOUT = 30
|
||||
|
||||
def __init__(self, typ, config, serial_port):
|
||||
self.type = typ
|
||||
self.config = config
|
||||
self.timeout = self.TIMEOUT
|
||||
self.serial_port = serial_port
|
||||
self.accept_thread = None
|
||||
self.data_validation = False
|
||||
|
||||
def set_timeout(self, timeout):
|
||||
self.timeout = timeout
|
||||
|
||||
def init_context(self):
|
||||
pass
|
||||
|
||||
def connect(self, remote_ip, remote_port, local_ip=0, local_port=0):
|
||||
pass
|
||||
|
||||
def listen(self, local_port=0, local_ip=0):
|
||||
pass
|
||||
|
||||
def send(self, size, data):
|
||||
pass
|
||||
|
||||
def recv(self, length, timeout):
|
||||
pass
|
||||
|
||||
def set_data_validation(self, validation):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
if self.accept_thread is not None:
|
||||
self.accept_thread.exit()
|
||||
self.accept_thread.join(5)
|
||||
pass
|
||||
|
||||
|
||||
class TargetSSLHandler(SSLHandler):
|
||||
def __init__(self, typ, config, serial_port):
|
||||
SSLHandler.__init__(self, typ, config, serial_port)
|
||||
self.ssl_id = None
|
||||
self.server_id = None
|
||||
|
||||
@ssl_handler_wrapper("Target")
|
||||
def init_context(self):
|
||||
self.serial_port.flush()
|
||||
self.serial_port.write_line("soc -T")
|
||||
self.serial_port.check("+CLOSEALL")
|
||||
|
||||
if self.type == "client":
|
||||
version = Parameter.VERSION[self.config["client_version"]]
|
||||
fragment = self.config["client_fragment_size"]
|
||||
ca = self.config["client_trust_anchor"]
|
||||
cert = self.config["client_certificate"]
|
||||
key = self.config["client_key"]
|
||||
verify_required = 0x01 if self.config["verify_server"] is True else 0x00
|
||||
context_type = 1
|
||||
else:
|
||||
version = Parameter.VERSION[self.config["server_version"]]
|
||||
fragment = self.config["server_fragment_size"]
|
||||
ca = self.config["server_trust_anchor"]
|
||||
cert = self.config["server_certificate"]
|
||||
key = self.config["server_key"]
|
||||
verify_required = 0x02 if self.config["verify_client"] is True else 0x00
|
||||
context_type = 2
|
||||
ssc_cmd = "ssl -I -t %u -r %u -v %u -o %u" % (context_type, fragment, version, verify_required)
|
||||
|
||||
if ca is not None:
|
||||
_index = PKIDict.PKIDict.CERT_DICT[ca]
|
||||
ssc_cmd += " -a %d" % _index
|
||||
if cert is not None:
|
||||
_index = PKIDict.PKIDict.CERT_DICT[cert]
|
||||
ssc_cmd += " -c %d" % _index
|
||||
if key is not None:
|
||||
_index = PKIDict.PKIDict.KEY_DICT[key]
|
||||
ssc_cmd += " -k %d" % _index
|
||||
# write command and check result
|
||||
self.serial_port.flush()
|
||||
self.serial_port.write_line(ssc_cmd)
|
||||
self.serial_port.check(["+SSL:OK", "AND", "!+SSL:ERROR"])
|
||||
|
||||
@ssl_handler_wrapper("Target")
|
||||
def connect(self, remote_ip, remote_port, local_ip=0, local_port=0):
|
||||
self.serial_port.flush()
|
||||
self.serial_port.write_line("soc -B -t SSL -i %s -p %s" % (local_ip, local_port))
|
||||
self.serial_port.check(["OK", "AND", "!ERROR"])
|
||||
self.serial_port.flush()
|
||||
self.serial_port.write_line("soc -C -s 0 -i %s -p %s" % (remote_ip, remote_port))
|
||||
self.serial_port.check(["OK", "AND", "!ERROR"], timeout=30)
|
||||
self.ssl_id = 0
|
||||
pass
|
||||
|
||||
def accept_succeed(self):
|
||||
self.ssl_id = 1
|
||||
|
||||
class Accept(threading.Thread):
|
||||
def __init__(self, serial_port, succeed_cb):
|
||||
threading.Thread.__init__(self)
|
||||
self.setDaemon(True)
|
||||
self.serial_port = serial_port
|
||||
self.succeed_cb = succeed_cb
|
||||
self.exit_flag = threading.Event()
|
||||
|
||||
def run(self):
|
||||
while self.exit_flag.isSet() is False:
|
||||
try:
|
||||
self.serial_port.check("+ACCEPT:", timeout=1)
|
||||
self.succeed_cb()
|
||||
break
|
||||
except StandardError:
|
||||
pass
|
||||
|
||||
def exit(self):
|
||||
self.exit_flag.set()
|
||||
|
||||
@ssl_handler_wrapper("Target")
|
||||
def listen(self, local_port=0, local_ip=0):
|
||||
self.serial_port.flush()
|
||||
self.serial_port.write_line("soc -B -t SSL -i %s -p %s" % (local_ip, local_port))
|
||||
self.serial_port.check(["OK", "AND", "!ERROR"])
|
||||
self.serial_port.flush()
|
||||
self.serial_port.write_line("soc -L -s 0")
|
||||
self.serial_port.check(["OK", "AND", "!ERROR"])
|
||||
self.server_id = 0
|
||||
self.accept_thread = self.Accept(self.serial_port, self.accept_succeed)
|
||||
self.accept_thread.start()
|
||||
pass
|
||||
|
||||
@ssl_handler_wrapper("Target")
|
||||
def send(self, size=10, data=None):
|
||||
if data is not None:
|
||||
size = len(data)
|
||||
self.serial_port.flush()
|
||||
self.serial_port.write_line("soc -S -s %s -l %s" % (self.ssl_id, size))
|
||||
self.serial_port.check(["OK", "AND", "!ERROR"])
|
||||
pass
|
||||
|
||||
@ssl_handler_wrapper("Target")
|
||||
def recv(self, length, timeout=SSLHandler.TIMEOUT):
|
||||
pattern = re.compile("\+RECV:\d+,(\d+)\r\n")
|
||||
data_len = 0
|
||||
data = ""
|
||||
time1 = time.time()
|
||||
while time.time() - time1 < timeout:
|
||||
data += self.serial_port.read_data()
|
||||
if self.data_validation is True:
|
||||
if "+DATA_ERROR" in data:
|
||||
raise SSLHandlerFail("target data validation fail")
|
||||
while True:
|
||||
match = pattern.search(data)
|
||||
if match is None:
|
||||
break
|
||||
else:
|
||||
data_len += int(match.group(1))
|
||||
data = data[data.find(match.group())+len(match.group()):]
|
||||
if data_len >= length:
|
||||
result = True
|
||||
break
|
||||
else:
|
||||
result = False
|
||||
if result is False:
|
||||
raise SSLHandlerFail("Target recv fail")
|
||||
|
||||
def set_data_validation(self, validation):
|
||||
self.data_validation = validation
|
||||
self.serial_port.flush()
|
||||
self.serial_port.write_line("soc -V -s %s -o %s" % (self.ssl_id, 1 if validation is True else 0))
|
||||
self.serial_port.check(["OK", "AND", "!ERROR"])
|
||||
|
||||
@ssl_handler_wrapper("Target")
|
||||
def close(self):
|
||||
SSLHandler.close(self)
|
||||
self.serial_port.flush()
|
||||
self.serial_port.write_line("ssl -D")
|
||||
self.serial_port.check(["+SSL:OK", "OR", "+SSL:ERROR"])
|
||||
self.serial_port.write_line("soc -T")
|
||||
self.serial_port.check("+CLOSEALL")
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def calc_hash(index):
|
||||
return (index & 0xffffffff) % 83 + (index & 0xffffffff) % 167
|
||||
|
||||
|
||||
def verify_data(data, start_index):
|
||||
for i, c in enumerate(data):
|
||||
if ord(c) != calc_hash(start_index + i):
|
||||
NativeLog.add_trace_critical("[Data Validation Error] target sent data index %u is error."
|
||||
" Sent data is %x, should be %x"
|
||||
% (start_index + i, ord(c), calc_hash(start_index + i)))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def make_validation_data(length, start_index):
|
||||
return bytes().join([chr(calc_hash(start_index + i)) for i in range(length)])
|
||||
|
||||
|
||||
class PCSSLHandler(SSLHandler):
|
||||
PROTOCOL_MAPPING = {
|
||||
"SSLv23": ssl.PROTOCOL_SSLv23,
|
||||
"SSLv23_2": ssl.PROTOCOL_SSLv23,
|
||||
"SSLv20": ssl.PROTOCOL_SSLv2,
|
||||
"SSLv30": ssl.PROTOCOL_SSLv3,
|
||||
"TLSv10": ssl.PROTOCOL_TLSv1,
|
||||
"TLSv11": ssl.PROTOCOL_TLSv1_1,
|
||||
"TLSv12": ssl.PROTOCOL_TLSv1_2,
|
||||
}
|
||||
CERT_FOLDER = os.path.join(".", "PKI", PKIDict.PKIDict.CERT_FOLDER)
|
||||
KEY_FOLDER = os.path.join(".", "PKI", PKIDict.PKIDict.KEY_FOLDER)
|
||||
|
||||
def __init__(self, typ, config, serial_port):
|
||||
SSLHandler.__init__(self, typ, config, serial_port)
|
||||
self.ssl_context = None
|
||||
self.ssl = None
|
||||
self.server_sock = None
|
||||
self.send_index = 0
|
||||
self.recv_index = 0
|
||||
|
||||
class InitContextThread(threading.Thread):
|
||||
def __init__(self, handler, version, cipher_suite, ca, cert, key, verify_required, remote_cert):
|
||||
threading.Thread.__init__(self)
|
||||
self.setDaemon(True)
|
||||
self.handler = handler
|
||||
self.version = version
|
||||
self.cipher_suite = cipher_suite
|
||||
self.ca = ca
|
||||
self.cert = cert
|
||||
self.key = key
|
||||
self.verify_required = verify_required
|
||||
self.remote_cert = remote_cert
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def handle_cert(cert_file, ca_file):
|
||||
cert = PKIItem.Certificate()
|
||||
cert.parse_file(cert_file)
|
||||
ca = PKIItem.Certificate()
|
||||
ca.parse_file(ca_file)
|
||||
if cert.file_encoding == "PEM" and ca.name in cert.cert_chain:
|
||||
cert_chain_t = cert.cert_chain[1:cert.cert_chain.index(ca.name)]
|
||||
ret = ["%s.pem" % c for c in cert_chain_t]
|
||||
else:
|
||||
ret = []
|
||||
return ret
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
ssl_context = ssl.SSLContext(self.version)
|
||||
# cipher suite
|
||||
ssl_context.set_ciphers(self.cipher_suite)
|
||||
if self.ca is not None:
|
||||
ssl_context.load_verify_locations(cafile=os.path.join(self.handler.CERT_FOLDER, self.ca))
|
||||
# python ssl can't verify cert chain, don't know why
|
||||
# need to load cert between cert and ca for pem (pem cert contains cert chain)
|
||||
if self.remote_cert is not None:
|
||||
cert_chain = self.handle_cert(self.remote_cert, self.ca)
|
||||
for c in cert_chain:
|
||||
NativeLog.add_trace_info("load ca chain %s" % c)
|
||||
ssl_context.load_verify_locations(cafile=os.path.join(self.handler.CERT_FOLDER, c))
|
||||
if self.cert is not None:
|
||||
cert = os.path.join(self.handler.CERT_FOLDER, self.cert)
|
||||
key = os.path.join(self.handler.KEY_FOLDER, self.key)
|
||||
ssl_context.load_cert_chain(cert, keyfile=key)
|
||||
if self.verify_required is True:
|
||||
ssl_context.verify_mode = ssl.CERT_REQUIRED
|
||||
else:
|
||||
ssl_context.verify_mode = ssl.CERT_NONE
|
||||
self.handler.ssl_context = ssl_context
|
||||
except StandardError, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
pass
|
||||
pass
|
||||
|
||||
@ssl_handler_wrapper("PC")
|
||||
def init_context(self):
|
||||
if self.type == "client":
|
||||
version = self.PROTOCOL_MAPPING[self.config["client_version"]]
|
||||
cipher_suite = Parameter.CIPHER_SUITE[self.config["client_cipher_suite"]]
|
||||
ca = self.config["client_trust_anchor"]
|
||||
cert = self.config["client_certificate"]
|
||||
key = self.config["client_key"]
|
||||
verify_required = self.config["verify_server"]
|
||||
remote_cert = self.config["server_certificate"]
|
||||
else:
|
||||
version = self.PROTOCOL_MAPPING[self.config["server_version"]]
|
||||
cipher_suite = Parameter.CIPHER_SUITE[self.config["server_cipher_suite"]]
|
||||
ca = self.config["server_trust_anchor"]
|
||||
cert = self.config["server_certificate"]
|
||||
key = self.config["server_key"]
|
||||
verify_required = self.config["verify_client"]
|
||||
remote_cert = self.config["client_certificate"]
|
||||
|
||||
_init_context = self.InitContextThread(self, version, cipher_suite, ca, cert, key, verify_required, remote_cert)
|
||||
_init_context.start()
|
||||
_init_context.join(5)
|
||||
if self.ssl_context is None:
|
||||
raise StandardError("Init Context Fail")
|
||||
|
||||
pass
|
||||
|
||||
@ssl_handler_wrapper("PC")
|
||||
def connect(self, remote_ip, remote_port, local_ip=0, local_port=0):
|
||||
sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
|
||||
# reuse socket in TIME_WAIT state
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
sock.settimeout(self.timeout)
|
||||
sock.bind((local_ip, local_port))
|
||||
self.ssl = self.ssl_context.wrap_socket(sock)
|
||||
self.ssl.connect((remote_ip, remote_port))
|
||||
pass
|
||||
|
||||
def accept_succeed(self, ssl_new):
|
||||
ssl_new.settimeout(self.timeout)
|
||||
self.ssl = ssl_new
|
||||
|
||||
class Accept(threading.Thread):
|
||||
def __init__(self, server_sock, ssl_context, succeed_cb):
|
||||
threading.Thread.__init__(self)
|
||||
self.setDaemon(True)
|
||||
self.server_sock = server_sock
|
||||
self.ssl_context = ssl_context
|
||||
self.succeed_cb = succeed_cb
|
||||
self.exit_flag = threading.Event()
|
||||
|
||||
def run(self):
|
||||
while self.exit_flag.isSet() is False:
|
||||
try:
|
||||
new_socket, addr = self.server_sock.accept()
|
||||
ssl_new = self.ssl_context.wrap_socket(new_socket, server_side=True)
|
||||
self.succeed_cb(ssl_new)
|
||||
break
|
||||
except StandardError:
|
||||
pass
|
||||
pass
|
||||
|
||||
def exit(self):
|
||||
self.exit_flag.set()
|
||||
|
||||
@ssl_handler_wrapper("PC")
|
||||
def listen(self, local_port=0, local_ip=0):
|
||||
self.server_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
|
||||
# reuse socket in TIME_WAIT state
|
||||
self.server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.server_sock.settimeout(1)
|
||||
self.server_sock.bind((local_ip, local_port))
|
||||
self.server_sock.listen(5)
|
||||
self.accept_thread = self.Accept(self.server_sock, self.ssl_context, self.accept_succeed)
|
||||
self.accept_thread.start()
|
||||
pass
|
||||
|
||||
@ssl_handler_wrapper("PC")
|
||||
def send(self, size=10, data=None):
|
||||
if data is None:
|
||||
self.ssl.send(make_validation_data(size, self.send_index))
|
||||
if self.data_validation is True:
|
||||
self.send_index += size
|
||||
else:
|
||||
self.ssl.send(data)
|
||||
|
||||
@ssl_handler_wrapper("PC")
|
||||
def recv(self, length, timeout=SSLHandler.TIMEOUT, data_validation=False):
|
||||
time1 = time.time()
|
||||
data_len = 0
|
||||
while time.time() - time1 < timeout:
|
||||
data = self.ssl.read()
|
||||
|
||||
if data_validation is True and len(data) > 0:
|
||||
if verify_data(data, self.recv_index) is False:
|
||||
raise SSLHandlerFail("PC data validation fail, index is %s" % self.recv_index)
|
||||
self.recv_index += len(data)
|
||||
data_len += len(data)
|
||||
if data_len >= length:
|
||||
result = True
|
||||
break
|
||||
else:
|
||||
result = False
|
||||
if result is False:
|
||||
raise SSLHandlerFail("PC recv fail")
|
||||
|
||||
def set_data_validation(self, validation):
|
||||
self.data_validation = validation
|
||||
|
||||
@ssl_handler_wrapper("PC")
|
||||
def close(self):
|
||||
SSLHandler.close(self)
|
||||
if self.ssl is not None:
|
||||
self.ssl.close()
|
||||
self.ssl = None
|
||||
if self.server_sock is not None:
|
||||
self.server_sock.close()
|
||||
self.server_sock = None
|
||||
del self.ssl_context
|
||||
|
||||
|
||||
def main():
|
||||
ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||
# cipher suite
|
||||
ssl_context.set_ciphers("AES256-SHA")
|
||||
ssl_context.load_cert_chain("D:\workspace\\auto_test_script\PKI\Certificate\\"
|
||||
"L2CertRSA512sha1_L1CertRSA512sha1_RootCertRSA512sha1.pem",
|
||||
keyfile="D:\workspace\\auto_test_script\PKI\Key\PrivateKey2RSA512.pem")
|
||||
ssl_context.verify_mode = ssl.CERT_NONE
|
||||
server_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
|
||||
# reuse socket in TIME_WAIT state
|
||||
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
server_sock.settimeout(100)
|
||||
server_sock.bind(("192.168.111.5", 443))
|
||||
server_sock.listen(5)
|
||||
while True:
|
||||
try:
|
||||
new_socket, addr = server_sock.accept()
|
||||
ssl_new = ssl_context.wrap_socket(new_socket, server_side=True)
|
||||
print "server connected"
|
||||
break
|
||||
except StandardError:
|
||||
pass
|
||||
|
||||
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
240
components/test/TestCaseScript/SSLTest/SSLHandshake.py
Executable file
240
components/test/TestCaseScript/SSLTest/SSLHandshake.py
Executable file
@@ -0,0 +1,240 @@
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
import re
|
||||
|
||||
from TCAction import TCActionBase
|
||||
from TCAction import PerformanceTCBase
|
||||
from NativeLog import NativeLog, HTMLGenerator
|
||||
from Utility import MakeFolder
|
||||
|
||||
import ConfigUtility
|
||||
import Capability
|
||||
import SSLHandler
|
||||
|
||||
LOG_FOLDER = os.path.join("AT_LOG", "TEMP")
|
||||
|
||||
HEAP_SIZE_LIMIT = 30000
|
||||
|
||||
|
||||
class SSLHandshake(PerformanceTCBase.PerformanceTCBase):
|
||||
|
||||
def __init__(self, name, test_env, cmd_set, timeout=15, log_path=TCActionBase.LOG_PATH):
|
||||
PerformanceTCBase.PerformanceTCBase.__init__(self, name, test_env, cmd_set=cmd_set,
|
||||
timeout=timeout, log_path=log_path)
|
||||
self.client_type = None
|
||||
self.server_type = None
|
||||
self.client_capability = dict()
|
||||
self.server_capability = dict()
|
||||
# load param from excel
|
||||
for i in range(1, len(cmd_set)):
|
||||
if cmd_set[i][0] != "dummy":
|
||||
cmd_string = "self." + cmd_set[i][0]
|
||||
exec cmd_string
|
||||
timestamp = time.strftime("%d%H%M%S", time.localtime())
|
||||
folder = MakeFolder.make_folder(os.path.join(LOG_FOLDER, "SSLHandshake_%s" % timestamp))
|
||||
self.tested_log = os.path.join(folder, "SSLHandshakeTested.log")
|
||||
self.failed_log = os.path.join(folder, "SSLHandshakeFailed.log")
|
||||
self.memory_track_log = os.path.join(folder, "SSLHandshakeMemTrack.log")
|
||||
self.succeed_log = os.path.join(folder, "SSLHandshakeSucceed.log")
|
||||
# store test result for failed config
|
||||
self.failed_log2 = os.path.join(folder, "SSLHandshakeFailed2.log")
|
||||
self.succeed_log2 = os.path.join(folder, "SSLHandshakeSucceed2.log")
|
||||
|
||||
self.heap_size_pattern = re.compile("\+FREEHEAP:(\d+)\r\n")
|
||||
|
||||
@staticmethod
|
||||
def close(client, server):
|
||||
try:
|
||||
client.close()
|
||||
except StandardError:
|
||||
pass
|
||||
try:
|
||||
server.close()
|
||||
except StandardError:
|
||||
pass
|
||||
|
||||
def query_heap_size(self, scenario="idle"):
|
||||
self.flush_data("SSC1")
|
||||
self.serial_write_line("SSC1", "ram -H")
|
||||
match = self.check_regular_expression("SSC1", self.heap_size_pattern)
|
||||
if match is None:
|
||||
NativeLog.add_trace_critical("No response for SSC ram command")
|
||||
else:
|
||||
heap_size = int(match.group(1))
|
||||
self.log_memory("[heap size][%s] %s" % (scenario, heap_size))
|
||||
if heap_size < HEAP_SIZE_LIMIT and scenario == "idle":
|
||||
NativeLog.add_trace_critical("[HeapSize] %s" % heap_size)
|
||||
|
||||
pass
|
||||
|
||||
def prepare_handshake_test(self):
|
||||
# check if connected
|
||||
self.flush_data("SSC1")
|
||||
self.serial_write_line("SSC1", "sta -Q")
|
||||
if self.check_response("SSC1", "+JAP:CONNECTED,") is False:
|
||||
ap_ssid = self.get_parameter("ap_ssid")
|
||||
ap_password = self.get_parameter("ap_password")
|
||||
self.serial_write_line("SSC1", "sta -C -s %s -p %s" % (ap_ssid, ap_password))
|
||||
self.check_response("SSC1", "+JAP:CONNECTED,")
|
||||
self.query_heap_size()
|
||||
|
||||
@staticmethod
|
||||
def log_data_to_file(file_name, data):
|
||||
with open(file_name, "ab+") as f:
|
||||
f.write(data+"\r\n")
|
||||
|
||||
def log_test_config(self, data):
|
||||
# append to log
|
||||
with self.sync_lock:
|
||||
_formatted_data = HTMLGenerator.process_one_log_item(data)
|
||||
self.append_to_log_file(_formatted_data)
|
||||
self.log_data_to_file(self.tested_log, data)
|
||||
|
||||
def log_memory(self, data):
|
||||
self.log_data_to_file(self.memory_track_log, data)
|
||||
|
||||
def log_fail(self, data, log_type="succeed"):
|
||||
print data
|
||||
if log_type == "succeed":
|
||||
self.log_data_to_file(self.failed_log, data)
|
||||
else:
|
||||
self.log_data_to_file(self.failed_log2, data)
|
||||
|
||||
def log_succeed(self, data, log_type="succeed"):
|
||||
if log_type == "succeed":
|
||||
self.log_data_to_file(self.succeed_log, data)
|
||||
else:
|
||||
self.log_data_to_file(self.succeed_log2, data)
|
||||
|
||||
def execute(self):
|
||||
TCActionBase.TCActionBase.execute(self)
|
||||
# rewrite the following code
|
||||
if self.client_type == "PC":
|
||||
client_capability = Capability.PCSSLCapability("PCClient")
|
||||
client_handler = SSLHandler.PCSSLHandler
|
||||
client_ip = self.get_parameter("pc_ip")
|
||||
else:
|
||||
client_capability = Capability.TargetSSLCapability("TargetClient", **self.client_capability)
|
||||
client_handler = SSLHandler.TargetSSLHandler
|
||||
client_ip = self.get_parameter("target_ip")
|
||||
if self.server_type == "PC":
|
||||
server_capability = Capability.PCSSLCapability("PCServer")
|
||||
server_handler = SSLHandler.PCSSLHandler
|
||||
server_ip = self.get_parameter("pc_ip")
|
||||
else:
|
||||
server_capability = Capability.TargetSSLCapability("TargetServer", **self.server_capability)
|
||||
server_handler = SSLHandler.TargetSSLHandler
|
||||
server_ip = self.get_parameter("target_ip")
|
||||
|
||||
serial_port = SSLHandler.SerialPort(self, "SSC1")
|
||||
# generate config
|
||||
config_utility = ConfigUtility.ConfigUtility(client_capability, server_capability)
|
||||
config_list_dict = config_utility.get_all_test_config()
|
||||
|
||||
# succeed
|
||||
for config in config_list_dict["succeed"]:
|
||||
self.prepare_handshake_test()
|
||||
self.log_test_config("[Succeed config] %s" % config)
|
||||
port = random.randint(500, 50000)
|
||||
client = client_handler("client", config, serial_port)
|
||||
server = server_handler("server", config, serial_port)
|
||||
try:
|
||||
client.init_context()
|
||||
server.init_context()
|
||||
server.listen(local_ip=server_ip, local_port=port)
|
||||
client.connect(server_ip, port, local_ip=client_ip)
|
||||
self.query_heap_size(scenario="connected")
|
||||
self.log_succeed("[Succeed config] %s" % config)
|
||||
except SSLHandler.TargetFail, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
self.log_fail("[Target][%s]\r\n[Failed][Succeed config] %s" % (e, config))
|
||||
except SSLHandler.PCFail, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
self.log_fail("[PC][%s]\r\n[Failed][Succeed config] %s" % (e, config))
|
||||
|
||||
self.close(client, server)
|
||||
|
||||
# init context fail
|
||||
for config in config_list_dict["context_fail"]:
|
||||
self.prepare_handshake_test()
|
||||
port = random.randint(500, 50000)
|
||||
self.log_test_config("[Init context fail config] %s" % config)
|
||||
client = client_handler("client", config, serial_port)
|
||||
server = server_handler("server", config, serial_port)
|
||||
try:
|
||||
client.init_context()
|
||||
server.init_context()
|
||||
server.listen(local_ip=server_ip, local_port=port)
|
||||
client.connect(server_ip, port, local_ip=client_ip)
|
||||
self.log_fail("[Target]\r\n[Failed][Init context fail config] %s" % config, log_type="failed")
|
||||
except StandardError, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
self.log_succeed("[init context fail] %s" % config, log_type="failed")
|
||||
self.close(client, server)
|
||||
pass
|
||||
|
||||
# negotiation fail
|
||||
for config in config_list_dict["negotiation_fail"]:
|
||||
self.prepare_handshake_test()
|
||||
self.log_test_config("[negotiation_fail] %s" % config)
|
||||
port = random.randint(500, 50000)
|
||||
client = client_handler("client", config, serial_port)
|
||||
server = server_handler("server", config, serial_port)
|
||||
try:
|
||||
client.init_context()
|
||||
server.init_context()
|
||||
server.listen(local_ip=server_ip, local_port=port)
|
||||
except SSLHandler.TargetFail, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
self.log_fail("[Target][%s]\r\n[Failed][negotiation fail config] %s" % (e, config), log_type="failed")
|
||||
self.close(client, server)
|
||||
continue
|
||||
except SSLHandler.PCFail, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
self.log_fail("[PC][%s]\r\n[Failed][negotiation fail config] %s" % (e, config), log_type="failed")
|
||||
self.close(client, server)
|
||||
continue
|
||||
try:
|
||||
client.connect(server_ip, port, local_ip=client_ip)
|
||||
self.log_fail("[Target]\r\n[Failed][negotiation fail config] %s" % config, log_type="failed")
|
||||
except StandardError, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
self.log_succeed("[negotiation fail] %s" % config, log_type="failed")
|
||||
self.close(client, server)
|
||||
|
||||
# cert key fail
|
||||
for config in config_list_dict["cert_key_fail"]:
|
||||
self.prepare_handshake_test()
|
||||
self.log_test_config("[cert_key_fail] %s" % config)
|
||||
port = random.randint(500, 50000)
|
||||
client = client_handler("client", config, serial_port)
|
||||
server = server_handler("server", config, serial_port)
|
||||
try:
|
||||
client.init_context()
|
||||
server.init_context()
|
||||
server.listen(local_ip=server_ip, local_port=port)
|
||||
except SSLHandler.TargetFail, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
self.log_fail("[Target][%s]\r\n[Failed][cert_key fail config] %s" % (e, config), log_type="failed")
|
||||
self.close(client, server)
|
||||
continue
|
||||
except SSLHandler.PCFail, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
self.log_fail("[PC][%s]\r\n[Failed][cert_key fail config] %s" % (e, config), log_type="failed")
|
||||
self.close(client, server)
|
||||
continue
|
||||
try:
|
||||
client.connect(server_ip, port, local_ip=client_ip)
|
||||
self.log_fail("[Target][Failed][cert_key fail config] %s" % config, log_type="failed")
|
||||
except StandardError, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
self.log_succeed("[cert_key_fail] %s" % config, log_type="failed")
|
||||
self.close(client, server)
|
||||
|
||||
|
||||
def main():
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
140
components/test/TestCaseScript/SSLTest/SSLLowMem.py
Normal file
140
components/test/TestCaseScript/SSLTest/SSLLowMem.py
Normal file
@@ -0,0 +1,140 @@
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
import re
|
||||
|
||||
from TCAction import TCActionBase
|
||||
from TCAction import PerformanceTCBase
|
||||
from NativeLog import NativeLog, HTMLGenerator
|
||||
from Utility import MakeFolder
|
||||
|
||||
import ConfigUtility
|
||||
import Capability
|
||||
import SSLHandler
|
||||
|
||||
LOG_FOLDER = os.path.join("AT_LOG", "TEMP")
|
||||
|
||||
HEAP_SIZE_LIMIT = 30000
|
||||
|
||||
|
||||
class SSLLowMem(PerformanceTCBase.PerformanceTCBase):
|
||||
|
||||
def __init__(self, name, test_env, cmd_set, timeout=15, log_path=TCActionBase.LOG_PATH):
|
||||
PerformanceTCBase.PerformanceTCBase.__init__(self, name, test_env, cmd_set=cmd_set,
|
||||
timeout=timeout, log_path=log_path)
|
||||
self.client_type = None
|
||||
self.server_type = None
|
||||
self.client_capability = dict()
|
||||
self.server_capability = dict()
|
||||
self.heap_usage_range = (10000, 30000)
|
||||
self.test_time = 120
|
||||
# load param from excel
|
||||
for i in range(1, len(cmd_set)):
|
||||
if cmd_set[i][0] != "dummy":
|
||||
cmd_string = "self." + cmd_set[i][0]
|
||||
exec cmd_string
|
||||
timestamp = time.strftime("%d%H%M%S", time.localtime())
|
||||
self.heap_size_pattern = re.compile("\+FREEHEAP:(\d+)\r\n")
|
||||
|
||||
@staticmethod
|
||||
def close(client, server):
|
||||
try:
|
||||
client.close()
|
||||
except StandardError:
|
||||
pass
|
||||
try:
|
||||
server.close()
|
||||
except StandardError:
|
||||
pass
|
||||
|
||||
def query_heap_size(self, scenario="idle"):
|
||||
self.flush_data("SSC1")
|
||||
self.serial_write_line("SSC1", "ram -H")
|
||||
match = self.check_regular_expression("SSC1", self.heap_size_pattern)
|
||||
if match is None:
|
||||
NativeLog.add_trace_critical("No response for SSC ram command")
|
||||
else:
|
||||
heap_size = int(match.group(1))
|
||||
if heap_size < HEAP_SIZE_LIMIT and scenario == "idle":
|
||||
NativeLog.add_trace_critical("[HeapSize] %s" % heap_size)
|
||||
|
||||
pass
|
||||
|
||||
def prepare_handshake_test(self):
|
||||
# check if connected
|
||||
self.flush_data("SSC1")
|
||||
self.serial_write_line("SSC1", "sta -Q")
|
||||
if self.check_response("SSC1", "+JAP:CONNECTED,") is False:
|
||||
ap_ssid = self.get_parameter("ap_ssid")
|
||||
ap_password = self.get_parameter("ap_password")
|
||||
self.serial_write_line("SSC1", "sta -C -s %s -p %s" % (ap_ssid, ap_password))
|
||||
self.check_response("SSC1", "+JAP:CONNECTED,")
|
||||
# random alloc memory
|
||||
while True:
|
||||
memory_size = random.randint(self.heap_usage_range[0], self.heap_usage_range[1])
|
||||
self.serial_write_line("SSC1", "soc -M -l %s" % memory_size)
|
||||
if self.check_response("SSC1", "+SOC_BUFFER:OK", timeout=1) is True:
|
||||
break
|
||||
# query size
|
||||
self.query_heap_size()
|
||||
|
||||
@staticmethod
|
||||
def log_data_to_file(file_name, data):
|
||||
with open(file_name, "ab+") as f:
|
||||
f.write(data+"\r\n")
|
||||
|
||||
def execute(self):
|
||||
TCActionBase.TCActionBase.execute(self)
|
||||
# rewrite the following code
|
||||
if self.client_type == "PC":
|
||||
client_capability = Capability.PCSSLCapability("PCClient")
|
||||
client_handler = SSLHandler.PCSSLHandler
|
||||
client_ip = self.get_parameter("pc_ip")
|
||||
else:
|
||||
client_capability = Capability.TargetSSLCapability("TargetClient", **self.client_capability)
|
||||
client_handler = SSLHandler.TargetSSLHandler
|
||||
client_ip = self.get_parameter("target_ip")
|
||||
if self.server_type == "PC":
|
||||
server_capability = Capability.PCSSLCapability("PCServer")
|
||||
server_handler = SSLHandler.PCSSLHandler
|
||||
server_ip = self.get_parameter("pc_ip")
|
||||
else:
|
||||
server_capability = Capability.TargetSSLCapability("TargetServer", **self.server_capability)
|
||||
server_handler = SSLHandler.TargetSSLHandler
|
||||
server_ip = self.get_parameter("target_ip")
|
||||
|
||||
test_time = self.test_time * 60 # convert test time from minutes to seconds
|
||||
|
||||
serial_port = SSLHandler.SerialPort(self, "SSC1")
|
||||
# generate config
|
||||
config_utility = ConfigUtility.ConfigUtility(client_capability, server_capability)
|
||||
config_list_dict = config_utility.get_all_test_config()
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
# succeed
|
||||
for config in config_list_dict["succeed"]:
|
||||
if time.time() - start_time > test_time:
|
||||
break
|
||||
self.prepare_handshake_test()
|
||||
port = random.randint(500, 50000)
|
||||
client = client_handler("client", config, serial_port)
|
||||
server = server_handler("server", config, serial_port)
|
||||
try:
|
||||
client.init_context()
|
||||
server.init_context()
|
||||
server.listen(local_ip=server_ip, local_port=port)
|
||||
client.connect(server_ip, port, local_ip=client_ip)
|
||||
self.query_heap_size(scenario="connected")
|
||||
except SSLHandler.TargetFail, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
except SSLHandler.PCFail, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
self.close(client, server)
|
||||
|
||||
|
||||
def main():
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
147
components/test/TestCaseScript/SSLTest/SSLSendRecv.py
Normal file
147
components/test/TestCaseScript/SSLTest/SSLSendRecv.py
Normal file
@@ -0,0 +1,147 @@
|
||||
import random
|
||||
import time
|
||||
|
||||
from TCAction import TCActionBase
|
||||
from TCAction import PerformanceTCBase
|
||||
from NativeLog import NativeLog
|
||||
import ConfigUtility
|
||||
import Capability
|
||||
import SSLHandler
|
||||
|
||||
|
||||
class SSLSendRecv(PerformanceTCBase.PerformanceTCBase):
|
||||
|
||||
def __init__(self, name, test_env, cmd_set, timeout=15, log_path=TCActionBase.LOG_PATH):
|
||||
PerformanceTCBase.PerformanceTCBase.__init__(self, name, test_env, cmd_set=cmd_set,
|
||||
timeout=timeout, log_path=log_path)
|
||||
self.target_role = "Client"
|
||||
self.max_send_len = 2048
|
||||
self.test_time = 120
|
||||
self.data_validation = False
|
||||
|
||||
self.target_capability = {"version": ["SSLv23"],
|
||||
"cipher_suite": ["TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA"],
|
||||
"fragment_size": [2048],
|
||||
"verify_server": False,
|
||||
"verify_client": False,
|
||||
"key_algorithm": ["RSA2048"],
|
||||
"key_encoding": ["PEM"],
|
||||
"pem_encryption": [None],
|
||||
"certificate_encoding": ["PEM"],
|
||||
"certificate_digest": ["sha1"],
|
||||
}
|
||||
# load param from excel
|
||||
for i in range(1, len(cmd_set)):
|
||||
if cmd_set[i][0] != "dummy":
|
||||
cmd_string = "self." + cmd_set[i][0]
|
||||
exec cmd_string
|
||||
|
||||
@staticmethod
|
||||
def close(client, server):
|
||||
try:
|
||||
client.close()
|
||||
except StandardError:
|
||||
pass
|
||||
try:
|
||||
server.close()
|
||||
except StandardError:
|
||||
pass
|
||||
|
||||
def cleanup(self):
|
||||
self.serial_write_line("SSC1", "ssl -D")
|
||||
self.check_response("SSC1", "SSL")
|
||||
|
||||
def execute(self):
|
||||
TCActionBase.TCActionBase.execute(self)
|
||||
|
||||
target_role = self.target_role
|
||||
max_send_len = self.max_send_len
|
||||
test_time = self.test_time * 60
|
||||
data_validation = self.data_validation
|
||||
|
||||
ssl_port = random.randint(10000, 50000)
|
||||
NativeLog.add_prompt_trace("SSL port is %s" % ssl_port)
|
||||
|
||||
# make sure ssl context deinit
|
||||
self.serial_write_line("SSC1", "ssl -D")
|
||||
self.check_response("SSC1", "SSL")
|
||||
|
||||
# close all sockets and enlarge send buffer
|
||||
self.serial_write_line("SSC1", "soc -T")
|
||||
self.check_response("SSC1", "CLOSEALL")
|
||||
|
||||
self.serial_write_line("SSC1", "soc -M -l %s" % max_send_len)
|
||||
self.check_response("SSC1", "+SOC_BUFFER:OK")
|
||||
|
||||
# rewrite the following code
|
||||
if target_role == "Server":
|
||||
client_capability = Capability.PCSSLCapability("PCClient")
|
||||
client_handler = SSLHandler.PCSSLHandler
|
||||
client_ip = self.get_parameter("pc_ip")
|
||||
server_capability = Capability.TargetSSLCapability("TargetServer", **self.target_capability)
|
||||
server_handler = SSLHandler.TargetSSLHandler
|
||||
server_ip = self.get_parameter("target_ip")
|
||||
elif target_role == "Client":
|
||||
client_capability = Capability.TargetSSLCapability("TargetClient", **self.target_capability)
|
||||
client_handler = SSLHandler.TargetSSLHandler
|
||||
client_ip = self.get_parameter("target_ip")
|
||||
server_capability = Capability.PCSSLCapability("PCServer")
|
||||
server_handler = SSLHandler.PCSSLHandler
|
||||
server_ip = self.get_parameter("pc_ip")
|
||||
else:
|
||||
raise StandardError("Unsupported target role %s" % target_role)
|
||||
|
||||
serial_port = SSLHandler.SerialPort(self, "SSC1")
|
||||
|
||||
# generate one succeed config
|
||||
config_utility = ConfigUtility.ConfigUtility(client_capability, server_capability)
|
||||
config_list_dict = config_utility.get_all_test_config()
|
||||
|
||||
for config in config_list_dict["succeed"]:
|
||||
try:
|
||||
# create connection
|
||||
NativeLog.add_prompt_trace(str(config)) # do print config
|
||||
client = client_handler("client", config, serial_port)
|
||||
server = server_handler("server", config, serial_port)
|
||||
client.init_context()
|
||||
server.init_context()
|
||||
server.listen(local_ip=server_ip, local_port=ssl_port)
|
||||
client.connect(server_ip, ssl_port, local_ip=client_ip)
|
||||
except StandardError, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
return
|
||||
|
||||
# set data validation
|
||||
client.set_data_validation(data_validation)
|
||||
server.set_data_validation(data_validation)
|
||||
|
||||
# do send recv
|
||||
time_start = time.time()
|
||||
while time.time() - time_start < test_time:
|
||||
send_len = random.randint(1, max_send_len)
|
||||
try:
|
||||
client.send(size=send_len)
|
||||
client.send(size=send_len)
|
||||
server.recv(send_len*2)
|
||||
except StandardError, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
NativeLog.add_prompt_trace("client send / server recv fail")
|
||||
break
|
||||
try:
|
||||
# do send twice, try to create a tcp segment with 2 records
|
||||
server.send(size=send_len)
|
||||
server.send(size=send_len)
|
||||
client.recv(send_len*2)
|
||||
except StandardError, e:
|
||||
NativeLog.add_exception_log(e)
|
||||
NativeLog.add_prompt_trace("server send / client recv fail")
|
||||
break
|
||||
else:
|
||||
self.set_result("Succeed")
|
||||
|
||||
|
||||
def main():
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
1
components/test/TestCaseScript/SSLTest/__init__.py
Executable file
1
components/test/TestCaseScript/SSLTest/__init__.py
Executable file
@@ -0,0 +1 @@
|
||||
__all__ = ["Capability", "ConfigUtility", "Parameter", "SSLHandler", "SSLHandshake"]
|
Reference in New Issue
Block a user