EmbedTLS + Eclipse C/C++测试用例SSL客户端和服务器

EmbedTLS + Eclipse C/C++测试用例SSL客户端和服务器


(1)说明

STM32移植使用mbedtls-2.24.0点这里:https://blog.csdn.net/qq153471503/article/details/109461794

mbedtls下载地址:https://github.com/ARMmbed/mbedtls

embedtls的ssl示例代码在这里可以找到:https://github.com/ARMmbed/mbedtls/tree/development/programs/ssl


(2)Eclipse的embedtls移植

我是用的是Eclipse C/C++和MinGW编译工具链,embedtls移植很简单,只需要把源码目录下的include和library文件夹拷贝到工程目录下即可,如下图:
在这里插入图片描述

然后右键工程->Properties->C/C++ Build->Settings->Tool Sttings->GCC C Compiler->Include添加头文件包含,如下图:
在这里插入图片描述

然后使用C99语法编译规则:
在这里插入图片描述

因为mingw使用的标准系统调用,在win上就得链接windows系统的库,所以还需要添加一个链接标记:
在这里插入图片描述


(3)OpenSSL公私钥及证书生成

点这里:https://blog.csdn.net/qq153471503/article/details/109524764


(4)测试

embedtls认证模式说明

  • MBEDTLS_SSL_VERIFY_NONE:不检查对等证书(也就是无认证)。(服务器默认值,如果客户端配置为此选项那么连接是不安全的;如果服务器配置为此值那么是单向认证。

  • MBEDTLS_SSL_VERIFY_OPTIONAL :检查对等证书(也就是单向认证),但即使验证失败,握手仍将继续;可以在握手完成后调用mbedtls_ssl_get_verify_result()查看验证结果。

  • MBEDTLS_SSL_VERIFY_REQUIRED :客户端服务器必须同时出示有效证书(也就是双向认证),如果验证失败,握手将终止。(客户端默认值)

embedtls单向认证设置

  • 服务器认证模式设置:MBEDTLS_SSL_VERIFY_OPTIONAL、MBEDTLS_SSL_VERIFY_NONE。如果服务器设置为MBEDTLS_SSL_VERIFY_NONE,不管客户端设置什么属性,在握手时候都不会对证书进行认证;如果设置为MBEDTLS_SSL_VERIFY_OPTIONAL,那么进行单向认证,验证失败的话,通信仍然有效。

  • 客户端认证模式设置:根据需求可选择MBEDTLS_SSL_VERIFY_NONE(不认证)、MBEDTLS_SSL_VERIFY_OPTIONAL(验证若失败也会继续保持通信)、MBEDTLS_SSL_VERIFY_REQUIRED(验证失败将终止连接)。

embedtlss双向认证设置:

  • 服务器设置为MBEDTLS_SSL_VERIFY_REQUIRED

  • 客户端根据安全需求选择MBEDTLS_SSL_VERIFY_NONE(不检查)、MBEDTLS_SSL_VERIFY_OPTIONAL(验证但是验证失败通信仍有效)、MBEDTLS_SSL_VERIFY_REQUIRED(验证失败通信无效)

在代码中这个宏定义控制着是否加载服务器的证书和密钥,如果是单向认证,客户端是不需要加载服务器的证书和密钥的,当然加载上也不影响。
在这里插入图片描述

代码示例

1、客户端代码模型
/*
 * main.c
 *
 *  Created on: 2020年10月29日
 *      Author: hello
 */

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "mbedtls/config.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/certs.h"

#define debug_e(fmt, ...) do{fprintf(stderr, fmt, ##__VA_ARGS__);fflush(stderr);}while(0);
#define debug(fmt, ...)   do{printf(fmt, ##__VA_ARGS__);fflush(stdout);}while(0);

unsigned char mbedtls_ca_crt[] =
{
	"-----BEGIN CERTIFICATE-----\r\n"                                      \
	"MIIDPTCCAiUCFAyaaimE7qW89Z0Verz2WN3cABu4MA0GCSqGSIb3DQEBCwUAMFox\r\n" \
	"CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoM\r\n" \
	"BFFEWlkxFTATBgNVBAsMDHd3dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwIBcNMjAx\r\n" \
	"MTA1MDgxOTM0WhgPMjEyMDEwMTIwODE5MzRaMFoxCzAJBgNVBAYTAkNOMQswCQYD\r\n" \
	"VQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoMBFFEWlkxFTATBgNVBAsMDHd3\r\n" \
	"dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\r\n" \
	"ggEKAoIBAQDWU0v4jZ1OPxpGJT8kGKer3tWtLE8Lc7DdDIiikerznKsBXtjxMjZH\r\n" \
	"+HlEjf/dp5LqQhsEfVQa7+YXJGVmdXvTpGrIkP0YiAlQscdgmFkoRcyEVJY/oCgE\r\n" \
	"BhIKh68otjZkVgK/E4qzpv2C6575iR4WxJG01LAVzdRvDPYyK08aXfKgTxygxJOC\r\n" \
	"40iQicOVZ8/s9iBfPxXXPaYf5tOf9nGi4fOba8eGa32ZtpJCBHS45Z5JYAWSM2aW\r\n" \
	"s9O7WQRvehw4eOza5gtw/+SlKHB4SlguwNBxz+kMS6t5PN16GPZW+vsY4aVSaXw6\r\n" \
	"5z2fZTTtvFoUT0j40fRF8N1BPV5ubZr5AgMBAAEwDQYJKoZIhvcNAQELBQADggEB\r\n" \
	"AK+6MRg6U7cT2fFsKRlhYGB1Q7pY8jn8RmdEOHwfbEFiW1as2DantVs1S8ZWgIL8\r\n" \
	"+gu0FlNC1QlPOVceF2SCl/44dtgXSSGqivZfnK9v8Gg7HMQMSgXtQlULu4piVpVw\r\n" \
	"pi3HkzIBsQiHtBaLB7ukmOmFXFXorrHbVxsIK9ZZW+OAP+E8O0byEVkyUMCLugxd\r\n" \
	"B8IQiGN0SmIOIuM5VoRujnLBBs8GCY+XmEf3qgHU+Tv5I6IhSL+p0eTfVP17ZFU4\r\n" \
	"a6xkq64n74XDOKlpIEQ9NnHpHiQmCYkMBZwC2NBNXKG/uw5PKkV51kFqaHe8T29n\r\n" \
	"4uhXD15/+AkOnvhSt7Uuooc=\r\n"                                         \
	"-----END CERTIFICATE-----\r\n"
};

unsigned char mbedtls_client_crt[] =
{
	"-----BEGIN CERTIFICATE-----\r\n" \
	"MIIDYDCCAkgCFG2ck7C9+1Hyz/ipV3TxBxUYfvHdMA0GCSqGSIb3DQEBCwUAMFox\r\n" \
	"CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoM\r\n" \
	"BFFEWlkxFTATBgNVBAsMDHd3dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwIBcNMjAx\r\n" \
	"MTA2MDUzNjM2WhgPMjEyMDEwMTMwNTM2MzZaMH0xCzAJBgNVBAYTAkNOMQswCQYD\r\n" \
	"VQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoMBFFEWlkxFTATBgNVBAsMDHd3\r\n" \
	"dy50ZXN0LmNvbTEPMA0GA1UEAwwGQ0xJRU5UMR0wGwYJKoZIhvcNAQkBFg5hZG1p\r\n" \
	"bkB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK/MX5t+\r\n" \
	"FU6de4bgZer45C5CjkwtbS7nSdBiMmZSbN4NRHDqhsBTnqK4W2TkYxKjY+YOos5S\r\n" \
	"LCN/gaRY1SANJ10Ohdvyr+GJBv/MKPdCWA0MScCUT9B+ihgX4MhBLwz0SNnlcT97\r\n" \
	"zA5owB6ynj/hY26foOto9eFVRVl1tUaXm94g6JcMZdI7/ie0KtzMLb0vnSII5eXk\r\n" \
	"61vRQ03XOh9D3iiYQ6CfYLwC7NA2i2fYi7mFCGhFJyUIgZSF70Qd5lzd2bYZEfYr\r\n" \
	"zZs7m4TZ60Gs78meystKN1AxtPHTMhW3tjekWIqvbVWE2H+QQwWosmOovRr1dNDh\r\n" \
	"h+JNJZeNJAY7rHMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAZnoOOJfqLVxYLKrQ\r\n" \
	"o9nlhHmN+Fh/8Gs+gECocg0f4Yj+XFHnwGut3M79aPHGgNLt62sIK03tAPzjBh89\r\n" \
	"+PLMsM80nh17AgE5xNEJUl2jxOzwAKMuBILgP9IAXSTqAs+xEd7ZJki0eiNXIAoV\r\n" \
	"GJgsXxL7MoXMO/x6B5inwIIhbaPdC2VzHC/SV5V1HvGVV/OJnJuLwemjCaJTEcaZ\r\n" \
	"x9JVlal7CXk8W8DeSz+PgrdFwdnT0NU+KGFuW5hCZHdsASYtURsdpO9jYFBxQdsF\r\n" \
	"jMGWYZbUH6t5hHVfjp/lLPxGHvqR90EcYS+PwWzNSw2IACw2EnyvDYZwzmUM9J9g\r\n" \
	"Ak7ypg==\r\n" \
	"-----END CERTIFICATE-----\r\n"
};


unsigned char mbedtls_client_key[] =
{
	"-----BEGIN RSA PRIVATE KEY-----\r\n"                                  \
	"Proc-Type: 4,ENCRYPTED\r\n"                                           \
	"DEK-Info: AES-256-CBC,784C65C31E5AB3918DD25BC12DF00B4B\r\n"           \
	"\r\n"                                                                 \
	"R3IW5IZg7ClBUiPec7wTdjBBs6WSWLacnThO/3X77kY3OzEApIpQq8RVS8oiMZB7\r\n" \
	"N7Q65KTP1TOCZl/AWiiGcW0RCUAeuVM9cWw4GqfEYk0l1x7OWdc8AZu11FJ8WcUy\r\n" \
	"BJDgv1h1fY+XzM4+cgDUUzHOJt9QHjQ6iEaheisqeHIZkHfRYqR8kNQOBi1280tL\r\n" \
	"9lO8Ns75py9YvkPWHT9lUy1T3avJeuoU7JiL1v4iUHW9wUi1NuPwxamoDjrtwUtJ\r\n" \
	"zi0vy8/Xs4x38gLT0fv1UIvD1yS7W1R+c5melHkLYboPUg8i5azuSLYXSD0yIHh/\r\n" \
	"Xhb2AhpQF6PuGdapR1+tMne6pP2+rI3B9J9bPwfMN0m/SBy4me9McYfLs08dsmuz\r\n" \
	"eLGwwcLWQDtigCjFshTwhXVeStS0vVDEJmLGMOPiLtXFNdPyZthdI/QvJVlLAOXS\r\n" \
	"76Q4mKzczWBqWRDLknkKxq5fgGqvXkiIRgecXNTkFanVebIT74O8egWvTQT6CSQ6\r\n" \
	"TYckto3rBw+5MCM0wlhEh+5CgDJ3+1UsQkeqAizz3We/p0qTKR+0bwnm9HO8V3MW\r\n" \
	"62QmPzLEzdDvPSLxjSOT61Qe5LxQMyhvRw9JXl1flcJex/PLCZIu9/Qn/QlM9oyU\r\n" \
	"rspMDEJH9nVI8VyE94krwvCQYJ163bRRvraj/zQ8hPaCnpMuORYbBl1BG1e6DeHH\r\n" \
	"o++DtJ1aEPF2M8QNIORi5YQKfgcfqzEMMULw8ZoToomEIj3Mox/gL3idB9YYX5o+\r\n" \
	"GgerK6mjNkbAErpcf5XQG8jKdaQILp/JyUy8a+HdP7oFUr9Sc7Wr+Kg0KqVnlhMM\r\n" \
	"w09U3xHAcbc4yuRK7inozGixWEBvXlb4e7SEAg2Jeh6gjDEBWOCDQR09FXmkZw/I\r\n" \
	"dY484u0r/Uikme39IXVtPE8ovaNUjLrTf8pcKgZiRg51+k/xoRJXRmUTFc2pE67g\r\n" \
	"niy4JhdG1bd1SWy3AYfVSd6aST/VJGjxxu71qg6LPAzu7S9ihuRQNaiEabk+O34x\r\n" \
	"cHKbD7QO0O4ke/1wCeJFmcVEFHxrscoQM7g2TD5T4F0lA+c+D/jDq/LIOLvHIWSb\r\n" \
	"CAXnOsJd0vxg99IBZV+9IqvIiWuxh0Aian1XUxaQU/Uc0qE9h/JL2wxMLgG9CVxU\r\n" \
	"U2KdbcBLnq3/UqFDr536ANufJss/9eccowT/jr3vwoIfnRMYyp++D6XfmZqWlPuF\r\n" \
	"SKw20WGADuAl1vHYdDbaPBbH2IkvIRwO/tjCG16D/I1KnAZcMIAPSAzDIi9vhvfS\r\n" \
	"w2YXgTXJ3jXzJ7T30pc+0GVFckVqivMDNyq0kIWOR47CrL5dBub/KZyIBtKASHMe\r\n" \
	"AguG7jvtz/3zIVdVJwGc31MxPrtINf0A33IGOx/uwzlcxOChwKNeRn63IGLU3rqW\r\n" \
	"0xWpYNeeL/YKxKYttnpw3JQ0/8J2TrGvMg7hWLKl1rCXdIqAaz1ZmlczDRLbznCl\r\n" \
	"dNBKN67zwe/YqyGAoi6jfvIEHs7k7JPQQhwbDlY9XzEDAvc5kNQ4BToeDf8DFW+N\r\n" \
	"wvbgXy04sFIXOYCCkgEcrqOURMTU8dQ+/gSqAnMdFE1CbZSELQVe9pcO8ea3Usis\r\n" \
	"-----END RSA PRIVATE KEY-----\r\n"                                    \
};

typedef struct
{
	mbedtls_net_context netctx;
	mbedtls_ssl_context sslctx;
	mbedtls_ssl_config sslcfg;
	mbedtls_ctr_drbg_context drbgctx;
	mbedtls_entropy_context etpyctx;
	mbedtls_x509_crt x509cacrt;
	mbedtls_x509_crt x509clicrt;
	mbedtls_pk_context pkey;
}mbedtls_client_t;

size_t mbedtls_client_key_len = sizeof(mbedtls_client_key);
size_t mbedtls_client_crt_len = sizeof(mbedtls_client_crt);
size_t mbedtls_ca_crt_len = sizeof(mbedtls_ca_crt);

unsigned char Buffer[1024];
mbedtls_client_t client;

#define IP "192.168.31.16"
#define PORT "5004"

mbedtls_x509_crt_profile x509_crt_profile =
{
    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
    0xFFFFFFF, /* Any PK alg    */
    0xFFFFFFF, /* Any curve     */
    2048,      /* 密钥长度为2048 */
};

static int mbedtls_ssl_sig_hashes[] =
{
    MBEDTLS_MD_SHA512,
    MBEDTLS_MD_SHA384,
    MBEDTLS_MD_SHA256,
    MBEDTLS_MD_SHA224,
    MBEDTLS_MD_SHA1,
    MBEDTLS_MD_NONE
};

int mbedtls_ssl_client_init(mbedtls_client_t* client,
							const void* cacert, size_t cacertLength,
							const void* clicert,size_t clicertLength,
							const void* clikey, size_t clikeyLength,
							const void* clipwd, size_t clipwdLength,
                            const void* pers,   size_t persLength,
							const void* CNname)
{
	int ret = 0;

	//
	// 初始化
	//
	mbedtls_net_init(&client->netctx);
	mbedtls_ssl_init(&client->sslctx);
	mbedtls_ssl_config_init(&client->sslcfg);
	mbedtls_ctr_drbg_init(&client->drbgctx);
	mbedtls_x509_crt_init(&client->x509cacrt);
	mbedtls_x509_crt_init(&client->x509clicrt);
	mbedtls_pk_init(&client->pkey);
	mbedtls_entropy_init(&client->etpyctx);

	// 加载CA证书
	if((ret = mbedtls_x509_crt_parse(&client->x509cacrt, (const unsigned char *)cacert, cacertLength)) != 0)
		return -1;

	if(clicert != NULL)
	{
		// 加载客户端证书
		if((ret = mbedtls_x509_crt_parse(&client->x509clicrt, (const unsigned char *)clicert, clicertLength)) != 0)
			return -2;

		// 加载服务器密钥
		if((ret = mbedtls_pk_parse_key(&client->pkey, (const unsigned char *) clikey, clikeyLength, (const unsigned char *)clipwd, clipwdLength)) != 0)
			return -3;

		// 设置客户端证书和密钥关联
		if ((ret = mbedtls_ssl_conf_own_cert(&client->sslcfg, &client->x509clicrt, &client->pkey)) != 0)
			return -4;
	}

	// 设置SSL/TLS熵源
	if((ret = mbedtls_ctr_drbg_seed(&client->drbgctx, mbedtls_entropy_func, &client->etpyctx, (const unsigned char *)pers, persLength)) != 0)
		return -5;

	// 设置SSL为客户端
	ret = mbedtls_ssl_config_defaults(&client->sslcfg, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
	if(ret != 0)
		return -6;

	// 设置用于验证的X.509安全配置文件
	mbedtls_ssl_conf_cert_profile(&client->sslcfg, &x509_crt_profile);

	// 设置握手签名的允许/首选散列算法
	mbedtls_ssl_conf_sig_hashes(&client->sslcfg, mbedtls_ssl_sig_hashes);

	//
	// 设置认证模式
	//
	// MBEDTLS_SSL_VERIFY_NONE     :不检查对等证书(服务器默认值)。如果客户端配置为此选项那么连接是不安全的。
	//
	// MBEDTLS_SSL_VERIFY_OPTIONAL :检查对等证书,但即使验证失败,握手仍将继续;
	//                               可以在握手完成后调用mbedtls_ssl_get_verify_result()查看验证结果。
	//
	// MBEDTLS_SSL_VERIFY_REQUIRED :同时必须出示有效证书,如果验证失败,握手将终止。(客户端默认值)
	//
	mbedtls_ssl_conf_authmode(&client->sslcfg, MBEDTLS_SSL_VERIFY_REQUIRED);

	// 设置随机数生成器回调
	mbedtls_ssl_conf_rng(&client->sslcfg, mbedtls_ctr_drbg_random, &client->drbgctx);

	// 设置CA证书
	mbedtls_ssl_conf_ca_chain(&client->sslcfg, &client->x509cacrt, NULL);

	// 配置设置
	if((ret = mbedtls_ssl_setup(&client->sslctx, &client->sslcfg)) != 0)
		return -7;

	// 设置SSL服务器CN名称
	if((ret = mbedtls_ssl_set_hostname(&client->sslctx, (const char *)CNname)) != 0)
		return -8;

	return 0;
}

int mbedtls_ssl_client_connect(mbedtls_client_t* client,const void* ip, const void* port)
{
	int ret = 0;

	// 重置客户端连接
	mbedtls_net_free(&client->netctx);

	// 重置SSL会话信息
	mbedtls_ssl_session_reset(&client->sslctx);

	// 连接到服务器
	if((ret = mbedtls_net_connect(&client->netctx, (const char *)ip, (const char *)port, MBEDTLS_NET_PROTO_TCP)) != 0)
		return -1;

	// 设置数据接收发送回调
	mbedtls_ssl_set_bio(&client->sslctx,
						&client->netctx,
						mbedtls_net_send,
						mbedtls_net_recv,
						mbedtls_net_recv_timeout);

	// 握手
	while((ret = mbedtls_ssl_handshake(&client->sslctx)) != 0)
	{
		if((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE))
			return -2;
	}

	// 获取验证结果
	if((ret = mbedtls_ssl_get_verify_result(&client->sslctx)) != 0)
	{
		char vrfy_buf[128];
		int flags = mbedtls_ssl_get_verify_result(&client->sslctx);
		mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", flags );
		debug_e( "%s\n", vrfy_buf );
//		return -3;
	}

	return 0;
}

void mbedtls_ssl_client_destory(mbedtls_client_t* client)
{
	mbedtls_net_free(&client->netctx);
	mbedtls_x509_crt_free(&client->x509cacrt);
	mbedtls_x509_crt_free(&client->x509clicrt);
	mbedtls_pk_free(&client->pkey);
	mbedtls_ssl_free(&client->sslctx);
	mbedtls_ssl_config_free(&client->sslcfg);
	mbedtls_ctr_drbg_free(&client->drbgctx);
	mbedtls_entropy_free(&client->etpyctx);
}

void mbedtls_ssl_client_disconnect(mbedtls_client_t* client)
{
	mbedtls_ssl_close_notify(&client->sslctx);
}

#define AUTOMODE 1   // =1:双向认证  =0:单向认证

int main(void)
{
	int ret = 0;

	debug("-------------------- SSL Client Demo ---------------------------\r\n");

#if (AUTOMODE == 1)
	if((ret = mbedtls_ssl_client_init(&client,
			  mbedtls_ca_crt,
			  mbedtls_ca_crt_len,
			  mbedtls_client_crt,
			  mbedtls_client_crt_len,
			  mbedtls_client_key,
			  mbedtls_client_key_len,
			  "zxcvbnm.",
			  strlen("zxcvbnm."),
			  "ssl_client",
			  strlen("ssl_client"),
			  "SERVER")) != 0)
#else
	if((ret = mbedtls_ssl_client_init(&client,
			  mbedtls_ca_crt,
			  mbedtls_ca_crt_len,
			  NULL,
			  0,
			  NULL,
			  0,
			  NULL,
			  0,
			  "ssl_client",
			  strlen("ssl_client"),
			  "SERVER")) != 0)
#endif
	{
		debug_e(" init failed,err:%d.\r\n", ret);
		goto __exit;
	}
	debug(" ssl client init ok. \r\n");

	if((ret = mbedtls_ssl_client_connect(&client, IP, PORT)) != 0)
	{
		debug_e(" connect failed,err:%X\r\n", ret);
		goto __exit;
	}

	debug(" ssl connect ok. \r\n");

	if(mbedtls_ssl_write(&client.sslctx, (const unsigned char *)"Hello Server !", strlen("Hello Server !")) < 0)
	{
		debug_e(" write failed,errcode:%d.\r\n", ret);
		goto __exit;
	}

	debug(" %d bytes written. \r\n", strlen("Hello Server !"));

	do
	{
		memset(Buffer, 0X00, sizeof(Buffer));

		ret = mbedtls_ssl_read(&client.sslctx, Buffer, sizeof(Buffer));

		if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
		{
			continue;
		}

		if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)  // 远程关闭了连接
		{
			break;
		}

		if(ret <= 0)
		{
			break;
		}

		debug(" %d bytes read:[%s]\r\n", ret, Buffer);

	}while(1);

__exit:
	mbedtls_ssl_client_disconnect(&client);
	mbedtls_ssl_client_destory(&client);
	return 0;
}

2、服务器代码模型
/*
 * main.c
 *
 *  Created on: 2020年10月29日
 *      Author: hello
 */


#include <stdlib.h>
#include <string.h>

#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/certs.h"
#include "mbedtls/x509.h"
#include "mbedtls/ssl.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
#include "mbedtls/config.h"

#define debug_e(fmt, ...) do{fprintf(stderr, fmt, ##__VA_ARGS__);fflush(stderr);}while(0);
#define debug(fmt, ...)   do{printf(fmt, ##__VA_ARGS__);fflush(stdout);}while(0);

#define IP   "192.168.31.16"
#define PORT "5004"

unsigned char mbedtls_ca_crt[] =
{
	"-----BEGIN CERTIFICATE-----\r\n"                                      \
	"MIIDPTCCAiUCFAyaaimE7qW89Z0Verz2WN3cABu4MA0GCSqGSIb3DQEBCwUAMFox\r\n" \
	"CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoM\r\n" \
	"BFFEWlkxFTATBgNVBAsMDHd3dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwIBcNMjAx\r\n" \
	"MTA1MDgxOTM0WhgPMjEyMDEwMTIwODE5MzRaMFoxCzAJBgNVBAYTAkNOMQswCQYD\r\n" \
	"VQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoMBFFEWlkxFTATBgNVBAsMDHd3\r\n" \
	"dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\r\n" \
	"ggEKAoIBAQDWU0v4jZ1OPxpGJT8kGKer3tWtLE8Lc7DdDIiikerznKsBXtjxMjZH\r\n" \
	"+HlEjf/dp5LqQhsEfVQa7+YXJGVmdXvTpGrIkP0YiAlQscdgmFkoRcyEVJY/oCgE\r\n" \
	"BhIKh68otjZkVgK/E4qzpv2C6575iR4WxJG01LAVzdRvDPYyK08aXfKgTxygxJOC\r\n" \
	"40iQicOVZ8/s9iBfPxXXPaYf5tOf9nGi4fOba8eGa32ZtpJCBHS45Z5JYAWSM2aW\r\n" \
	"s9O7WQRvehw4eOza5gtw/+SlKHB4SlguwNBxz+kMS6t5PN16GPZW+vsY4aVSaXw6\r\n" \
	"5z2fZTTtvFoUT0j40fRF8N1BPV5ubZr5AgMBAAEwDQYJKoZIhvcNAQELBQADggEB\r\n" \
	"AK+6MRg6U7cT2fFsKRlhYGB1Q7pY8jn8RmdEOHwfbEFiW1as2DantVs1S8ZWgIL8\r\n" \
	"+gu0FlNC1QlPOVceF2SCl/44dtgXSSGqivZfnK9v8Gg7HMQMSgXtQlULu4piVpVw\r\n" \
	"pi3HkzIBsQiHtBaLB7ukmOmFXFXorrHbVxsIK9ZZW+OAP+E8O0byEVkyUMCLugxd\r\n" \
	"B8IQiGN0SmIOIuM5VoRujnLBBs8GCY+XmEf3qgHU+Tv5I6IhSL+p0eTfVP17ZFU4\r\n" \
	"a6xkq64n74XDOKlpIEQ9NnHpHiQmCYkMBZwC2NBNXKG/uw5PKkV51kFqaHe8T29n\r\n" \
	"4uhXD15/+AkOnvhSt7Uuooc=\r\n"                                         \
	"-----END CERTIFICATE-----\r\n"
};

unsigned char mbedtls_srv_crt[] =
{
	"-----BEGIN CERTIFICATE-----\r\n" \
	"MIIDQTCCAikCFG2ck7C9+1Hyz/ipV3TxBxUYfvHbMA0GCSqGSIb3DQEBCwUAMFox\r\n" \
	"CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoM\r\n" \
	"BFFEWlkxFTATBgNVBAsMDHd3dy5xZHp5LmNvbTELMAkGA1UEAwwCQ0EwIBcNMjAx\r\n" \
	"MTA1MDgyMDAwWhgPMjEyMDEwMTIwODIwMDBaMF4xCzAJBgNVBAYTAkNOMQswCQYD\r\n" \
	"VQQIDAJTRDELMAkGA1UEBwwCSk4xDTALBgNVBAoMBFFEWlkxFTATBgNVBAsMDHd3\r\n" \
	"dy5xZHp5LmNvbTEPMA0GA1UEAwwGU0VSVkVSMIIBIjANBgkqhkiG9w0BAQEFAAOC\r\n" \
	"AQ8AMIIBCgKCAQEAt9su9lcpQ+UjSuk9t3WDes/XmRNvC05XfyEWELwFAJXtumAD\r\n" \
	"HSLD3xiZE+VPOdYkicUl9LwJmZrpS+M+777klhYUKijrinz9f3pFdT9e3s1cDFu4\r\n" \
	"J4+DE6rtIq7tXlS9bC54SKua+HPsVnNd3xEyxIFyEahZKAkYfB9gb9Qh/meHFQC7\r\n" \
	"q0erggt8/haabjvAqdXw8A1I1zgVfqTAVP9TuHAN+sZsnkA4uIXJh9bjtmQDP7k9\r\n" \
	"tvTO3+WJz3KwYp5Q9VeHv3zXRlnILfyyNgQuGFUyjoTnyY6DfLsYUn81Vv+e3S3H\r\n" \
	"NdujwhulZKY7Nc43VPunLUk9HEjGpCli8VVQpwIDAQABMA0GCSqGSIb3DQEBCwUA\r\n" \
	"A4IBAQB0tQ7PbyxnTWCLCbNFZMlbj2yerI5QhOI+3RKoIlkUh6OaTuJhczzhhJ5C\r\n" \
	"RuUqwAtxjF6AShp7yL8WQl9JHkohDi9JZ2qZMnFWigEJejjW+t66k85zh5zbYGNI\r\n" \
	"HV+5wJlkF+SyXZCZgAB0u2j/21itqhNSPQ/Y2UH4eENq0vNbehZiFFzdFZyqHIXl\r\n" \
	"N2UAT6cyWdf5WqRHmXlymSpwXgHikpnXCXYxYNvHYgRacMPMR2DqcbvkZ8FY9n8x\r\n" \
	"bNK0HLzmKp2Gk73MMySmsDCAnv4TXSJriR08WTAUEvVBDQQfSZGtYhXCtCS9zLAj\r\n" \
	"SAo+7/18VhyYyAsWq5W4fUtTY+rV\r\n"                                     \
	"-----END CERTIFICATE-----\r\n"
};

unsigned char mbedtls_srv_key[] =
{
	"-----BEGIN RSA PRIVATE KEY-----\r\n" \
	"Proc-Type: 4,ENCRYPTED\r\n" \
	"DEK-Info: AES-256-CBC,D40A7C926A0DFC3E4F0B137FE4D2AC74\r\n" \
	"\r\n" \
	"xxjNIwzrrFMQ2iWhlCHh0Ck8z2tgp/C8ieXHbjUdvOzHVTLeNsGIaGK4m9mGbcBn\r\n" \
	"HEheWMqHAnEYTNzA2SFxZdQlzxhee1d7ATu4TSSkN4JM8Ahi3f44w2irqL3hBiHT\r\n" \
	"sQMRUjg62snAiNS5Cz0CllP74kZwJXFuiRWCJSFaXUI0U2yrp6AuFIOBPVSN5cvM\r\n" \
	"if8+8lMRaXlESB9LzQomg8q4Qh1vQGBR5k10pVn/GhngwBDm8uhCyqH0lq+RKq3H\r\n" \
	"wCGYmL8v1qW7CG8Wqm4UexZpgbMnOWg0xLEnr8Xvjl1YmCFWcG+wRtybEErSxlbD\r\n" \
	"QzWQCK51UE5HTmdD3O5F0FZ/ksopH+SD/xPpKRdMa9px8wIeAlXc5jY2U2IbaTe5\r\n" \
	"Bo0ma5O7QrmqxjkiVIXOT+hJgzR3xm/AxYNVB8vSP+L427C+eynI43hcHNpyVD/1\r\n" \
	"n60bYR9cGf6rilpW9F6fvBOAleRsQ4m40TGszwlh42HsnrLY+nNtsBr3Z7h2nCEr\r\n" \
	"UFfWENvqSa1+r5J9MqCnQorqvXEGSoNdtr2NPQDgSJb0cJx45XgKMqwP/i0+nz5B\r\n" \
	"0imaJ6/9J/oLaiNfcEJHFRsZL/Gs558oCypzfhhJEuRnrmKn4deGboGdFS+1ChiP\r\n" \
	"4lCIJqUEpj7ExTae/Ea7L+xd3UGmrRGnF4aJ9O4i4ElyY6CRK9O/19k2s/F5m+WP\r\n" \
	"LkFJMdxHDIkJWzIxix7sTVd92zBcnsoqS/h6zlU+LspfZ8GGMf4ThObi7zg80Zsk\r\n" \
	"xxJNahlyItZzGSeXu2FGhzt9I30gle2kIY8febB+c8OdHH+giFZGEiE6oqgbuKgc\r\n" \
	"8W6xqaBQpL8LnTkfizcH9IfiZdUCPwrUsUssa5PXsiehUZB0DLYNAFM7jiVZfeQM\r\n" \
	"GwAzPQJi2Y/GIkP7eSxRcGfB4FM2UWUBKA5awfYh7UbunGu85rgsFVfunwNXYrcd\r\n" \
	"BFy8CK8sXFUwhwiprawfya6iO5GXfbOeSoi3HMhbXbdcdxFxMWPBzKzag+GQhB9M\r\n" \
	"Q08ujKWW3WYrCvby0K5yZq4Up7+4bBQgWiifcL7laEfl0snio2oD9dtZBezgy6/n\r\n" \
	"vWiTW0lounaU/tK5GsHtgsgDBcOwbVLirt8KXHsWlI22weLrBLYaImgzmxXn0U7O\r\n" \
	"06ab+3aP12ICQY1stWLK9DowDmjCqWsBiuUoMMtB9a2yF/ra2a3QVe99N6yxGRz2\r\n" \
	"xmtv9NJwkTX7KSmLw0SWHHhqepwOEFW4ckkLd7Y5jD053bgSFNrBtbfPi+C9Ustv\r\n" \
	"GXdnvGzrAkhy9vq+tCAHuzwuBXnTMTf43fbWRbzQi7ZKVpubYFS7mqEfXXqkHhpl\r\n" \
	"v1P3fpURqWfSQOfPt5kIwjzc3swUKo1czZnfACcIB274FQlDOZq2sxNJYxyI2iAG\r\n" \
	"hK9hPqbYfswT53978BYe2R9ChDsFHFcSZyJFb4Sydr755PFFHL6LV1k2w8z4RGpJ\r\n" \
	"dZbH4WuYHlNs04K8TqbZGg0d8T544yHPdlMGY72YFJ4DbW/uckjSo/z4djyls6NT\r\n" \
	"vJPCm1ZvcTu+FyL/lEL/jNsNF17kdipDhtmhFr3KPbxKycFe+mZnhVHPTZ/Gcm3U\r\n" \
	"-----END RSA PRIVATE KEY-----\r\n"
};

typedef struct
{
	mbedtls_net_context listen_netctx;
	mbedtls_net_context client_netctx;
	mbedtls_ssl_context sslctx;
	mbedtls_ssl_config sslcfg;
	mbedtls_ctr_drbg_context drbgctx;
	mbedtls_entropy_context etpyctx;
	mbedtls_x509_crt x509cacrt;
	mbedtls_x509_crt x509srvcrt;
	mbedtls_pk_context pkey;
} mbedtls_server_t;

mbedtls_server_t server;

size_t mbedtls_ca_crt_len = sizeof(mbedtls_ca_crt);
size_t mbedtls_srv_crt_len = sizeof(mbedtls_srv_crt);
size_t mbedtls_srv_key_len = sizeof(mbedtls_srv_key);

mbedtls_x509_crt_profile x509_crt_profile =
{
    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
    0xFFFFFFF, /* Any PK alg    */
    0xFFFFFFF, /* Any curve     */
    2048,      /* 密钥长度为2048 */
};

static int mbedtls_ssl_sig_hashes[] =
{
    MBEDTLS_MD_SHA512,
    MBEDTLS_MD_SHA384,
    MBEDTLS_MD_SHA256,
    MBEDTLS_MD_SHA224,
    MBEDTLS_MD_SHA1,
    MBEDTLS_MD_NONE
};

uint8_t Buffer[1024];

/**
 * SSL服务器网络初始化
 * @param  server
 * @param  ip     ip地址字符串形式
 * @param  port   端口字符串形式
 * @return        成功返回0,失败返回负值
 */
int mbedtls_ssl_server_wait_for_connect(mbedtls_server_t* server, const void* ip, const void* port)
{
	int ret = 0;

	// 绑定本地IP地址端口
	if ((ret = mbedtls_net_bind(&server->listen_netctx, (const char *)ip, (const char *)port, MBEDTLS_NET_PROTO_TCP)) != 0)
		return -1;

	// 清理客户端连接
	mbedtls_net_free(&server->client_netctx);

	// 清理SSL会话信息
	mbedtls_ssl_session_reset(&server->sslctx);

	// 等待客户端连接
	if ((ret = mbedtls_net_accept(&server->listen_netctx, &server->client_netctx, NULL, 0, NULL)) != 0)
		return -2;

	// 设置收发数据接口函数
	mbedtls_ssl_set_bio(&server->sslctx, &server->client_netctx, mbedtls_net_send, mbedtls_net_recv, NULL);

	// 握手
	while ((ret = mbedtls_ssl_handshake(&server->sslctx)) != 0)
	{
		if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
			return -3;
	}

	// 获取验证结果
	if((ret = mbedtls_ssl_get_verify_result(&server->sslctx)) != 0)
	{
		char vrfy_buf[128];
		int flags = mbedtls_ssl_get_verify_result(&server->sslctx);
		mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", flags );
		debug_e( "%s\n", vrfy_buf );
//		return -4;
	}

	return 0;
}

/// 断开连接
void mbedtls_ssl_server_close(mbedtls_server_t* server)
{
	mbedtls_ssl_close_notify(&server->sslctx);
}

/// 清理
void mbedtls_ssl_server_destory(mbedtls_server_t* server)
{
	mbedtls_net_free(&server->client_netctx);
	mbedtls_net_free(&server->listen_netctx);
	mbedtls_x509_crt_free(&server->x509cacrt);
	mbedtls_x509_crt_free(&server->x509srvcrt);
	mbedtls_pk_free(&server->pkey);
	mbedtls_ssl_free(&server->sslctx);
	mbedtls_ssl_config_free(&server->sslcfg);
	mbedtls_ctr_drbg_free(&server->drbgctx);
	mbedtls_entropy_free(&server->etpyctx);
}

/**
 * SSL服务器初始化
 * @param  server
 * @param  cacrt        CA证书
 * @param  cacrtLength  CA证书长度
 * @param  srvcrt       服务器证书
 * @param  srvcrtLength 服务器整数长度
 * @param  srvkey       服务器密钥
 * @param  srvkeyLength 服务器密钥长度
 * @param  srvpwd       服务器密码
 * @param  srvpwdLength 服务器密码长度
 * @param  pers         熵字符串,任意字符串即可
 * @param  persLength   熵字符串长度
 * @return              成功返回0,失败返回负值
 */
int mbedtls_ssl_server_init(
    mbedtls_server_t* server,
    const void* cacrt, size_t cacrtLength,
    const void* srvcrt, size_t srvcrtLength,
    const void* srvkey, size_t srvkeyLength,
    const void* srvpwd, size_t srvpwdLength,
    const void* pers, size_t persLength)
{
	int ret = 0;

	//
	// 初始化
	//
	mbedtls_net_init(&server->listen_netctx);
	mbedtls_net_init(&server->client_netctx);
	mbedtls_ssl_init(&server->sslctx);
	mbedtls_ssl_config_init(&server->sslcfg);
	mbedtls_x509_crt_init(&server->x509cacrt);
	mbedtls_x509_crt_init(&server->x509srvcrt);
	mbedtls_pk_init(&server->pkey);
	mbedtls_entropy_init(&server->etpyctx);
	mbedtls_ctr_drbg_init(&server->drbgctx);

	// 加载服务器证书
	if ((ret = mbedtls_x509_crt_parse(&server->x509srvcrt, (const unsigned char *) srvcrt, srvcrtLength)) != 0)
		return -1;

	// 加载CA证书
	if ((ret = mbedtls_x509_crt_parse(&server->x509cacrt, (const unsigned char *) cacrt, cacrtLength)) != 0)
		return -2;

	// 加载服务器密钥
	if ((ret = mbedtls_pk_parse_key(&server->pkey, (const unsigned char *) srvkey, srvkeyLength, (const unsigned char *)srvpwd, srvpwdLength)) != 0)
		return -3;

	// 设置SSL/TLS熵源
	if ((ret = mbedtls_ctr_drbg_seed(&server->drbgctx, mbedtls_entropy_func, &server->etpyctx, (const unsigned char *) pers, persLength)) != 0)
		return -4;

	// 设置SSL连接模式
	if ((ret = mbedtls_ssl_config_defaults(&server->sslcfg, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
		return -5;

	// 设置随机数生成器回调
	mbedtls_ssl_conf_rng(&server->sslcfg, mbedtls_ctr_drbg_random, &server->drbgctx);

	// 设置CA证书认证关联到SSL结构上
	mbedtls_ssl_conf_ca_chain(&server->sslcfg, &server->x509cacrt, NULL);

	// 设置服务器证书和密钥关联
	if ((ret = mbedtls_ssl_conf_own_cert(&server->sslcfg, &server->x509srvcrt, &server->pkey)) != 0)
		return -6;

	// 设置用于验证的X.509安全配置文件
	mbedtls_ssl_conf_cert_profile(&server->sslcfg, &x509_crt_profile);

	// 设置握手签名的允许/首选散列算法
	mbedtls_ssl_conf_sig_hashes(&server->sslcfg, mbedtls_ssl_sig_hashes);

	//
	// 设置认证模式
	//
	// MBEDTLS_SSL_VERIFY_NONE     :不检查对等证书
	//                              (服务器默认值,如果客户端配置为此选项那么连接是不安全的;如果服务器配置为此值那么是单向认证。)
	//
	// MBEDTLS_SSL_VERIFY_OPTIONAL :检查对等证书,但即使验证失败,握手仍将继续;
	//                               可以在握手完成后调用mbedtls_ssl_get_verify_result()查看验证结果。
	//                                (如果服务器设置为此值,那么就是双向认证)
	//
	// MBEDTLS_SSL_VERIFY_REQUIRED :同时必须出示有效证书,如果验证失败,握手将终止。
	//                               (客户端默认值,如果服务器设置为此值,那么就是双向认证)
	//
	mbedtls_ssl_conf_authmode(&server->sslcfg, MBEDTLS_SSL_VERIFY_REQUIRED);

	// 配置设置
	if ((ret = mbedtls_ssl_setup(&server->sslctx, &server->sslcfg)) != 0)
		return -7;

	return 0;
}

int main(void)
{
	int ret = 0;

	debug("-------------------- SSL Server Demo ---------------------------\r\n");

	ret = mbedtls_ssl_server_init(
	          &server,
	          mbedtls_ca_crt,
	          mbedtls_ca_crt_len,
	          mbedtls_srv_crt,
	          mbedtls_srv_crt_len,
	          mbedtls_srv_key,
	          mbedtls_srv_key_len,
	          "zxcvbnm.",
	          strlen("zxcvbnm."),
	          "ssl_server",
	          strlen("ssl_server"));
	if(ret != 0)
	{
		debug_e(" ssl server init failed,errcode:%d\r\n", ret);
		goto __exit;
	}

	debug(" ssl server init ok. \r\n");

	debug(" wait for connect...\r\n");
	if ((ret = mbedtls_ssl_server_wait_for_connect(&server, IP, PORT)) != 0)
	{
		debug_e(" wait for connect failed,errcode:%d\r\n", ret);
		goto __exit;
	}

	debug(" client connected.\r\n");

	//
	// 接收数据
	//
	do
	{
		ret = mbedtls_ssl_read(&server.sslctx, Buffer, sizeof(Buffer));
		if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
		{
			continue;
		}

		if (ret <= 0)
		{
			break;
		}

		Buffer[ret] = 0;
		debug(" %d bytes recv:[%s]\r\n", ret, Buffer);
		break;
	} while (1);

	//
	// 发送数据
	//
	while ((ret = mbedtls_ssl_write(&server.sslctx, (const unsigned char *)"Hello Client !", strlen("Hello Client !"))) <= 0)
	{
		if (ret == MBEDTLS_ERR_NET_CONN_RESET)
		{
			goto __exit;
		}

		if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
		{
			goto __exit;
		}
	}
	debug(" %d bytes written.\r\n", strlen("Hello Client !"));

__exit:
	mbedtls_ssl_server_close(&server);
	mbedtls_ssl_server_destory(&server);
	return 0;
}


ends…

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

觉皇嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值