灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:4392回复:0

[系统教程]Linux安全体系学习笔记之二:OpenSSL源代码分析

楼主#
更多 发布于:2011-12-27 11:31
OpenSSL的源代码包括三部分:加密算法库、SSL库和应用程序。
 
 
 
加密算法库的源代码主要在crypto文件夹里,包括ASN.1编码与解码接口(crypto/asn1/asn1.h),伪随机数产生器(crypto/rand/rand.h),ENGINE机制(crypto/engine),统一密码算法的EVP密码算法接口(crypto/evp/evp.h),大数运算接口(crypto/bn/bn.h),私钥信息语法(crypto/x509/x509.h),非对称密码算法(crypto/rsa/ras.h)等。
 
 
 
SSL库的源代码主要在ssl文件夹里,我们重点分析。
 
 
 
SSL相关的几个重要的数据结构包括:
 
 
 
1、SSL连接结构:核心结构,应用程序通过该结构获取所有其他结构。
 
 
 
2、上下文结构SSL_CTX:是全局的上下文结构,含有结构SSL的主要默认值,包含SSL会话结构。
 
 
 
3、会话结构SSL_SESSION:含有链接的当前TLS/SSL会话细节。
 
 
 
4、密码结构SSL_CIPHER:含有制定的加密算法信息。
 
 
 
5、方法结构SSL_METHOD:功能函数接口,统一了各种SSL协议版本(SSLv1, SSLv2, SSLv3, TLSv1)。
 
 
 
SSL连接结构列出如下:
 
 
 
<span style="font-size:18px;">struct ssl_st
 
    {
 
    /* protocol version
 
     * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
 
     */
 
    int version;
 
    int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */
 
 
 
    const SSL_METHOD *method; /* SSLv3 */
 
 
 
    /* There are 2 BIO's even though they are normally both the
 
     * same.  This is so data can be read and written to different
 
     * handlers */
 
 
 
#ifndef OPENSSL_NO_BIO
 
    BIO *rbio; /* used by SSL_read */
 
    BIO *wbio; /* used by SSL_write */
 
    BIO *bbio; /* used during session-id reuse to concatenate
 
            * messages */
 
#else
 
    char *rbio; /* used by SSL_read */
 
    char *wbio; /* used by SSL_write */
 
    char *bbio;
 
#endif
 
    /* This holds a variable that indicates what we were doing
 
     * when a 0 or -1 is returned.  This is needed for
 
     * non-blocking IO so we know what request needs re-doing when
 
     * in SSL_accept or SSL_connect */
 
    int rwstate;
 
 
 
    /* true when we are actually in SSL_accept() or SSL_connect() */
 
    int in_handshake;
 
    int (*handshake_func)(SSL *);
 
 
 
    /* Imagine that here's a boolean member "init" that is
 
     * switched as soon as SSL_set_{accept/connect}_state
 
     * is called for the first time, so that "state" and
 
     * "handshake_func" are properly initialized.  But as
 
     * handshake_func is == 0 until then, we use this
 
     * test instead of an "init" member.
 
     */
 
www.atcpu.com

    int server; /* are we the server side? - mostly used by SSL_clear*/
 
 
 
    int new_session;/* 1 if we are to use a new session.
 
                     * 2 if we are a server and are inside a handshake
 
                     *   (i.e. not just sending a HelloRequest)
 
                     * NB: For servers, the 'new' session may actually be a previously
 
                     * cached session or even the previous session unless
 
                     * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
 
    int quiet_shutdown;/* don't send shutdown packets */
 
    int shutdown;   /* we have shut things down, 0x01 sent, 0x02
 
             * for received */
 
    int state;  /* where we are */
 
    int rstate; /* where we are when reading */
 
 
 
    BUF_MEM *init_buf;  /* buffer used during init */
 
    void *init_msg;     /* pointer to handshake message body, set by ssl3_get_message() */
 
    int init_num;       /* amount read/written */
 
    int init_off;       /* amount read/written */
 
 
 
    /* used internally to point at a raw packet */
 
    unsigned char *packet;
 
    unsigned int packet_length;
 
 
 
    struct ssl2_state_st *s2; /* SSLv2 variables */
 
    struct ssl3_state_st *s3; /* SSLv3 variables */
 
    struct dtls1_state_st *d1; /* DTLSv1 variables */
 
 
 
    int read_ahead;     /* Read as many input bytes as possible
 
                         * (for non-blocking reads) */
 
 
 
    /* callback that allows applications to peek at protocol messages */
 
    void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
 
    void *msg_callback_arg;
 
 
 
    int hit;        /* reusing a previous session */
 
 
 
    X509_VERIFY_PARAM *param;
 
 
 
#if 0
 
    int purpose;        /* Purpose setting */
 
    int trust;      /* Trust setting */
 
#endif
 
 
 
    /* crypto */
 
    STACK_OF(SSL_CIPHER) *cipher_list;
 
    STACK_OF(SSL_CIPHER) *cipher_list_by_id;
 
 
 
    /* These are the ones being used, the ones in SSL_SESSION are
 
     * the ones to be 'copied' into these ones */
 
    int mac_flags;  
 
    EVP_CIPHER_CTX *enc_read_ctx;       /* cryptographic state */
 
    EVP_MD_CTX *read_hash;      /* used for mac generation */
 
#ifndef OPENSSL_NO_COMP
 
    COMP_CTX *expand;           /* uncompress */
 
#else
 
    char *expand;
 
#endif
 
 
 
    EVP_CIPHER_CTX *enc_write_ctx;      /* cryptographic state */
 
    EVP_MD_CTX *write_hash;     /* used for mac generation */
 
#ifndef OPENSSL_NO_COMP
 
    COMP_CTX *compress;         /* compression */
 
#else
 
    char *compress;  
 
#endif
 
 
 
    /* session info */
 
 
 
    /* client cert? */
 
    /* This is used to hold the server certificate used */
 
    struct cert_st /* CERT */ *cert;
 
 
 
    /* the session_id_context is used to ensure sessions are only reused
 
     * in the appropriate context */
 
    unsigned int sid_ctx_length;
 
    unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 
 
 
    /* This can also be in the session once a session is established */
 
    SSL_SESSION *session;
 
 
 
    /* Default generate session ID callback. */
 
    GEN_SESSION_CB generate_session_id;
 
 
 
    /* Used in SSL2 and SSL3 */
 
    int verify_mode;    /* 0 don't care about verify failure.
 
                 * 1 fail if verify fails */
 
    int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */
 
 
 
    void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */
 
 
 
    int error;      /* error bytes to be written */
 
    int error_code;     /* actual code */
 
 
 
#ifndef OPENSSL_NO_KRB5
 
    KSSL_CTX *kssl_ctx;     /* Kerberos 5 context */
 
#endif  /* OPENSSL_NO_KRB5 */
 
 
 
#ifndef OPENSSL_NO_PSK
 
    unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
 
        unsigned int max_identity_len, unsigned char *psk,
 
        unsigned int max_psk_len);
 
    unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
 
        unsigned char *psk, unsigned int max_psk_len);
 
#endif
 
 
 
    SSL_CTX *ctx;
 
    /* set this flag to 1 and a sleep(1) is put into all SSL_read()
 
     * and SSL_write() calls, good for nbio debuging :-) */
 
    int debug;  
 
 
 
    /* extra application data */
 
    long verify_result;
 
    CRYPTO_EX_DATA ex_data;
 
 
 
    /* for server side, keep the list of CA_dn we can use */
 
    STACK_OF(X509_NAME) *client_CA;
 
 
 
    int references;
 
    unsigned long options; /* protocol behaviour */
 
    unsigned long mode; /* API behaviour */
 
    long max_cert_list;
 
    int first_packet;
 
    int client_version; /* what was passed, used for
 
                 * SSLv3/TLS rollback check */
 
    unsigned int max_send_fragment;
 
#ifndef OPENSSL_NO_TLSEXT
 
    /* TLS extension debug callback */
 
    void (*tlsext_debug_cb)(SSL *s, int client_server, int type,
 
                    unsigned char *data, int len,
 
                    void *arg);
 
    void *tlsext_debug_arg;
 
    char *tlsext_hostname;
 
    int servername_done;   /* no further mod of servername
 
                              0 : call the servername extension callback.
 
                              1 : prepare 2, allow last ack just after in server callback.
 
                              2 : don't call servername callback, no ack in server hello
 
                           */
 
    /* certificate status request info */
 
    /* Status type or -1 if no status type */
 
    int tlsext_status_type;
 
    /* Expect OCSP CertificateStatus message */
 
    int tlsext_status_expected;
 
    /* OCSP status request only */
 
    STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
 
    X509_EXTENSIONS *tlsext_ocsp_exts;
 
    /* OCSP response received or to be sent */
 
    unsigned char *tlsext_ocsp_resp;
 
    int tlsext_ocsp_resplen;
 
 
 
    /* RFC4507 session ticket expected to be received or sent */
 
    int tlsext_ticket_expected;
 
#ifndef OPENSSL_NO_EC
 
    size_t tlsext_ecpointformatlist_length;
 
    unsigned char *tlsext_ecpointformatlist; /* our list */
 
    size_t tlsext_ellipticcurvelist_length;
 
    unsigned char *tlsext_ellipticcurvelist; /* our list */
 
#endif /* OPENSSL_NO_EC */
 
 
 
    /* draft-rescorla-tls-opaque-prf-input-00.txt information to be used for handshakes */
 
    void *tlsext_opaque_prf_input;
 
    size_t tlsext_opaque_prf_input_len;
 
 
 
    /* TLS Session Ticket extension override */
 
    TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
 
 
 
    /* TLS Session Ticket extension callback */
 
    tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
 
    void *tls_session_ticket_ext_cb_arg;
 
 
 
    /* TLS pre-shared secret session resumption */
 
    tls_session_secret_cb_fn tls_session_secret_cb;
 
    void *tls_session_secret_cb_arg;
 
 
 
    SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
 
#define session_ctx initial_ctx
 
#else
 
#define session_ctx ctx
 
#endif /* OPENSSL_NO_TLSEXT */
 
    };</span>
 
 
 
列出SSL方法结构SSL_METHOD如下:
 
 
 
view plain
 
<span style="font-size:18px;">/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
 
typedef struct ssl_method_st
 
    {
 
    int version;
 
    int (*ssl_new)(SSL *s);
 
    void (*ssl_clear)(SSL *s);
 
    void (*ssl_free)(SSL *s);
 
    int (*ssl_accept)(SSL *s);
 
    int (*ssl_connect)(SSL *s);
 
    int (*ssl_read)(SSL *s,void *buf,int len);
 
    int (*ssl_peek)(SSL *s,void *buf,int len);
 
    int (*ssl_write)(SSL *s,const void *buf,int len);
 
    int (*ssl_shutdown)(SSL *s);
 
    int (*ssl_renegotiate)(SSL *s);
 
    int (*ssl_renegotiate_check)(SSL *s);
 
    long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
 
        max, int *ok);
 
    int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len,  
 
        int peek);
 
    int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
 
    int (*ssl_dispatch_alert)(SSL *s);
 
    long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);
 
    long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);
 
    const SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);
 
    int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr);
 
    int (*ssl_pending)(const SSL *s);
 
    int (*num_ciphers)(void);
 
    const SSL_CIPHER *(*get_cipher)(unsigned ncipher);
 
    const struct ssl_method_st *(*get_ssl_method)(int version);
 
    long (*get_timeout)(void);
 
    struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
 
    int (*ssl_version)(void);
 
    long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
 
    long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
 
    } SSL_METHOD;</span>
 

喜欢0 评分0
游客

返回顶部