fn parse(reader: &mut &'a [u8]) -> Result<Self, Error> {
        let tag_id = reader.read_u32::<LittleEndian>()?;
        let tag_len = reader.read_u32::<LittleEndian>()?;

        if tag_len > TAG_SIZE_LIMIT {
            return Err(Error::parse_err(format!(
                "tag {:04X} exceeds size limit of {} bytes (length = {} bytes)",
                tag_id, TAG_SIZE_LIMIT, tag_len
            )));
        }

        // zero-copy-read the tag contents and move `reader` to point after that
        let mut tag_buf = reader.get(..tag_len as usize).ok_or_else(|| {
            Error::parse_err(format!("tag length {} exceeds total file length", tag_len))
        })?;
        *reader = &reader[tag_len as usize..];

        let tag_id = TagId::from_u32(tag_id)
            .ok_or_else(|| Error::parse_err(format!("invalid GBL tag {:010X}", tag_id)))?;
        debug!("tag {:?}, {} bytes", tag_id, tag_len);
        match tag_id {
            TagId::Header => Ok(Tag::Header(Header::parse(&tag_buf)?)),
            TagId::End => {
                // end tag contains CRC32 checksum
                if tag_len != 4 {
                    return Err(Error::parse_err(format!(
                        "invalid end tag length: expected 4 bytes, got {}",
                        tag_len
                    )));
                }

                let checksum = tag_buf.read_u32::<LittleEndian>()?;
                info!("checksum: {:#010X}", checksum);
                Ok(Tag::End(checksum))
            }
            TagId::AppInfo => {
                debug!("raw appinfo: {:?}", Blob(tag_buf));

                Ok(Tag::AppInfo(AppInfo::parse(&tag_buf)?))
            }
            TagId::EncryptionInitHeader => {
                debug!("raw encryption header: {:?}", Blob(tag_buf));
                // According to the PDF, this contains the used nonce and
                // the total amount of encrypted data.
                // Encryption is done using AES-CTR-128.

                if tag_len != 4 + 12 {
                    // 4 byte length, 12 byte IV
                    return Err(Error::parse_err(format!(
                        "unexpected length of encryption init header: got {}, expected 16",
                        tag_len
                    )));
                }

                // Total number of encrypted bytes (summation of the lengths
                // of all EncryptedProgramData tags).
                let total_enc_bytes = tag_buf.read_u32::<LittleEndian>()?;

                // The rest should be exactly 12 Bytes, which (96 bits) is the
                // nonce used for the IV (see `aes::build_iv`).
                let mut nonce = [0; 12];
                tag_buf.read_exact(&mut nonce)?;

                let parsed = EncryptionHeader {
                    total_bytes: total_enc_bytes,
                    nonce: nonce.into(),
                };
                debug!("encryption header: {:?}", parsed);
                Ok(Tag::EncryptionHeader(parsed))
            }
            TagId::ProgramData | TagId::ProgramData2 => {
                let data = if tag_len > 64 {
                    &tag_buf[..64]
                } else {
                    &tag_buf
                };
                debug!("raw program data: {:?}", Blob(data));

                // The raw data to be programmed is prefixed by its offset
                // into flash memory.
                let flash_addr = tag_buf.read_u32::<LittleEndian>()?;
                Ok(Tag::ProgramData(ProgramData {
                    flash_addr,
                    data: Blob(tag_buf.into()),
                }))
            }
            TagId::EncryptedProgramData => Ok(Tag::EncryptedData(tag_buf.into())),
            TagId::Signature => {
                debug!("raw signature: {:?}", Blob(tag_buf));

                if tag_len != 64 {
                    return Err(Error::parse_err(format!(
                        "signature is {} Bytes, expected 64",
                        tag_len
                    )));
                }

                Ok(Tag::Signature(Signature {
                    raw: Blob(tag_buf.into()),
                }))
            }
            TagId::Bootloader | TagId::Metadata => {
                if cfg!(fuzzing) {
                    // When fuzzing, we don't want to panic
                    Err(Error::parse_err("NYI: bootloader/metadata tag"))
                } else {
                    unimplemented!()
                }
            }
        }
    }
/// Parses a tag from `reader`, adjusting it to point after the tag.
Parses a tag from `reader`, adjusting it to point after the tag.
Parses a tag from ` reader ` adjusting it to point after the tag .
fn parse(reader: &mut &'a [u8]) -> Result<Self, Error> {
        let tag_id = reader.read_u32::<LittleEndian>()?;
        let tag_len = reader.read_u32::<LittleEndian>()?;
        if tag_len > TAG_SIZE_LIMIT {
            return Err(Error::parse_err(format!(
                "tag {:04X} exceeds size limit of {} bytes (length = {} bytes)",
                tag_id, TAG_SIZE_LIMIT, tag_len
            )));
        }
        // zero-copy-read the tag contents and move `reader` to point after that
        let mut tag_buf = reader.get(..tag_len as usize).ok_or_else(|| {
            Error::parse_err(format!("tag length {} exceeds total file length", tag_len))
        })?;
        *reader = &reader[tag_len as usize..];
        let tag_id = TagId::from_u32(tag_id)
            .ok_or_else(|| Error::parse_err(format!("invalid GBL tag {:010X}", tag_id)))?;
        debug!("tag {:?}, {} bytes", tag_id, tag_len);
        match tag_id {
            TagId::Header => Ok(Tag::Header(Header::parse(&tag_buf)?)),
            TagId::End => {
                // end tag contains CRC32 checksum
                if tag_len != 4 {
                    return Err(Error::parse_err(format!(
                        "invalid end tag length: expected 4 bytes, got {}",
                        tag_len
                    )));
                }
                let checksum = tag_buf.read_u32::<LittleEndian>()?;
                info!("checksum: {:#010X}", checksum);
                Ok(Tag::End(checksum))
            }
            TagId::AppInfo => {
                debug!("raw appinfo: {:?}", Blob(tag_buf));
                Ok(Tag::AppInfo(AppInfo::parse(&tag_buf)?))
            }
            TagId::EncryptionInitHeader => {
                debug!("raw encryption header: {:?}", Blob(tag_buf));
                // According to the PDF, this contains the used nonce and
                // the total amount of encrypted data.
                // Encryption is done using AES-CTR-128.
                if tag_len != 4 + 12 {
                    // 4 byte length, 12 byte IV
                    return Err(Error::parse_err(format!(
                        "unexpected length of encryption init header: got {}, expected 16",
                        tag_len
                    )));
                }
                // Total number of encrypted bytes (summation of the lengths
                // of all EncryptedProgramData tags).
                let total_enc_bytes = tag_buf.read_u32::<LittleEndian>()?;
                // The rest should be exactly 12 Bytes, which (96 bits) is the
                // nonce used for the IV (see `aes::build_iv`).
                let mut nonce = [0; 12];
                tag_buf.read_exact(&mut nonce)?;
                let parsed = EncryptionHeader {
                    total_bytes: total_enc_bytes,
                    nonce: nonce.into(),
                };
                debug!("encryption header: {:?}", parsed);
                Ok(Tag::EncryptionHeader(parsed))
            }
            TagId::ProgramData | TagId::ProgramData2 => {
                let data = if tag_len > 64 {
                    &tag_buf[..64]
                } else {
                    &tag_buf
                };
                debug!("raw program data: {:?}", Blob(data));
                // The raw data to be programmed is prefixed by its offset
                // into flash memory.
                let flash_addr = tag_buf.read_u32::<LittleEndian>()?;
                Ok(Tag::ProgramData(ProgramData {
                    flash_addr,
                    data: Blob(tag_buf.into()),
                }))
            }
            TagId::EncryptedProgramData => Ok(Tag::EncryptedData(tag_buf.into())),
            TagId::Signature => {
                debug!("raw signature: {:?}", Blob(tag_buf));
                if tag_len != 64 {
                    return Err(Error::parse_err(format!(
                        "signature is {} Bytes, expected 64",
                        tag_len
                    )));
                }
                Ok(Tag::Signature(Signature {
                    raw: Blob(tag_buf.into()),
                }))
            }
            TagId::Bootloader | TagId::Metadata => {
                if cfg!(fuzzing) {
                    // When fuzzing, we don't want to panic
                    Err(Error::parse_err("NYI: bootloader/metadata tag"))
                } else {
                    unimplemented!()
                }
            }
        }
    }
fn parse ( reader : & mut & ' a [ u8 ] ) -> Result < Self , Error > { let tag_id = reader . read_u32 :: < LittleEndian > ( ) ? ; let tag_len = reader . read_u32 :: < LittleEndian > ( ) ? ; if tag_len > TAG_SIZE_LIMIT { return Err ( Error :: parse_err ( format ! ( " " tag_id TAG_SIZE_LIMIT tag_len ) ) ) ; } // zero-copy-read the tag contents and move `reader` to point after that let mut tag_buf = reader . get ( .. tag_len as usize ) . ok_or_else ( | | { Error :: parse_err ( format ! ( " " tag_len ) ) } ) ? ; * reader = & reader [ tag_len as usize .. ] ; let tag_id = TagId :: from_u32 ( tag_id ) . ok_or_else ( | | Error :: parse_err ( format ! ( " " tag_id ) ) ) ? ; debug ! ( " " tag_id tag_len ) ; match tag_id { TagId :: Header => Ok ( Tag :: Header ( Header :: parse ( & tag_buf ) ? ) ) , TagId :: End => { // end tag contains CRC32 checksum if tag_len != 4 { return Err ( Error :: parse_err ( format ! ( " " tag_len ) ) ) ; } let checksum = tag_buf . read_u32 :: < LittleEndian > ( ) ? ; info ! ( " " checksum ) ; Ok ( Tag :: End ( checksum ) ) } TagId :: AppInfo => { debug ! ( " " Blob ( tag_buf ) ) ; Ok ( Tag :: AppInfo ( AppInfo :: parse ( & tag_buf ) ? ) ) } TagId :: EncryptionInitHeader => { debug ! ( " " Blob ( tag_buf ) ) ; // According to the PDF, this contains the used nonce and // the total amount of encrypted data. // Encryption is done using AES-CTR-128. if tag_len != 4 + 12 { // 4 byte length, 12 byte IV return Err ( Error :: parse_err ( format ! ( " " tag_len ) ) ) ; } // Total number of encrypted bytes (summation of the lengths // of all EncryptedProgramData tags). let total_enc_bytes = tag_buf . read_u32 :: < LittleEndian > ( ) ? ; // The rest should be exactly 12 Bytes, which (96 bits) is the // nonce used for the IV (see `aes::build_iv`). let mut nonce = [ 0 ; 12 ] ; tag_buf . read_exact ( & mut nonce ) ? ; let parsed = EncryptionHeader { total_bytes : total_enc_bytes , nonce : nonce . into ( ) , } ; debug ! ( " " parsed ) ; Ok ( Tag :: EncryptionHeader ( parsed ) ) } TagId :: ProgramData | TagId :: ProgramData2 => { let data = if tag_len > 64 { & tag_buf [ .. 64 ] } else { & tag_buf } ; debug ! ( " " Blob ( data ) ) ; // The raw data to be programmed is prefixed by its offset // into flash memory. let flash_addr = tag_buf . read_u32 :: < LittleEndian > ( ) ? ; Ok ( Tag :: ProgramData ( ProgramData { flash_addr , data : Blob ( tag_buf . into ( ) ) , } ) ) } TagId :: EncryptedProgramData => Ok ( Tag :: EncryptedData ( tag_buf . into ( ) ) ) , TagId :: Signature => { debug ! ( " " Blob ( tag_buf ) ) ; if tag_len != 64 { return Err ( Error :: parse_err ( format ! ( " " tag_len ) ) ) ; } Ok ( Tag :: Signature ( Signature { raw : Blob ( tag_buf . into ( ) ) , } ) ) } TagId :: Bootloader | TagId :: Metadata => { if cfg ! ( fuzzing ) { // When fuzzing, we don't want to panic Err ( Error :: parse_err ( " " ) ) } else { unimplemented ! ( ) } } } }
Parses a tag from `reader`, adjusting it to point after the tag.
Parses a tag from ` reader ` adjusting it to point after the tag .
reader
&mut &'a [u8]