深圳粤嵌嵌入式开发培训
粤嵌嵌入式开发培训不会让你后悔!
快速咨询研发出身的大牛讲师,为你指点迷津
精通Orcad、PADS等开发工具,精通ARM、MIPS、Blackfin等架构处理器、精通ARM嵌入式系统开发和编程,精通ARM平台上各种外设接口开发、ARM的硬件设计和调试,具有丰富的产品开发经验。 善于解决工程中遇到的疑难杂症,并对嵌入式专业人才的培养体系及培训方法有深入研究。
教学经验有着10年以上嵌入式系统开发经验,资深开发工程师,承担着多项嵌入式系统产品的研发。
精通Linux、C/C++语言、Android等技术,精通STL和boost库,Java语言和eclipse及其插件开发方法。 具有全面和扎实的计算机科学基础知识,严谨的思维方式,强大的的数据结构和算法设计能力。负责嵌入式课程体系制定与培训,对嵌入式专业人才的培养体系及培训方法有深入研究。
教学经验7年嵌入式开发经验,曾在著名的手机公司从事Symbian手机平台开发和安卓前期预研工作。
精通Linux系统开发等开发工具,精通ARM_linux及编译器与调试器,精通线程,内核链表。精通linux系统移植,Linux初级高级设备驱动开发。 曾在国内大型企业做过多个出口嵌入式大型项目,对嵌入式软件开发有很多实际工程经验,对嵌入式专业人才的培养体系及培训方法有深入研究。
教学经验华中科技大学工学硕士,10年以上嵌入式系统开发经验,承担着多项嵌入式系统产品的研发。
精通Linux下C语言编程,精通数据结构算法与实现,有着丰富的银行交易系统开发经验,并且精通SCO系统下shell编程与系统编程。更有着多年的授课经验,他娴熟的授课技巧以及成体系化的教学理论与经验,上课风格多样化,善于并乐于传播IT技术,热衷于教育行业,对学生认真负责。
教学经验7年多嵌入式系统软件开发经验,资深嵌入式Linux研发工程师,致力于嵌入式Linux应用软件等。
嵌入式开发技术基础课程
搭建嵌入式Linux开发环境
Linux系统基础入门
高质量的编码规范
嵌入式Linux应用开发基础
Linux IO编程
Linux多线程编程
Cortex-M4应用开发
Cortex-M4开发基础
uC/OS-11操作系统
Cortex-M4开发高级
嵌入式Linux应用开发高级
嵌入式web服务器搭建及开发
Linux音视频编程
Linux串口编程
嵌入式GUI系统编程开发
C++语法及编程提高
QT应用开发进阶
嵌入式Linux应用开发高级
嵌入式平台软硬件架构分析
Linux设备驱动开发
系统移植
1
从0开始利用人工智能技术,通过与机器人人机日常语音交互、人面识别、手势识别等方式完成指定动作,如智能家居/电器控制、日常交流、播放音乐/电影、查天气、问问题等多种功能。
2
风飞送货无人机采用八旋翼飞行器,配有GPS自控导航系统、iGPS接收器、各种传感器以及无线信号发收装置。无人机具有GPS自控导航、定点悬浮、人工控制等多种飞行模式,集成了三轴加速度计、三轴陀螺仪、磁力计、气压高度计等多种高精度传感器和先进的控制算法。
3
项目通过人机交互技术,借助VR头盔、驾驶模拟器、三轴动感平台,对基本驾驶功能进行模拟,如点火、倒车、手刹等功能的实现,给人现实的驾驶体验。一比一复制练习场地,如倒车入库等,还会有虚拟教练针对驾考科目进行指导。
4
项目集中运用人工智能及自动控制技术,采用功能强大的嵌入式ARM对小车进行模块化设计,在普通车辆的基础上增加了先进的传感器(雷达、摄像)、控制器、执行器等装置,实现遥控器控制、超声波智能避障、运行轨迹自动优化等功能。
课程研发团队时刻关注前沿技术和市场需求的变化,一年两次更新课程大纲,及时吸纳新的行业技术、
项目案例,并根据实际教学效果进行调整,保证学员学得扎实且不落伍。
拒绝复制代码敲键盘等硬编程方式,粤嵌注重培养你的“编程思维”。粤嵌讲师也不仅仅给你传授知识,
更教你如何拆解分析项目难题,提升解决实际问题的能力。
课上有资深讲师授课,课余有技术工程师全程陪伴,只要你不懂就问,
就会有技术老师随时随地答疑,帮你解决所有技术难点,不让难题陪你过夜。
每个学习阶段结束,都会进行阶段测试 ,确保每个学员听懂学会。
整个学习过程绝不会放任自由,考试不过,毕业无门,对每一个学员负责到底。
从学员学习状态调整,到生活中的困难协助,
从课上班级氛围塑造到课下多彩的班级活动,都有班主任家人般的鼓励支持。
粤嵌拥有上千家合作企业,每年几十次专场招聘会为粤嵌学员提供海量就业机会。
从简历设计到笔试复习计划、面试培训,都有就业老师全程指导,让学员轻松砍获高薪Offer!
1
安装一个Linux的发行版本,能够熟悉使用Linux,
掌握Linux下的目录结构等
嵌入式开发环境的搭建。
2
了解C语言,C语言是嵌入式开发中最重要的编程语言,
对着部分内容不仅要会写程序,
还要看得懂他人写的程序。
3
学会shell编程,shell几乎可以作为一个入门语言来学习,
最基本的是能够看得懂自己
版本的Linux的配置脚本。
4
多做案例分析,不仅要多看书籍和视频资料,
还应该多动手去练习。
5
可以选择一门或是几门
语言社区常用的编程语言,掌握多种知识。
6
无论学习什么学科,掌握哪种技能,
都需要要有好的学习方法作为支撑,当然嵌入式也不例外。
粤嵌嵌入式培训讲师整理了6点,希望有帮助。 1、必须非常熟练的掌握C语言。 2、操作系统原理,是必需的。 3、Linu.....
盈达教务团队认真负责。平时有个小毛病请假也会照顾得到,学习卡让您知道学习进度和课程情况,开发板、电脑需要就找教务老师借,真是贴心的小管家了。就业服务呢,就是就.....
很多的人在面对这种高薪行业的时候都会有不知从何学起的时候,也不知道应该具体要学习什么样的内容,所以这个时候参加嵌入式培训机构就是非常的有必要的。参加嵌入式培训机.....
信盈达培训是非常不错的计算机IT培训机构,这里有专业的计算机IT人才任教,信盈达金牌讲师,具有丰富的嵌入式系统软件开发经验,资深嵌入式ARM、Linux研发工程.....
关于mbedTLS实现的嵌入式固件知识产权的保护办法 时间:2019-07-24
随着知识经济的快速发展,各行各业对各类产品有效的知识产权保护已经成为当前提升企业竞争力的核心手段。对软件企业来说,如何运用各种法律手段保护自己的软件产品,就显得更为重要了。
嵌入式应用的领域越来越广泛,功能需求也越来越复杂,有些嵌入式产品要求在产品出厂后,使用过程中保留有固件升级的功能,以保证用户可以使用最新的功能和及时修正产品bug。支持固件升级就意味着在软件上留有“后门”(Bootloader与外界的交互),如果这个“后门”保护不当会造成固件代码泄露,针对这一安全隐患,本文讨论的话题就是如何提高嵌入式Bootloader程序的安全性,有效防止黑客的hacking和cloning,借助的工具是arm的mbedTLS加密算法库。
我们先来了解一下什么是mbedTLS。MbedTLS前身是开源加密算法库PolarSLL,现已被arm公司收购并由arm技术团队进行维护更新,是对TLS和SSL协议实现的算法库。mbedTLS的目标是:易于理解,使用,集成和扩展。mbedTLS核心代码用C编程语言编写,实现SSL模块和各种加密算法,并提供各种加密算法的自测试代码。和其他TLS/SSL算法库实现不同,mbedTLS主要是面向小型嵌入式设备,代码紧凑,最小完整的TLS堆栈需要60KB的程序空间和64KB的RAM空间,而且执行效率高,可以说是行业内最小巧的SSL加密算法库。另外,mbedTLS是高度模块化的设计:每个组件,如加密函数,可以独立于框架的其余部分使用。mbedTLS完全是由C语言编写的,没有外部依赖,因此,mbedTLS是应用于嵌入式系统最理想的TLS加密算法库。更重要的一点是,mbedTSL是完全OpenSource的,支持Apache 2.0 license 或者GPL 2.0 license双重许可,可以自由应用于商业项目中。
上海润欣科技正在开发一个用于智能门锁等领域的指纹模块项目,用到的主控芯片是基于ARM Cortex-M4内核的MCU,但是这个MCU没有代码读出保护功能,为了避免产品被非法克隆,必须引入一种保护机制来提高产品的安全性。我们使用mbedTSL算法库中的RSASSA-PSS数字签名算法对MCU芯片中的UID和指纹传感器UID来进行签名(Sign)和验证(Verify),保证每个被签名产品的唯一性(不可复制)和合法性。
基于mbedTLS实现的嵌入式固件知识产权保护方案
原文签名(Sign)以及签名验证(Verify)
一、具体的实施步骤:
第1步:将mbedTLS生成的密钥对中的私钥存放与本地服务器,并禁止外部访问,以保证私钥的安全性;
第2步:利用MCU的UID和指纹传感器的UID通过上述本地服务器上的私钥及签名生成工具生成数字签名sig文件;
基于mbedTLS实现的嵌入式固件知识产权保护方案
第3步:将上述第二步生成的sig签名文件保存到Bootloader特定区域;
第4步:将mbedTLS生成的密钥对中的公钥保存到APP固件中;
第5步:Bootloader更新APP固件时,利用APP中的公钥对Bootloader中的签名文件sig进行校验(Verify),校验通过,说明Bootloader和APP固件均为原厂合法固件,否则Bootloader拒绝引导执行APP固件,达到保护产品软硬版权的目的。
二、使用到的mbedTLS资源和API函数
1、mbedTSL代码包目录下使用VS2010或以上版本生成RSA密钥对生成工具:rsa_genkey.exe,用来生成上述步骤中第一步中的密钥对;
2、mbedTSL代码包目录下使用VS2010或以上版本生成RSASSA签名生成工具rsa_sign_pss.exe,以用来生成上述步骤中第二步中的sig文件;
3、mbedTSL代码包目录下使用VS2010或以上版本生成RSASSA签名验证工具rsa_verify_pss.exe,已确保代码的正确性;
4、MCU代码中使用到的mbedTLS API函数:
/*
* Initialize an RSA context 初始化RSA算法内容
*/
void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
int padding,
int hash_id )
{
memset( ctx, 0, sizeof( mbedtls_rsa_context ) );
mbedtls_rsa_set_padding( ctx, padding, hash_id );
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex );
#endif
}
#if defined(MBEDTLS_PKCS1_V21)
/*
* Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
* RSASSA-PSS签名算法实现函数
*/
int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
mbedtls_md_type_t md_alg,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig )
{
size_t olen;
unsigned char *p = sig;
unsigned char salt[MBEDTLS_MD_MAX_SIZE];
unsigned int slen, hlen, offset = 0;
int ret;
size_t msb;
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
if( f_rng == NULL )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
olen = ctx->len;
if( md_alg != MBEDTLS_MD_NONE )
{
/* Gather length of hash to sign */
md_info = mbedtls_md_info_from_type( md_alg );
if( md_info == NULL )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
hashlen = mbedtls_md_get_size( md_info );
}
md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
if( md_info == NULL )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
hlen = mbedtls_md_get_size( md_info );
slen = hlen;
if( olen < hlen + slen + 2 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
memset( sig, 0, olen );
/* Generate salt of length slen */
if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
/* Note: EMSA-PSS encoding is over the length of N - 1 bits */
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
p += olen - hlen * 2 - 2;
*p++ = 0x01;
memcpy( p, salt, slen );
p += slen;
mbedtls_md_init( &md_ctx );
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
goto exit;
/* Generate H = Hash( M' ) */
if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 )
goto exit;
/* Compensate for boundary condition when applying mask */
if( msb % 8 == 0 )
offset = 1;
/* maskedDB: Apply dbMask to DB */
if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen,
&md_ctx ) ) != 0 )
goto exit;
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
sig[0] &= 0xFF >> ( olen * 8 - msb );
p += hlen;
*p++ = 0xBC;
mbedtls_zeroize( salt, sizeof( salt ) );
exit:
mbedtls_md_free( &md_ctx );
if( ret != 0 )
return( ret );
return( ( mode == MBEDTLS_RSA_PUBLIC )
? mbedtls_rsa_public( ctx, sig, sig )
: mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
}
#endif /* MBEDTLS_PKCS1_V21 */
#if defined(MBEDTLS_PKCS1_V21)
/*
* Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function
* RSASSA-PSS签名算法校验函数
*/
int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
mbedtls_md_type_t md_alg,
unsigned int hashlen,
const unsigned char *hash,
mbedtls_md_type_t mgf1_hash_id,
int expected_salt_len,
const unsigned char *sig )
{
int ret;
size_t siglen;
unsigned char *p;
unsigned char *hash_start;
unsigned char result[MBEDTLS_MD_MAX_SIZE];
unsigned char zeros[8];
unsigned int hlen;
size_t observed_salt_len, msb;
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
siglen = ctx->len;
if( siglen < 16 || siglen > sizeof( buf ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
ret = ( mode == MBEDTLS_RSA_PUBLIC )
? mbedtls_rsa_public( ctx, sig, buf )
: mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf );
if( ret != 0 )
return( ret );
p = buf;
if( buf[siglen - 1] != 0xBC )
return( MBEDTLS_ERR_RSA_INVALID_PADDING );
if( md_alg != MBEDTLS_MD_NONE )
{
/* Gather length of hash to sign */
md_info = mbedtls_md_info_from_type( md_alg );
if( md_info == NULL )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
hashlen = mbedtls_md_get_size( md_info );
}
md_info = mbedtls_md_info_from_type( mgf1_hash_id );
if( md_info == NULL )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
hlen = mbedtls_md_get_size( md_info );
memset( zeros, 0, 8 );
/*
* Note: EMSA-PSS verification is over the length of N - 1 bits
*/
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
if( buf[0] >> ( 8 - siglen * 8 + msb ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
/* Compensate for boundary condition when applying mask */
if( msb % 8 == 0 )
{
p++;
siglen -= 1;
}
if( siglen < hlen + 2 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
hash_start = p + siglen - hlen - 1;
mbedtls_md_init( &md_ctx );
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
goto exit;
ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx );
if( ret != 0 )
goto exit;
buf[0] &= 0xFF >> ( siglen * 8 - msb );
while( p < hash_start - 1 && *p == 0 )
p++;
if( *p++ != 0x01 )
{
ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
goto exit;
}
observed_salt_len = hash_start - p;
if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY &&
observed_salt_len != (size_t) expected_salt_len )
{
ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
goto exit;
}
/*
* Generate H = Hash( M' )
*/
ret = mbedtls_md_starts( &md_ctx );
if ( ret != 0 )
goto exit;
ret = mbedtls_md_update( &md_ctx, zeros, 8 );
if ( ret != 0 )
goto exit;
ret = mbedtls_md_update( &md_ctx, hash, hashlen );
if ( ret != 0 )
goto exit;
ret = mbedtls_md_update( &md_ctx, p, observed_salt_len );
if ( ret != 0 )
goto exit;
ret = mbedtls_md_finish( &md_ctx, result );
if ( ret != 0 )
goto exit;
if( memcmp( hash_start, result, hlen ) != 0 )
{
ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
goto exit;
}
exit:
mbedtls_md_free( &md_ctx );
return( ret );
}
/*
* Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function
*/
int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
mbedtls_md_type_t md_alg,
unsigned int hashlen,
const unsigned char *hash,
const unsigned char *sig )
{
mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE )
? (mbedtls_md_type_t) ctx->hash_id
: md_alg;
return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode,
md_alg, hashlen, hash,
mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY,
sig ) );
}
#endif /* MBEDTLS_PKCS1_V21 */