mbedtls学习(12)DTLS

概述

DTLS(Datagram Transport Layer Security)是运行在UDP之上的安全通讯协议,大部分和TLS是一样的,只是针对UDP在不可靠传输问题增加了新特性,用来解决UDP传输的报文乱序和报文丢失等问题,DTLS主要通过下面方法来解决

  • 禁止密码流,避免记录层报文前后关联
  • 在记录层增加计数值和序列号字段,用于排序和数据确认
  • 在握手子协议中加入重传机制,防止握手过程中报文丢失
  • 在握手子协议中加入序列号,保证握手报文顺序正确
  • 在握手协议中增加偏移量(fragment_offset)和帧长度(fragment_length)字段,IP层会在报文长度大于1500分片,用这2个字段重组
DTLS握手协议变化
  • 防止DDos攻击
    握手子协议中加入HelloVerifyRequest,服务器收到ClientHello后将会为客户端分配一个cookie,并把这个cookie包含在HelloVerifyRequest中,客户端在收到带有cookie的ClientHello后,需要重新发ClientHello。如果服务器在短时间内收到某个IP重复报文则会丢弃。
    在这里插入图片描述
mbedtls DTLS例子

DTLS加入了超时重传机制,所以需要注册设置定时器和获得定时器接口,这个例子不是加载X.509证书派发密钥,而是采用PSK密钥交换。

/* mbed TLS feature support */
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED 启用PSK密钥协商方案
#define MBEDTLS_SSL_PROTO_TLS1_2  选择TLS1.2
#define MBEDTLS_SSL_PROTO_DTLS    启用DTLS
/* mbed TLS modules */
#define MBEDTLS_AES_C
#define MBEDTLS_CCM_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_MD_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_TLS_C  启用TLS/SSL功能
#define MBEDTLS_AES_ROM_TABLES
/* Save some RAM by adjusting to your exact needs */
#define MBEDTLS_PSK_MAX_LEN    16 /* 128-bits keys are generally enough */
/*
 * You should adjust this to the exact number of sources you're using: default
 * is the "platform_entropy_poll" source, but you may want to add other ones
 * Minimum is 2 for the entropy test suite.
 */
#define MBEDTLS_ENTROPY_MAX_SOURCES 2
/*
 * Use only CCM_8 ciphersuites, and
 * save ROM and a few bytes of RAM by specifying our own ciphersuite list
 */
#define MBEDTLS_SSL_CIPHERSUITES  MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8
/*
 * Save RAM at the expense of interoperability: do this only if you control
 * both ends of the connection!  (See comments in "mbedtls/ssl.h".)
 * The optimal size here depends on the typical size of records.
 */
#define MBEDTLS_SSL_MAX_CONTENT_LEN  4096 TLS缓存区,这个可以极大减少TLS占用RAM
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>

#include "mbedtls/net.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/platform.h"

#define assert_exit(cond, ret) \
    do { if (!(cond)) { \
        printf("  !. assert: failed [line: %d, error: -0x%04X]\n", __LINE__, -ret); \
        goto cleanup; \
    } } while (0)

#define SERVER_PORT             "8888"
#define SERVER_ADDR             "192.168.1.101"
#define MESSAGE 				"Echo this\r\n"

// 000102030405060708090a0b0c0d0e0f
const uint8_t psk[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};
const char psk_id[] = "Client_identity";

struct dtls_timing_context 
{
    uint32_t snapshot;
    uint32_t int_ms;
    uint32_t fin_ms;
};
static struct dtls_timing_context timer;

//这里是获得系统时间函数
uint32_t OS_Get_time()
{
	return 0;
}
void dtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms)
{
    struct dtls_timing_context *ctx = (struct dtls_timing_context *)data;

    ctx->int_ms = int_ms;
    ctx->fin_ms = fin_ms;

    if (fin_ms != 0) {
        ctx->snapshot = OS_Get_time();
    }
}

int dtls_timing_get_delay(void *data)
{
    struct dtls_timing_context *ctx = (struct dtls_timing_context *)data;
    unsigned long elapsed_ms;

    if (ctx->fin_ms == 0) {
        return -1;
    }

    elapsed_ms = OS_Get_time() - ctx->snapshot;

    if (elapsed_ms >= ctx->fin_ms)
        return 2;

    if (elapsed_ms >= ctx->int_ms)
        return 1;
    return 0;
}
/*
static int entropy_source(void *data, uint8_t *output, size_t len, size_t *olen)
{
    uint32_t seed;
    ARG_UNUSED(data);

    seed = sys_rand32_get();
    if (len > sizeof(seed)) {
        len = sizeof(seed);
    }

    memcpy(output, &seed, len);
    *olen = len;

    return 0;
}*/

int main(void)
{ 
    int ret = 0, len = 0;
    unsigned char buf[256];
    const char *pers = "dtls_client";
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;

    mbedtls_platform_set_printf(printf);

    mbedtls_ssl_context ssl;
    mbedtls_ssl_config conf;
    mbedtls_net_context ctx; 
    
    mbedtls_net_init(&ctx);
    mbedtls_ssl_init(&ssl);
    mbedtls_ssl_config_init(&conf);
    mbedtls_ctr_drbg_init(&ctr_drbg);

    mbedtls_printf("\n  . Seeding the random number generator...");
    mbedtls_entropy_init(&entropy);
    /*mbedtls_entropy_add_source(&entropy, entropy_source, NULL,
                   MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG);*/
    ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                      (const uint8_t *)pers, strlen(pers));
    assert_exit(ret == 0, ret);
    
    mbedtls_printf(" ok\n  . Setting up the SSL/TLS structure...");
	//这里是DATAGRAM
    ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,
                MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT);
    assert_exit(ret == 0, ret);

    mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
	//这里选择PSK密钥
    mbedtls_ssl_conf_psk(&conf, psk, sizeof(psk),
                 (const uint8_t *)psk_id, strlen((char*)psk_id));

    ret = mbedtls_ssl_setup(&ssl, &conf);
    assert_exit(ret == 0, ret);
    
    mbedtls_printf(" ok\n  . Connecting to %s:%s...", SERVER_ADDR, SERVER_PORT);
	//连接采用UDP
    ret = mbedtls_net_connect( &ctx, SERVER_ADDR, SERVER_PORT, MBEDTLS_NET_PROTO_UDP );
    assert_exit(ret == 0, ret);
	//注册设置定时器和获取定时器回调
    mbedtls_ssl_set_timer_cb(&ssl, &timer, dtls_timing_set_delay, dtls_timing_get_delay);
    mbedtls_ssl_set_bio( &ssl, &ctx, mbedtls_net_send, mbedtls_net_recv, NULL );
    
    mbedtls_printf(" ok\n  . Performing the SSL/TLS handshake...");
    while ((ret = mbedtls_ssl_handshake(&ssl)) != 0)
    {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
        {
            mbedtls_printf(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret);
            goto cleanup;
        }
    }

    mbedtls_printf(" ok\n  > Write to server:");
    do {
        ret = mbedtls_ssl_write(&ssl, (const uint8_t *)MESSAGE, strlen(MESSAGE));
    } while (ret == MBEDTLS_ERR_SSL_WANT_READ ||
         ret == MBEDTLS_ERR_SSL_WANT_WRITE);
    assert_exit(ret > 0, ret);
    len = ret;
    mbedtls_printf( " %d bytes written\n\n%s\n", len, MESSAGE);

    mbedtls_printf("  > Read from server:");
    len = sizeof(buf) - 1;
    memset(buf, 0x00, sizeof(buf));

    do {
        ret = mbedtls_ssl_read(&ssl, buf, len);
    } while (ret == MBEDTLS_ERR_SSL_WANT_READ ||
         ret == MBEDTLS_ERR_SSL_WANT_WRITE);
    assert_exit(ret > 0, ret);

    len = ret;
    mbedtls_printf( " %d bytes read\n\n%s\n", len, buf);
    
    mbedtls_ssl_close_notify(&ssl);
    mbedtls_printf(" . Closing the connection ... done\n");

cleanup:
    mbedtls_net_free(&ctx);
    mbedtls_ssl_free(&ssl);
    mbedtls_ssl_config_free(&conf);
    mbedtls_ctr_drbg_free(&ctr_drbg);
    mbedtls_entropy_free(&entropy);

    return ret;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值