@@ -478,6 +478,13 @@ pub struct CertPair {
478478/// Magic prefix for gzip-compressed event log (version 1)
479479pub const EVENTLOG_GZIP_MAGIC : & [ u8 ] = b"ELGZv1" ;
480480
481+ /// Maximum allowed decompressed size of the event log extension (in bytes).
482+ ///
483+ /// This protects against gzip decompression bombs in RA-TLS certificate
484+ /// extensions by bounding the amount of memory we are willing to allocate.
485+ /// 16 KiB is sufficient for typical event logs we embed in certs.
486+ pub const MAX_EVENTLOG_EXT_SIZE : u64 = 16 * 1024 ;
487+
481488/// Compress a certificate extension value
482489pub fn compress_ext_value ( data : & [ u8 ] ) -> Result < Vec < u8 > > {
483490 use flate2:: write:: GzEncoder ;
@@ -507,11 +514,19 @@ pub fn decompress_ext_value(data: &[u8]) -> Result<Vec<u8>> {
507514 if data. starts_with ( EVENTLOG_GZIP_MAGIC ) {
508515 // Compressed format
509516 let compressed = & data[ EVENTLOG_GZIP_MAGIC . len ( ) ..] ;
510- let mut decoder = GzDecoder :: new ( compressed) ;
517+ let decoder = GzDecoder :: new ( compressed) ;
518+ // Limit the total amount of decompressed data to avoid gzip bombs.
519+ let mut limited = decoder. take ( MAX_EVENTLOG_EXT_SIZE + 1 ) ;
511520 let mut decompressed = Vec :: new ( ) ;
512- decoder
521+ limited
513522 . read_to_end ( & mut decompressed)
514523 . context ( "failed to decompress event log" ) ?;
524+ if decompressed. len ( ) as u64 > MAX_EVENTLOG_EXT_SIZE {
525+ bail ! (
526+ "event log extension too large (>{} bytes)" ,
527+ MAX_EVENTLOG_EXT_SIZE
528+ ) ;
529+ }
515530 Ok ( decompressed)
516531 } else {
517532 // Uncompressed format (backwards compatibility)
0 commit comments