修复证书校验安全问题

Signed-off-by: Tiga Ultraman <liaoxude@huawei.com>
Change-Id: I6f0dd948e8fd09e9bd9117a0c14980cbeaf468bc
This commit is contained in:
Tiga Ultraman
2026-05-30 11:04:54 +08:00
parent c15e5ec969
commit ef7316b92f
3 changed files with 35 additions and 13 deletions
@@ -36,9 +36,9 @@ extern "C" {
pub(crate) fn EVP_DigestFinal_ex(
ctx: *mut EVP_MD_CTX,
buf: *const c_uchar,
start: *const c_uint,
);
buf: *mut c_uchar,
out_len: *mut c_uint,
) -> c_int;
}
pub(crate) enum C_X509 {}
@@ -149,5 +149,5 @@ extern "C" {
pub(crate) fn X509_PUBKEY_free(x509: *mut X509_PUBKEY);
pub(crate) fn i2d_X509_PUBKEY(pubkey: *const X509_PUBKEY, buf: *mut *const c_uchar) -> c_int;
pub(crate) fn i2d_X509_PUBKEY(pubkey: *const X509_PUBKEY, buf: *mut *mut c_uchar) -> c_int;
}
@@ -305,6 +305,13 @@ pub(crate) fn verify_server_cert(ssl: *const SSL, pinned_key: &str) -> Result<()
fn verify_pinned_pubkey(pinned_key: &str, certificate: *mut C_X509) -> Result<(), SslError> {
let pubkey = unsafe { X509_get_X509_PUBKEY(certificate) };
if pubkey.is_null() {
unsafe { X509_free(certificate) };
return Err(SslError {
code: SslErrorCode::SSL,
internal: Some(InternalError::Ssl(ErrorStack::get())),
});
}
// Get the length of the serialized data
let buf_size = unsafe { i2d_X509_PUBKEY(pubkey, ptr::null_mut()) };
@@ -315,9 +322,10 @@ fn verify_pinned_pubkey(pinned_key: &str, certificate: *mut C_X509) -> Result<()
internal: Some(InternalError::Ssl(ErrorStack::get())),
});
}
let key = vec![0u8; buf_size as usize];
let mut key = vec![0u8; buf_size as usize];
let mut key_ptr = key.as_mut_ptr();
// The actual serialization
let serialized_data_size = unsafe { i2d_X509_PUBKEY(pubkey, &mut key.as_ptr()) };
let serialized_data_size = unsafe { i2d_X509_PUBKEY(pubkey, &mut key_ptr) };
if buf_size != serialized_data_size || serialized_data_size <= 0 {
unsafe { X509_free(certificate) };
@@ -13,7 +13,7 @@
use std::collections::HashMap;
use libc::c_int;
use libc::{c_int, c_uint};
use ylong_http::request::uri::Uri;
use crate::util::c_openssl::error::ErrorStack;
@@ -25,6 +25,9 @@ use crate::util::c_openssl::ssl::{InternalError, SslError, SslErrorCode};
use crate::ErrorKind::Build;
use crate::HttpClientError;
/// OpenSSL EVP digest functions convention: 1 for success, 0 for failure.
const EVP_DIGEST_SUCCESS: c_int = 1;
/// A structure that serves Certificate and Public Key Pinning.
/// The map key is server authority(host:port), value is Base64(sha256(Server's
/// Public Key)).
@@ -248,21 +251,32 @@ pub(crate) unsafe fn sha256_digest(
internal: Some(InternalError::Ssl(ErrorStack::get())),
});
}
let init = EVP_DigestInit(md_ctx, EVP_sha256());
if init == 0 {
if EVP_DigestInit(md_ctx, EVP_sha256()) != EVP_DIGEST_SUCCESS {
EVP_MD_CTX_free(md_ctx);
return Err(SslError {
code: SslErrorCode::SSL,
internal: Some(InternalError::Ssl(ErrorStack::get())),
});
}
if EVP_DigestUpdate(md_ctx, pub_key.as_ptr(), len) != EVP_DIGEST_SUCCESS {
EVP_MD_CTX_free(md_ctx);
return Err(SslError {
code: SslErrorCode::SSL,
internal: Some(InternalError::Ssl(ErrorStack::get())),
});
}
EVP_DigestUpdate(md_ctx, pub_key.as_ptr(), len);
let start = 0;
EVP_DigestFinal_ex(md_ctx, digest.as_mut_ptr(), &start);
let mut out_len: c_uint = 0;
let final_ret = EVP_DigestFinal_ex(md_ctx, digest.as_mut_ptr(), &mut out_len);
EVP_MD_CTX_free(md_ctx);
if final_ret != EVP_DIGEST_SUCCESS {
return Err(SslError {
code: SslErrorCode::SSL,
internal: Some(InternalError::Ssl(ErrorStack::get())),
});
}
Ok(())
}