首页 > 其他分享 >uboot添加密码保护功能

uboot添加密码保护功能

时间:2024-12-07 19:56:59浏览次数:5  
标签:uboot ubootpwd int 密码保护 unsigned char 密码 添加 MD5

uboot添加密码保护功能

让boot更具安全性

linux在进入系统后,一般都有用户名和密码验证,可以有效的防止非授权用户获取操作权限。密码一般密存在/etc/passwd文件中。
但是我们常用的uboot、pmon等bootloader程序,很少看到有做密码保护功能。进入boot循环后,可以操作内核及文件系统分区,或则设置成其它的启动方式,一样可以绕过linux系统的保护功能,到达损坏或则窃取系统信息的目的,这个问题好像也一直没有引起行业的重视。
直到一次和友商的合作中,看到他们所有的平台都作了boot的密码保护功能,所以赶紧研究了以下把现有的平台都实现了bootloader的密码功能。
其实在CSDN网上也有博主分享了怎么实现uboot密码的功能,此功能的完善也是借鉴了很多同行的无私分享,在此表示感谢。
但是网上能够搜索到的资料有限,只讲了一些基础的实现方式,既然做了就一定要把他做好。所以参考了linux系统的密码实现方式,使用了MD5算法对密码进行保护,同时支持密码重置、超级密码等功能,通过算法保护的密码,即使对boot镜像进行dump打印,也是无法获取到原始密码的,所以这也是很多安全密码只允许重置,不允许找回的原因,因为就算是后台也不能通过密存的数据反推出原始密码。当然有些平台非法的操作就不保证了。
后来读了以下pmon的源码,这个boot是考虑了密码保护的,但是配置一番之后还是没有跑起来。所以也按照下文介绍的方式,写了一个减配版的pmon密码保护程序。

MD5介绍

MD5是一种单向散列函数,可以将任意长度的一段数据散列成固定长度,这样就保证了环境变量中存放的密码是固定长度的认证码,通过该认证码是无法反推出源数据的,这样就保证系统管理员甚至看到代码以及将执行文件dump出来也无法获取到超级密码以及用户密码。这样就大大提高了我们的boot程序以及系统的安全性。不过据说国外有教授已经破解了MD5的算法,不过用于我们普通的boot保护,也已经完全足够了。

添加uboot的密码保护后效果

用户敲击指定按键,打断uboot的引导,进入boot命令行,系统提示输入密码:

Hit SPACE key to stop autoboot:  0 
Please input uboot password:
********
WARNING: Incorrect password, re-enter the password.
	
Please input uboot password:

输入错误密码(密码通过*号保护),系统提示密码错误重新输入密码;
如果不想继续输入密码,执行ctrl+c可以打断本次boot,uboot将重启,这样就可以正常引导系统,而不需要断电重启。
输入默认密码:admin123或者超级密码(boot代码中固定,且不可修改)可以直接进入boot命令行;如下所示:

Hit SPACE key to stop autoboot:  0 
Please input uboot password:
********(输入的是默认密码admin123)
boot# 

Hit SPACE key to stop autoboot:  0 
Please input uboot password:
****************(输入的是超级密码)
boot# 

进入命令行后执行printenv,或者printenv ubootpwd,可以看到密码是被*符号隐藏了的;因为密码是以环境变量的方式保存在flash中,所以需要对密码环境变量进行基础的保护,避免进入boot循环后就可以查看密码。
后来想想这个操作可能有点多余了,既然已经将密码通过MD5散列,那么直接展示散列值同样是可以起到隐藏密码的功能。后续按照我这个方法移植的,可以采用这个思路,而不用去搞很复杂的环境变量的隐藏工作。

boot# printenv
baudrate=115200
bootargs=console=ttyS1,115200 mem=256M@0x0  ip=off init=/linuxrc rootfstype=jffs2 root=/dev/mtdblock3 rw flashtype=nor
bootcmd=set uImage 0x80a00000; set dtb 0x83000000; sfcnor read 0x40000 0x600000 ${uImage}; sfcnor read 0x640000 0x20000 ${dtb}; bootm ${uImage} - ${dtb}
bootdelay=3
ethact=GMAC-9161
ethaddr=00:11:22:33:44:55
gatewayip=192.168.4.1
ipaddr=192.168.4.145
loads_echo=1
netmask=255.255.255.0
serverip=192.168.4.13
stderr=serial
stdin=serial
stdout=serial
ubootpwd=********						(可见密码内容及长度已被隐藏)

Environment size: 565/4092 bytes
boot#
boot# printenv ubootpwd
ubootpwd=********						(可见密码内容及长度已经被隐藏)
boot# 

密码可以被修改,但是不能不删除(一般的删除环境变量的方式为:setenv env_name,不传入env_value则删除),使用setenv ubootpwd命令删除该环境变量,直接返回,不执行删除动作;

boot# setenv ubootpwd		(删除ubootpwd环境变量命令)
boot# saveenv				(执行保存)
save ok!!
boot# printenv
.
.
.
ubootpwd=********			(可以看到该环境变量任然存在)
.
.
.
Environment size: 565/4092 bytes
boot# 

修改uboot密码的方式为:
setenv ubootpwd password
输入的password会被MD5散列成一段16字节长度的认证码,然后将该认证码转换为字符串后(16进制源数据中常包含‘\0’,不能作为环境变量存放),存放到环境变量中去。

boot# setenv ubootpwd password
密码无法找回,请牢记登录密码:password
执行<saveenv>命令使密码生效
boot# saveenv
save ok!!
boot# 

密码修改成功,此时输入的password密码将被散列,散列的16位数据将以字符串的方式存放到环境变量中,下一次进行密码验证的时候,也是将键入的密码进行散列后进行字符串比对。

添加过程

先完成一个计算密码字符串MD5值的函数代码,后面的增加初始密码和超级密码也需要用的上。

  • 计算初始MD5
    这里只附上主程序代码,ctx16_md5函数和boot中添加的一样,后面附上。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ctx16_md5.h"
static void HexToStr(char *pszDest, char* pbSrc, int nLen)
{
	char ddl,ddh;
	int i;
	for(i = 0; i < nLen; i++)
	{
		ddh = 48 + ((pbSrc[i] >> 4) & 0xf);
		ddl = 48 + (pbSrc[i] &0xf);
		if(ddh > 57) 
			ddh = ddh + 7;
		if(ddl > 57) 
			ddl = ddl + 7;
		pszDest[i*2] = ddh;
		pszDest[i*2 + 1] = ddl;
	}
	pszDest[nLen * 2] = '\0';
}

static void StrToHex(char *pbDest, char *pbSrc, int nLen)
{
	char h1, h2;
	char s1, s2;
	int i;
	for(i = 0; i < nLen / 2; i++)
	{
		h1 = pbSrc[2*i];
		h2 = pbSrc[2*i+1];
		s1 = toupper(h1) - 0x30;
		if(s1 > 9)
			s1 -= 7;
		s2 = toupper(h2) - 0x30;
		if(s2 > 9)
			s2 -= 7;
		pbDest[i] = s1*16 + s2;
	}
}

int main(int argc, char* argv[])
{
	int ret;
	MD5_CTX md5;
	MD5Init(&md5);
	unsigned char ctx_root[16] = {0};
	unsigned char ctx_root_str[33] = {0};
	
	MD5Update(&md5, argv[1], strlen(argv[1]));			//如果argv[1]输入的特殊字符需要用'\'转义
	MD5Final(&md5, ctx_root);   
	HexToStr(ctx_root_str, ctx_root, sizeof(ctx_root));
	
	printf("%s\n", ctx_root_str);
	return 0;
}
  • 修改入口文件
    主要入口修改文件:common/main.c中的readline函数;该函数的修改时为了打断uboot直接进入命令行,提供密码输入交互入口;
/*
 * Prompt for input and read a line.
 * If  CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
 * time out when time goes past endtime (timebase time in ticks).
 * Return:  number of read characters
 *      -1 if break
 *      -2 if timed out
 */
int readline (const char *const prompt)
{

#ifdef CONFIG_UBOOT_PWD
    char pwd[64];
    char c;
    int index;
    static int bPwd = 1;
    unsigned long ts;
    unsigned char ctx_root[16] = {0};
    unsigned char ctx_root_str[33] = {0};
    MD5_CTX md5;
    
    while(bPwd)
    {
        puts("Please input uboot password:\n");
        index = 0;
        while((c = getc()) != '\r'){
            if (c == 8) /*backspace*/
            {
                if(index > 0){
                    printf("\b \b");
                    index--;
                }
                continue;
            }
            else if (c == 3){
                do_reset(NULL, 0, 0, NULL);
            }
            putc('*');
            pwd[index] = c;
            index++;
        }
        pwd[index] = '\0';
        putc('\n');
        char *s;
        s = getenv("ubootpwd");                         /*从环境变量中获取密码密文*/                            
        if(!s){																			/*如果没有该环境变量,则使用以下秘闻*/
            s = "21232f297a57a5a743894a0e4a801fc3";     /*admin*/
        }
        /*通过输入的密码计算出MD5值*/
        MD5Init(&md5);
        MD5Update(&md5, pwd, strlen((char*)pwd));
        MD5Final(&md5, ctx_root);   
        /*将MD5值转换成字符串*/
        HexToStr(ctx_root_str, ctx_root, sizeof(ctx_root));
        
        if(!strcmp(ctx_root_str,s))                                         //环境变量密码
        {
            bPwd = 0;																										//推出循环
        }
        else if(!strcmp(ctx_root_str,CONFIG_SUPER_UBOOTPWD))                //超级密码MD5值和输入密码的MD5值对比
        {
            bPwd = 0;
        }
        
        else{																													//密码错误
            puts("WARNING: Incorrect password, re-enter the password.\n\n");
            udelay(50000);
        }
    }
#endif
    /*
    * If console_buffer isn't 0-length the user will be prompted to modify
     * it instead of entering it from scratch as desired.
     */
    console_buffer[0] = '\0';

    return readline_into_buffer(prompt, console_buffer, 0);
}

以上函数中调用了HexToStr()16进制转字符串的函数,在测试代码中有实现,函数比较简单,直接实现在各自文件中就可以,不再独立提取出来,移植过程中有需要的地方复制到对应文件中即可。

  • 添加配置文件
    修改环境变量配置文件,路径如下:include/env_default.h
    主要代码:
#ifdef  CONFIG_UBOOT_PWD
    "ubootpwd=" CONFIG_UBOOTPWD "\0"
#endif

该修改是为了让uboot的执行文件中包含默认的环境变量以及变量值,即ubootpwd=admin123

修改板级配置文件:include/config/目标板卡.h

#define CONFIG_UBOOT_PWD
#define CONFIG_UBOOTPWD       "0192023A7BBD73250516F069DF18B500"
#define CONFIG_SUPER_UBOOTPWD   "C357EC5A045A962AF062ED9341DAC732"

密码散列值就是用初始MD5程序计算就可以,可以测试CONFIG_UBOOTPWD是否为admin123散列计算后的值。

  • 环境变量ubootpwd通过MD5散列加密
    进入uboot的命令行,通过setenv命令,可以修改ubootpwd变量值,即修改了环境变量密码,此时ubootpwd这个变量值则是设置的uboot密码,设置的密码被MD5算法散列后,保存到环境变量中;
    以下修改时为了对输入的ubootpwd环境变量的值进行MD5散列加密存储,同时禁止删除ubootpwd环境变量;
    修改文件:common/cmd_nvedit.c文件下的_do_env_set ()函数
/*
 * Set a new environment variable,
 * or replace or delete an existing one.
 */
static int _do_env_set(int flag, int argc, char * const argv[])
{
    int   i, len;
    char  *name, *value, *s;
    ENTRY e, *ep;
    int env_flag = H_INTERACTIVE;
    MD5_CTX md5;
    
    debug("Initial value for argc=%d\n", argc);
    while (argc > 1 && **(argv + 1) == '-') {
        char *arg = *++argv;

        --argc;
        while (*++arg) {
            switch (*arg) {
            case 'f':       /* force */
                env_flag |= H_FORCE;
                break;
            default:
                return CMD_RET_USAGE;
            }
        }
    }
    debug("Final value for argc=%d\n", argc);
    name = argv[1];
    value = argv[2];

    if (strchr(name, '=')) {
        printf("## Error: illegal character '='"
               "in variable name \"%s\"\n", name);
        return 1;
    }

    env_id++;

    /* Delete only ? */
    if (argc < 3 || argv[2] == NULL) {
        if(!strncmp("ubootpwd",argv[1],strlen("ubootpwd")))         //密码不允许设空,"setenv ubootpwd" 命令不执行
            return 0;
        int rc = hdelete_r(name, &env_htab, env_flag);
        return !rc;
    }

    /*
     * Insert / replace new value
     */
    for (i = 2, len = 0; i < argc; ++i)
        len += strlen(argv[i]) + 1;
        
    value = malloc(len);
    if (value == NULL) {
        printf("## Can't malloc %d bytes\n", len);
        return 1;
    }
    for (i = 2, s = value; i < argc; ++i) {
        char *v = argv[i];

        while ((*s++ = *v++) != '\0')
            ;
        *(s - 1) = ' ';
    }
    if (s != value)
        *--s = '\0';

    e.key   = name;
    e.data  = value;
    
    //检测到时设置密码,启动MD5计算
    if(!strncmp("ubootpwd",e.key,strlen("ubootpwd")))
    {
        MD5Init(&md5);
        unsigned char decrypt_hex[16];  
        unsigned char decrypt_str[33] = {0};  
        MD5Update(&md5,e.data,strlen((char*)e.data));
        MD5Final(&md5,decrypt_hex);  
        HexToStr(decrypt_str, decrypt_hex, sizeof(decrypt_hex));
        printf("密码无法找回,请牢记登录密码:%s\n",e.data);
        printf("执行<saveenv>命令使密码生效\n");
        //printf("密码哈希校验:%s\n",decrypt_str);
        e.data = decrypt_str;                       //密存密码信息    
    }   
    hsearch_r(e, ENTER, &ep, &env_htab, env_flag);
    free(value);
    if (!ep) {
        printf("## Error inserting \"%s\" variable, errno=%d\n",
            name, errno);
        return 1;
    }

    return 0;
}
  • 隐藏环境变量中的ubootpwd变量值
    进入boot命令行后,可以查看环境变量,所以需要同时隐藏ubootpwd这个变量值的长度和字符,所有秘密默认显示为“********”,不论是通过printenv 遍历还是 printenv ubootpwd直接读取,都显示为密码样式。

通过修改common/cmd_nvedit.c文件下的static int env_print()函数,可以在该函数下修改指定变量为ubootpwd时候的变量值显示,即执行printenv ubootpwd时,显示密码样式:
关键代码:

if (name) {        /* print a single name */
        ENTRY e, *ep;

        e.key = name;
        e.data = NULL;
        hsearch_r(e, FIND, &ep, &env_htab, flag);
        if (ep == NULL)
            return 0;
        if(strncmp("ubootpwd",e.key,strlen("ubootpwd")))
            len = printf("%s=%s\n", ep->key, ep->data);
        else
            len = printf("%s=********\n", ep->key);     //隐藏密码字符串以及密码长度
        return len;
    }

而当调用printenv命令显示所有环境变量值时,则需要修改哈希查找内部的函数,将哈希查找到的ubootpwd变量值保护起来;修改地址是:lib/hashtable.c
修改的关键函数是复制修改一个原有的函数:

ssize_t hexport_r_pwd(struct hsearch_data *htab, const char sep, int flag,
         char **resp, size_t size,
         int argc, char * const argv[])

if(0 == strncmp("ubootpwd", list[i]->key, strlen("ubootpwd")))
        {
            s = "********";                                 //隐藏密码字符串以及密码长度
            while (*s) {
                if ((*s == sep) || (*s == '\\'))
                    *p++ = '\\';    /* escape */
                {
                    *p++ = *s++;
                }
            }
        }

把以关于MD5的代码,添加到common/路径下,并修改Makefile,选择CONFIG_UBOOT_PWD条件编译。
ctx16_md5.c

/*#include <string.h>*/
#include "ctx16_md5.h"

unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void MD5Init(MD5_CTX *context)
{
     context->count[0] = 0;
     context->count[1] = 0;
     context->state[0] = 0x67452301;
     context->state[1] = 0xEFCDAB89;
     context->state[2] = 0x98BADCFE;
     context->state[3] = 0x10325476;
}

void MD5Update(MD5_CTX *context,unsigned char*input,unsigned int inputlen)
{
    unsigned int i = 0,index = 0,partlen = 0;
    index = (context->count[0] >> 3) & 0x3F;
    partlen = 64 - index;
    context->count[0] += inputlen << 3;
    if(context->count[0] < (inputlen << 3))
       context->count[1]++;
    context->count[1] += inputlen >> 29; 

    if(inputlen >= partlen)
    {
       memcpy(&context->buffer[index],input,partlen);
       MD5Transform(context->state,context->buffer);
       for(i = partlen;i+64 <= inputlen;i+=64)
           MD5Transform(context->state,&input[i]);
       index = 0;        
    }  
    else
    {
        i = 0;
    }
    memcpy(&context->buffer[index],&input[i],inputlen-i);
}

void MD5Final(MD5_CTX *context,unsigned char digest[16])
{
    unsigned int index = 0,padlen = 0;
    unsigned char bits[8];
    index = (context->count[0] >> 3) & 0x3F;
    padlen = (index < 56)?(56-index):(120-index);
    MD5Encode(bits,context->count,8);
    MD5Update(context,PADDING,padlen);
    MD5Update(context,bits,8);
    MD5Encode(digest,context->state,16);
}

void MD5Encode(unsigned char*output,unsigned int*input,unsigned int len)
{
    unsigned int i = 0,j = 0;
    while(j < len)
    {
		output[j] = input[i] & 0xFF;  
        output[j+1] = (input[i] >> 8) & 0xFF;
        output[j+2] = (input[i] >> 16) & 0xFF;
        output[j+3] = (input[i] >> 24) & 0xFF;
        i++;
        j+=4;
    }
}

void MD5Decode(unsigned int*output,unsigned char*input,unsigned int len)
{
     unsigned int i = 0,j = 0;
     while(j < len)
     {
		output[i] = (input[j]) |
			 (input[j+1] << 8) |
			(input[j+2] << 16) |
			(input[j+3] << 24);
		i++;
		j+=4; 
     }
}

void MD5Transform(unsigned int state[4],unsigned char block[64])
{
	unsigned int a = state[0];
	unsigned int b = state[1];
	unsigned int c = state[2];
	unsigned int d = state[3];
	unsigned int x[64];
	
	MD5Decode(x,block,64);
	FF(a, b, c, d, x[ 0], 7, 0xd76aa478);/* 1 */
	FF(d, a, b, c, x[ 1], 12, 0xe8c7b756);/* 2 */
	FF(c, d, a, b, x[ 2], 17, 0x242070db);/* 3 */
	FF(b, c, d, a, x[ 3], 22, 0xc1bdceee);/* 4 */
	FF(a, b, c, d, x[ 4], 7, 0xf57c0faf);/* 5 */
	FF(d, a, b, c, x[ 5], 12, 0x4787c62a);/* 6 */
	FF(c, d, a, b, x[ 6], 17, 0xa8304613);/* 7 */
	FF(b, c, d, a, x[ 7], 22, 0xfd469501);/* 8 */
	FF(a, b, c, d, x[ 8], 7, 0x698098d8);/* 9 */
	FF(d, a, b, c, x[ 9], 12, 0x8b44f7af);/* 10 */
	FF(c, d, a, b, x[10], 17, 0xffff5bb1);/* 11 */
	FF(b, c, d, a, x[11], 22, 0x895cd7be);/* 12 */
	FF(a, b, c, d, x[12], 7, 0x6b901122);/* 13 */
	FF(d, a, b, c, x[13], 12, 0xfd987193);/* 14 */
	FF(c, d, a, b, x[14], 17, 0xa679438e);/* 15 */
	FF(b, c, d, a, x[15], 22, 0x49b40821);/* 16 */

	/* Round 2 */
	GG(a, b, c, d, x[ 1], 5, 0xf61e2562);/* 17 */
	GG(d, a, b, c, x[ 6], 9, 0xc040b340);/* 18 */
	GG(c, d, a, b, x[11], 14, 0x265e5a51);/* 19 */
	GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);/* 20 */
	GG(a, b, c, d, x[ 5], 5, 0xd62f105d);/* 21 */	
	GG(d, a, b, c, x[10], 9,  0x2441453);/* 22 */
	GG(c, d, a, b, x[15], 14, 0xd8a1e681);/* 23 */
	GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);/* 24 */
	GG(a, b, c, d, x[ 9], 5, 0x21e1cde6);/* 25 */
	GG(d, a, b, c, x[14], 9, 0xc33707d6);/* 26 */
	GG(c, d, a, b, x[ 3], 14, 0xf4d50d87);/* 27 */
	GG(b, c, d, a, x[ 8], 20, 0x455a14ed);/* 28 */
	GG(a, b, c, d, x[13], 5, 0xa9e3e905);/* 29 */
	GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8);/* 30 */
	GG(c, d, a, b, x[ 7], 14, 0x676f02d9);/* 31 */
	GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);/* 32 */
	
	/* Round 3 */
	HH(a, b, c, d, x[ 5], 4, 0xfffa3942);/* 33 */
	HH(d, a, b, c, x[ 8], 11, 0x8771f681);/* 34 */
	HH(c, d, a, b, x[11], 16, 0x6d9d6122);/* 35 */
	HH(b, c, d, a, x[14], 23, 0xfde5380c);/* 36 */
	HH(a, b, c, d, x[ 1], 4, 0xa4beea44);/* 37 */
	HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9);/* 38 */
	HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60);/* 39 */
	HH(b, c, d, a, x[10], 23, 0xbebfbc70);/* 40 */
	HH(a, b, c, d, x[13], 4, 0x289b7ec6);/* 41 */
	HH(d, a, b, c, x[ 0], 11, 0xeaa127fa);/* 42 */
	HH(c, d, a, b, x[ 3], 16, 0xd4ef3085);/* 43 */
	HH(b, c, d, a, x[ 6], 23,  0x4881d05);/* 44 */
	HH(a, b, c, d, x[ 9], 4, 0xd9d4d039);/* 45 */
	HH(d, a, b, c, x[12], 11, 0xe6db99e5);/* 46 */
	HH(c, d, a, b, x[15], 16, 0x1fa27cf8);/* 47 */
	HH(b, c, d, a, x[ 2], 23, 0xc4ac5665);/* 48 */

	/* Round 4 */
	II(a, b, c, d, x[ 0], 6, 0xf4292244);/* 49 */
	II(d, a, b, c, x[ 7], 10, 0x432aff97);/* 50 */
	II(c, d, a, b, x[14], 15, 0xab9423a7);/* 51 */
	II(b, c, d, a, x[ 5], 21, 0xfc93a039);/* 52 */
	II(a, b, c, d, x[12], 6, 0x655b59c3);/* 53 */
	II(d, a, b, c, x[ 3], 10, 0x8f0ccc92);/* 54 */
	II(c, d, a, b, x[10], 15, 0xffeff47d);/* 55 */
	II(b, c, d, a, x[ 1], 21, 0x85845dd1);/* 56 */
	II(a, b, c, d, x[ 8], 6, 0x6fa87e4f);/* 57 */
	II(d, a, b, c, x[15], 10, 0xfe2ce6e0);/* 58 */
	II(c, d, a, b, x[ 6], 15, 0xa3014314);/* 59 */
	II(b, c, d, a, x[13], 21, 0x4e0811a1);/* 60 */
	II(a, b, c, d, x[ 4], 6, 0xf7537e82);/* 61 */
	II(d, a, b, c, x[11], 10, 0xbd3af235);/* 62 */
	II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);/* 63 */
	II(b, c, d, a, x[ 9], 21, 0xeb86d391);/* 64 */

    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;
}

ctx16_md5.h

#ifndef CTX16_MD5_H
#define CTX16_MD5_H

typedef struct
{
    unsigned int count[2];
    unsigned int state[4];
    unsigned char buffer[64];   
}MD5_CTX;

#define F(x,y,z) ((x & y) | (~x & z))
#define G(x,y,z) ((x & z) | (y & ~z))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y ^ (x | ~z))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
#define FF(a,b,c,d,x,s,ac) \
          { \
          a += F(b,c,d) + x + ac; \
          a = ROTATE_LEFT(a,s); \
          a += b; \
          }

#define GG(a,b,c,d,x,s,ac) \
          { \
          a += G(b,c,d) + x + ac; \
          a = ROTATE_LEFT(a,s); \
          a += b; \
          }

#define HH(a,b,c,d,x,s,ac) \
          { \
          a += H(b,c,d) + x + ac; \
          a = ROTATE_LEFT(a,s); \
          a += b; \
          }

#define II(a,b,c,d,x,s,ac) \
          { \
          a += I(b,c,d) + x + ac; \
          a = ROTATE_LEFT(a,s); \
          a += b; \
          }                                            

void MD5Init(MD5_CTX *context);

void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen);
     
void MD5Final(MD5_CTX *context,unsigned char digest[16]);
     
void MD5Transform(unsigned int state[4],unsigned char block[64]);
     
void MD5Encode(unsigned char* output,unsigned int *input,unsigned int len);
     
void MD5Decode(unsigned int* output,unsigned char *input,unsigned int len);

#endif

后续

Pmon行业用的比较少,等哪天整理出来重新写一片文章来介绍。也可以参考以上思路,完成一个基本的密码保护功能完全足够。

标签:uboot,ubootpwd,int,密码保护,unsigned,char,密码,添加,MD5
From: https://blog.csdn.net/weixin_41972926/article/details/144259419

相关文章

  • k8s阶段06 k8s认证体系和插件, 添加用户账号认证, kubeconfig使用, serviceaccount,
    1Kubernetes的访问控制体系认证:APIServer:https://control_host:6443/#集群外部访问控制平面节点ip+6443https://kubernetes.default.svc.cluster.local#集群内部访问集群网关:APIServer#执行安全策略:认证,鉴权,准入控制(其他地方很少用到)......
  • 如何添加辅助线(几何问题)如何画辅助线
    如何添加辅助线?⭐️⭐️⭐️⭐️⭐️添加辅助线的方法主要包括按定义添加和按基本图形添加两种情况‌:‌按定义添加辅助线‌:例如,证明两直线垂直可以延长使它们相交后证明交角为90°;证明线段倍半关系可以倍线段取中点或半线段加倍;证明角的倍半关系也可以类似添加辅助线。‌1‌按基本图形添......
  • CreadWindow创建控件,设置控件ID,添加消息响应
    1、设置控件ID,资源头文件中,添加一行---> #defineIDC_控件名   (int)控件ID号; 随便你给定ID号,只要和其他的不重复就好了。2、HWNDh控件句柄=CreateWindow(控件类名,控件描述,控件风格,左上角坐标X, 左上角坐标Y,宽,高,控件的父句柄,(HMENU)菜单句柄,应用......
  • nginx中添加lua模块,结合exporter计算内存使用率动态负载均衡调度
    一、nginx中添加lua模块1、安装依赖yuminstallgccgcc++readline-develwgetvimbash-completionpcrepcre-develzlibzlib-developensslopenssl-develunziplualua-devel-y2、编译安装luajit2wgethttps://github.com/openresty/luajit2/archive/refs/tags/v2......
  • 怎么给手持设备添加特殊样式?
    给手持设备添加特殊样式,主要通过CSS媒体查询@media来实现。以下是一些常用的方法和技巧:1.基于视口宽度(ViewportWidth)的媒体查询:这是最常用的方法,通过设置max-width来针对不同屏幕尺寸应用不同的样式。/*针对小于768px宽度屏幕的样式*/@media(max-width:768......
  • JavaScript中todolist操作--待办事项的添加 删除 完成功能
    效果图在文本框中输入内容点击添加按钮会在下面生成添加功能html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><......
  • 一文教你用vite创建vue3项目初始化并添加router、axios、Pinia保姆级教程
    文章目录一、什么是vite二、什么是vue3三、什么是router四、什么是axios五、什么是pinia六、详细教程1.查看nodejs版本2.使用vite最新版3.配置@指代src目录(可选)4.安装router5.引入axios6.引入pinia一、什么是viteVite是新一代的前端构建工具,在尤雨溪开发Vue3.0的......
  • 保姆级教程用vite创建vue3项目并初始化添加PrimeVue UI踩坑实录
    文章目录一、什么是PrimeVue二、详细教程1.添加PrimeVue2.配置main.js3.添加自动引入4.配置vite.config.js5.创建测试页面一、什么是PrimeVuePrimeVue是一个用于Vue.js3.x开发的一款高质量、广受欢迎的WebUI组件库。官网地址:https://primevue.org/二......
  • 实战示例:在报表中添加权限管控
    本文目录一:修改代码二、创建用户角色并测试三、对更改后的代码进行测试补充示例:给用户增加权限业务场景:需要给报表添加权限管控,没有工厂权限的用户使用该事务码查询不到对应的数据。一、修改代码①确定权限管控的位置:一般权限检查写在最开始,在STARTOFSELECTION部分;也......
  • day09(Linux底层)Uboot分析及配置编译
    目录Uboot分析及配置编译1、uboot源码结构2、uboot配置与编译2.1、uboot配置3、uboot编译4、总结5、配置编译内核5.1配置交叉编译工具链5.2读README5.3配置内核源码支持当前的硬件平台5.4指定自己的硬件平台5.5驱动配置5.6内核编译5.7测试内核Uboot分......