OpenSSL源代码分析

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连接结构列出如下:

[cpp]
  1. struct ssl_st  
  2.     {  
  3.     /* protocol version 
  4.      * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION) 
  5.      */  
  6.     int version;  
  7.     int type; /* SSL_ST_CONNECT or SSL_ST_ACCEPT */  
  8.   
  9.     const SSL_METHOD *method; /* SSLv3 */  
  10.   
  11.     /* There are 2 BIO's even though they are normally both the 
  12.      * same.  This is so data can be read and written to different 
  13.      * handlers */  
  14.   
  15. #ifndef OPENSSL_NO_BIO   
  16.     BIO *rbio; /* used by SSL_read */  
  17.     BIO *wbio; /* used by SSL_write */  
  18.     BIO *bbio; /* used during session-id reuse to concatenate 
  19.             * messages */  
  20. #else   
  21.     char *rbio; /* used by SSL_read */  
  22.     char *wbio; /* used by SSL_write */  
  23.     char *bbio;  
  24. #endif   
  25.     /* This holds a variable that indicates what we were doing 
  26.      * when a 0 or -1 is returned.  This is needed for 
  27.      * non-blocking IO so we know what request needs re-doing when 
  28.      * in SSL_accept or SSL_connect */  
  29.     int rwstate;  
  30.   
  31.     /* true when we are actually in SSL_accept() or SSL_connect() */  
  32.     int in_handshake;  
  33.     int (*handshake_func)(SSL *);  
  34.   
  35.     /* Imagine that here's a boolean member "init" that is 
  36.      * switched as soon as SSL_set_{accept/connect}_state 
  37.      * is called for the first time, so that "state" and 
  38.      * "handshake_func" are properly initialized.  But as 
  39.      * handshake_func is == 0 until then, we use this 
  40.      * test instead of an "init" member. 
  41.      */  
  42.   
  43.     int server; /* are we the server side? - mostly used by SSL_clear*/  
  44.   
  45.     int new_session;/* 1 if we are to use a new session. 
  46.                      * 2 if we are a server and are inside a handshake 
  47.                      *   (i.e. not just sending a HelloRequest) 
  48.                      * NB: For servers, the 'new' session may actually be a previously 
  49.                      * cached session or even the previous session unless 
  50.                      * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */  
  51.     int quiet_shutdown;/* don't send shutdown packets */  
  52.     int shutdown;   /* we have shut things down, 0x01 sent, 0x02 
  53.              * for received */  
  54.     int state;  /* where we are */  
  55.     int rstate; /* where we are when reading */  
  56.   
  57.     BUF_MEM *init_buf;  /* buffer used during init */  
  58.     void *init_msg;     /* pointer to handshake message body, set by ssl3_get_message() */  
  59.     int init_num;       /* amount read/written */  
  60.     int init_off;       /* amount read/written */  
  61.   
  62.     /* used internally to point at a raw packet */  
  63.     unsigned char *packet;  
  64.     unsigned int packet_length;  
  65.   
  66.     struct ssl2_state_st *s2; /* SSLv2 variables */  
  67.     struct ssl3_state_st *s3; /* SSLv3 variables */  
  68.     struct dtls1_state_st *d1; /* DTLSv1 variables */  
  69.   
  70.     int read_ahead;     /* Read as many input bytes as possible 
  71.                          * (for non-blocking reads) */  
  72.   
  73.     /* callback that allows applications to peek at protocol messages */  
  74.     void (*msg_callback)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);  
  75.     void *msg_callback_arg;  
  76.   
  77.     int hit;        /* reusing a previous session */  
  78.   
  79.     X509_VERIFY_PARAM *param;  
  80.   
  81. #if 0   
  82.     int purpose;        /* Purpose setting */  
  83.     int trust;      /* Trust setting */  
  84. #endif   
  85.   
  86.     /* crypto */  
  87.     STACK_OF(SSL_CIPHER) *cipher_list;  
  88.     STACK_OF(SSL_CIPHER) *cipher_list_by_id;  
  89.   
  90.     /* These are the ones being used, the ones in SSL_SESSION are 
  91.      * the ones to be 'copied' into these ones */  
  92.     int mac_flags;   
  93.     EVP_CIPHER_CTX *enc_read_ctx;       /* cryptographic state */  
  94.     EVP_MD_CTX *read_hash;      /* used for mac generation */  
  95. #ifndef OPENSSL_NO_COMP   
  96.     COMP_CTX *expand;           /* uncompress */  
  97. #else   
  98.     char *expand;  
  99. #endif   
  100.   
  101.     EVP_CIPHER_CTX *enc_write_ctx;      /* cryptographic state */  
  102.     EVP_MD_CTX *write_hash;     /* used for mac generation */  
  103. #ifndef OPENSSL_NO_COMP   
  104.     COMP_CTX *compress;         /* compression */  
  105. #else   
  106.     char *compress;   
  107. #endif   
  108.   
  109.     /* session info */  
  110.   
  111.     /* client cert? */  
  112.     /* This is used to hold the server certificate used */  
  113.     struct cert_st /* CERT */ *cert;  
  114.   
  115.     /* the session_id_context is used to ensure sessions are only reused 
  116.      * in the appropriate context */  
  117.     unsigned int sid_ctx_length;  
  118.     unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];  
  119.   
  120.     /* This can also be in the session once a session is established */  
  121.     SSL_SESSION *session;  
  122.   
  123.     /* Default generate session ID callback. */  
  124.     GEN_SESSION_CB generate_session_id;  
  125.   
  126.     /* Used in SSL2 and SSL3 */  
  127.     int verify_mode;    /* 0 don't care about verify failure. 
  128.                  * 1 fail if verify fails */  
  129.     int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */  
  130.   
  131.     void (*info_callback)(const SSL *ssl,int type,int val); /* optional informational callback */  
  132.   
  133.     int error;      /* error bytes to be written */  
  134.     int error_code;     /* actual code */  
  135.   
  136. #ifndef OPENSSL_NO_KRB5   
  137.     KSSL_CTX *kssl_ctx;     /* Kerberos 5 context */  
  138. #endif  /* OPENSSL_NO_KRB5 */   
  139.   
  140. #ifndef OPENSSL_NO_PSK   
  141.     unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,  
  142.         unsigned int max_identity_len, unsigned char *psk,  
  143.         unsigned int max_psk_len);  
  144.     unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,  
  145.         unsigned char *psk, unsigned int max_psk_len);  
  146. #endif   
  147.   
  148.     SSL_CTX *ctx;  
  149.     /* set this flag to 1 and a sleep(1) is put into all SSL_read() 
  150.      * and SSL_write() calls, good for nbio debuging :-) */  
  151.     int debug;    
  152.   
  153.     /* extra application data */  
  154.     long verify_result;  
  155.     CRYPTO_EX_DATA ex_data;  
  156.   
  157.     /* for server side, keep the list of CA_dn we can use */  
  158.     STACK_OF(X509_NAME) *client_CA;  
  159.   
  160.     int references;  
  161.     unsigned long options; /* protocol behaviour */  
  162.     unsigned long mode; /* API behaviour */  
  163.     long max_cert_list;  
  164.     int first_packet;  
  165.     int client_version; /* what was passed, used for 
  166.                  * SSLv3/TLS rollback check */  
  167.     unsigned int max_send_fragment;  
  168. #ifndef OPENSSL_NO_TLSEXT   
  169.     /* TLS extension debug callback */  
  170.     void (*tlsext_debug_cb)(SSL *s, int client_server, int type,  
  171.                     unsigned char *data, int len,  
  172.                     void *arg);  
  173.     void *tlsext_debug_arg;  
  174.     char *tlsext_hostname;  
  175.     int servername_done;   /* no further mod of servername  
  176.                               0 : call the servername extension callback. 
  177.                               1 : prepare 2, allow last ack just after in server callback. 
  178.                               2 : don't call servername callback, no ack in server hello 
  179.                            */  
  180.     /* certificate status request info */  
  181.     /* Status type or -1 if no status type */  
  182.     int tlsext_status_type;  
  183.     /* Expect OCSP CertificateStatus message */  
  184.     int tlsext_status_expected;  
  185.     /* OCSP status request only */  
  186.     STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;  
  187.     X509_EXTENSIONS *tlsext_ocsp_exts;  
  188.     /* OCSP response received or to be sent */  
  189.     unsigned char *tlsext_ocsp_resp;  
  190.     int tlsext_ocsp_resplen;  
  191.   
  192.     /* RFC4507 session ticket expected to be received or sent */  
  193.     int tlsext_ticket_expected;  
  194. #ifndef OPENSSL_NO_EC   
  195.     size_t tlsext_ecpointformatlist_length;  
  196.     unsigned char *tlsext_ecpointformatlist; /* our list */  
  197.     size_t tlsext_ellipticcurvelist_length;  
  198.     unsigned char *tlsext_ellipticcurvelist; /* our list */  
  199. #endif /* OPENSSL_NO_EC */   
  200.   
  201.     /* draft-rescorla-tls-opaque-prf-input-00.txt information to be used for handshakes */  
  202.     void *tlsext_opaque_prf_input;  
  203.     size_t tlsext_opaque_prf_input_len;  
  204.   
  205.     /* TLS Session Ticket extension override */  
  206.     TLS_SESSION_TICKET_EXT *tlsext_session_ticket;  
  207.   
  208.     /* TLS Session Ticket extension callback */  
  209.     tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;  
  210.     void *tls_session_ticket_ext_cb_arg;  
  211.   
  212.     /* TLS pre-shared secret session resumption */  
  213.     tls_session_secret_cb_fn tls_session_secret_cb;  
  214.     void *tls_session_secret_cb_arg;  
  215.   
  216.     SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */  
  217. #define session_ctx initial_ctx   
  218. #else   
  219. #define session_ctx ctx   
  220. #endif /* OPENSSL_NO_TLSEXT */   
  221.     };  

列出SSL方法结构SSL_METHOD如下:

[cpp]
  1. /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */  
  2. typedef struct ssl_method_st  
  3.     {  
  4.     int version;  
  5.     int (*ssl_new)(SSL *s);  
  6.     void (*ssl_clear)(SSL *s);  
  7.     void (*ssl_free)(SSL *s);  
  8.     int (*ssl_accept)(SSL *s);  
  9.     int (*ssl_connect)(SSL *s);  
  10.     int (*ssl_read)(SSL *s,void *buf,int len);  
  11.     int (*ssl_peek)(SSL *s,void *buf,int len);  
  12.     int (*ssl_write)(SSL *s,const void *buf,int len);  
  13.     int (*ssl_shutdown)(SSL *s);  
  14.     int (*ssl_renegotiate)(SSL *s);  
  15.     int (*ssl_renegotiate_check)(SSL *s);  
  16.     long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long  
  17.         max, int *ok);  
  18.     int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len,   
  19.         int peek);  
  20.     int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);  
  21.     int (*ssl_dispatch_alert)(SSL *s);  
  22.     long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);  
  23.     long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);  
  24.     const SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);  
  25.     int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr);  
  26.     int (*ssl_pending)(const SSL *s);  
  27.     int (*num_ciphers)(void);  
  28.     const SSL_CIPHER *(*get_cipher)(unsigned ncipher);  
  29.     const struct ssl_method_st *(*get_ssl_method)(int version);  
  30.     long (*get_timeout)(void);  
  31.     struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */  
  32.     int (*ssl_version)(void);  
  33.     long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));  
  34.     long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));  
  35.     } SSL_METHOD;

SSL工作方式:双向证书认证的SSL握手过程。
以下简要介绍SSL协议的工作方式。客户端要收发几个握手信号:
1、发送一个“ClientHello”消息,说明它支持的密码算法列表、压缩方法及最高协议版本,也发送稍后将被使用的随机数。
2、然后收到一个“ServerHello”消息,包含服务器选择的连接参数,源自客户端初期所提供的“ClientHello”。
3、当双方知道了连接参数,客户端与服务器交换证书(依靠被选择的公钥系统)。这些证书通常基于X.509,不过已有草案支持以OpenPGP为基础的证书。
4、服务器请求客户端公钥。客户端有证书即双向身份认证,没证书时随机生成公钥。
5、客户端与服务器通过公钥保密协商共同的主私钥(双方随机协商),这通过精心谨慎设计的伪随机数功能实现。结果可能使用Diffie-Hellman交换,或简化的公钥加密,双方各自用私钥解密。所有其他关键数据的加密均使用这个“主密钥”。

数据传输中记录层(Record layer)用于封装更高层的HTTP等协议。记录层数据可以被随意压缩、加密,与消息验证码压缩在一起。每个记录层包都有一个Content-Type段用以记录更上层用的协议。

使用SSL层接口函数有以下几个步骤:

1、初始化OpenSSL库

初始化函数列出如下:

#define OpenSSL_add_ssl_algorithms()SSL_library_init()
#define SSLeay_add_ssl_algorithms() SSL_library_init()


2、选择会话协议

客户端使用下面的函数选择会话协议:

const SSL_METHOD *SSLv2_client_method(void);/* SSLv2 */


const SSL_METHOD *SSLv3_client_method(void);/* SSLv3 */


const SSL_METHOD *SSLv23_client_method(void);/* SSLv3 but can rollback to v2 */


const SSL_METHOD *TLSv1_client_method(void);/* TLSv1.0 */


const SSL_METHOD *DTLSv1_client_method(void);/* DTLSv1.0 */


服务器端使用下面的函数选择会话协议:

const SSL_METHOD *SSLv2_server_method(void);/* SSLv2 */
const SSL_METHOD *SSLv3_server_method(void); /* SSLv3 */
const SSL_METHOD *SSLv23_server_method(void); /* SSLv3 but can rollback to v2 */
const SSL_METHOD *TLSv1_server_method(void); /* TLSv1.0 */
const SSL_METHOD *DTLSv1_server_method(void); /* DTLSv1.0 */


3、创建会话环境

创建会话环境:

SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);


设置证书验证方式:

void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,
int (*callback)(int, X509_STORE_CTX *));


给会话环境加载CA证书:

int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);


给会话环境加载用户私钥:

int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
int SSL_CTX_use_PrivateKey_ASN1(int pk,SSL_CTX *ctx,
const unsigned char *d, long len);


验证私钥和证书是否相符:

int SSL_CTX_check_private_key(const SSL_CTX *ctx);


4、建立SSL套接字

SSL套接字建立在普通的TCP套接字基础上,应用程序在创建普通套接字、得到套接字描述符fd之后,再创建SSL套接字,并将fd绑定在SSL套接字上。

SSL *SSL_new(SSL_CTX *ctx);


intSSL_set_fd(SSL *s, int fd);
int SSL_set_rfd(SSL *s, int fd);
int SSL_set_wfd(SSL *s, int fd);


5、完成SSL握手

与普通socket编程类似,创建SSL套接字后,客户端使用SSL_connect替代普通socket的connect函数,服务器端则以SSL_accept代替普通socket的accept()函数。

int SSL_accept(SSL *ssl);
int SSL_connect(SSL *ssl);


握手完成之后,询问通信双方的证书信息:

X509 *SSL_get_peer_certificate(const SSL *s);


X509_NAME *X509_get_subject_name(X509 *a);  // <openssl/x509.h>


6、数据传输

对数据的安全传输包括了加密/解密、压缩/解压缩的过程。

int SSL_read(SSL *ssl,void *buf,int num);
int SSL_peek(SSL *ssl,void *buf,int num);
int SSL_write(SSL *ssl,const void *buf,int num);


7、SSL通信结束

关闭SSL套接字、释放会话环境。

int SSL_shutdown(SSL *s);

voidSSL_free(SSL *ssl);


voidSSL_CTX_free(SSL_CTX *);


BIO是对IO操作的封装,OpenSSL的BIO抽象接口不仅可以对SSL连接的I/O使用,也可以对非加密的网络连接和文件的I/O使用。BIO的相关源代码在crypto/bio文件夹下。

BIO的相关数据结构列出如下。

BIO结构:

[cpp] view plaincopyprint?
  1. struct bio_st  
  2.     {  
  3.     BIO_METHOD *method;  
  4.     /* bio, mode, argp, argi, argl, ret */  
  5.     long (*callback)(struct bio_st *,int,const char *,intlong,long);  
  6.     char *cb_arg; /* first argument for the callback */  
  7.   
  8.     int init;  
  9.     int shutdown;  
  10.     int flags;  /* extra storage */  
  11.     int retry_reason;  
  12.     int num;  
  13.     void *ptr;  
  14.     struct bio_st *next_bio;    /* used by filter BIOs */  
  15.     struct bio_st *prev_bio;    /* used by filter BIOs */  
  16.     int references;  
  17.     unsigned long num_read;  
  18.     unsigned long num_write;  
  19.   
  20.     CRYPTO_EX_DATA ex_data;  
  21.     };  
BIO操作的结构:

[cpp] view plaincopyprint?
  1. typedef struct bio_method_st  
  2.     {  
  3.     int type;  
  4.     const char *name;  
  5.     int (*bwrite)(BIO *, const char *, int);  
  6.     int (*bread)(BIO *, char *, int);  
  7.     int (*bputs)(BIO *, const char *);  
  8.     int (*bgets)(BIO *, char *, int);  
  9.     long (*ctrl)(BIO *, intlongvoid *);  
  10.     int (*create)(BIO *);  
  11.     int (*destroy)(BIO *);  
  12.         long (*callback_ctrl)(BIO *, int, bio_info_cb *);  
  13.     } BIO_METHOD;  
BIO接口类型分为源/接收类型和过滤类型两种。

[cpp] view plaincopyprint?
  1. #define BIO_TYPE_DESCRIPTOR0x0100 /* socket, fd, connect or accept */   
  2. #define BIO_TYPE_FILTER 0x0200   
  3. #define BIO_TYPE_SOURCE_SINK 0x0400  

1、源/接收类型

[cpp] view plaincopyprint?
  1. #define BIO_TYPE_MEM(1|0x0400)   
  2. #define BIO_TYPE_FILE (2|0x0400)   
  3. #define BIO_TYPE_FD (4|0x0400|0x0100)   
  4. #define BIO_TYPE_SOCKET (5|0x0400|0x0100)   
  5. #define BIO_TYPE_NULL (6|0x0400)   
  6. #define BIO_TYPE_CONNECT(12|0x0400|0x0100)/* socket - connect */   
  7. #define BIO_TYPE_ACCEPT(13|0x0400|0x0100)/* socket for accept */   
  8. #define BIO_TYPE_BIO(19|0x0400)/* (half a) BIO pair */   
  9. #define BIO_TYPE_DGRAM(21|0x0400|0x0100)  

2、过滤类型

[cpp] view plaincopyprint?
  1. #define BIO_TYPE_SSL(7|0x0200)   
  2. #define BIO_TYPE_MD(8|0x0200) /* passive filter */   
  3. #define BIO_TYPE_BUFFER (9|0x0200)/* filter */   
  4. #define BIO_TYPE_CIPHER (10|0x0200)/* filter */   
  5. #define BIO_TYPE_BASE64 (11|0x0200)/* filter */   
  6. #define BIO_TYPE_PROXY_CLIENT (14|0x0200)/* client proxy BIO */   
  7. #define BIO_TYPE_PROXY_SERVER (15|0x0200)/* server proxy BIO */   
  8. #define BIO_TYPE_NBIO_TEST (16|0x0200)/* server proxy BIO */   
  9. #define BIO_TYPE_NULL_FILTER (17|0x0200)   
  10. #define BIO_TYPE_BER (18|0x0200)/* BER -> bin filter */   
  11. #define BIO_TYPE_LINEBUFFER (20|0x0200)/* filter */   
  12. #define BIO_TYPE_ASN1 (22|0x0200)/* filter */   
  13. #define BIO_TYPE_COMP (23|0x0200)/* filter */  

BIO过滤缓冲结构:

[cpp] view plaincopyprint?
  1. typedef struct bio_f_buffer_ctx_struct  
  2.     {  
  3.     /* BIO *bio; */ /* this is now in the BIO struct */  
  4.     int ibuf_size;  /* how big is the input buffer */  
  5.     int obuf_size;  /* how big is the output buffer */  
  6.   
  7.     char *ibuf;     /* the char array */  
  8.     int ibuf_len;       /* how many bytes are in it */  
  9.     int ibuf_off;       /* write/read offset */  
  10.   
  11.     char *obuf;     /* the char array */  
  12.     int obuf_len;       /* how many bytes are in it */  
  13.     int obuf_off;       /* write/read offset */  
  14.     } BIO_F_BUFFER_CTX;  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值