Skip to content

Commit 9238c1a

Browse files
committed
ospf: Preparation work for RFC 5613.
- Update V::decode_auth_validate() signature to use references rather than taking ownership of PacketHdrAuth and AuthDecodeCtx. These structures are required for OSPFv2 LLS data blocks authentication - Extend PacketVersion interface with function to retrieve Options field from Hello and DbDesc packets. - Move digest validation logic in a separate function as it will be required for LLS CA-TLV authentication. Signed-off-by: Nicolas Rybowski <[email protected]>
1 parent 0e6fc0e commit 9238c1a

File tree

3 files changed

+95
-66
lines changed

3 files changed

+95
-66
lines changed

holo-ospf/src/ospfv2/packet/mod.rs

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -804,8 +804,8 @@ impl PacketVersion<Self> for Ospfv2 {
804804
fn decode_auth_validate(
805805
data: &[u8],
806806
pkt_len: u16,
807-
hdr_auth: PacketHdrAuth,
808-
auth: Option<AuthDecodeCtx<'_>>,
807+
hdr_auth: &PacketHdrAuth,
808+
auth: Option<&AuthDecodeCtx<'_>>,
809809
) -> DecodeResult<Option<u64>> {
810810
// Discard the packet if its authentication type doesn't match the
811811
// interface's configured authentication type.
@@ -824,49 +824,17 @@ impl PacketVersion<Self> for Ospfv2 {
824824
auth_len,
825825
seqno,
826826
} => {
827-
// Get authentication key.
828-
let auth = auth.as_ref().unwrap();
829-
let auth_key = match auth.method {
830-
AuthMethod::ManualKey(key) => {
831-
// Check if the Key ID matches.
832-
if key.id != key_id as u64 {
833-
return Err(DecodeError::AuthKeyIdNotFound(
834-
key_id as u32,
835-
));
836-
}
837-
key
838-
}
839-
AuthMethod::Keychain(keychain) => keychain
840-
.key_lookup_accept(key_id as u64)
841-
.ok_or(DecodeError::AuthKeyIdNotFound(key_id as u32))?,
842-
};
843-
844-
// Sanity check.
845-
if auth_key.algo.digest_size() != auth_len {
846-
return Err(DecodeError::AuthLenError(auth_len as u16));
847-
}
848-
849827
// Get the authentication trailer.
850828
let auth_trailer = &data
851-
[pkt_len as usize..pkt_len as usize + auth_len as usize];
829+
[pkt_len as usize..pkt_len as usize + *auth_len as usize];
852830

853831
// Compute message digest.
854832
let data = &data[..pkt_len as usize];
855-
let digest = auth::message_digest(
856-
data,
857-
auth_key.algo,
858-
&auth_key.string,
859-
None,
860-
None,
861-
);
862833

863-
// Check if the received message digest is valid.
864-
if *auth_trailer != digest {
865-
return Err(DecodeError::AuthError);
866-
}
834+
validate_digest(*key_id, *auth_len, auth, auth_trailer, data)?;
867835

868836
// Authentication succeeded.
869-
Ok(Some(seqno.into()))
837+
Ok(Some((*seqno).into()))
870838
}
871839
}
872840
}
@@ -881,4 +849,62 @@ impl PacketVersion<Self> for Ospfv2 {
881849
);
882850
buf.put_slice(&digest);
883851
}
852+
853+
fn packet_options(data: &[u8]) -> Option<Options> {
854+
let pkt_type = PacketType::from_u8(data[1]).unwrap();
855+
match pkt_type {
856+
PacketType::Hello => {
857+
let options = &data[PacketHdr::LENGTH as usize + 6..];
858+
Some(Options::from_bits_truncate(options[0]))
859+
}
860+
PacketType::DbDesc => {
861+
let options = &data[PacketHdr::LENGTH as usize + 2..];
862+
Some(Options::from_bits_truncate(options[0]))
863+
}
864+
PacketType::LsRequest
865+
| PacketType::LsUpdate
866+
| PacketType::LsAck => None,
867+
}
868+
}
869+
}
870+
871+
// ===== helper functions =====
872+
873+
pub(crate) fn validate_digest(
874+
key_id: u8,
875+
auth_len: u8,
876+
auth: Option<&AuthDecodeCtx<'_>>,
877+
digest_rx: &[u8],
878+
data: &[u8],
879+
) -> DecodeResult<()> {
880+
// Get authentication key.
881+
let auth = auth.as_ref().unwrap();
882+
let auth_key = match auth.method {
883+
AuthMethod::ManualKey(key) => {
884+
// Check if the Key ID matches.
885+
if key.id != key_id as u64 {
886+
return Err(DecodeError::AuthKeyIdNotFound(key_id as u32));
887+
}
888+
key
889+
}
890+
AuthMethod::Keychain(keychain) => keychain
891+
.key_lookup_accept(key_id as u64)
892+
.ok_or(DecodeError::AuthKeyIdNotFound(key_id as u32))?,
893+
};
894+
895+
// Sanity check.
896+
if auth_key.algo.digest_size() != auth_len {
897+
return Err(DecodeError::AuthLenError(auth_len as u16));
898+
}
899+
900+
// Compute message digest.
901+
let digest =
902+
auth::message_digest(data, auth_key.algo, &auth_key.string, None, None);
903+
904+
// Check if the received message digest is valid.
905+
if *digest_rx != digest {
906+
return Err(DecodeError::AuthError);
907+
}
908+
909+
Ok(())
884910
}

holo-ospf/src/ospfv3/packet/mod.rs

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -780,10 +780,10 @@ impl PacketVersion<Self> for Ospfv3 {
780780
fn decode_auth_validate(
781781
data: &[u8],
782782
pkt_len: u16,
783-
_hdr_auth: PacketHdrAuth,
784-
auth: Option<AuthDecodeCtx<'_>>,
783+
_hdr_auth: &PacketHdrAuth,
784+
auth: Option<&AuthDecodeCtx<'_>>,
785785
) -> DecodeResult<Option<u64>> {
786-
let options = packet_options(data);
786+
let options = Self::packet_options(data);
787787

788788
// Check for authentication type mismatch.
789789
//
@@ -905,28 +905,23 @@ impl PacketVersion<Self> for Ospfv3 {
905905
);
906906
buf.put_slice(&digest);
907907
}
908-
}
909-
910-
// ===== helper functions =====
911908

912-
// Retrieves the Options field from Hello and Database Description packets.
913-
//
914-
// Assumes the packet length has been validated beforehand.
915-
fn packet_options(data: &[u8]) -> Option<Options> {
916-
let pkt_type = PacketType::from_u8(data[1]).unwrap();
917-
match pkt_type {
918-
PacketType::Hello => {
919-
let options = &data[PacketHdr::LENGTH as usize + 6..];
920-
let options = ((options[0] as u16) << 8) | options[1] as u16;
921-
Some(Options::from_bits_truncate(options))
922-
}
923-
PacketType::DbDesc => {
924-
let options = &data[PacketHdr::LENGTH as usize + 2..];
925-
let options = ((options[0] as u16) << 8) | options[1] as u16;
926-
Some(Options::from_bits_truncate(options))
927-
}
928-
PacketType::LsRequest | PacketType::LsUpdate | PacketType::LsAck => {
929-
None
909+
fn packet_options(data: &[u8]) -> Option<Options> {
910+
let pkt_type = PacketType::from_u8(data[1]).unwrap();
911+
match pkt_type {
912+
PacketType::Hello => {
913+
let options = &data[PacketHdr::LENGTH as usize + 6..];
914+
let options = ((options[0] as u16) << 8) | options[1] as u16;
915+
Some(Options::from_bits_truncate(options))
916+
}
917+
PacketType::DbDesc => {
918+
let options = &data[PacketHdr::LENGTH as usize + 2..];
919+
let options = ((options[0] as u16) << 8) | options[1] as u16;
920+
Some(Options::from_bits_truncate(options))
921+
}
922+
PacketType::LsRequest
923+
| PacketType::LsUpdate
924+
| PacketType::LsAck => None,
930925
}
931926
}
932927
}

holo-ospf/src/packet/mod.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,17 @@ pub trait PacketVersion<V: Version> {
8383
fn decode_auth_validate(
8484
data: &[u8],
8585
pkt_len: u16,
86-
hdr_auth: V::PacketHdrAuth,
87-
auth: Option<AuthDecodeCtx<'_>>,
86+
hdr_auth: &V::PacketHdrAuth,
87+
auth: Option<&AuthDecodeCtx<'_>>,
8888
) -> DecodeResult<Option<u64>>;
8989

9090
// Encode the authentication trailer.
9191
fn encode_auth_trailer(buf: &mut BytesMut, auth: AuthEncodeCtx<'_>);
92+
93+
// Retrieves the Options field from Hello and Database Description packets.
94+
//
95+
// Assumes the packet length has been validated beforehand.
96+
fn packet_options(data: &[u8]) -> Option<Self::PacketOptions>;
9297
}
9398

9499
// OSPF version-specific code.
@@ -307,9 +312,12 @@ impl<V: Version> Packet<V> {
307312
let _span_guard = span.enter();
308313

309314
// Validate the packet authentication.
310-
if let Some(auth_seqno) =
311-
V::decode_auth_validate(buf_orig.as_ref(), pkt_len, hdr_auth, auth)?
312-
{
315+
if let Some(auth_seqno) = V::decode_auth_validate(
316+
buf_orig.as_ref(),
317+
pkt_len,
318+
&hdr_auth,
319+
auth.as_ref(),
320+
)? {
313321
hdr.set_auth_seqno(auth_seqno);
314322
}
315323

0 commit comments

Comments
 (0)