zoukankan      html  css  js  c++  java
  • OpenSSL对称加密算法中如何添加新算法

     

    1.关于加密算法的加载

    在调用加密算法之前,通过调用OpenSSL_add_all_algorithms来加载加密算法函数和单向散列算法函数

    void OpenSSL_add_all_algorithms(void)

    {

    OpenSSL_add_all_ciphers(); /* 加载加密算法 */

    OpenSSL_add_all_digests(); /* 加载单向散列函数 */

    }

    void OpenSSL_add_all_ciphers(void)函数实现如下:

    void OpenSSL_add_all_ciphers(void)

    {

    EVP_add_cipher(EVP_rc2_cfb());

    。。。。。。

    PKCS12_PBE_add();

    PKCS5_PBE_add();

    }

    /* 这个过程的主要任务是向全局变量,static LHASH *names_lh,注册加密算法,如果添加了新的加密算法,必需向names_lh注册。 */

    由于DES算法接口内容较多,所以我们从IDEA算法的接口开始研究!

    #ifndef NO_IDEA

    EVP_add_cipher(EVP_idea_ecb()); /*添加EBC加密模式 */

    EVP_add_cipher(EVP_idea_cfb()); /*添加CFB加密模式 */

    EVP_add_cipher(EVP_idea_ofb()); /*添加OCF加密模式 */

    EVP_add_cipher(EVP_idea_cbc()); /*添加CBC加密模式 */

    EVP_add_cipher_alias(SN_idea_cbc,"IDEA"); /*添加cbc加密算法的别名 “IDEA” */

    EVP_add_cipher_alias(SN_idea_cbc,"idea"); /*添加cbc加密算法的别名 “idea” */

    #endif

    在包括IDEA加密算法的情况下,OpenSSL将会选择IDAE加密算法模块!

    下面来看看EVP_add_cipher函数是怎么实现的,

    int EVP_add_cipher(EVP_CIPHER *c)

    {

    int r;

    r=OBJ_NAME_add(OBJ_nid2sn(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(char *)c);

    if (r == 0) return(0);

    r=OBJ_NAME_add(OBJ_nid2ln(c->nid),OBJ_NAME_TYPE_CIPHER_METH,(char *)c);

    return(r);

    }

    /* 向全决变量names_lh 注册 obj_name_types 变量的过程 */

    int OBJ_NAME_add(const char *name, int type, const char *data)

    {

    OBJ_NAME *onp,*ret;

    int alias;

    if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);

    alias=type&OBJ_NAME_ALIAS;

    type&= ~OBJ_NAME_ALIAS;

    onp=(OBJ_NAME *)OPENSSL_malloc(sizeof(OBJ_NAME));

    if (onp == NULL)

    {

    /* ERROR */

    return(0);

    }

    onp->name=name;

    onp->alias=alias;

    onp->type=type;

    onp->data=data;

    ret=(OBJ_NAME *)lh_insert(names_lh,onp);

    if (ret != NULL)

    {

    /* free things */

    if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))

    {

    /* XXX: I'm not sure I understand why the free

    * function should get three arguments...

    * -- Richard Levitte

    */

    sk_NAME_FUNCS_value(name_funcs_stack,ret->type)

    ->free_func(ret->name,ret->type,ret->data);

    }

    OPENSSL_free(ret);

    }

    else

    {

    if (lh_error(names_lh))

    {

    /* ERROR */

    return(0);

    }

    }

    return(1);

    }

    names_lh 是 LHASH的全局变量,用于维护obj_name_types的类型的变量。(在crypt/objects/o_names.c中定义)

    (crypt/objects/obj_dat.h)相关的全局变量

    static unsigned char lvalues[2896] 全局变量,已经初始化,存放了OpenSSL所有Object的相关信息。

    nid_objs 是ASN1_OBJECT结构的数组全局变量,已经初始化,记录了所有OpenSSL用到的类型的名字

    static ASN1_OBJECT *sn_objs[NUM_SN] 全局变量,已经初始化。

    static ASN1_OBJECT *ln_objs[NUM_LN] 全局变量,已经初始化。

    crypt/object/objects.h 中定义的结构

    typedef struct obj_name_st

    {

    int type;

    int alias;

    const char *name;

    const char *data;

    } OBJ_NAME;

    注意:crypto/objects 目录下面维护整个OpenSSL模块化的重要的程序,下面逐个做出介绍。

    objects.txt 按照一定的语法结构,定义了SN_base, LN_base, NID_base,OBJ_base。经过perl程序objects.pl通过命令perl objects.pl objects.txt obj_mac.num obj_mac.h 处理后,生成了obj_mac.num 和obj_mac.h两个文件。

    obj_mac.num 用来查阅 OBJ_base与NID_base之间的对应关系。

    obj_mac.h 用来提供c语言类型SN_base, LN_base, NID_base,OBJ_base定义。

    objects.h 同样提供了c语言类型SN_base, LN_base, NID_base,OBJ_base定义,在obj_mac.h 更新之后,必须对对应的objects.h 中的内容作出同步,及保持与obj_mac.h的定义一至,同时objects.h中也声明了一些对OBJ_name的操作函数。

    objects.h 经过perl程序perl obj_dat.pl objects.h obj_dat.h处理之后,生成obj_dat.h头文件。

    obj_dat.h 中定义了如下的全局变量。

    #define NUM_NID 393

    #define NUM_SN 392

    #define NUM_LN 392

    #define NUM_OBJ 366

    static unsigned char lvalues[2896],

    static ASN1_OBJECT nid_objs[NUM_NID],

    static ASN1_OBJECT *sn_objs[NUM_SN],

    static ASN1_OBJECT *ln_objs[NUM_LN],

    static ASN1_OBJECT *obj_objs[NUM_OBJ],

    这些变量多有ASN1_OBJECT有关,在objects.txt中定义的所有的对象都会体现出来,具体的作用还不太清楚,需要继续研究!

    对OpenSSL中宏的研究

    密码算法接口的定义

    typedef struct evp_cipher_st EVP_CIPHER;

    /* 加密算法后被names_lh来管理,可以通算法的名称或别名来检索 */

    struct evp_cipher_st

    {

    int nid; /*加密算法的nid*/

    int block_size; /*数据块的大小 */

    int key_len; /* Default value for variable length ciphers */

    int iv_len; /* 对于CBC,CFB,OFB的加密算法初始化矢量*/

    unsigned long flags; /* Various flags */

    int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key,

    const unsigned char *iv, int enc); /* init key */

    int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out,

    const unsigned char *in, unsigned int inl);/* encrypt/decrypt data */

    int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */

    int ctx_size; /* how big the ctx needs to be */

    int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Populate a ASN1_TYPE with parameters */

    int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Get parameters from a ASN1_TYPE */

    int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); /* Miscellaneous operations */

    void *app_data; /* Application data */

    };

    如果正确定义了EVP_CIPHER变量,这个算法就可以被OpenSSL所接受了。

    下面的宏将定义ECB,CBC,CFB,OFB算法EVP_CIPHER定义。

    #define BLOCK_CIPHER_defs(cname, kstruct, \

    nid, block_size, key_len, iv_len, flags,\

    init_key, cleanup, set_asn1, get_asn1, ctrl)\

    static EVP_CIPHER cname##_cbc = {\

    nid##_cbc, block_size, key_len, iv_len, \

    flags | EVP_CIPH_CBC_MODE,\

    init_key,\

    cname##_cbc_cipher,\

    cleanup,\

    sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\

    sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\

    set_asn1, get_asn1,\

    ctrl, \

    NULL \

    };\

    EVP_CIPHER *EVP_##cname##_cbc(void) { return &cname##_cbc; }\

    static EVP_CIPHER cname##_cfb = {\

    nid##_cfb64, 1, key_len, iv_len, \

    flags | EVP_CIPH_CFB_MODE,\

    init_key,\

    cname##_cfb_cipher,\

    cleanup,\

    sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\

    sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\

    set_asn1, get_asn1,\

    ctrl,\

    NULL \

    };\

    EVP_CIPHER *EVP_##cname##_cfb(void) { return &cname##_cfb; }\

    static EVP_CIPHER cname##_ofb = {\

    nid##_ofb64, 1, key_len, iv_len, \

    flags | EVP_CIPH_OFB_MODE,\

    init_key,\

    cname##_ofb_cipher,\

    cleanup,\

    sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\

    sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\

    set_asn1, get_asn1,\

    ctrl,\

    NULL \

    };\

    EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\

    static EVP_CIPHER cname##_ecb = {\

    nid##_ecb, block_size, key_len, iv_len, \

    flags | EVP_CIPH_ECB_MODE,\

    init_key,\

    cname##_ecb_cipher,\

    cleanup,\

    sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\

    sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\

    (ctx_size 其中有联合的结构,如何获取EVP_CIPHER_CTX数据长度)

    set_asn1, get_asn1,\

    ctrl,\

    NULL \

    };\

    EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; }

    上面的宏在经过处理之后,变成了四中加密模式的EVP_CIPHER定义,这个结构中封装了加密操作汉书,密钥初始化函数,以及密钥的清理函数。除了实现加密算法之外,还比需实现对应的密钥结构!

    EVP_CIPHER_CTX就是密钥结构,完成对加密算法密钥的管理。

    typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;

    struct evp_cipher_ctx_st

    {

    const EVP_CIPHER *cipher;

    int encrypt; /* encrypt or decrypt */

    int buf_len; /* number we have left */

    unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */

    unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */

    unsigned char buf[EVP_MAX_IV_LENGTH]; /* saved partial block */

    int num; /* used by cfb/ofb mode */

    void *app_data; /* application stuff */

    int key_len; /* May change for variable length cipher */

    /* 通过联合的方式管理密钥,对各种密钥实现灵活的管理 */

    union {

    #ifndef NO_RC4

    struct

    {

    unsigned char key[EVP_RC4_KEY_SIZE];

    RC4_KEY ks; /* working key */

    } rc4;

    #endif

    #ifndef NO_DES

    des_key_schedule des_ks;/* key schedule */

    struct

    {

    des_key_schedule ks;/* key schedule */

    des_cblock inw;

    des_cblock outw;

    } desx_cbc;

    struct

    {

    des_key_schedule ks1;/* key schedule */

    des_key_schedule ks2;/* key schedule (for ede) */

    des_key_schedule ks3;/* key schedule (for ede3) */

    } des_ede;

    #endif

    #ifndef NO_IDEA

    IDEA_KEY_SCHEDULE idea_ks;/* key schedule */

    #endif

    #ifndef NO_RC2

    struct {

    int key_bits; /* effective key bits */

    RC2_KEY ks;/* key schedule */

    } rc2;

    #endif

    #ifndef NO_RC5

    struct {

    int rounds; /* number of rounds */

    RC5_32_KEY ks;/* key schedule */

    } rc5;

    #endif

    #ifndef NO_BF

    BF_KEY bf_ks;/* key schedule */

    #endif

    #ifndef NO_CAST

    CAST_KEY cast_ks;/* key schedule */

    #endif

    } c;

    };

    下面的函数用来实现设定加密密钥和解密密钥。

    void set_encrypt_key(const unsigned char *key, KEY_SCHEDULE *ks)

    void set_decrypt_key(const unsigned char *key, KEY_SCHEDULE *ks)

    在这两个函数的基础上实现EVP_CIPHER中密钥初始化函数。

    static int init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,

    const unsigned char *iv, int enc)

    {

    if(!enc)

    {

    if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) enc = 1;

    else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) enc = 1;

    }

    if (enc)

    set_encrypt_key(key,&(ctx->c. ks));

    else

    {

    set_decrypt_key(key,&(ctx->c. ks));

    }

    return 1;

    }

    /* 清除保留在内存中的密码 */

    static int clean_key(EVP_CIPHER_CTX *ctx)

    {

    if(ctx)

    memset(&(ctx-c.ks),0,sizeof(ctx->c.ks));

    return 1;

    }

    如果加密算法结构EVP_CIPHER是通过BLOCK_CIPHER_defs宏定义的,则四种模式的算法接口必须何处理宏之后的接口一样:

    int cname_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl);

    int cname_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl);

    int cname_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl);

    int cname_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl);

    二:四种加密模式的实现

    四种加密模式与基本加解密算法之间的关系!

    假设加密算法和解密算法的实现函数接口如下

    void encrypt(const unsigned char *in, unsigned char *out, const KEY *key, int *length)

    void decrypt(const unsigned char *in, unsigned char *out, const KEY *key, int *length)

    void ecb_ encrypt(const unsigned char *in, unsigned char *out,

    long length, const KEY *key, unsigned char *iv, int enc)

    {/* 电子密码本: Electronic Code Book */

    register int i;

    int len = 8;

    register long l = length;

    unsigned char buf[8];

    if(enc)/*encryption*/

    {

    for(i=0;i<=l;i+=8)

    {

    encrypt(&in[i], &out[i], key, &len);/*len == 8 will always be true here*/

    }

    else

    {

    for(i=0;i<=l;i+=8)

    {

    decrypt(&in[i], &out[i], key, &len);/*len == 8 will always be true here*/

    }

    }

    }

    void cbc_encrypt(const unsigned char *in, unsigned char *out,

    long length, const KEY *key, unsigned char *iv, int enc)

    {/* 密钥分组连接模式 */

    register int i;

    int len = 8;

    register long l = length;

    unsigned char buf[8];

    if(enc)/*encryption*/

    {

    for(l-=8; l>=0; l-=8, in+=8, out+=8)

    {

    for(i=0; i<8;>

    buf[i] = in[i] ^ iv[i];

    encrypt(buf, iv, key, &len);/*len == 8 will always be true here*/

    for(i=0; i<8;>

    out[i] = iv[i];

    }

    /*final block*/

    if(l != -8)

    {

    for(i=0; i

    buf[i] = in[i] ^ iv[i];

    for(; i<8;>

    buf[i] = iv[i];

    encrypt(buf, iv, key, &len);/*len == 8 here*/

    for(i=0; i<8;>

    out[i] = iv[i];

    }

    /* 加密输出为做下一次得iv ,iv与in异或运算的结果作为加密输入*/

    }

    else/*decryption*/

    {

    for(l-=8; l>=0; l-=8, in+=8, out +=8)

    {

    decrypt(in, buf, key, &len);

    for(i=0; i<8;>

    out[i] = buf[i] ^ iv[i];

    for(i=0; i<8;>

    iv[i] = in[i];

    }

    /*final block*/

    if(l != -8)

    {

    decrypt(in, buf, key, &len);

    for(i=0; i

    out[i] = buf[i] ^ iv[i];

    for(i=0; i<8;>

    iv[i] = in[i];

    }

    }

    l = 0;

    i = 0;

    }

    void cfb64_encrypt(const unsigned char *in, unsigned char *out,

    long length, const KEY *key, unsigned char *iv, int *num, int enc)

    {/* 密码反馈模式 */

    register long l = length;

    unsigned char buf[8];

    register int i, save = 0, n = *num;/*start from previously saved processing position*/

    int len = 8;

    /*restore from previously saved iv*/

    for(i=n; i<8;>

    buf[i] = iv[i];

    if(enc)

    {

    while(l--)

    {

    if(n == 0)

    {

    encrypt(iv, buf, key, &len);

    save = 1;

    }

    *(out++) = iv[n] = *(in++) ^ buf[n];

    n = (n+1)&0x07;

    }

    }

    else

    {

    while(l--)

    {

    if(n == 0)

    {

    encrypt(iv, buf, key, &len);

    save = 1;

    }

    *(out++) = (iv[n]=*(in++)) ^ buf[n];

    n = (n+1)&0x07;

    }

    }

    if(save)/*store encrypted data into iv for next encryption*/

    for(i=n; i<8;>

    iv[i] = buf[i];

    /* cfb加密输出得结果作为下次得IV, in与加密IV的结果作异或运算的结果作为cfb加密的输出 */

    *num = n;/*store current processing position as entry of next encryption*/

    save = i = n = 0;

    }

    void ofb64_encrypt(const unsigned char *in, unsigned char *out,

    long length, const KEY *key, unsigned char *iv, int *num)

    {/* 输出反馈模式 */

    register long l = length;

    register int i, n = *num;/*start from previously saved processing position*/

    int len = 8;

    unsigned char buf[8];

    /*restore from previously saved iv*/

    if(n != 0)

    for(i=n; i<8;>

    buf[i] = iv[i];

    while(l--)

    {

    if(n == 0)

    {

    encrypt(iv, buf, key, &len);

    for(i=0; i<8;>

    iv[i] = buf[i];

    }

    *(out++) = *(in++) ^ buf[n];

    n = (n+1)&0x07; /* n=(n+1)%0x08*/

    /* iv加密输出结果作魏下一次iv, iv与in异或运算的结果作为ofb加密输出 */

    }

    *num = n;/*store current processing position as entry of next encryption*/

    i = n = 0;

    }

    三:如何在SSL协议中添加新的加密算法!

    首先,我们来看相关的全局变量 ssl3_ciphers[],在ssl/s3_lib.c中定义

    变量的类型定义如下:

    typedef struct ssl_cipher_st

    {

    int valid;

    const char *name; /* text name */

    unsigned long id; /* id, 4 bytes, first is version */

    unsigned long algorithms; /* what ciphers are used */

    unsigned long algo_strength; /* strength and export flags */

    unsigned long algorithm2; /* Extra flags */

    int strength_bits; /* Number of bits really used */

    int alg_bits; /* Number of bits for algorithm */

    unsigned long mask; /* used for matching */

    unsigned long mask_strength; /* also used for matching */

    } SSL_CIPHER;

    举例来说明

    /* Cipher 03 */

    {

    1,

    SSL3_TXT_RSA_RC4_40_MD5, //字符串,在ssl3.h中定义!

    SSL3_CK_RSA_RC4_40_MD5, //整形,在ssl3.h中定义

    SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_MD5 |SSL_SSLV3,(在ssl_loal.h中定义)

    //密钥交换算法|身份认证算法|加密算法|消息摘要算法|ssl协议版本号

    SSL_EXPORT|SSL_EXP40,

    0,

    40,

    128,

    SSL_ALL_CIPHERS,

    SSL_ALL_STRENGTHS,

    },

    如果增加了新的加密算法,必须注意定义的所数值是否可用,如果涉及到位与运算,还必须更改相应的掩码!

    EVP_CIPHER *ssl_cipher_methods在ssl_ciph中定义,在函数void load_ciphers(void) 中完成对ssl_cipher_methods的初始化工作!

    请在这里添加新的加密算法!并且在int ssl_cipher_get_evp(SSL_SESSION *s, const EVP_CIPHER **enc, const EVP_MD **md, SSL_COMP **comp)和static unsigned long ssl_cipher_get_disabled(void)中添加相应的实现算法!

  • 相关阅读:
    人月神话读后感2
    人月神话读后感1
    自己跟自己聊天的软件2
    做一个自己跟自己聊天的软件
    安装Android开发工具
    阅读笔记6
    阅读笔记5
    第16周学习进度总结
    个人课程总结
    第15周学习进度总结
  • 原文地址:https://www.cnblogs.com/adylee/p/899409.html
Copyright © 2011-2022 走看看