1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::error::{Error, Result};
use nom::number::complete::be_u8;

pub fn build_length(value_size: usize) -> Vec<u8> {
    if value_size < 128 {
        return vec![value_size as u8];
    }

    let mut shifted_length = value_size;
    let mut octets_count: u8 = 0;
    let mut encoded_length: Vec<u8> = Vec::new();

    while shifted_length > 0 {
        octets_count += 1;
        encoded_length.push(shifted_length as u8);
        shifted_length >>= 8;
    }

    encoded_length.push(octets_count | 0b10000000);

    encoded_length.reverse();

    return encoded_length;
}

/// To parse the object value length from DER, should not be overwritten
pub fn parse_length(raw: &[u8]) -> Result<(&[u8], usize)> {
    let (mut raw, len_byte) =
        be_u8(raw).map_err(|_: nom::Err<(&[u8], nom::error::ErrorKind)>| {
            Error::LengthEmpty
        })?;

    let is_short_form = (len_byte & 0x80) == 0;
    let length = (len_byte & 0x7F) as usize;
    if is_short_form {
        return Ok((raw, length));
    }

    let length_of_length = length;
    let mut length = 0;

    for _ in 1..(length_of_length + 1) {
        length <<= 8;
        let (raw_tmp, len_byte) = be_u8(raw).map_err(
            |_: nom::Err<(&[u8], nom::error::ErrorKind)>| {
                Error::NotEnoughLengthOctects
            },
        )?;
        length += len_byte as usize;
        raw = raw_tmp;
    }
    return Ok((raw, length));
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_build_length() {
        assert_eq!(vec![0x0], build_length(0));
        assert_eq!(vec![0x1], build_length(1));
        assert_eq!(vec![0x7F], build_length(127));
        assert_eq!(vec![0x81, 0x80], build_length(128));
        assert_eq!(vec![0x81, 0xFF], build_length(255));
        assert_eq!(vec![0x82, 0x01, 0x00], build_length(256));
        assert_eq!(vec![0x82, 0xFF, 0xFF], build_length(65535));
        assert_eq!(vec![0x83, 0x01, 0x00, 0x00], build_length(65536));

        assert_eq!(
            vec![0x84, 0x10, 0xf3, 0x91, 0xbd],
            build_length(0x10f391bd)
        );
        assert_eq!(vec![0x84, 0x0f, 0xc4, 0x69, 0x89], build_length(0xfc46989));
        assert_eq!(
            vec![0x84, 0x31, 0xb2, 0x50, 0x42],
            build_length(0x31b25042)
        );
        assert_eq!(
            vec![0x84, 0x13, 0x93, 0xaa, 0x93],
            build_length(0x1393aa93)
        );
        assert_eq!(vec![0x84, 0x05, 0x71, 0x6f, 0xa9], build_length(0x5716fa9));
    }

    #[test]
    fn test_parse_length() {
        let x: &[u8] = &[];
        assert_eq!((x, 0), parse_length(&[0x0]).unwrap());
        assert_eq!((x, 1), parse_length(&[0x1]).unwrap());
        assert_eq!((x, 127), parse_length(&[0x7F]).unwrap());
        assert_eq!((x, 128), parse_length(&[0x81, 0x80]).unwrap());
        assert_eq!((x, 255), parse_length(&[0x81, 0xFF]).unwrap());
        assert_eq!((x, 256), parse_length(&[0x82, 0x01, 0x00]).unwrap());
        assert_eq!((x, 65535), parse_length(&[0x82, 0xFF, 0xFF]).unwrap());
        assert_eq!(
            (x, 65536),
            parse_length(&[0x83, 0x01, 0x00, 0x00]).unwrap()
        );

        assert_eq!(
            (x, 0x10f391bd),
            parse_length(&[0x84, 0x10, 0xf3, 0x91, 0xbd]).unwrap()
        );
        assert_eq!(
            (x, 0xfc46989),
            parse_length(&[0x84, 0x0f, 0xc4, 0x69, 0x89]).unwrap()
        );
        assert_eq!(
            (x, 0x31b25042),
            parse_length(&[0x84, 0x31, 0xb2, 0x50, 0x42]).unwrap()
        );
        assert_eq!(
            (x, 0x1393aa93),
            parse_length(&[0x84, 0x13, 0x93, 0xaa, 0x93]).unwrap()
        );
        assert_eq!(
            (x, 0x5716fa9),
            parse_length(&[0x84, 0x05, 0x71, 0x6f, 0xa9]).unwrap()
        );
    }
}