LibreSSLÖ®CVE-2023-35784·ì϶·ÖÎö
°ä²¼¹¦·ò 2024-06-28LibreSSLÊÇ2014ÄêÐÄÔàµÎѪ·ì϶·¢×÷ºó£¬£¬£¬£¬£¬£¬£¬OpenBSD fork OpenSSL 1.0.1g²¢½øÐÐÊØ»¤µÄ°²È«SSL¿â¡£¡£¡£¡£¡£
Ò»¡¢·ì϶ÐÅÏ¢
A double free or use after free could occur after SSL_clear in OpenBSD 7.2 before errata 026 and 7.3 before errata 004, and in LibreSSL before 3.6.3 and 3.7.x before 3.7.3. NOTE: OpenSSL is not affected.
? ²¹¶¡
Index: lib/libssl/s3_lib.c
===================================================================
RCS file: /cvs/src/lib/libssl/s3_lib.c,v
diff -u -p -r1.238 s3_lib.c
--- lib/libssl/s3_lib.c 21 Aug 2022 19:39:44 -0000 1.238
+++ lib/libssl/s3_lib.c 15 May 2023 05:05:28 -0000
@@ -1573,6 +1573,7 @@ ssl3_free(SSL *s)
sk_X509_NAME_pop_free(s->s3->hs.tls12.ca_names, X509_NAME_free);
sk_X509_pop_free(s->internal->verified_chain, X509_free);
+ s->internal->verified_chain = NULL;
tls1_transcript_free(s);
tls1_transcript_hash_free(s)
ÉÏÃæµÄ·ìϼûèÊöºÍ²¹¶¡ÊÇĿǰÄÜÔÚÍøÂçÉÏÕÒµ½µÄËùÓÐÓÐÒâ˼µÄ¹«¿ªÄÚÈÝ¡£¡£¡£¡£¡£
¶þ¡¢·ì϶·ÖÎö
ÕâÀï·ÖÎö3.6.3°æ±¾´ò¹ý²¹¶¡ºóµÄssl3_freeº¯Êý£¨/// ...ÂÔ... ΪʡÂԵIJ¿ÃÅÎ޹شúÂ룬£¬£¬£¬£¬£¬£¬ÏÂÎÄÒ»Ñù£©£º
// 3.6.3 s3_lib.c
void
ssl3_free(SSL *s)
{
if (s == NULL)
return;
tls1_cleanup_key_block(s);
ssl3_release_read_buffer(s);
ssl3_release_write_buffer(s);
/// ...ÂÔ...
sk_X509_NAME_pop_free(s->s3->hs.tls12.ca_names, X509_NAME_free);
sk_X509_pop_free(s->internal->verified_chain, X509_free);////// [1]
s->internal->verified_chain = NULL;////// [2]
tls1_transcript_free(s);
/// ...ÂÔ...
freezero(s->s3,sizeof(*s->s3));
s->s3 = NULL;
}
Ïà±È3.6.2°æ±¾µÄssl3_freeº¯Êý£¬£¬£¬£¬£¬£¬£¬¸Ãº¯Êý¶àÁË[2]´¦¸³ÖµÎªNULLµÄÓï¾ä¡£¡£¡£¡£¡£
2.1 ¼¸¸ö½á¹¹Ìå
ÕâÀïÉæ¼°µ½¼¸¸öÖØÒªµÄ½á¹¹Ì壨v3.6.2£©£¬£¬£¬£¬£¬£¬£¬Ê×ÏÈÊÇSSL½á¹¹Ìå¡£¡£¡£¡£¡£
SSL½á¹¹ÌåÊÇLibreSSL£¨Ô̺¬OpenSSL£©½øÐа²È«Ì×½Ó×Ö±à³Ìʱ×îÖ±½ÓÓ뷨ʽԱ´ò½»Â·µÄ½á¹¹Ì壬£¬£¬£¬£¬£¬£¬°²È«±à³ÌÖØÒªµÄ²Ù×÷¶¼Ö±½Ó»ò¼ä½ÓÓëÆäÓйأ¬£¬£¬£¬£¬£¬£¬Òò¶ø£¬£¬£¬£¬£¬£¬£¬Æä³ÁÒªÐÔ²»ÑÔ¶øÓ÷¡£¡£¡£¡£¡£
2.1.1 SSL
typedef struct ssl_st SSL;
struct ssl_st {
/* protocol version
* (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
*/
int version;
const SSL_METHOD *method;
/// ...ÂÔ...
int server;/* are we the server side? - mostly used by SSL_clear*/
struct ssl3_state_st *s3; /* SSLv3 variables */ ////////// [1]
struct dtls1_state_st *d1; /* DTLSv1 variables */
X509_VERIFY_PARAM *param;
/// ...ÂÔ...
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
#define session_ctx initial_ctx
struct ssl_internal_st *internal; /////////// [2]
};
ÔڸýṹÌåÖУ¬£¬£¬£¬£¬£¬£¬³Áµã¹Ø×¢Ä©Î²µÄinternal³ÉÔ±±äÁ¿£¬£¬£¬£¬£¬£¬£¬ÓÉÓÚµ¼Ö·ì϶²úÉúµÄverified_chainλÓڸýṹÌå±äÁ¿ÄÚ£»£»£»£»£»£»£»£»ÎÒÃÇͬʱעÒâs3³ÉÔ±±äÁ¿£¬£¬£¬£¬£¬£¬£¬×¢ÒâµÄÔÒò¼ûÏÂÎÄ¡£¡£¡£¡£¡£
2.1.2 ssl_internal_st
ssl_internal_st½á¹¹ÌåµÄ½ç˵ÈçÏ£º
typedef struct ssl_internal_st {
struct tls13_ctx *tls13;
uint16_t min_tls_version;
uint16_t max_tls_version;
/*
* These may be zero to imply minimum or maximum version supported by
* the method.
*/
uint16_t min_proto_version;
uint16_t max_proto_version;
/// ...ÂÔ...
int empty_record_count;
size_t num_tickets;
/* Unused, for OpenSSL compatibility */
STACK_OF(X509) *verified_chain; /////// [1]
} SSL_INTERNAL;
·ì϶²úÉúµÄ³ÉÔ±±äÁ¿verified_chainλÓÚssl_internal_st½á¹¹ÌåµÄĩ⣬£¬£¬£¬£¬£¬£¬ÎªÒ»STACK_OF(X509)Ö¸Õë¡£¡£¡£¡£¡£
2.1.3 BTW
ÕâÀï˳±ãÌáÒ»ÏÂSSL£¨Ö¸¹ãÒåÉϵÄSSL£¬£¬£¬£¬£¬£¬£¬Ô̺¬ºóÐøµÄTLS£©µÄÖ¤Êéϵͳ£¬£¬£¬£¬£¬£¬£¬ÓÐÀûÓÚÎÒÃÇÀí½â·ì϶²úÉúµÄ»úÀí¡£¡£¡£¡£¡£
? SSLÖ¤Êéϵͳ
£¨1£©Öð¼¶Ç©·¢
ͨ³£À´Ëµ£¬£¬£¬£¬£¬£¬£¬·þÎñÆ÷·µ»ØµÄÖ¤ÊéÔ̺¬Á˶à¸ö»ú¹¹£¬£¬£¬£¬£¬£¬£¬ÓɸùÖ¤ÊéÐû¸æ»ú¹¹Öð¼¶ÏòÏÂÇ©·¢¡£¡£¡£¡£¡£Ò԰ٶȵÄÖ¤ÊéΪÀý£¬£¬£¬£¬£¬£¬£¬¸ùÖ¤ÊéÐû¸æ»ú¹¹GlobalSignÐû¸æ¸ø»ú¹¹GlobalSign BE£¬£¬£¬£¬£¬£¬£¬¶øGlobalSign BEÔÙÐû¸æ¸ø°Ù¶È¡£¡£¡£¡£¡£
£¨2£©Ö¤ÊéÔ̺¬Ðû¸æÕß¡¢Ðû¸æ¸øË¡¢¹«Ô¿¡¢Ð£ÑéµÈÐÅÏ¢
·þÎñÆ÷·µ»ØµÄÖ¤ÊéÖУ¬£¬£¬£¬£¬£¬£¬Ô̺¬Á˸÷¸ö»ú¹¹µÄ¶àÖÖÐÅÏ¢£¬£¬£¬£¬£¬£¬£¬ºÃ±ÈÐû¸æÕߣ¬£¬£¬£¬£¬£¬£¬Ðû¸æ¸øË£¬£¬£¬£¬£¬£¬£¬¹«Ô¿ÐÅÏ¢£¬£¬£¬£¬£¬£¬£¬°æ±¾¡¢ÓÐЧÆÚ¡¢ÒÔ¼°ÊðÃûµÈ¡£¡£¡£¡£¡£
£¨3£©Á´Ê½Ô̺¬
Öð¼¶Ç©·¢µÄÖ¤Ê飬£¬£¬£¬£¬£¬£¬È·¶¨ÁËÔÚÊý¾ÝÐòÁÐÉÏÓÉÏÂÖÁÉϵÄÁ´Ê½Ô̺¬½á¹¹¡£¡£¡£¡£¡£ ²Ù×÷ϵͳÖÁÉÙÔ̺¬¸ùÖ¤Êé¡£¡£¡£¡£¡£ Ö¤Êéϵͳȷ±£ÁËÁ´Ê½¿ÉÐÅ£¬£¬£¬£¬£¬£¬£¬´Ó¶øÒªÇó²Ù×÷ϵͳÖÁÉÙÒªÔ̺¬¸ùÖ¤Ê飬£¬£¬£¬£¬£¬£¬ºÃ±ÈGlobalSignµÄ¸ùÖ¤Êé¡£¡£¡£¡£¡£
£¨4£©×ÔÊðÃû
Ò»¼¶ ÖØÒª¹©²âÊÔÓà ȱµã£ºÖÐÑëÈ˹¥»÷
ÕâÀïÒ²ÌáÒ»ÏÂ×ÔÊðÃûÖ¤Ê飬£¬£¬£¬£¬£¬£¬Í¨³£ÓÉOpenSSL·¨Ê½ÌìÉú£¬£¬£¬£¬£¬£¬£¬ÓÉ×Ô¼ºÐû¸æ¸ø×Ô¼º£¬£¬£¬£¬£¬£¬£¬Ò²Òò¶ø£¬£¬£¬£¬£¬£¬£¬ÎÞ·¨Í¨¹ý²Ù×÷ϵͳµÄÖ¤ÊÖÔýÈÎÁ´£¬£¬£¬£¬£¬£¬£¬ÎÞ·¨Æ¥µÐÖÐÑëÈ˹¥»÷£¬£¬£¬£¬£¬£¬£¬Í¨³£½öÓÃÓÚ²âÊÔ¡£¡£¡£¡£¡£
ÏÂͼΪ·þÎñÆ÷·µ»ØµÄ°Ù¶ÈÖ¤ÊéÁ´£º

? STACK_OF(X)ºê
¸Ã·ì϶²úÉúÓÚSTACK_OF(X509)ºêÖ¸ÏòµÄ¶Ñ£¬£¬£¬£¬£¬£¬£¬Òò¶ø£¬£¬£¬£¬£¬£¬£¬ÓбØÒªÅªÃ÷ÏÔverified_chainµÄ¶Ñ½á¹¹¡£¡£¡£¡£¡£
#typedef STACK_OF(type) struct stack_st_##type
typedef struct stack_st {
int num;
char **data;
int sorted;
int num_alloc;
int (*comp)(const void *, const void *);
} _STACK; /* Use STACK_OF(...) instead */
STACK_OF(X509) *verified_chain;
ÕâÀ£¬£¬£¬£¬£¬£¬ÎÒÃÇÖØÒª¹Ø×¢num³ÉÔ±±äÁ¿ºÍÖ¸ÏòÊý×éµÄÖ¸Õëdata£¨LibreSSLʹÓÃÁËLinuxÆ«ÔçÆÚµÄ±àÂë·ç¸ñ£¬£¬£¬£¬£¬£¬£¬Ê¹ÓÃchar **°µÊ¾£©¡£¡£¡£¡£¡£
¿Í»§¶Ë»ñÈ¡µ½·þÎñÆ÷¶ËµÄÖ¤Êéºó£¬£¬£¬£¬£¬£¬£¬verified_chainÔÚ¶ÑÖеĽṹÈçÏÂͼ£º

Äܹ»¿´µ½£¬£¬£¬£¬£¬£¬£¬numµÄֵΪ3£¬£¬£¬£¬£¬£¬£¬°µÊ¾Ö¤ÊéÁ´ÎªÈý¼¶Ö¤ÊéÁ´£¨ÈÔÒ԰ٶȵÄÖ¤ÊéΪÀý£¬£¬£¬£¬£¬£¬£¬Èý¼¶±ðÀëΪGlobalSign¡¢GlobalSign BEºÍ°Ù¶È¸÷×ÔµÄÖ¤Ê飩£¬£¬£¬£¬£¬£¬£¬Òò¶ødataÊý×éÖ¸Ïò3¸öx509_stÖ¤Êé½á¹¹Ì壬£¬£¬£¬£¬£¬£¬ÉÏͼʾÀýÖдòÓ¡³öÁË×îµ×²ãµÄ¸ùÖ¤ÊéµÄ²¿ÃųÉÔ±±äÁ¿¡£¡£¡£¡£¡£
2.2 sk_X509_pop_freeºê
ÎÒÃÇ¿´Ò»ÏÂ×îÖÕ¿ªÊÍs->internal->verified_chainµÄsk_X509_pop_freeºê¡£¡£¡£¡£¡£
#define sk_X509_pop_free(st, free_func) SKM_sk_pop_free(X509, (st), (free_func))
#define SKM_sk_pop_free(type, st, free_func) \
sk_pop_free(CHECKED_STACK_OF(type, st), CHECKED_SK_FREE_FUNC(type, free_func))
void
sk_pop_free(_STACK *st, void (*func)(void *))
{
int i;
if (st == NULL) /////// [*]
return;
for (i = 0; i < st->num; i++)
if (st->data[i] != NULL)
func(st->data[i]); /////// [1]
sk_free(st); /////// [2]
}
Äܹ»¿´µ½£¬£¬£¬£¬£¬£¬£¬¸Ãºê×îÖÕŲÓÃsk_pop_freeº¯Êý¡£¡£¡£¡£¡£Ôڸú¯ÊýÄÚ£¬£¬£¬£¬£¬£¬£¬ÏÈÅжÏstÊÇ·ñµÅ×ÚNULL£¨[*]´¦£©£¬£¬£¬£¬£¬£¬£¬ÈôµÅ×ÚÔòÖ±½Ó·µ»Ø£¬£¬£¬£¬£¬£¬£¬×¢Ã÷ÒѾ²»ÔÙ±ØÒª¿ªÊÍÁË£»£»£»£»£»£»£»£»Èôst²»µÅ×ÚNULL£¬£¬£¬£¬£¬£¬£¬ÔòʹÓÃforÑ»·¹²Ñ»·stack_st½á¹¹ÌåÀïµÄnum´Î£¬£¬£¬£¬£¬£¬£¬²¢Ã¿´ÎʹÓú¯ÊýµÄµÚ¶þ¸ö²ÎÊý£¨ÎªÒ»º¯ÊýÖ¸Õ룩Öð¸ö¿ªÊÍÊý×éÄڵĸ÷¸ö³ÉÔ±£¨[1]´¦£©£¬£¬£¬£¬£¬£¬£¬¶ÔÓÚsk_X509_pop_free(s->internal->verified_chain, X509_free)¶øÑÔ£¬£¬£¬£¬£¬£¬£¬func¼´ÎªX509_freeº¯Êý£»£»£»£»£»£»£»£»×îºó¿ªÊÍst¡£¡£¡£¡£¡£
¼ò¶øÑÔÖ®£¬£¬£¬£¬£¬£¬£¬¶ÔÓÚ·ì϶¶øÑÔ£¬£¬£¬£¬£¬£¬£¬sk_pop_freeµÄµÚÒ»¸ö²ÎÊýst(¼´s->internal->verified_chain)ÉϴοªÊͺóûÓи³ÖµÎªNULL£¬£¬£¬£¬£¬£¬£¬µÚ¶þ´Îsk_pop_freeʱÓÉÓÚst²»µÅ×ÚNULL£¬£¬£¬£¬£¬£¬£¬´Ó¶øµ¼ÖÂÔٴα»sk_freeº¯Êý¿ªÊÍ¡£¡£¡£¡£¡£
Èý¡¢·ì϶ÑéÖ¤
ƾ¾Ý·ìϼûèÊöºÍ²¹¶¡ÐÅÏ¢£¬£¬£¬£¬£¬£¬£¬ÎÒÃÇ֪·±ØÒªÓлúÓöÖ´ÐÐsk_X509_pop_free(s->internal->verified_chain, X509_free)Á½´Î¡£¡£¡£¡£¡£
ÕâÉæ¼°µ½SSL½á¹¹ÌåµÄ³ÁÓ㬣¬£¬£¬£¬£¬£¬ÎÒÃÇÏÈ¿´Ò»¸ö×îµ¥Ò»µÄʹÓÃSSL½á¹¹ÌåµÄα´úÂë¡£¡£¡£¡£¡£
3.1 SSL_newºÍSSL_freeµÄÅä¶ÔʹÓÃ
Ê×ÏÈΪSSL½á¹¹Ìå±äÁ¿ÉêÇë³ö¶Ñ¿Õ¼ä£¬£¬£¬£¬£¬£¬£¬¶øºóʹÓÃSSL_connectº¯ÊýʵÏÖSSLÏνӵÄÎÕÊÖ£¬£¬£¬£¬£¬£¬£¬Õâʱ»áµÃµ½·þÎñÆ÷¶ËÏìÓ¦µÄÖ¤Ê飬£¬£¬£¬£¬£¬£¬×îºóʹÓÃSSL_freeº¯Êý¿ªÊͶѿռ䣬£¬£¬£¬£¬£¬£¬Î±´úÂëÈçÏ£º
SSL* ssl = SSL_new(sslCtx);
// ...
SSL_connect(ssl);
// ...
SSL_free(ssl);
3.2 SSL_clearº¯Êý
ƾ¾Ý·ìϼûèÊö£¬£¬£¬£¬£¬£¬£¬²é¿´OpenSSL¹Ù·½¶ÔSSL_clearº¯ÊýµÄÚ¹ÊÍ£¬£¬£¬£¬£¬£¬£¬¿´¿´ÄÜ»ñÈ¡µ½ÄÄЩÐÅÏ¢ÌáÐÑ¡£¡£¡£¡£¡£

Ò²¾ÍÊÇ˵£¬£¬£¬£¬£¬£¬£¬SSL_clearÌṩ³ÁÖÃSSL¶ÔÏóµÄÖ°ÄÜ£¬£¬£¬£¬£¬£¬£¬ÒÔΪÏ´ÎÐÂÏνÓ×ö³ï±¸£¬£¬£¬£¬£¬£¬£¬ÕâÑùÔ¤·ÀÄÚ²¿×ÊÔ´µÄÉêÇëºÍ³õʼ»¯£¬£¬£¬£¬£¬£¬£¬ÓÐÀûÓÚÌá¸ß×ÊÔ´µÄÀûÓÃЧÄÜ¡£¡£¡£¡£¡£²¢ÇÒÌáµ½ÁËSSL_shutdownº¯ÊýµÄʹÓᣡ£¡£¡£¡£ÏÂÃæÎªSSL_clearº¯ÊýµÄ´úÂ룺
int
SSL_clear(SSL *s)
{
if (s->method == NULL) {
SSLerror(s, SSL_R_NO_METHOD_SPECIFIED);
return (0);
}
/// ...ÂÔ...
s->internal->first_packet = 0;
/*
* Check to see if we were changed into a different method, if
* so, revert back if we are not doing session-id reuse.
*/
if (!s->internal->in_handshake && (s->session == NULL) &&
(s->method != s->ctx->method)) { /////// [1]
s->method->ssl_free(s); /////// [2]
s->method = s->ctx->method;
if (!s->method->ssl_new(s)) /////// [3]
return (0);
} else
s->method->ssl_clear(s);
return (1);
}
ÔÚ³ÁÖÃSSL½á¹¹Ìå¶ÔÏóʱ£¬£¬£¬£¬£¬£¬£¬ÈôÊÇÎÒÃÇ´´ÔìǰÌáÂú×ã[1]´¦£¬£¬£¬£¬£¬£¬£¬¿ÉÄÜʹ·¨Ê½´úÂëÔËÐе½[3]´¦£¬£¬£¬£¬£¬£¬£¬´Ó¶øÓлúÓöʹµÃsk_X509_pop_free(s->internal->verified_chain, X509_free)Ö´ÐÐÁ½´Î¡£¡£¡£¡£¡£×¢Òâµ½£¬£¬£¬£¬£¬£¬£¬ÔÚ[2]´¦ÒѾÓÐÒ»´Î¶Ôssl_freeÖ¸ÏòµÄº¯ÊýµÄŲÓ㬣¬£¬£¬£¬£¬£¬ÒÔ¼°[3]´¦µÄssl_newÖ¸ÏòµÄº¯ÊýµÄÒ»´ÎŲÓᣡ£¡£¡£¡£
3.3 ssl3_newº¯Êý
ÏÈ¿´¿´ssl3_newº¯Êý£º
int
ssl3_new(SSL *s)
{
if ((s->s3 = calloc(1, sizeof(*s->s3))) == NULL)
return (0);
s->method->ssl_clear(s); /////// [1]
return (1);
}
×¢Òâ[1]´¦¡£¡£¡£¡£¡£
3.4 ssl3_clearº¯Êý
»¹ÓУ¬£¬£¬£¬£¬£¬£¬ssl3_clearº¯ÊýµÄÔ´´úÂ룺
void
ssl3_clear(SSL *s)
{
unsigned char *rp, *wp;
size_t rlen, wlen;
tls1_cleanup_key_block(s);
sk_X509_NAME_pop_free(s->s3->hs.tls12.ca_names, X509_NAME_free);
sk_X509_pop_free(s->internal->verified_chain, X509_free); ///////// [1]
s->internal->verified_chain = NULL;
freezero(s->s3->hs.sigalgs, s->s3->hs.sigalgs_len);
s->s3->hs.sigalgs = NULL;
s->s3->hs.sigalgs_len = 0;
/// ...ÂÔ...
memset(s->s3, 0, sizeof(*s->s3));
s->s3->rbuf.buf = rp;
/// ...ÂÔ...
s->s3->hs.state = SSL_ST_BEFORE|((s->server) ? SSL_ST_ACCEPT : SSL_ST_CONNECT);
}
¹Û²ì[1]´¦µÄ´úÂë¡£¡£¡£¡£¡£
3.5 ´¥·¢¹ý³Ì
ÈôÊÇÎÒÃÇÄÜÏȺ󴥷¢ssl3_freeºÍssl3_new£¬£¬£¬£¬£¬£¬£¬ÄÇôҲ¾ÍÄÜ´¥·¢¸Ã·ì϶¡£¡£¡£¡£¡£
´´½¨SSL±ØÒªµÄ¸ßµÍÎÄ»·¾³£»£»£»£»£»£»£»£» ŲÓÃSSL_connectº¯Êý£¬£¬£¬£¬£¬£¬£¬Ê¹µÃSSLÏνӷµ»ØÖ¤ÊéÁ´; ¶øºóʹÓÃSSL_shutdownº¯Êý¹Ø¹Ø¸ÃSSLÏνÓ; ½ÓÏÂÀ´Å²ÓÃTLSv1_methodº¯Êý£¬£¬£¬£¬£¬£¬£¬ÒÔ·µ»ØÒ»¸öеÄSSL_METHODÖ¸Õ루ºÍµÚÒ»´ÎʹÓÃSSL_CTX_newº¯Êý´´½¨SSL_CTX±äÁ¿Ê±´«ÈëµÄ²ÎÊý·ÖÆç£©; ŲÓÃSSL_set_ssl_methodº¯Êý£¬£¬£¬£¬£¬£¬£¬ÆäµÚ¶þ¸ö²ÎÊýΪÉÏÒ»²½·µ»ØµÄÐÂSSL_METHODÖ¸Õ룻£»£»£»£»£»£»£» Õý³£¿ªÊÍÓйØ×ÊÔ´¡£¡£¡£¡£¡£
ʹÓÃTLSv1_methodº¯ÊýµÄÔÒò
ÎÒÃÇ¿´Ò»ÏÂTLSv1_methodº¯ÊýµÄÓйشúÂ룺
// ssl_methods.c
const SSL_METHOD *
TLSv1_method(void){
return (&TLSv1_method_data);
}
// ...
static const SSL_METHOD TLSv1_method_data = {
.dtls = 0,
.server = 1,
.version = TLS1_VERSION,
.min_tls_version = TLS1_VERSION,
.max_tls_version = TLS1_VERSION,
.ssl_new = tls1_new,
.ssl_clear = tls1_clear,
.ssl_free = tls1_free, /////// [1]
.ssl_accept = ssl3_accept,
.ssl_connect = ssl3_connect,
.ssl_shutdown = ssl3_shutdown,
/// ...ÂÔ...
.enc_flags = TLSV1_ENC_FLAGS,
};
¿ÉÄÜ¿´µ½£¬£¬£¬£¬£¬£¬£¬´Ëʱ£¬£¬£¬£¬£¬£¬£¬ssl_freeº¯ÊýÆäʵָÏòÁËtls1_freeº¯Êý£¬£¬£¬£¬£¬£¬£¬¶øtls1_freeº¯ÊýÄÚ²¿Å²ÓÃÁËssl3_free¡£¡£¡£¡£¡£
// t1_lib.c
void
tls1_free(SSL *s)
{
if (s == NULL)
return;
free(s->internal->tlsext_session_ticket);
ssl3_free(s); /////// [1]
}
ÎÒÃÇÔÙÀ´¿´Ò»ÏÂSSL_set_ssl_methodº¯Êý£º
int
SSL_set_ssl_method(SSL *s, const SSL_METHOD *method)
{
int (*handshake_func)(SSL *) = NULL;
int ret = 1;
if (s->method == method)
return (ret);
if (s->internal->handshake_func == s->method->ssl_connect)
handshake_func = method->ssl_connect;
else if (s->internal->handshake_func == s->method->ssl_accept)
handshake_func = method->ssl_accept;
if (s->method->version == method->version) { //// [1]
s->method = method;
} else {
s->method->ssl_free(s); //// [2]
s->method = method; //// [3]
ret = s->method->ssl_new(s); //// [4]
}
s->internal->handshake_func = handshake_func;
return (ret);
}
ÎÒÃÇʹÓÃTLSv1_methodº¯Êý·µ»ØµÄmethod->versionÓÐÒâ²»µÅ×Ús->method->version£¬£¬£¬£¬£¬£¬£¬´Ó¶øµ¼ÖÂ[2]µÄÖ´ÐУ¬£¬£¬£¬£¬£¬£¬¶ø´ËʱµÄs->method->ssl_freeµÄֵΪtls1_free£¬£¬£¬£¬£¬£¬£¬ÇÒÔËÐе½[4]´¦Ê±£¬£¬£¬£¬£¬£¬£¬s->method->ssl_newµÄֵΪtls1_new£º

ƾ¾Ýtls1_freeº¯ÊýµÄ´úÂ룬£¬£¬£¬£¬£¬£¬Ëü»áŲÓÃssl3_freeÒ»´Î£¬£¬£¬£¬£¬£¬£¬¶øssl3_freeÄÚ²¿»áÖ´ÐÐÒ»´Îsk_X509_pop_free(s->internal->verified_chain, X509_free)£¬£¬£¬£¬£¬£¬£¬µ¼ÖÂs->internal->verified_chain±»¿ªÊÍ¡£¡£¡£¡£¡£
µ±·¨Ê½Ö´Ðе½SSL_set_ssl_methodÄÚµÄ[4]´¦Ê±£¬£¬£¬£¬£¬£¬£¬»áŲÓÃtls1_newº¯Êý¡£¡£¡£¡£¡£
ÎÒÃÇÔÙÀ´¿´Ò»ÏÂtls1_newµÄ´úÂ룺
int
tls1_new(SSL *s)
{
if (!ssl3_new(s)) ///// [1]
return (0);
s->method->ssl_clear(s);
return (1);
}
Äܹ»¿´µ½£¬£¬£¬£¬£¬£¬£¬ÎÞÂÛÈôºÎ£¬£¬£¬£¬£¬£¬£¬[1]´¦µÄssl3_newº¯Êý³ÇÊÐÖ´ÐУ¬£¬£¬£¬£¬£¬£¬¶øssl3_newÄÚ²¿»áŲÓÃs->method->ssl_clear£¬£¬£¬£¬£¬£¬£¬´ËʱµÄs->method->ssl_clearÖ¸Ïòtls1_clearº¯Êý£¬£¬£¬£¬£¬£¬£¬tls1_clearº¯ÊýµÄʵÏÖÈçÏ£º
void
tls1_clear(SSL *s)
{
ssl3_clear(s); /////// [1]
s->version = s->method->version;
}
°ÑÎȵ½tls1_clearÄÚ²¿»áŲÓÃssl3_clear£¬£¬£¬£¬£¬£¬£¬¶øssl3_clearÄÚ²¿¿Ï¶¨»áÖ´ÐÐsk_X509_pop_free(s->internal->verified_chain, X509_free)Óï¾ä£¬£¬£¬£¬£¬£¬£¬´Ó¶øµ¼ÖÂs->internal->verified_chain±»ÔٴοªÊÍ¡£¡£¡£¡£¡£ÔÚµ÷ÊÔÆ÷ÖеıÀÀ£ÈçÏÂͼ£º

ËÄ¡¢·ì϶½¨¸´
4.1 ¶ÔÓÚ3.6.3
¶ÔÓÚ3.6.3°æ£¬£¬£¬£¬£¬£¬£¬¹Ù·½Ö±½ÓÔÚssl3_freeº¯ÊýÀï°Ñs->internal->verified_chain¸³ÖµÎªNULL£º
// ssl3_free(SSL *s)
sk_X509_pop_free(s->internal->verified_chain, X509_free); /////// [1]
s->internal->verified_chain = NULL; /////// [2]
4.2 ×îа汾3.9.2
ÔÚ·ÖÎö´ò¹ý²¹¶¡ºóµÄ½Ïа汾ʱ£¬£¬£¬£¬£¬£¬£¬»á·¢ÏÖssl3_freeº¯ÊýûÓÐÁË3.6.3°æÊ±°Ñverified_chain¸³ÖµÎªNULLµÄÓï¾ä£¬£¬£¬£¬£¬£¬£¬ºÃ±È×îаæ3.9.2µÄ£º
void
ssl3_free(SSL *s)
{
if (s == NULL)
return;
tls1_cleanup_key_block(s);
ssl3_release_read_buffer(s);
ssl3_release_write_buffer(s);
/// ...ÂÔ...
sk_X509_pop_free(s->s3->hs.peer_certs, X509_free);
sk_X509_pop_free(s->s3->hs.peer_certs_no_leaf, X509_free);
sk_X509_pop_free(s->s3->hs.verified_chain, X509_free); /////// [1]
tls_key_share_free(s->s3->hs.key_share);
/// ...ÂÔ...
freezero(s->s3->peer_quic_transport_params,
s->s3->peer_quic_transport_params_len);
freezero(s->s3, sizeof(*s->s3)); /////// [2]
s->s3 = NULL;
}
ͬʱ£¬£¬£¬£¬£¬£¬£¬×¢Òâ[2]´¦µÄfreezeroº¯Êý¡£¡£¡£¡£¡£
ÔÒòÔÚÓڽṹÌå½ç˵µÄ±ä¶¯£¬£¬£¬£¬£¬£¬£¬´Ósk_X509_pop_freeºêµÄµÚÒ»²ÎÊýÄܹ»¿´³öһЩ¶ËÄߣº
sk_X509_pop_free(s->s3->hs.verified_chain, X509_free);
¸Ã°æ±¾¼¸¸öÓйؽṹÌåµÄ½ç˵ÈçÏ£º
// 3.9.2
struct ssl_st
{
/* protocol version
* (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION)
*/
int version;
const SSL_METHOD *method;
/// ...ÂÔ...
int server; /* are we the server side? - mostly used by SSL_clear*/
struct ssl3_state_st *s3; /* SSLv3 variables */ /////// [1]
struct dtls1_state_st *d1; /* DTLSv1 variables */
/// ...ÂÔ...
};
typedef struct ssl3_state_st
{
long flags;
unsigned char server_random[SSL3_RANDOM_SIZE];
/// ...ÂÔ...
int in_read_app_data;
SSL_HANDSHAKE hs; /////// [2]
/// ...ÂÔ...
} SSL3_STATE;
ÒÔ¼°ssl_handshake_st£º
typedef struct ssl_handshake_st
{
/*
* Minimum and maximum versions supported for this handshake. These are
* initialised at the start of a handshake based on the method in use
* and the current protocol version configuration.
*/
uint16_t our_min_tls_version;
/// ...ÂÔ...
/* Certificate chain resulting from X.509 verification. */
STACK_OF(X509) *verified_chain; /////// [1]
SSL_HANDSHAKE_TLS12 tls12;
SSL_HANDSHAKE_TLS13 tls13;
}SSL_HANDSHAKE;
Äܹ»¿´µ½ÔÚ[2]´¦µÄhsÊÇÒ»¸öSSL_HANDSHAKEÀàÐ͵ĽṹÌå³ÉÔ±±äÁ¿¡£¡£¡£¡£¡£ssl3_freeº¯ÊýÀïµÄfreezeroº¯Êý
»á°Ñs->s3µÄ¶Ñ¿Õ¼äµÄÄÚÈÝÈ«ÊýÉèÖÃΪÁ㣬£¬£¬£¬£¬£¬£¬²é¿´freezeroº¯Êý¼°ÆäÄÚ²¿µÄexplicit_bzeroµÄ´úÂë¼´¿ÉµÃÖª¡£¡£¡£¡£¡£
? freezeroº¯ÊýºÍexplicit_bzeroº¯Êý
// freezero.c
void
freezero(void *ptr, size_t sz)
{
/* This is legal. */
if (ptr == NULL)
return;
explicit_bzero(ptr, sz);
free(ptr);
}
// explicit_bzero.c
void
explicit_bzero(void *buf, size_t len)
{
memset(buf, 0, len); /////// [1]
__explicit_bzero_hook(buf, len);
}
ÕâÑù£¬£¬£¬£¬£¬£¬£¬[1]´¦µÄmemsetº¯Êý»áµ¼ÖÂs->s3->hs.verified_chain±»¸³ÖµÎªNULL£¬£¬£¬£¬£¬£¬£¬´Ó¶øÔÚsk_pop_freeº¯Êý[1]´¦Ê±¼´·µ»Ø£¬£¬£¬£¬£¬£¬£¬½ø¶øÔ¤·ÀÁË·ì϶µÄ²úÉú¡£¡£¡£¡£¡£
[1]https://ftp.openbsd.org/pub/OpenBSD/patches/7.2/common/026_ssl.patch.sig
[2]https://www.cvedetails.com/cve/CVE-2023-35784/


¾©¹«Íø°²±¸11010802024551ºÅ