1#[cfg(feature = "async-tokio")]
2use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt};
3
4use super::headers::*;
5
6use crate::constants::*;
7
8use crate::errors::*;
9
10use super::Lead;
11
12#[cfg(feature = "signature-meta")]
13use crate::sequential_cursor::SeqCursor;
14#[cfg(feature = "signature-meta")]
15use crate::signature;
16
17use std::io::Read;
18#[cfg(feature = "signature-meta")]
19use std::io::{Seek, SeekFrom};
20
21#[derive(Debug)]
26pub struct RPMPackage {
27 pub metadata: RPMPackageMetadata,
31 pub content: Vec<u8>,
33}
34
35impl RPMPackage {
36 #[cfg(feature = "async-tokio")]
37 pub async fn parse_async<I: AsyncRead + Unpin>(input: &mut I) -> Result<Self, RPMError> {
38 let metadata = RPMPackageMetadata::parse_async(input).await?;
39 let mut content = Vec::new();
40 input.read_to_end(&mut content).await?;
41 Ok(RPMPackage { metadata, content })
42 }
43
44 pub fn parse<T: std::io::BufRead>(input: &mut T) -> Result<Self, RPMError> {
45 let metadata = RPMPackageMetadata::parse(input)?;
46 let mut content = Vec::new();
47 input.read_to_end(&mut content)?;
48 Ok(RPMPackage { metadata, content })
49 }
50
51 pub fn write<W: std::io::Write>(&self, out: &mut W) -> Result<(), RPMError> {
52 self.metadata.write(out)?;
53 out.write_all(&self.content)?;
54 Ok(())
55 }
56
57 #[cfg(feature = "async-tokio")]
58 pub async fn write_async<W: tokio::io::AsyncWrite + Unpin>(
59 &self,
60 out: &mut W,
61 ) -> Result<(), RPMError> {
62 self.metadata.write_async(out).await?;
63 out.write_all(&self.content).await?;
64 Ok(())
65 }
66
67 #[cfg(feature = "signature-meta")]
71 pub fn sign<S>(&mut self, signer: S) -> Result<(), RPMError>
72 where
73 S: signature::Signing<signature::algorithm::RSA, Signature = Vec<u8>>,
74 {
75 let mut header_bytes = Vec::<u8>::with_capacity(1024);
78 self.metadata.header.write(&mut header_bytes)?;
79
80 let mut header_and_content_cursor =
81 SeqCursor::new(&[header_bytes.as_slice(), self.content.as_slice()]);
82
83 let digest_md5 = {
84 use md5::Digest;
85 let mut hasher = md5::Md5::default();
86 {
87 let mut buf = [0u8; 256];
90 while let Ok(n) = header_and_content_cursor.read(&mut buf[..]) {
91 hasher.update(&buf[0..n]);
92 }
93 }
94 let hash_result = hasher.finalize();
95 hash_result.to_vec()
96 };
97
98 header_and_content_cursor.seek(SeekFrom::Start(0))?;
99
100 let digest_sha1 = {
101 use sha1::Digest;
102 let mut hasher = sha1::Sha1::default();
103 hasher.update(&header_bytes);
104 let digest = hasher.finalize();
105 hex::encode(digest)
106 };
107
108 let rsa_signature_spanning_header_only = signer.sign(header_bytes.as_slice())?;
109
110 let rsa_signature_spanning_header_and_archive =
111 signer.sign(&mut header_and_content_cursor)?;
112
113 self.metadata.signature = Header::<IndexSignatureTag>::new_signature_header(
116 header_and_content_cursor.len() as i32,
117 &digest_md5,
118 digest_sha1,
119 rsa_signature_spanning_header_only.as_slice(),
120 rsa_signature_spanning_header_and_archive.as_slice(),
121 );
122
123 Ok(())
124 }
125
126 #[cfg(feature = "signature-meta")]
130 pub fn verify_signature<V>(&self, verifier: V) -> Result<(), RPMError>
131 where
132 V: signature::Verifying<signature::algorithm::RSA, Signature = Vec<u8>>,
133 {
134 let mut header_bytes = Vec::<u8>::with_capacity(1024);
137 self.metadata.header.write(&mut header_bytes)?;
138
139 let signature_header_only = self
140 .metadata
141 .signature
142 .get_entry_binary_data(IndexSignatureTag::RPMSIGTAG_RSA)?;
143
144 crate::signature::echo_signature("signature_header(header only)", signature_header_only);
145
146 let signature_header_and_content = self
147 .metadata
148 .signature
149 .get_entry_binary_data(IndexSignatureTag::RPMSIGTAG_PGP)?;
150
151 crate::signature::echo_signature(
152 "signature_header(header and content)",
153 signature_header_and_content,
154 );
155
156 verifier.verify(header_bytes.as_slice(), signature_header_only)?;
157
158 let header_and_content_cursor =
159 SeqCursor::new(&[header_bytes.as_slice(), self.content.as_slice()]);
160
161 verifier.verify(header_and_content_cursor, signature_header_and_content)?;
162
163 Ok(())
164 }
165}
166
167#[derive(PartialEq, Debug)]
168pub struct RPMPackageMetadata {
169 pub lead: Lead,
170 pub signature: Header<IndexSignatureTag>,
171 pub header: Header<IndexTag>,
172}
173
174impl RPMPackageMetadata {
175 #[cfg(feature = "async-tokio")]
176 pub async fn parse_async<T: AsyncRead + Unpin>(input: &mut T) -> Result<Self, RPMError> {
177 let mut lead_buffer = [0; LEAD_SIZE];
178 input.read_exact(&mut lead_buffer).await?;
179 let lead = Lead::parse(&lead_buffer)?;
180 let signature_header = Header::parse_signature_async(input).await?;
181 let header = Header::parse_async(input).await?;
182 Ok(RPMPackageMetadata {
183 lead,
184 signature: signature_header,
185 header,
186 })
187 }
188
189 pub(crate) fn parse<T: std::io::BufRead>(input: &mut T) -> Result<Self, RPMError> {
190 let mut lead_buffer = [0; LEAD_SIZE];
191 input.read_exact(&mut lead_buffer)?;
192 let lead = Lead::parse(&lead_buffer)?;
193 let signature_header = Header::parse_signature(input)?;
194 let header = Header::parse(input)?;
195 Ok(RPMPackageMetadata {
196 lead,
197 signature: signature_header,
198 header,
199 })
200 }
201
202 pub(crate) fn write<W: std::io::Write>(&self, out: &mut W) -> Result<(), RPMError> {
203 self.lead.write(out)?;
204 self.signature.write_signature(out)?;
205 self.header.write(out)?;
206 Ok(())
207 }
208
209 #[cfg(feature = "async-tokio")]
210 pub async fn write_async<W: tokio::io::AsyncWrite + Unpin>(
211 &self,
212 out: &mut W,
213 ) -> Result<(), RPMError> {
214 self.lead.write_async(out).await?;
215 self.signature.write_signature_async(out).await?;
216 self.header.write_async(out).await?;
217 Ok(())
218 }
219}