加密原理先暂且不详说,这次只是把如何实现这个控制加载何种算法思路大致说一下,大家都知道,客户端和服务端在进行正真的应用数据通信之前,需要建立tcp三次握手连接之后,还要进行握手协商,客户端会把自己支持的算法套件,产生的随机数,还有支持的版本号,发给对端,这个阶段称为hello阶段,,在这个阶段,我们就可以控制选择把何种支持的算法套件发给服务器,大致如下:算法都有一个唯一的ID,这是可以区别不同的算法,各个不同的tls/ssl版本算法的名字可能会变化,但这个算法ID是不会变的,就像我们人类的省份证号码不会变,但自己的名字会变一样。首先,我们可以定义一个数组,使用各个算法的ID填充数组,像下面这样:
unsigned int g_ssl_cipher_support[32]=
{
0x03000002,
0x03000004,
0x03000005,
0x0300000A,
0x0300002F,
0x03000035,
0x0300003C,
0x0300003D,
0x03000067,
0x0300006B,
0x0300009C,
0x0300009E,
0x0300C027,
0x0300C02F,
};
由于是通过AT命令发送,首先是在AT命令里设置好INT32 g_ssl_cipher_flag = 0xffffffff;
g_ssl_cipher_is_support //0不选,1选择
g_ssl_cipher_id //相当于数组的下标,
再设置两个参数:如下
g_ssl_cipher_flag &=(~(1 << g_ssl_cipher_id));
g_ssl_cipher_flag |=(g_ssl_cipher_is_support <<g_ssl_cipher_id );
在hello阶段,在这个ssl_cipher_list_to_byte()函数中,调用自己写好的函数g_check_ssl_cipher_is_suppor()进行筛选我们想要的算法,这个函数实现如下:
extern UINT32 g_ssl_cipher_flag;
BOOL g_check_ssl_cipher_is_support(SSL_CIPHER *c)
{
UINT32 i=0;
int g_ssl_flag=0;
for(i=0;i<32;i++)
{
if(g_ssl_cipher_support[i] == c->id) //根据ID进行选择
{
g_ssl_flag=g_ssl_cipher_flag&(1 <<i);
if(g_ssl_flag)
{
return TRUE;
}
else
{
return FALSE;
}
}
}
return FALSE;
}
完整的ssl_cipher_list_to_bytes()函数实现如下,各个TLS或者SSL版本上都有这个函数实现:具体细节
下次找个时间不上,有时间会把SSL协议和源码都说一下。
int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
int (*put_cb)(const SSL_CIPHER *, unsigned char *))
{
int i,j=0;
SSL_CIPHER *c;
unsigned char *q;
#ifndef OPENSSL_NO_KRB5
int nokrb5 = !kssl_tgt_is_available(s->kssl_ctx);
#endif /* OPENSSL_NO_KRB5 */
if (sk == NULL) return(0);
q=p;
for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
{
CSW_TRACE(4,TSTXT("[ght]sk_SSL_CIPHER_num(sk)=%d\n"),sk_SSL_CIPHER_num(sk));
c=sk_SSL_CIPHER_value(sk,i);
if(c == NULL)
continue;
if(FALSE == g_check_ssl_cipher_is_support(c)) //在这里调用
{
continue;
}
/* Skip TLS v1.2 only ciphersuites if lower than v1.2 */
if ((c->algorithm_ssl & SSL_TLSV1_2) &&
(TLS1_get_client_version(s) < TLS1_2_VERSION))
continue;
#ifndef OPENSSL_NO_KRB5
if (((c->algorithm_mkey & SSL_kKRB5) || (c->algorithm_auth & SSL_aKRB5)) &&
nokrb5)
continue;
#endif /* OPENSSL_NO_KRB5 */
j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
p+=j;
}
/* If p == q, no ciphers and caller indicates an error. Otherwise
* add SCSV if not renegotiating.
*/
#if 0
if (p != q && !s->renegotiate)
{
static SSL_CIPHER scsv =
{
0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
j = put_cb ? put_cb(&scsv,p) : ssl_put_cipher_by_char(s,&scsv,p);
p+=j;
#ifdef OPENSSL_RI_DEBUG
fprintf(stderr, "SCSV sent by client\n");
#endif
}
#endif
return(p-q);