1#![no_std]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
7)]
8#![forbid(unsafe_code)]
9#![warn(
10 clippy::mod_module_files,
11 clippy::unwrap_used,
12 missing_docs,
13 rust_2018_idioms,
14 unused_qualifications
15)]
16
17extern crate alloc;
18
19use der::{
20 AnyRef, DecodeValue, Encode, EncodeValue, FixedTag, Length, Reader, Tag, TagNumber, Writer,
21};
22use spki::ObjectIdentifier;
23
24pub mod negotiation;
25
26pub type MechType = ObjectIdentifier;
34
35#[derive(Clone, Debug, Eq, PartialEq)]
50pub struct InitialContextToken<'a> {
51 pub this_mech: MechType,
53 pub inner_context_token: AnyRef<'a>,
55}
56
57impl<'a> FixedTag for InitialContextToken<'a> {
58 const TAG: Tag = Tag::Application {
59 constructed: true,
60 number: TagNumber::new(0),
61 };
62}
63
64impl<'a> DecodeValue<'a> for InitialContextToken<'a> {
65 fn decode_value<R: Reader<'a>>(reader: &mut R, _header: der::Header) -> der::Result<Self> {
66 Ok(Self {
67 this_mech: reader.decode()?,
68 inner_context_token: reader.decode()?,
69 })
70 }
71}
72
73impl<'a> EncodeValue for InitialContextToken<'a> {
74 fn value_len(&self) -> der::Result<Length> {
75 self.this_mech.encoded_len()? + self.inner_context_token.encoded_len()?
76 }
77
78 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
79 self.this_mech.encode(writer)?;
80 self.inner_context_token.encode(writer)?;
81
82 Ok(())
83 }
84}
85
86pub type SubsequentContextToken<'a> = AnyRef<'a>;
95
96pub type PerMsgToken<'a> = AnyRef<'a>;
105
106pub type SealedMessage<'a> = AnyRef<'a>;
118
119#[cfg(test)]
120mod tests {
121 use hex_literal::hex;
122 use spki::ObjectIdentifier;
123
124 use super::*;
125
126 use der::Decode;
127
128 #[test]
129 fn initial_context_token() {
130 let gss_bytes = hex!("604806062b0601050502a03e303ca00e300c060a2b06010401823702020aa22a04284e544c4d535350000100000005028862000000000000000000000000000000000601b01d0000000f");
131 let inner_bytes = hex!("303ca00e300c060a2b06010401823702020aa22a04284e544c4d535350000100000005028862000000000000000000000000000000000601b01d0000000f");
132
133 let gss = InitialContextToken::from_der(&gss_bytes).unwrap();
134
135 assert_eq!(ObjectIdentifier::new_unwrap("1.3.6.1.5.5.2"), gss.this_mech);
136 assert_eq!(
137 AnyRef::new(
138 Tag::ContextSpecific {
139 constructed: true,
140 number: TagNumber::N0
141 },
142 &inner_bytes
143 )
144 .unwrap(),
145 gss.inner_context_token
146 );
147
148 let output = InitialContextToken {
149 this_mech: MechType::new_unwrap("1.3.6.1.5.5.2"),
150 inner_context_token: AnyRef::new(
151 Tag::ContextSpecific {
152 constructed: true,
153 number: TagNumber::N0,
154 },
155 &inner_bytes,
156 )
157 .unwrap(),
158 };
159
160 let output_bytes = output.to_der().unwrap();
161
162 assert_eq!(&gss_bytes[..], &output_bytes);
163 }
164}