简单认识一下mbedTLS

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 简单认识一下mbedTLS

认识mbedTLS

认识mbedTLS是在code里面一个文件夹的名字,好奇这个是什么。

mbedTLS(前身 PolarSSL)是一个由 ARM 公司开源和维护的 SSL/TLS 算法库。其使用 C 编程语言以最小的编码占用空间实现了 SSL/TLS 功能及各种加密算法,易于理解、使用、集成和扩展,方便开发人员轻松地在嵌入式产品中使用 SSL/TLS 功能。

mbedTLS主要是面向小型嵌入式设备,代码紧凑,最小完整的TLS堆栈需要60KB的程序空间和64KB的RAM空间,而且执行效率高,可以说是行业内最小巧的SSL加密算法库。

另外,mbedTLS是高度模块化的设计:每个组件,如加密函数,可以独立于框架的其余部分使用。mbedTLS完全是由C语言编写的,没有外部依赖,因此,mbedTLS是应用于嵌入式系统最理想的TLS加密算法库。更重要的一点是,mbedTSL是完全OpenSource的,支持Apache 2.0 license 或者GPL 2.0 license双重许可,可以自由应用于商业项目中。

mbedTLS 软件包提供了如下的能力:

  • 完整的 SSL v3、TLS v1.0、TLS v1.1 和 TLS v1.2 协议实现
  • X.509 证书处理
  • 基于 TCP 的 TLS 传输加密+
  • 基于 UDP 的 DTLS(Datagram TLS)传输加密
  • 其它加解密库实现

二、安全通信连接应用工作原理

mbedTLS 建立安全通信连接需要经过以下几个步骤:

  • 初始化 SSL/TLS 上下文
  • 建立 SSL/TLS 握手
  • 发送、接收数据
  • 交互完成,关闭连接

其中,最关键的步骤就是 SSL/TLS 握手 连接的建立,这里需要进行证书校验。

1-SSL/TLS 握手流程

2-DTLS 握手流程

为了避免拒绝服务攻击,DTLS采用和IKE一样的无状态 cookie 技术。当客户端发送 client hello 消息后,服务器发送 HelloVerifyRequest 消息,这个消息包含了无状态 cookie。客户端收到之后必须重传添加上了 cookie 的 clienthello。

DTLS 握手流程如下图所示:

三、mbedTLS常用结构体

1. 公钥算法类型mbedtls_pk_type_t

/*
 * \brief          Public key types
 */
typedef enum {
    MBEDTLS_PK_NONE=0,
    MBEDTLS_PK_RSA,
    MBEDTLS_PK_ECKEY,
    MBEDTLS_PK_ECKEY_DH,
    MBEDTLS_PK_ECDSA,
    MBEDTLS_PK_RSA_ALT,
    MBEDTLS_PK_RSASSA_PSS,
  MBEDTLS_PK_SM2,
} mbedtls_pk_type_t;

2. 摘要算法类型mbedtls_md_type_t

typedef enum {
    MBEDTLS_MD_NONE=0,
    MBEDTLS_MD_MD2,
    MBEDTLS_MD_MD4,
    MBEDTLS_MD_MD5,
    MBEDTLS_MD_SHA1,
    MBEDTLS_MD_SHA224,
    MBEDTLS_MD_SHA256,
    MBEDTLS_MD_SHA384,
    MBEDTLS_MD_SHA512,
    MBEDTLS_MD_RIPEMD160,
  MBEDTLS_MD_SM3,
} mbedtls_md_type_t;

3. 公钥上下文mbedtls_pk_context

/**
 * \brief           Public key container
 */
typedef struct
{
    const mbedtls_pk_info_t *   pk_info; /**< Public key informations  公钥信息        */
    void *                      pk_ctx;  /**< Underlying public key context  底层公钥上下文*/
} mbedtls_pk_context;

4. 解析证书得到的mbedtls_pk_info_t

struct mbedtls_pk_info_t //解析证书得到的
{
    /** Public key type */
    mbedtls_pk_type_t type;
    /** Type name */
    const char *name;
    /** Get key size in bits */
    size_t (*get_bitlen)( const void * );
    /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */
    int (*can_do)( mbedtls_pk_type_t type );
    /** Verify signature *///验证签名,证书,秘钥交换时服务器签名(如果有的话)
    int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg,
                        const unsigned char *hash, size_t hash_len,
                        const unsigned char *sig, size_t sig_len );
    /** Make signature *///用秘钥来加密
    int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg,
                      const unsigned char *hash, size_t hash_len,
                      unsigned char *sig, size_t *sig_len,
                      int (*f_rng)(void *, unsigned char *, size_t),
                      void *p_rng );
    /** Decrypt message *///秘钥交换,服务器解密使用
    int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
                         unsigned char *output, size_t *olen, size_t osize,
                         int (*f_rng)(void *, unsigned char *, size_t),
                         void *p_rng );
    /** Encrypt message */ //秘钥交换时加密秘钥用
    int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
                         unsigned char *output, size_t *olen, size_t osize,
                         int (*f_rng)(void *, unsigned char *, size_t),
                         void *p_rng );
    /** Check public-private key pair */
    int (*check_pair_func)( const void *pub, const void *prv );
    /** Allocate a new context */
    void * (*ctx_alloc_func)( void );
    /** Free the given context */
    void (*ctx_free_func)( void *ctx );
    /** Interface with the debug module */
    void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items );
};

四、mbedTLS使用事例

下面我们通过一个示例来说明如何使用mbedtls。这个示例通过介绍如何使用HMAC算法生成一个消息认证码。

hmac-test.c代码如下:

#include <string.h>
#include <stdio.h>
#include "mbedtls/md.h"
#define mbedtls_printf     printf
int main(void)
{
    int ret;
    unsigned char secret[] = "a secret";
    unsigned char buffer[] = "some data to hash";
    unsigned char digest[32];
    mbedtls_md_context_t sha_ctx;
    mbedtls_md_init(&sha_ctx);
    memset(digest, 0x00, sizeof(digest));
    ret = mbedtls_md_setup(&sha_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
    if (ret != 0)
    {
        mbedtls_printf("  ! mbedtls_md_setup() returned -0x%04x\n", -ret);
        goto exit;
    }
    mbedtls_md_hmac_starts(&sha_ctx, secret, sizeof(secret) - 1);
    mbedtls_md_hmac_update(&sha_ctx, buffer, sizeof(buffer) - 1);
    mbedtls_md_hmac_finish(&sha_ctx, digest );
    mbedtls_printf("HMAC: ");
    for (int i = 0; i < sizeof(digest); i++)
        mbedtls_printf("%02X", digest[i]);
    mbedtls_printf("\n");
exit:
    mbedtls_md_free( &sha_ctx );
    return ret;
}
  • hmac算法需要两个参数,一个称为秘钥,此处为secret,另一个称为消息,此处为buffer
  • 消息认证码保留在 digest 数组中
  • 此处hmac算法选择sha256算法作为单向散列函数,所以hmac的计算结果一定为32字节

在mbedtls中,消息认证码的生成分为三个步骤:

  • mbedtls_md_hmac_starts 设置密钥
  • mbedtls_md_hmac_update 填充消息,本示例仅填充了一次
  • mbedtls_md_hmac_finish 生成消息认证码,结果保存至digest中

最后把digest使用HEX格式打印至控制台。

五、mbedTLS_API分析

应用层 API 是提供给用户在 App 中直接使用的 API,这部分 API 屏蔽了 mbedtls 内部具体的操作步骤,简化了用户使用。

这里分享 【ARM mbedtls API】 手册给大家。

六、mbedtls安装与入门

如果你实在忍不住你的手,想自己实际操作一下,可以参考前辈的这篇blog:【mbedtls安装与入门】


目录
相关文章
|
5月前
|
存储 算法 编译器
C语言的一些值得深入探究的细节
C语言的一些值得深入探究的细节
|
存储 编译器 C语言
【C++知识点】多文件编程
【C++知识点】多文件编程
248 0
|
C语言
一直没有搞懂的C语言参数传递,今天终于明白了
一直没有搞懂的C语言参数传递,今天终于明白了
107 0
|
存储 程序员 C语言
【C语言】文件的相关操作(一文10分钟彻底弄懂)
🐳文件简介 当程序结束时,内存中的数据就会丢失,这样每次运行程序时都要重新输入数据。那么有没有可以长久保存数据的方法呢?当然是有的啦!这个方法就是使用文件操作,用文件保存键盘输入和屏幕输出的数据,将数据以文件的形式存放在光盘、磁盘等外存储器上,可达到重复使用、永久保存数据的目的。
94 0
|
编译器 程序员
高级语言是什么意思?底层原理是什么?
高级语言是什么意思?底层原理是什么?
335 0
|
C语言 索引
详解C语言操作符(史上最全的重点总结!全在这里!)
详解C语言操作符(史上最全的重点总结!全在这里!)
228 0
详解C语言操作符(史上最全的重点总结!全在这里!)
|
存储 自然语言处理 编译器
用c语言手搓一个500+行的类c语言解释器: 给编程初学者的编译器教程(2)- 简介和设计
通常我们说的 “编译器” 是一种计算机程序,负责把一种编程语言编写的源码转换成另外一种计算机代码,后者往往是以二进制的形式被称为目标代码(object code)。这个转换的过程通常的目的是生成可执行的程序。 而解释器是一种计算机程序,它直接执行由编程语言或脚本语言编写的代码,它并不会把源代码预编译成机器码,而是一行一行地分析源代码并且直接执行,相对编译器而言可能效率较为低下,但实现也相对简单,并且容易在不同的机器上进行移植(比如x86和mips指令集的机器)。
473 0
|
编译器 BI C语言
用c语言手搓一个500+行的类c语言解释器: 给编程初学者的编译器教程(1)- 目标和前言
这一系列教程希望面向初学者,使用c语言手工实现一个简单的解释器来玩,不需要您掌握除了c语言以外的其他前置知识,也不需要您学习过编译原理的相关知识(当然如果能对简单的数据结构有所了解的话会更好,比如树、栈等)。 > 写一个能执行代码的解释器不仅是一件很有(zhuang)趣(bi)的事情,大概也可以作为刚学习完c语言的一个练手的小项目啦 不同于大部分常见的其他只支持四则运算的所谓”手工解释器“教程,我们希望在代码结构尽量清晰的600行代码中,手工(不借助lex/yacc等工具)完成一个脚本语言“try”,实现以下功能:
1741 0
|
Java iOS开发
千字掌握“代码块”概念 | 带你学《Java面向对象编程》之十二
本节通过多组案例深刻讲解了“{}”在Java世界中扮演的重要角色,简明扼要的介绍了普通代码块、构造块、静态块的异同点。