小言_互联网的博客

上云安全,有我守护。初观HaaS100中AliOS Things系统安全能力

463人阅读  评论(0)

1、智能设备安全考虑

1.1、消费者关注

根据权威机构调查报告显示消费者在购买智能设备时的考量因素,安全和隐私的因素占比大约在50%。 

1.2、安全风险

著名网络安全公司SonicWall在其2020年发布的网络安全报告中揭露,去年(2019)其记录的针对IoT智能设备的安全攻击增长5%,并且可以预见未来针对IoT智能设备的攻击将会越来越多。

安全在智能设备开发中非常重要, 同时作为普通的开发者和中小企业从0构建一套全面且稳定的安全防护能力,也是比较困难的。 那如何轻松地构建智能设备的安全能力,免遭黑客的攻击呢?

答案就是使用AliOS Things来进行智能设备的开发, AliOS Things是阿里巴巴自主研发、面向 IoT 领域的、高可伸缩的物联网操作系统。  AliOS Things 致力于搭建云端一体化 IoT 基础设施,具备极致性能、极简开发、云端一体、丰富组件、安全防护等关键能力。

2、AliOS Things安全能力

AliOS Things在加速智能设备产品开发的同时, 注重建设智能设备的安全防护能力。

在端上安全能力的建设是以ID2为中心,目标是为物联网设备提供设备身份认证, 在上方提供使用ID2的tls安全连接协议(itls:基于mbedtls修改,主要修改mbedtls中tls协议的认证部分,改用ID2认证), 在下方需要对接各种不同厂家的不同等级的安全芯片(tee, se, mcu中的安全能力)。应用的开发者可以使用大家比较熟悉的mbedtls api来开发应用。 

 

AliOS Things的安全能力比较丰富,后续会有一系列的文章来阐述。

本文章先从应用开发者接触比较多的Mbed TLS开始介绍。

 

3、Mbed TLS 介绍

3.1、Mbed TLS 是什么

Mbed TLS 是一个提供安全基础能力的库,它提供了安全算法,X.509证书,TLS/DTLS协议的实现。

安全算法方面它主要提供了下列功能

  • 对称加密算法

AES, Blowfish, Triple-DES (3DES), DES, ARC4, Camellia, XTEA, ChaCha20

  • 对称加密算法的工作模式

ECB, CBC, CFB, CTR, GCM, CCM

  • 非对称加密算法

RSA, DH, ECC, ECDHE, ECDSA

  • Hash算法

MD2, MD4, MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, RIPEMD-160

  • 随机数
  • 消息认证算法

HMAC, Poly1305

  • 编码

ASN.1, BASE64

 

协议实现方面它提供了TLS/DTLS协议的客户端和服务端实现,支持SSL 3.0,TLS 1.0,TLS 1.1,TLS 1.2, DTLS 1.0, DTLS 1.2。 

一言以蔽之, Mbed TLS是OpenSSL的替代品,Mbed TLS比OpenSSL更轻量级,适用于资源比较受限的嵌入式设备上。

3.2、Mbed TLS 使用场景

鉴于Mbed TLS是一个提供安全基础能力的库,提供的能力比较全面,大多功能都可以单独使用。所以它的使用场景特别丰富。

  • 使用Mbed TLS把自己的web server进行安全加固,从http变成https的web站点。
  • 使用Mbed TLS访问一个https的web站点。
  • 使用Mbed TLS对数据进行加密/解密,签名/验签, Hash运算,证书生成/解析,产生随机数等。

4、Mbed TLS 源码分析

前提说明:Transport Layer Security (TLS)  是Secure Sockets Layer (SSL) 的更高级版本, TLS 1.0是在SSL 3.0的基础上开发的,TLS是IETF标准化后的重新命名。在多种代码实现中并不区分TLS与SSL的名称,在API, 数据结构中大多都使用SSL的名称。

4.1、一次握手过程

Mbed TLS的源码特别多, 下面以TLS客户端的一次TLS握手的代码实现为例,来分析一下TLS握手的处理过程。


  
  1. // 执行SSL握手,协商SSL连接的各个因素。
  2. int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl )
  3. {
  4. int ret = 0;
  5. if( ssl == NULL || ssl->conf == NULL )
  6. return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  7. MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
  8. while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
  9. {
  10. // 根据SSL握手的状态,循环处理SSL握手的各个阶段,直到握手结束。
  11. ret = mbedtls_ssl_handshake_step( ssl );
  12. if( ret != 0 )
  13. break;
  14. }
  15. MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) );
  16. return( ret );
  17. }

  
  1. // 处理SSL握手的单个步骤
  2. int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl )
  3. {
  4. int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
  5. if( ssl == NULL || ssl->conf == NULL )
  6. return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  7. #if defined(MBEDTLS_SSL_CLI_C)
  8. if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
  9. // SSL客户端主动发起SSL连接请求,在这里处理SSL握手的单个步骤。
  10. ret = mbedtls_ssl_handshake_client_step( ssl );
  11. #endif
  12. #if defined(MBEDTLS_SSL_SRV_C)
  13. if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
  14. // SSL被动接受SSL连接请求,在这里处理SSL握手的单个步骤。
  15. ret = mbedtls_ssl_handshake_server_step( ssl );
  16. #endif
  17. return( ret );
  18. }

  
  1. // SSL客户端的单个阶段的握手处理
  2. int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl )
  3. {
  4. int ret = 0;
  5. // SSL状态和参数和合法性检查
  6. if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL )
  7. return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  8. MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
  9. // flush此连接上的数据,防止上一个步骤的数据未完全发出去
  10. if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
  11. return( ret );
  12. #if defined(MBEDTLS_SSL_PROTO_DTLS)
  13. // DTLS处理
  14. if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
  15. ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
  16. {
  17. if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
  18. return( ret );
  19. }
  20. #endif /* MBEDTLS_SSL_PROTO_DTLS */
  21. /* Change state now, so that it is right in mbedtls_ssl_read_record(), used
  22. * by DTLS for dropping out-of-sequence ChangeCipherSpec records */
  23. #if defined(MBEDTLS_SSL_SESSION_TICKETS)
  24. if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC &&
  25. ssl->handshake->new_session_ticket != 0 )
  26. {
  27. ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET;
  28. }
  29. #endif
  30. switch( ssl->state )
  31. {
  32. case MBEDTLS_SSL_HELLO_REQUEST:
  33. // 切换状态hello request到发送client hello状态
  34. ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
  35. break;
  36. /*
  37. * ==> ClientHello
  38. */
  39. case MBEDTLS_SSL_CLIENT_HELLO:
  40. //发送client hello报文,主要包括ssl协议的版本,随机数,加密算法套件, 压缩算法,协议扩展。
  41. //此阶段主要是客户端用来告知服务端,自己所具备的能力,如支持的算法,协议版本,协议扩展等,
  42. //就这些能力与服务端进行协商,如服务端会选择一个算法套件。
  43. ret = ssl_write_client_hello( ssl );
  44. break;
  45. /*
  46. * <== ServerHello
  47. * Certificate
  48. * ( ServerKeyExchange )
  49. * ( CertificateRequest )
  50. * ServerHelloDone
  51. */
  52. case MBEDTLS_SSL_SERVER_HELLO:
  53. // 解析服务端发送过来的server hello报文,处理服务端发来的协议版本,随机数,session id,
  54. // 服务端选择的加密算法套件,压缩算法(一般不使用压缩),协议扩展等。
  55. // 另外如果客户端发来是重协商请求,执行重协商检查和处理。
  56. ret = ssl_parse_server_hello( ssl );
  57. break;
  58. case MBEDTLS_SSL_SERVER_CERTIFICATE:
  59. // 解析服务端发送过来的server 证书,协议证书,进行证书的合法性检查,
  60. // 检查通过后利用信任的CA证书进行验证,验证通过后检查证书的用途,检查用途合法后切换状态到
  61. // 下一个阶 MBEDTLS_SSL_SERVER_KEY_EXCHANGE。
  62. ret = mbedtls_ssl_parse_certificate( ssl );
  63. break;
  64. case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
  65. // 解析服务端的key交换,或者key计算的材料。
  66. ret = ssl_parse_server_key_exchange( ssl );
  67. break;
  68. case MBEDTLS_SSL_CERTIFICATE_REQUEST:
  69. // 解析服务度发送的证书请求报文(可选),只有在服务端要求认证客户端时才有这个报文。
  70. // 客户端在收到服务端发来的证书请求报文后,发送自己的认证给对端认证。
  71. ret = ssl_parse_certificate_request( ssl );
  72. break;
  73. case MBEDTLS_SSL_SERVER_HELLO_DONE:
  74. //解析服务度发送的server hello done报文,表示server hello阶段的报文到此结束
  75. ret = ssl_parse_server_hello_done( ssl );
  76. break;
  77. /*
  78. * ==> ( Certificate/Alert )
  79. * ClientKeyExchange
  80. * ( CertificateVerify )
  81. * ChangeCipherSpec
  82. * Finished
  83. */
  84. case MBEDTLS_SSL_CLIENT_CERTIFICATE:
  85. //发送客户端的证书,只有在收到服务端发来的证书请求时才发送。服务端会对发过去的证书进行认证
  86. //以确定客户端身份的合法性。
  87. ret = mbedtls_ssl_write_certificate( ssl );
  88. break;
  89. case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:
  90. //发送客户端的KEY协商报文,主要包括KEY协商的协议如DH, 和协商的材料。
  91. ret = ssl_write_client_key_exchange( ssl );
  92. break;
  93. case MBEDTLS_SSL_CERTIFICATE_VERIFY:
  94. ret = ssl_write_certificate_verify( ssl );
  95. break;
  96. case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:
  97. // 客户端发送changecipherspec报文,表明接下来开始使用协商计算出来的key,进行加密通信
  98. ret = mbedtls_ssl_write_change_cipher_spec( ssl );
  99. break;
  100. case MBEDTLS_SSL_CLIENT_FINISHED:
  101. // 客户端发送finished报文,表明握手结束。消息包括客户端交换过的重要信息的MAC,此消息是被加密的
  102. // 重要信息包括客户端发送的随机数,KEY交换的材料等, 这个报文的意义在于之前协商的报文虽然是明文,
  103. // 但确是不能被篡改的,所以需要一个握手最后过程的完整性保护。
  104. ret = mbedtls_ssl_write_finished( ssl );
  105. break;
  106. /*
  107. * <== ( NewSessionTicket )
  108. * ChangeCipherSpec
  109. * Finished
  110. */
  111. #if defined(MBEDTLS_SSL_SESSION_TICKETS)
  112. case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET:
  113. // 解析服务端的session ticket。
  114. ret = ssl_parse_new_session_ticket( ssl );
  115. break;
  116. #endif
  117. case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:
  118. // 解析服务端发送的changecipherspec报文,表明服务端接下来会使用之前
  119. // 协商出来的key,进行加密通信。
  120. ret = mbedtls_ssl_parse_change_cipher_spec( ssl );
  121. break;
  122. case MBEDTLS_SSL_SERVER_FINISHED:
  123. // 解析服务端的finished报文,计算之前协商过程重要信息的MAC值,保证之前的协商信息
  124. // 虽然是明文的, 但没有被篡改过。
  125. ret = mbedtls_ssl_parse_finished( ssl );
  126. break;
  127. case MBEDTLS_SSL_FLUSH_BUFFERS:
  128. // flush之前发送的协商报文
  129. MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
  130. ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
  131. break;
  132. case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
  133. // SSL连接已经建立,准备切换当前的ssl session和传输层,并释放之前旧的session和传输层数据。
  134. mbedtls_ssl_handshake_wrapup( ssl );
  135. break;
  136. default:
  137. //其他无效状态
  138. MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
  139. return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
  140. }
  141. return( ret );
  142. }

4.2、AliOS Things Mbed TLS

AliOS Things Mbed TLS是在开源的Mbed TLS 2.16.0 基础上,适配到AliOS Things。 秉承的宗旨是尽量少改动,API与开源的完全保持一致,方便开发者使用和移植上面的应用。相关代码路径在components/security/mbedtls。

AliOS Things Mbed TLS组件在开源的基础上主要有以下几点修改:

  • thread的实现。
  • network socket的发送和接受实现。
  • 动态内存的管理。
  • 适应AliOS Things的配置, 完整配置文件 components/security/mbedtls/aos/include/mbedtls_config.h 。

为适应嵌入式设备资源非常受限的场景,AliOS Things对Mbed TLS还提供了组件化的配置, 用户可以执行aos make menuconfig, 依次进入到 Utility Configuration -> Mbed TLS 2.16.0 -> Mbedtls Configuration 根据自己的场景需要,进行适当的配置, 我们对Mbed TLS组件提供了默认配置,能覆盖大部分场景。

5、Mbed TLS 使用例程

以一个简单的TLS客户端为例, 该TLS客户端访问阿里云物联网平台(上海站点)iot-as-mqtt.cn-shanghai.aliyuncs.com。


  
  1. ......
  2. #define SERVER_PORT "1883"
  3. #define SERVER_NAME "a1MZxOdcBnO.iot-as-mqtt.cn-shanghai.aliyuncs.com"
  4. #define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
  5. // 验证对端证书所需要的CA认证
  6. const char* tls_client_test_ca_pem = \
  7. "-----BEGIN CERTIFICATE-----\r\n"
  8. "MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\r\n" \
  9. "A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\r\n" \
  10. "b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\r\n" \
  11. "MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\r\n" \
  12. "YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\r\n" \
  13. "aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\r\n" \
  14. "jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\r\n" \
  15. "xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\r\n" \
  16. "1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\r\n" \
  17. "snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\r\n" \
  18. "U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\r\n" \
  19. "9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\r\n" \
  20. "BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\r\n" \
  21. "AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\r\n" \
  22. "yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\r\n" \
  23. "38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\r\n" \
  24. "AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\r\n" \
  25. "DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\r\n" \
  26. "HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\r\n" \
  27. "-----END CERTIFICATE-----\r\n";
  28. int tls_client_test( void )
  29. {
  30. mbedtls_net_context server_fd;
  31. mbedtls_ssl_context ssl;
  32. mbedtls_ssl_config conf;
  33. mbedtls_x509_crt cacert;
  34. ......
  35. /* 设置DEBUG级别 */
  36. #if defined(MBEDTLS_DEBUG_C)
  37. mbedtls_debug_set_threshold( DEBUG_LEVEL );
  38. #endif
  39. // 0. 初始化需要的数据结构,
  40. mbedtls_net_init( &server_fd );
  41. mbedtls_ssl_init( &ssl );
  42. mbedtls_ssl_config_init( &conf );
  43. mbedtls_x509_crt_init( &cacert );
  44. // 1. 加载信任的CA证书
  45. mbedtls_x509_crt_parse( &cacert, (const unsigned char *) tls_client_test_ca_pem,
  46. strlen( tls_client_test_ca_pem ) + 1 );
  47. // 2. 建立TCP的连接
  48. mbedtls_net_connect( &server_fd, SERVER_NAME, SERVER_PORT, MBEDTLS_NET_PROTO_TCP )
  49. // 3. 使用SSL默认配置, 设定为SSL客户端,采用TCP。
  50. mbedtls_ssl_config_defaults( &conf,
  51. MBEDTLS_SSL_IS_CLIENT,
  52. MBEDTLS_SSL_TRANSPORT_STREAM,
  53. MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
  54. // 3.1. 配置ssl的认证模式为需要认证对端。
  55. mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED );
  56. // 3.2. 配置信任的CA链
  57. mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
  58. // 3.3. 配置系统的随机数发生函数。这里tls_client_random为自己实现的随机数发生函数。
  59. mbedtls_ssl_conf_rng( &conf, tls_client_random, NULL );
  60. // 3.4. 配置debug函数,这里my_debug为自己实现的debug函数,比如是一个简单的打印到串口的函数。
  61. mbedtls_ssl_conf_dbg( &conf, my_debug, NULL );
  62. #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
  63. // 3.5. 配置SSL的最大分片长度。
  64. mbedtls_ssl_conf_max_frag_len( &conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096 );
  65. #endif
  66. // 3.6. 使以上的配置conf对当前SSL连接 ssl 生效。
  67. mbedtls_ssl_setup( &ssl, &conf )
  68. // 3.7. 为当前SSL连接ssl设置对端的主机名。
  69. mbedtls_ssl_set_hostname( &ssl, SERVER_NAME )
  70. // 3.8. 为当前SSL连接ssl设置ssl的I/O函数分别为mbedtls_net_recv/mbedtls_net_send。
  71. mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
  72. // 4. 发起SSL握手
  73. mbedtls_ssl_handshake( &ssl );
  74. // 5. 获得对端证书的认证结果。注意这里只是得到认证结果,真正的认证过程是在上一步SSL握手过程中。
  75. mbedtls_ssl_get_verify_result( &ssl );
  76. // 6. 发送数据给对端。SSL握手成功后,SSL连接已经建立,此时可以利用SSL连接
  77. // 发送出去的数据是被加密和完整性保护的。
  78. mbedtls_ssl_write( &ssl, buf, len );
  79. // 7. 从SSL连接中读取数据。
  80. do {
  81. ret = mbedtls_ssl_read( &ssl, buf, buf_len -1 );
  82. if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
  83. continue;
  84. if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY )
  85. break;
  86. if(ret <= 0)
  87. break;
  88. ......
  89. } while (1);
  90. // 8. 关闭SSL连接。
  91. mbedtls_ssl_close_notify( &ssl );
  92. // 9. 释放SSL相关资源。
  93. mbedtls_net_free( &server_fd );
  94. mbedtls_x509_crt_free( &cacert );
  95. mbedtls_ssl_free( &ssl );
  96. mbedtls_ssl_config_free( &conf );
  97. mbedtls_free(buf);
  98. ......
  99. }

6、Mbed TLS 使用常见问题

1、TLS 握手失败,Debug消息显示"buffer too small ..." 或者 "bad message length"

这可能是TLS消息出来的I/O buffer小于消息的长度, 通过配置增大I/O buffer即可, 下列通过AliOS Things的menuconfig来配置,Mbedtls Configuration -> TLS/DTLS protocol support -> TLS/DTLS maximum incoming/outgoing content length , AliOS Things默认配置的I/O buffer为4KB, 一般扩大到16384 (16KB)可以解决所有的此类问题。

2、支持TLS1.3吗?

暂不支持TLS1.3,  AliOS Things 的Mbeb TLS组件能力与社区的相同版本能力保持一致,目前支持的协议版本:SSL 3.0,TLS 1.0,TLS 1.1,TLS 1.2, DTLS 1.0, DTLS 1.2。 现在主流服务器都会向后兼容支持TLS1.2等,不会强制客户端使用TLS1.3版本。 

7、开发者技术支持

如需更多技术支持,可加入钉钉开发者群

更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/

 


转载:https://blog.csdn.net/HaaSTech/article/details/111029069
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场