Skip to content

Commit 1cc1f47

Browse files
bors[bot]Taowyoo
andauthored
Merge #308 #312
308: fix: return error when verify empty cert chain r=Taowyoo a=Taowyoo For #307 on master. Several back-port PRs needed for older versions. Only return X509BadInputData error when candidate certificate chain is empty because: - underlying `mbedtls` does not have null pointer check on it. - underlying `mbedtls` has null pointer check on `trust_ca` chain during the process of finding parent certificate in the chain. 312: Update CI r=Taowyoo a=Taowyoo Refactor is prime test Fix bors status problem Co-authored-by: Yuxiang Cao <[email protected]>
3 parents 57c7efc + 2958dce + e0b9114 commit 1cc1f47

File tree

9 files changed

+137
-85
lines changed

9 files changed

+137
-85
lines changed

.config/nextest.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ store-failure-output = true
113113
[[profile.default.overrides]]
114114
# `hyper` test targeting external Google's service, it would sometomes failed because of rate limit
115115
# `is_probably_prime` test heavily use rdrand, sometimes the VM where test is running has shortage on it
116-
filter = 'binary(=hyper) or test(=is_probably_prime)'
117-
retries = { backoff = "exponential", count = 4, delay = "1s", jitter = true, max-delay = "10s" }
116+
filter = 'binary(=hyper) or test(is_prime_tests::)'
117+
retries = { backoff = "exponential", count = 4, delay = "1s", jitter = true }
118118
test-group = 'serial-integration'
119119

120120
[[profile.default.overrides]]

.github/workflows/test.yml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Test
1+
name: CI
22

33
on:
44
push:
@@ -19,8 +19,8 @@ env:
1919
CARGO_NET_RETRY: 10
2020

2121
jobs:
22-
build:
23-
name: test
22+
test:
23+
name: Test
2424
strategy:
2525
matrix:
2626
include:
@@ -74,3 +74,13 @@ jobs:
7474
TARGET: ${{ matrix.target }}
7575
ZLIB_INSTALLED: ${{ matrix.target == 'x86_64-unknown-linux-gnu' && 'true' || '' }}
7676
AES_NI_SUPPORT: ${{ matrix.target == 'x86_64-unknown-linux-gnu' && 'true' || '' }}
77+
ci-success:
78+
name: ci
79+
if: always()
80+
needs:
81+
- test
82+
runs-on: ubuntu-20.04
83+
steps:
84+
- run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
85+
- name: Done
86+
run: exit 0

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bors.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
status = [
2-
"test",
2+
"ci",
33
]
44
timeout_sec = 36000 # ten hours

mbedtls/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mbedtls"
3-
version = "0.11.0"
3+
version = "0.11.1"
44
authors = ["Jethro Beekman <[email protected]>"]
55
build = "build.rs"
66
edition = "2018"

mbedtls/src/ssl/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,9 @@ impl Config {
338338
}
339339

340340
pub fn push_cert(&mut self, own_cert: Arc<MbedtlsList<Certificate>>, own_pk: Arc<Pk>) -> Result<()> {
341+
if own_cert.is_empty() {
342+
return Err(crate::error::codes::SslBadInputData.into());
343+
}
341344
// Need to ensure own_cert/pk_key outlive the config.
342345
self.own_cert.push(own_cert.clone());
343346
self.own_pk.push(own_pk.clone());

mbedtls/src/ssl/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ impl HandshakeContext {
573573
key: Arc<Pk>,
574574
) -> Result<()> {
575575
// mbedtls_ssl_set_hs_own_cert does not check for NULL handshake.
576-
if self.inner.private_handshake as *const _ == ::core::ptr::null() {
576+
if self.inner.private_handshake as *const _ == ::core::ptr::null() || chain.is_empty() {
577577
return Err(codes::SslBadInputData.into());
578578
}
579579

mbedtls/src/x509/certificate.rs

Lines changed: 59 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,15 @@ impl Certificate {
9595
pub fn from_pem(pem: &[u8]) -> Result<MbedtlsBox<Certificate>> {
9696
let mut cert = MbedtlsBox::<Certificate>::init()?;
9797
unsafe { x509_crt_parse((&mut (*cert)).into(), pem.as_ptr(), pem.len()) }.into_result()?;
98-
98+
9999
if !(*cert).inner.next.is_null() {
100100
// Use from_pem_multiple for parsing multiple certificates in a pem.
101101
return Err(codes::X509BadInputData.into());
102102
}
103103

104104
Ok(cert)
105105
}
106-
106+
107107
/// Input must be NULL-terminated
108108
pub fn from_pem_multiple(pem: &[u8]) -> Result<MbedtlsList<Certificate>> {
109109
let mut cert = MbedtlsBox::<Certificate>::init()?;
@@ -113,7 +113,7 @@ impl Certificate {
113113
list.push(cert);
114114
Ok(list)
115115
}
116-
116+
117117
pub fn check_key_usage(&self, usage: super::KeyUsage) -> bool {
118118
unsafe { x509_crt_check_key_usage(&self.inner, usage.bits()) }
119119
.into_result()
@@ -233,6 +233,9 @@ impl Certificate {
233233
where
234234
F: VerifyCallback + 'static,
235235
{
236+
if chain.is_empty() {
237+
return Err(codes::X509BadInputData.into());
238+
}
236239
let (f_vrfy, p_vrfy): (Option<unsafe extern "C" fn(_, _, _, _) -> _>, _) = if let Some(cb) = cb.as_ref() {
237240
(Some(x509::verify_callback::<F>),
238241
cb as *const _ as *mut c_void)
@@ -509,11 +512,11 @@ impl MbedtlsBox<Certificate> {
509512

510513
let inner = NonNull::new(inner).ok_or(codes::X509AllocFailed)?;
511514
x509_crt_init(inner.as_ptr());
512-
515+
513516
Ok(MbedtlsBox { inner: inner.cast() })
514517
}
515518
}
516-
519+
517520
fn list_next(&self) -> Option<&MbedtlsBox<Certificate>> {
518521
unsafe {
519522
<&Option<MbedtlsBox<_>> as UnsafeFrom<_>>::from(&(**self).inner.next).unwrap().as_ref()
@@ -566,11 +569,11 @@ impl MbedtlsList<Certificate> {
566569
// This leaks a *mut Certificate that we can cast to x509_crt as it's transparent and has no extra fields.
567570
self.inner.take().map(|x| x.into_raw()).unwrap_or(core::ptr::null_mut()) as *mut x509_crt
568571
}
569-
572+
570573
pub fn is_empty(&self) -> bool {
571574
self.inner.is_none()
572575
}
573-
576+
574577
pub fn push(&mut self, certificate: MbedtlsBox<Certificate>) -> () {
575578
self.append(MbedtlsList::<Certificate> { inner: Some(certificate) });
576579
}
@@ -585,12 +588,12 @@ impl MbedtlsList<Certificate> {
585588
}
586589
prev = cur;
587590
}
588-
591+
589592
// no iterations in for loop: head equals tail
590593
self.inner.take()
591594
}
592595

593-
596+
594597
pub fn pop_front(&mut self) -> Option<MbedtlsBox<Certificate>> {
595598
let mut ret = self.inner.take()?;
596599
self.inner = ret.list_next_mut().take();
@@ -605,7 +608,7 @@ impl MbedtlsList<Certificate> {
605608
};
606609
*tail = list.inner;
607610
}
608-
611+
609612
pub fn iter(&self) -> Iter<'_> {
610613
Iter { next: self.inner.as_ref() }
611614
}
@@ -874,7 +877,7 @@ JS7pkcufTIoN0Yj0SxAWLW711FgB
874877
assert_eq!(output, TEST_PEM);
875878
}
876879

877-
880+
878881
const TEST_CERT_PEM: &'static str = "-----BEGIN CERTIFICATE-----
879882
MIIDLDCCAhSgAwIBAgIRALY0SS5pY9Yb/aIHvSAvmOswDQYJKoZIhvcNAQELBQAw
880883
HzEQMA4GA1UEAxMHVGVzdCBDQTELMAkGA1UEBhMCVVMwHhcNMTkwMTA4MDAxODM1
@@ -898,7 +901,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
898901
#[test]
899902
fn cert_field_access() {
900903
let cert = Certificate::from_pem(TEST_CERT_PEM.as_bytes()).unwrap();
901-
904+
902905
assert_eq!(cert.version().unwrap(), CertificateVersion::V3);
903906
assert_eq!(cert.issuer().unwrap(), "CN=Test CA, C=US");
904907
assert_eq!(cert.subject().unwrap(), "CN=Test Cert, O=Test");
@@ -975,7 +978,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
975978

976979
let mut iter = list.iter();
977980
let cert = iter.next().unwrap();
978-
981+
979982
let pk = cert.public_key();
980983

981984
assert_eq!(pk.pk_type(), crate::pk::Type::Rsa);
@@ -1011,7 +1014,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
10111014
let c_int1 = Certificate::from_pem(C_INT1.as_bytes()).unwrap();
10121015
let c_int2 = Certificate::from_pem(C_INT2.as_bytes()).unwrap();
10131016
let mut c_root = Certificate::from_pem_multiple(C_ROOT.as_bytes()).unwrap();
1014-
1017+
10151018
// Certificate C_INT2 is missing at the beginning so the verification should fail at first
10161019
let mut chain = MbedtlsList::<Certificate>::new();
10171020
chain.push(c_leaf.clone());
@@ -1041,7 +1044,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
10411044
Err(e) => panic!("Failed to verify, error: {}, err_str: {}", e, err_str),
10421045
};
10431046
}
1044-
1047+
10451048
#[test]
10461049
fn clone_test() {
10471050
let cert_chain = Certificate::from_pem(TEST_CERT_PEM.as_bytes()).unwrap();
@@ -1050,7 +1053,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
10501053
chain.push(cert_chain.clone());
10511054
chain.push(cert_chain.clone());
10521055
chain.push(cert_chain);
1053-
1056+
10541057
let clone = chain.clone();
10551058
let mut it = clone.iter();
10561059

@@ -1085,7 +1088,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
10851088
let c1_info = format!("{:?}", c1.iter().next().unwrap());
10861089
let c2_info = format!("{:?}", c2.iter().next().unwrap());
10871090
let c3_info = format!("{:?}", c3.iter().next().unwrap());
1088-
1091+
10891092
chain.append(c1.clone());
10901093
chain.append(c2.clone());
10911094
chain.append(c3.clone());
@@ -1105,7 +1108,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
11051108
assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
11061109
assert!(it.next().is_none());
11071110
}
1108-
1111+
11091112
chain.append(c3.clone());
11101113
chain.append(c1.clone());
11111114
{
@@ -1133,7 +1136,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
11331136
let mut it = chain.iter();
11341137
assert!(it.next().is_none());
11351138
}
1136-
1139+
11371140
assert!(chain.pop_back().is_none());
11381141
{
11391142
let mut it = chain.iter();
@@ -1167,7 +1170,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
11671170
let c1_info = format!("{:?}", c1);
11681171
let c2_info = format!("{:?}", c2);
11691172
let c3_info = format!("{:?}", c3);
1170-
1173+
11711174
chain.push(c1.clone());
11721175
chain.push(c2.clone());
11731176
chain.push(c3.clone());
@@ -1187,7 +1190,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
11871190
assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
11881191
assert!(it.next().is_none());
11891192
}
1190-
1193+
11911194
chain.push(c3.clone());
11921195
chain.push(c1.clone());
11931196
{
@@ -1215,7 +1218,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
12151218
let mut it = chain.iter();
12161219
assert!(it.next().is_none());
12171220
}
1218-
1221+
12191222
assert!(chain.pop_front().is_none());
12201223
{
12211224
let mut it = chain.iter();
@@ -1302,7 +1305,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
13021305
}
13031306

13041307
let clone = chain.clone();
1305-
1308+
13061309
{
13071310
let mut it = chain.into_iter();
13081311
assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
@@ -1331,7 +1334,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
13311334
<&mut Option<MbedtlsBox<_>> as UnsafeFrom<_>>::from(ptr_test).unwrap()
13321335
};
13331336
assert!(option.is_none());
1334-
1337+
13351338
let cert_list : Option<&mut MbedtlsList<Certificate>> = unsafe { UnsafeFrom::from(ptr_test) };
13361339
assert!(cert_list.is_none());
13371340

@@ -1341,7 +1344,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
13411344
assert!(cert_list.is_none());
13421345

13431346

1344-
1347+
13451348
}
13461349

13471350
#[test]
@@ -1358,7 +1361,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
13581361

13591362
// Using debug strings so failing unit tests can identify any issue with contents.
13601363
let c1_info = format!("{:?}", c1);
1361-
1364+
13621365
chain.push(c1.clone());
13631366
chain.push(c2.clone());
13641367
chain.push(c3.clone());
@@ -1375,7 +1378,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
13751378
assert_eq!((*cert).inner.next, ::core::ptr::null_mut());
13761379
assert_eq!(c1_info, format!("{:?}", cert));
13771380

1378-
1381+
13791382
let cert = chain.clone().into_iter().next().unwrap();
13801383

13811384
// Using into_iter and extracting a certificate must have its next set to null
@@ -1406,7 +1409,7 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
14061409

14071410
let cert : &Certificate = unsafe { UnsafeFrom::from(ptr).unwrap() };
14081411
assert_eq!(c1_info, format!("{:?}", cert));
1409-
1412+
14101413
let ptr : *mut x509_crt = (&mut chain).into();
14111414
assert_ne!(ptr, ::core::ptr::null_mut());
14121415

@@ -1424,6 +1427,34 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
14241427
assert!(crate::tests::TestTrait::<dyn Sync, MbedtlsList<Certificate>>::new().impls_trait(), "MbedtlsList<Certificate> should be Sync");
14251428
}
14261429

1430+
#[test]
1431+
fn empty_cert_chain_test() {
1432+
const C_CERT: &'static str = concat!(include_str!("../../tests/data/certificate.crt"), "\0");
1433+
const C_ROOT: &'static str = concat!(include_str!("../../tests/data/root.crt"), "\0");
1434+
1435+
let mut certs = MbedtlsList::new();
1436+
certs.push(Certificate::from_pem(&C_CERT.as_bytes()).unwrap());
1437+
let mut roots = MbedtlsList::new();
1438+
roots.push(Certificate::from_pem(&C_ROOT.as_bytes()).unwrap());
1439+
1440+
assert!(Certificate::verify(&certs, &roots, None, None).is_ok());
1441+
1442+
let empty_certs = MbedtlsList::new();
1443+
1444+
assert_eq!(
1445+
Certificate::verify(&certs, &empty_certs, None, None).unwrap_err(),
1446+
codes::X509CertVerifyFailed.into()
1447+
);
1448+
assert_eq!(
1449+
Certificate::verify(&empty_certs, &roots, None, None).unwrap_err(),
1450+
codes::X509BadInputData.into()
1451+
);
1452+
assert_eq!(
1453+
Certificate::verify(&empty_certs, &empty_certs, None, None).unwrap_err(),
1454+
codes::X509BadInputData.into()
1455+
);
1456+
}
1457+
14271458
#[test]
14281459
fn empty_crl_test() {
14291460
const C_CERT: &'static str = concat!(include_str!("../../tests/data/certificate.crt"), "\0");

0 commit comments

Comments
 (0)