sequoia_autocrypt/
lib.rs

1//! This crate deals with Autocrypt encoded data (see the [Autocrypt
2//! Spec]).
3//!
4//!   [Autocrypt Spec]: https://autocrypt.org/level1.html#openpgp-based-key-data
5//!
6//! # Scope
7//!
8//! This implements low-level functionality like encoding and decoding
9//! of Autocrypt headers and setup messages.  Note: Autocrypt is more
10//! than just headers; it requires tight integration with the MUA.
11
12#![doc(html_favicon_url = "https://docs.sequoia-pgp.org/favicon.png")]
13#![doc(html_logo_url = "https://docs.sequoia-pgp.org/logo.svg")]
14#![warn(missing_docs)]
15
16use std::convert::TryFrom;
17use std::io;
18use std::io::prelude::*;
19use std::io::BufReader;
20use std::path::Path;
21use std::fmt::Debug;
22use std::fs::File;
23use std::str;
24
25use base64::Engine;
26use base64::engine::general_purpose::STANDARD as base64std;
27
28use sequoia_openpgp as openpgp;
29use openpgp::armor;
30use openpgp::Error;
31pub use openpgp::Result;
32use openpgp::Packet;
33use openpgp::packet::SKESK;
34use openpgp::cert::prelude::*;
35use openpgp::parse::{
36    Parse,
37    PacketParserResult, PacketParser,
38    buffered_reader::BufferedReader,
39};
40use openpgp::serialize::Serialize;
41use openpgp::serialize::stream::{
42    Message, LiteralWriter, Encryptor,
43};
44use openpgp::crypto::Password;
45use openpgp::policy::Policy;
46use openpgp::types::RevocationStatus;
47
48mod cert;
49pub use cert::cert_builder;
50
51/// Version of Autocrypt to use. `Autocrypt::default()` always returns the
52/// latest version.
53pub enum Autocrypt {
54    /// Autocrypt <= 1.0.1
55    V1,
56    /// Autocrypt version 1.1 (January 2019)
57    V1_1,
58}
59
60impl Default for Autocrypt {
61    fn default() -> Self { Autocrypt::V1_1 }
62}
63
64/// An autocrypt header attribute.
65#[derive(Debug, PartialEq)]
66pub struct Attribute {
67    /// Whether the attribute is critical.
68    pub critical: bool,
69    /// The attribute's name.
70    ///
71    /// If the attribute is not critical, the leading underscore has
72    /// been stripped.
73    pub key: String,
74    /// The attribute's value.
75    pub value: String,
76}
77
78/// Whether the data comes from an "Autocrypt" or "Autocrypt-Gossip"
79/// header.
80#[derive(Debug, PartialEq)]
81pub enum AutocryptHeaderType {
82    /// An "Autocrypt" header.
83    Sender,
84    /// An "Autocrypt-Gossip" header.
85    Gossip,
86}
87
88/// A parsed Autocrypt header.
89#[derive(Debug, PartialEq)]
90pub struct AutocryptHeader {
91    /// Whether this is an "Autocrypt" or "Autocrypt-Gossip" header.
92    pub header_type: AutocryptHeaderType,
93
94    /// The parsed key data.
95    pub key: Option<Cert>,
96
97    /// All attributes.
98    pub attributes: Vec<Attribute>,
99}
100
101impl AutocryptHeader {
102    fn empty(header_type: AutocryptHeaderType) -> Self {
103        AutocryptHeader {
104            header_type,
105            key: None,
106            attributes: Vec::new(),
107        }
108    }
109
110    /// Creates a new "Autocrypt" header.
111    pub fn new_sender<'a, P>(policy: &dyn Policy,
112                             cert: &Cert, addr: &str, prefer_encrypt: P)
113                             -> Result<Self>
114        where P: Into<Option<&'a str>>
115    {
116        // Minimize Cert.
117        let mut acc = Vec::new();
118
119        // The primary key and the most recent selfsig.
120        let primary = cert.primary_key().with_policy(policy, None)?;
121        acc.push(primary.key().clone().into());
122        primary.self_signatures().take(1)
123            .for_each(|s| acc.push(s.clone().into()));
124
125        // The subkeys and the most recent selfsig.
126        for skb in cert.keys().with_policy(policy, None).subkeys() {
127            // Skip if revoked.
128            if let RevocationStatus::Revoked(_) = skb.revocation_status() {
129                continue;
130            }
131            if skb.for_signing() || skb.for_transport_encryption() {
132                let k = skb.key().clone();
133                acc.push(k.into());
134                acc.push(skb.binding_signature().clone().into());
135            }
136        }
137
138        // The UserIDs matching ADDR.
139        let mut found_one = false;
140        for uidb in cert.userids().with_policy(policy, None) {
141            // XXX: Fix match once we have the rfc2822-name-addr.
142            if let Ok(Some(a)) = uidb.userid().email() {
143                if a == addr {
144                    acc.push(uidb.userid().clone().into());
145                    acc.push(uidb.binding_signature().clone().into());
146                    found_one = true;
147                } else {
148                    // Address is not matching.
149                    continue;
150                }
151            } else {
152                // Malformed UserID.
153                continue;
154            }
155        }
156
157        // User ids are only decorative in Autocrypt.  By convention,
158        // the cert should include a user id matching the sender's
159        // address, but we should include at least one user id.
160        if ! found_one {
161            if let Ok(uidb) = cert.with_policy(policy, None)?.primary_userid() {
162                acc.push(uidb.userid().clone().into());
163                acc.push(uidb.binding_signature().clone().into());
164            }
165        }
166
167        let cleaned_cert = Cert::try_from(acc)?;
168
169        Ok(AutocryptHeader {
170            header_type: AutocryptHeaderType::Sender,
171            key: Some(cleaned_cert),
172            attributes: vec![
173                Attribute {
174                    critical: true,
175                    key: "addr".into(),
176                    value: addr.into(),
177                },
178                Attribute {
179                    critical: true,
180                    key: "prefer-encrypt".into(),
181                    value: prefer_encrypt.into()
182                        .unwrap_or("nopreference").into(),
183                },
184            ],
185        })
186    }
187
188    /// Looks up an attribute.
189    pub fn get(&self, key: &str) -> Option<&Attribute> {
190        for a in &self.attributes {
191            if a.key == key {
192                return Some(a);
193            }
194        }
195
196        None
197    }
198
199    /// Writes a serialized version of the object to `o`.
200    pub fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
201        if self.key.is_none() {
202            return Err(Error::InvalidOperation("No key".into()).into());
203        }
204
205        for attr in self.attributes.iter() {
206            write!(o, "{}={}; ", attr.key, attr.value)?;
207        }
208
209        let mut buf = Vec::new();
210        self.key.as_ref().unwrap().serialize(&mut buf)?;
211        write!(o, "keydata={} ", base64std.encode(&buf))?;
212        Ok(())
213    }
214
215}
216
217/// A set of parsed Autocrypt headers.
218#[derive(Debug, PartialEq)]
219pub struct AutocryptHeaders {
220    /// The value in the from header.
221    pub from: Option<String>,
222
223    /// Any autocrypt headers.
224    pub headers: Vec<AutocryptHeader>,
225}
226
227impl AutocryptHeaders {
228    fn empty() -> Self {
229        AutocryptHeaders {
230            from: None,
231            headers: Vec::new(),
232        }
233    }
234
235    fn from_lines<I: Iterator<Item = io::Result<String>>>(mut lines: I)
236        -> Result<Self>
237    {
238        let mut headers = AutocryptHeaders::empty();
239
240        let mut next_line = lines.next();
241        while let Some(line) = next_line {
242            // Return any error.
243            let mut line = line?;
244
245            if line.is_empty() {
246                // End of headers.
247                break;
248            }
249
250            next_line = lines.next();
251
252            // If the line is folded (a line break was inserted in
253            // front of whitespace (either a space (0x20) or a
254            // horizontal tab (0x09)), then unfold it.
255            //
256            // See https://tools.ietf.org/html/rfc5322#section-2.2.3
257            while let Some(Ok(nl)) = next_line {
258                if !nl.is_empty() && (nl.starts_with(|c| c == ' ' || c == '\t'))
259                {
260                    line.push_str(&nl);
261                    next_line = lines.next();
262                } else {
263                    // Put it back.
264                    next_line = Some(Ok(nl));
265                    break;
266                }
267            }
268
269            const AUTOCRYPT : &str = "Autocrypt: ";
270            const AUTOCRYPT_GOSSIP : &str = "Autocrypt-Gossip: ";
271            const FROM : &str = "From: ";
272
273            if let Some(rest) = line.strip_prefix(FROM) {
274                headers.from = Some(rest.trim_matches(' ').into());
275            } else {
276                if let Some((key, value)) =
277                    if let Some(v) = line.strip_prefix(AUTOCRYPT) {
278                        Some((AutocryptHeaderType::Sender, v))
279                    } else if let Some(v) = line.strip_prefix(AUTOCRYPT_GOSSIP) {
280                        Some((AutocryptHeaderType::Gossip, v))
281                    } else {
282                        None
283                    }
284                {
285                    headers.headers.push(
286                        Self::decode_autocrypt_like_header(key, value));
287                }
288            }
289        }
290
291        Ok(headers)
292    }
293
294    /// Decode header that has the same format as the Autocrypt header.
295    /// This function should be called only on "Autocrypt" or "Autocrypt-Gossip"
296    /// headers.
297    fn decode_autocrypt_like_header(header_type: AutocryptHeaderType,
298                                    ac_value: &str)
299        -> AutocryptHeader
300    {
301        let mut header = AutocryptHeader::empty(header_type);
302
303        for pair in ac_value.split(';') {
304            let pair = pair
305                .splitn(2, '=')
306                .collect::<Vec<&str>>();
307
308            let (key, value) : (&str, String) = if pair.len() == 1 {
309                // No value...
310                (pair[0].trim_matches(' '), "".into())
311            } else {
312                (pair[0].trim_matches(' '),
313                 pair[1].trim_matches(' ').into())
314            };
315
316            if key == "keydata" {
317                if let Ok(decoded) = base64std.decode(
318                    &value.replace(' ', "")[..]) {
319                    if let Ok(cert) = Cert::from_bytes(&decoded[..]) {
320                        header.key = Some(cert);
321                    }
322                }
323            }
324
325            let (critical, key) = if let Some(key) = key.strip_prefix('_') {
326                (true, key)
327            } else {
328                (false, key)
329            };
330            header.attributes.push(Attribute {
331                critical,
332                key: key.to_string(),
333                value,
334            });
335        }
336        header
337    }
338
339    /// Parses an autocrypt header.
340    ///
341    /// `data` should be all of a mail's headers.
342    pub fn from_bytes(data: &[u8]) -> Result<Self> {
343        let lines = BufReader::new(io::Cursor::new(data)).lines();
344        Self::from_lines(lines)
345    }
346
347    /// Parses an autocrypt header.
348    ///
349    /// `path` should name a file containing a single mail.  If the
350    /// file is in mbox format, then only the first mail is
351    /// considered.
352    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
353        Self::from_reader(File::open(path)?)
354    }
355
356    /// Parses an autocrypt header.
357    ///
358    /// `reader` contain a single mail.  If it contains multiple
359    /// emails, then only the first mail is considered.
360    pub fn from_reader<R: io::Read>(reader: R) -> Result<Self> {
361        Self::from_lines(BufReader::new(reader).lines())
362    }
363
364    /// Parses an autocrypt header.
365    ///
366    /// `reader` should be all of a mail's headers.
367    pub fn from_buffered_reader<R, C>(mut reader: R) -> Result<Self>
368    where R: BufferedReader<C>,
369          C: Debug + Send + Sync
370    {
371        Self::from_bytes(reader.data_eof()?)
372    }
373}
374
375/// Holds an Autocrypt Setup Message.
376///
377/// An [Autocrypt Setup Message] is used to transfer a private key from
378/// one device to another.
379///
380/// [Autocrypt Setup Message]:
381///   https://autocrypt.org/level1.html#autocrypt-setup-message
382#[derive(Debug, PartialEq)]
383pub struct AutocryptSetupMessage {
384    prefer_encrypt: Option<String>,
385    passcode_format: Option<String>,
386    passcode: Option<Password>,
387    // We only emit a "Passcode-Begin" header if this is set.  Note:
388    // we don't check if this actually matches the start of the
389    // passcode.
390    passcode_begin: Option<String>,
391
392    cert: Cert,
393}
394
395impl AutocryptSetupMessage {
396    /// Creates a new Autocrypt Setup Message for the specified `Cert`.
397    ///
398    /// You can set the `prefer_encrypt` setting, which defaults to
399    /// "nopreference", using `set_prefer_encrypt`.
400    ///
401    /// Note: this generates a random passcode.  To retrieve the
402    /// passcode, use the `passcode` method.
403    ///
404    /// To decode an Autocrypt Setup Message, use the `from_bytes` or
405    /// `from_reader` methods.
406    pub fn new(cert: Cert) -> Self {
407        AutocryptSetupMessage {
408            prefer_encrypt: None,
409            passcode: None,
410            passcode_format: None,
411            passcode_begin: None,
412            cert,
413        }
414    }
415
416    /// Sets the prefer encrypt header.
417    pub fn set_prefer_encrypt(mut self, value: &str) -> Self {
418        self.prefer_encrypt = Some(value.into());
419        self
420    }
421
422    /// Returns the prefer encrypt header.
423    pub fn prefer_encrypt(&self) -> Option<&str> {
424        self.prefer_encrypt.as_ref().map(|v| &v[..])
425    }
426
427
428    /// Sets the "Passcode-Format" header.
429    pub fn set_passcode_format(mut self, value: &str) -> Self {
430        self.passcode_format = Some(value.into());
431        self
432    }
433
434    /// Returns the "Passcode-Format" header.
435    pub fn passcode_format(&self) -> Option<&str> {
436        self.passcode_format.as_ref().map(|v| &v[..])
437    }
438
439
440    /// Sets the passcode.
441    pub fn set_passcode(mut self, passcode: Password) -> Self {
442        self.passcode = Some(passcode);
443        self
444    }
445
446    /// Returns the ASM's passcode.
447    ///
448    /// If the passcode has not yet been generated, this returns
449    /// `None`.
450    pub fn passcode(&self) -> Option<&Password> {
451        self.passcode.as_ref()
452    }
453
454
455    /// Sets the "Passcode-Begin" header.
456    pub fn set_passcode_begin(mut self, value: &str) -> Self {
457        self.passcode_begin = Some(value.into());
458        self
459    }
460
461    /// Returns the "Passcode-Begin" header.
462    pub fn passcode_begin(&self) -> Option<&str> {
463        self.passcode_begin.as_ref().map(|v| &v[..])
464    }
465
466
467    // Generates a new passcode in "numeric9x4" format.
468    fn passcode_gen() -> Result<Password> {
469        use openpgp::crypto::mem;
470        // Generate a random passcode.
471
472        // The passcode consists of 36 digits, which encode
473        // approximately 119 bits of information.  120 bits = 15
474        // bytes.
475        let mut p_as_vec = mem::Protected::from(vec![0; 15]);
476        openpgp::crypto::random(&mut p_as_vec[..])?;
477
478        // Turn it into a 128-bit number.
479        let mut p_as_u128 = 0u128;
480        for v in p_as_vec.iter() {
481            p_as_u128 = (p_as_u128 << 8) + *v as u128;
482        }
483
484        // Turn it into ASCII.
485        let mut p : Vec<u8> = Vec::new();
486        for i in 0..36 {
487            if i > 0 && i % 4 == 0 {
488                p.push(b'-');
489            }
490
491            p.push(b'0' + ((p_as_u128 as u8) % 10));
492            p_as_u128 /= 10;
493        }
494
495        Ok(p.into())
496    }
497
498    /// If there is no passcode, generates one.
499    fn passcode_ensure(&mut self) -> Result<()> {
500        if self.passcode.is_some() {
501            return Ok(());
502        }
503
504        let passcode = Self::passcode_gen()?;
505        self.passcode_format = Some("numeric9x4".into());
506        self.passcode_begin = passcode.map(|p| {
507            Some(str::from_utf8(&p[..2]).unwrap().into())
508        });
509        self.passcode = Some(passcode);
510        Ok(())
511    }
512
513    /// Generates the Autocrypt Setup Message.
514    ///
515    /// The message is written to `w`.
516    pub fn serialize<W>(&mut self, w: &mut W) -> Result<()>
517        where W: io::Write + Send + Sync,
518    {
519        // The outer message is an ASCII-armored encoded message
520        // containing a single SK-ESK and a single SEIP packet.  The
521        // SEIP packet contains a literal data packet whose content is
522        // the inner message.
523
524        self.passcode_ensure()?;
525
526        let mut headers : Vec<(&str, &str)> = Vec::new();
527        if let Some(ref format) = self.passcode_format {
528            headers.push(
529                ("Passphrase-Format", &format[..]));
530        }
531        if let Some(ref begin) = self.passcode_begin {
532            headers.push(
533                ("Passphrase-Begin", &begin[..]));
534        }
535
536        let mut armor_writer =
537            armor::Writer::with_headers(w, armor::Kind::Message, headers)?;
538
539        {
540            // Passphrase-Format header with value numeric9x4
541            let m = Message::new(&mut armor_writer);
542            let m = Encryptor::with_passwords(
543                m, vec![self.passcode.clone().unwrap()]).build()?;
544
545            let m = LiteralWriter::new(m).build()?;
546
547            // The inner message is an ASCII-armored encoded Cert.
548            let mut w = armor::Writer::with_headers(
549                m, armor::Kind::SecretKey,
550                vec![("Autocrypt-Prefer-Encrypt",
551                      self.prefer_encrypt().unwrap_or("nopreference"))])?;
552
553            self.cert.as_tsk().serialize(&mut w)?;
554            let m = w.finalize()?;
555            m.finalize()?;
556        }
557        armor_writer.finalize()?;
558        Ok(())
559    }
560
561
562    /// Parses the autocrypt setup message in `r`.
563    ///
564    /// `passcode` is the passcode used to protect the message.
565    pub fn from_bytes(bytes: &[u8])
566        -> Result<AutocryptSetupMessageParser>
567    {
568        Self::from_reader(bytes)
569    }
570
571    /// Parses the autocrypt setup message in `r`.
572    ///
573    /// `passcode` is the passcode used to protect the message.
574    pub fn from_reader<'a, R: io::Read + Send + Sync + 'a>(r: R)
575        -> Result<AutocryptSetupMessageParser<'a>> {
576        // The outer message uses ASCII-armor.  It includes a password
577        // hint.  Hence, we need to parse it aggressively.
578        let mut r = armor::Reader::from_reader(
579            r, armor::ReaderMode::Tolerant(Some(armor::Kind::Message)));
580
581        // Note, it is essential that we call r.headers here so that
582        // we can return any error now and not in
583        // AutocryptSetupMessageParser::header.
584        let (format, begin) = {
585            let headers = r.headers()?;
586
587            let format = headers.iter()
588                .filter_map(|(k, v)| {
589                    if k == "Passphrase-Format" { Some(v) } else { None }
590                })
591                .collect::<Vec<&String>>();
592            let format = if !format.is_empty() {
593                // If there are multiple headers, then just silently take
594                // the first one.
595                Some(format[0].clone())
596            } else {
597                None
598            };
599
600            let begin = headers.iter()
601                .filter_map(|(k, v)| {
602                    if k == "Passphrase-Begin" { Some(v) } else { None }
603                })
604                .collect::<Vec<&String>>();
605            let begin = if !begin.is_empty() {
606                // If there are multiple headers, then just silently take
607                // the first one.
608                Some(begin[0].clone())
609            } else {
610                None
611            };
612
613            (format, begin)
614        };
615
616        // Get the first packet, which is the SK-ESK packet.
617
618        let mut ppr = PacketParser::from_reader(r)?;
619
620        // The outer message consists of exactly three packets: a
621        // SK-ESK and a SEIP packet, which contains a Literal data
622        // packet.
623
624        let pp = if let PacketParserResult::Some(pp) = ppr {
625            pp
626        } else {
627            return Err(
628                Error::MalformedMessage(
629                    "Premature EOF: expected an SK-ESK, encountered EOF".into())
630                .into());
631        };
632
633        let (packet, ppr_) = pp.next()?;
634        ppr = ppr_;
635
636        let skesk = match packet {
637            Packet::SKESK(skesk) => skesk,
638            p => return Err(
639                Error::MalformedMessage(
640                    format!("Expected a SKESK packet, found a {}", p.tag()))
641                .into()),
642        };
643
644        let pp = match ppr {
645            PacketParserResult::EOF(_) =>
646                return Err(
647                    Error::MalformedMessage(
648                        "Pre-mature EOF after reading SK-ESK packet".into())
649                    .into()),
650            PacketParserResult::Some(pp) => {
651                match pp.packet {
652                    Packet::SEIP(_) => (),
653                    ref p => return Err(
654                        Error::MalformedMessage(
655                            format!("Expected a SEIP packet, found a {}",
656                                    p.tag()))
657                        .into()),
658                }
659
660                pp
661            }
662        };
663
664        Ok(AutocryptSetupMessageParser {
665            passcode_format: format,
666            passcode_begin: begin,
667            skesk,
668            pp,
669            passcode: None,
670        })
671    }
672
673    /// Returns the Cert consuming the `AutocryptSetupMessage` in the
674    /// process.
675    pub fn into_cert(self) -> Cert {
676        self.cert
677    }
678}
679
680/// A Parser for an `AutocryptSetupMessage`.
681pub struct AutocryptSetupMessageParser<'a> {
682    passcode_format: Option<String>,
683    passcode_begin: Option<String>,
684    skesk: SKESK,
685    pp: PacketParser<'a>,
686    passcode: Option<Password>,
687}
688
689impl<'a> AutocryptSetupMessageParser<'a> {
690    /// Returns the "Passcode-Format" header.
691    pub fn passcode_format(&self) -> Option<&str> {
692        self.passcode_format.as_ref().map(|v| &v[..])
693    }
694
695    /// Returns the "Passcode-Begin" header.
696    pub fn passcode_begin(&self) -> Option<&str> {
697        self.passcode_begin.as_ref().map(|v| &v[..])
698    }
699
700    /// Tries to decrypt the message.
701    ///
702    /// On success, follow up with
703    /// `AutocryptSetupMessageParser::parse()` to extract the
704    /// `AutocryptSetupMessage`.
705    pub fn decrypt(&mut self, passcode: &Password) -> Result<()> {
706        if self.pp.processed() {
707            return Err(
708                Error::InvalidOperation("Already decrypted".into()).into());
709        }
710
711        let (algo, key) = self.skesk.decrypt(passcode)?;
712        self.pp.decrypt(algo, &key)?;
713
714        self.passcode = Some(passcode.clone());
715
716        Ok(())
717    }
718
719    /// Finishes parsing the `AutocryptSetupMessage`.
720    ///
721    /// Before calling this, you must decrypt the payload using
722    /// `decrypt`.
723    ///
724    /// If the payload has not been decrypted, returns
725    /// `Error::InvalidOperation`.
726    ///
727    /// If the payload is malformed, returns
728    /// `Error::MalformedMessage`.
729    pub fn parse(self) -> Result<AutocryptSetupMessage> {
730        if ! self.pp.processed() {
731            return Err(
732                Error::InvalidOperation("Not decrypted".into()).into());
733        }
734
735        // Recurse into the SEIP packet.
736        let mut ppr = self.pp.recurse()?.1;
737        if ppr.as_ref().map(|pp| pp.recursion_depth()).ok() != Some(1) {
738            return Err(
739                Error::MalformedMessage(
740                    "SEIP container empty, but expected a Literal Data packet"
741                    .into())
742                .into());
743        }
744
745        // Get the literal data packet.
746        let (prefer_encrypt, cert) = if let PacketParserResult::Some(mut pp) = ppr {
747            match pp.packet {
748                Packet::Literal(_) => (),
749                p => return Err(Error::MalformedMessage(
750                    format!("SEIP container contains a {}, \
751                             expected a Literal Data packet",
752                            p.tag())).into()),
753            }
754
755            // The inner message consists of an ASCII-armored encoded
756            // Cert.
757            let (prefer_encrypt, cert) = {
758                let mut r = armor::Reader::from_reader(
759                    &mut pp,
760                    armor::ReaderMode::Tolerant(
761                        Some(armor::Kind::SecretKey)));
762
763                let prefer_encrypt = {
764                    let headers = r.headers()?;
765                    let prefer_encrypt = headers.iter()
766                        .filter_map(|(k, v)| {
767                            if k == "Autocrypt-Prefer-Encrypt" {
768                                Some(v)
769                            } else {
770                                None
771                            }
772                        })
773                        .collect::<Vec<&String>>();
774
775                    if !prefer_encrypt.is_empty() {
776                        // If there are multiple headers, then just
777                        // silently take the first one.
778                        Some(prefer_encrypt[0].clone())
779                    } else {
780                        None
781                    }
782                };
783
784                let cert = Cert::from_reader(r)?;
785
786                (prefer_encrypt, cert)
787            };
788
789            ppr = pp.recurse()?.1;
790
791            (prefer_encrypt, cert)
792        } else {
793            return Err(
794                Error::MalformedMessage(
795                    "Pre-mature EOF after reading SEIP packet".into())
796                    .into());
797        };
798
799        // Get the MDC packet.
800        if let PacketParserResult::Some(pp) = ppr {
801            match pp.packet {
802                #[allow(deprecated)]
803                Packet::MDC(_) => (),
804                ref p => return
805                    Err(Error::MalformedMessage(
806                        format!("Expected an MDC packet, got a {}",
807                                p.tag()))
808                        .into()),
809            }
810
811            ppr = pp.recurse()?.1;
812        }
813
814        // Make sure we reached the end of the outer message.
815        match ppr {
816            PacketParserResult::EOF(pp) => {
817                // If we've gotten this far, then the outer message
818                // has the right sequence of packets, but we haven't
819                // carefully checked the nesting.  We do that now.
820                if let Err(err) = pp.is_message() {
821                    return Err(err.context("Invalid OpenPGP Message"));
822                }
823            }
824            PacketParserResult::Some(pp) =>
825                return Err(Error::MalformedMessage(
826                    format!("Extraneous packet: {}.", pp.packet.tag()))
827                           .into()),
828        }
829
830        // We're done!
831        Ok(AutocryptSetupMessage {
832            prefer_encrypt,
833            passcode: self.passcode,
834            passcode_format: self.passcode_format,
835            passcode_begin: self.passcode_begin,
836            cert,
837        })
838    }
839}
840
841#[cfg(test)]
842mod test {
843    use sequoia_openpgp::parse::buffered_reader;
844    use super::*;
845
846    use openpgp::policy::StandardPolicy as P;
847
848    #[test]
849    fn decode_test() {
850        let ac = AutocryptHeaders::from_bytes(
851            &include_bytes!("../tests/data/hpk.txt")[..]
852        )
853        .unwrap();
854        //eprintln!("ac: {:#?}", ac);
855
856        // We expect exactly one Autocrypt header.
857        assert_eq!(ac.headers.len(), 1);
858
859        assert_eq!(ac.headers[0].header_type, AutocryptHeaderType::Sender);
860        assert_eq!(ac.headers[0].get("addr").unwrap().value,
861                   "holger@merlinux.eu");
862
863        assert_eq!(ac.headers[0].get("prefer-encrypt").unwrap().value,
864                   "mutual");
865
866        let cert = ac.headers[0].key.as_ref()
867            .expect("Failed to parse key material.");
868        assert_eq!(cert.fingerprint(),
869                   "156962B0F3115069ACA970C68E3B03A279B772D6".parse().unwrap());
870        assert_eq!(cert.userids().next().unwrap().userid().value(),
871                   &b"holger krekel <holger@merlinux.eu>"[..]);
872
873
874        let ac = AutocryptHeaders::from_bytes(
875            &include_bytes!("../tests/data/vincent.txt")[..]
876        )
877        .unwrap();
878        //eprintln!("ac: {:#?}", ac);
879
880        assert_eq!(ac.from,
881                   Some("Vincent Breitmoser <look@my.amazin.horse>".into()));
882
883        // We expect exactly one Autocrypt header.
884        assert_eq!(ac.headers.len(), 1);
885
886        assert_eq!(ac.headers[0].get("addr").unwrap().value,
887                   "look@my.amazin.horse");
888
889        assert!(ac.headers[0].get("prefer_encrypt").is_none());
890
891        let cert = ac.headers[0].key.as_ref()
892            .expect("Failed to parse key material.");
893        assert_eq!(cert.fingerprint(),
894                   "D4AB192964F76A7F8F8A9B357BD18320DEADFA11".parse().unwrap());
895        assert_eq!(cert.userids().next().unwrap().userid().value(),
896                   &b"Vincent Breitmoser <look@my.amazin.horse>"[..]);
897
898
899        let ac = AutocryptHeaders::from_bytes(
900            &include_bytes!("../tests/data/patrick.txt")[..]
901        )
902        .unwrap();
903        //eprintln!("ac: {:#?}", ac);
904
905        assert_eq!(ac.from,
906                   Some("Patrick Brunschwig <patrick@enigmail.net>".into()));
907
908        // We expect exactly one Autocrypt header.
909        assert_eq!(ac.headers.len(), 1);
910
911        assert_eq!(ac.headers[0].get("addr").unwrap().value,
912                   "patrick@enigmail.net");
913
914        assert!(ac.headers[0].get("prefer_encrypt").is_none());
915
916        let cert = ac.headers[0].key.as_ref()
917            .expect("Failed to parse key material.");
918        assert_eq!(cert.fingerprint(),
919                   "4F9F89F5505AC1D1A260631CDB1187B9DD5F693B".parse().unwrap());
920        assert_eq!(cert.userids().next().unwrap().userid().value(),
921                   &b"Patrick Brunschwig <patrick@enigmail.net>"[..]);
922
923        let ac2 = AutocryptHeaders::from_bytes(
924            &include_bytes!("../tests/data/patrick_unfolded.txt")[..]
925        )
926        .unwrap();
927        assert_eq!(ac, ac2);
928    }
929
930    #[test]
931    fn parse_from_buffered_reader() {
932        // This test relies on 'from_bytes(...)' parser which, in case of a bug,
933        // may cause this test to fail as well.
934        let ac1_bytes = AutocryptHeaders::from_bytes(
935            &include_bytes!("../tests/data/hpk.txt")[..]
936        )
937        .unwrap();
938        let ac2_bytes = AutocryptHeaders::from_bytes(
939            &include_bytes!("../tests/data/vincent.txt")[..]
940        )
941        .unwrap();
942        let ac3_bytes = AutocryptHeaders::from_bytes(
943            &include_bytes!("../tests/data/patrick_unfolded.txt")[..]
944        )
945        .unwrap();
946
947        let ac1_br = AutocryptHeaders::from_buffered_reader(
948            buffered_reader::File::open("tests/data/hpk.txt").unwrap()
949        )
950        .unwrap();
951        let ac2_br = AutocryptHeaders::from_buffered_reader(
952            buffered_reader::File::open("tests/data/vincent.txt").unwrap()
953        )
954        .unwrap();
955        let ac3_br = AutocryptHeaders::from_buffered_reader(
956            buffered_reader::File::open("tests/data/patrick_unfolded.txt").unwrap()
957        )
958        .unwrap();
959
960        assert_eq!(ac1_bytes, ac1_br);
961        assert_eq!(ac2_bytes, ac2_br);
962        assert_eq!(ac3_bytes, ac3_br);
963    }
964
965    #[test]
966    fn decode_gossip() {
967        let ac = AutocryptHeaders::from_bytes(
968            &include_bytes!("../tests/data/gossip.txt")[..]
969        )
970        .unwrap();
971        //eprintln!("ac: {:#?}", ac);
972
973        // We expect exactly two Autocrypt headers.
974        assert_eq!(ac.headers.len(), 2);
975
976        assert_eq!(ac.headers[0].header_type, AutocryptHeaderType::Gossip);
977        assert_eq!(ac.headers[0].get("addr").unwrap().value,
978                "dkg@fifthhorseman.net");
979
980        assert_eq!(ac.headers[1].get("addr").unwrap().value,
981                "neal@walfield.org");
982
983        let cert = ac.headers[0].key.as_ref()
984            .expect("Failed to parse key material.");
985        assert_eq!(cert.fingerprint(),
986                   "C4BC2DDB38CCE96485EBE9C2F20691179038E5C6".parse().unwrap());
987        assert_eq!(cert.userids().next().unwrap().userid().value(),
988                &b"Daniel Kahn Gillmor <dkg@fifthhorseman.net>"[..]);
989
990    }
991
992    #[test]
993    fn passcode_gen_test() {
994        let mut dist = [0usize; 10];
995
996        let samples = 8 * 1024;
997
998        // 36 digits grouped into four digits, each group
999        // separated by a dash.
1000        let digits = 36;
1001        let passcode_len = 36 + (36 / 4 - 1);
1002
1003        for _ in 0..samples {
1004            let p = AutocryptSetupMessage::passcode_gen().unwrap();
1005            p.map(|p| {
1006                assert_eq!(p.len(), passcode_len);
1007
1008                for c in p.iter() {
1009                    match *c as char {
1010                        '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' => {
1011                            let i = *c as usize - ('0' as usize);
1012                            dist[i] = dist[i] + 1
1013                        },
1014                        '-' => (),
1015                        _ => panic!("Unexpected character in passcode: {}", c),
1016                    }
1017                }
1018            });
1019        }
1020
1021        // Make sure the distribution is reasonable.  If this runs
1022        // long enough, then of course, this test will eventually
1023        // fail.  But, it is extremely unlikely and suggests a failure
1024        // in the random number generator or the code.
1025
1026        let expected_value = (samples * digits) as f32 / 10.;
1027        // We expect each digit to occur within 10% of its expected
1028        // value.
1029        let lower = (expected_value * 0.9) as usize;
1030        let upper = (expected_value * 1.1) as usize;
1031        let expected_value = expected_value as usize;
1032
1033        eprintln!("Distribution (expected value: {}, bounds: {}..{}):",
1034                  expected_value, lower, upper);
1035        let mut bad = 0;
1036        for (i, count) in dist.iter()
1037            .map(|x| *x)
1038            .enumerate()
1039            .collect::<Vec<(usize, usize)>>()
1040        {
1041            let is_good = lower < count && count < upper;
1042            eprintln!("{}: {} occurrences{}.",
1043                      i, count, if is_good { "" } else { " UNLIKELY" });
1044
1045            if !is_good {
1046                bad = bad + 1;
1047            }
1048        }
1049
1050        // Allow one digit to be out of the bounds.
1051        //
1052        // Dear developer: if this test has failed more than once for
1053        // you over years of development, then there is almost
1054        // certainly a bug!  Report it, please!
1055        assert!(bad <= 1);
1056    }
1057
1058    #[test]
1059    fn autocrypt_setup_message() {
1060        // Try the example autocrypt setup message.
1061        let mut asm = AutocryptSetupMessage::from_bytes(
1062            &include_bytes!("../tests/data/setup-message.txt")[..]).unwrap();
1063
1064        // A bad passcode.
1065        assert!(asm.decrypt(&"123".into()).is_err());
1066        // Now the right one.
1067        assert!(asm.decrypt(
1068            &"1742-0185-6197-1303-7016-8412-3581-4441-0597".into()
1069        ).is_ok());
1070        let asm = asm.parse().unwrap();
1071
1072        // A basic check to make sure we got the key.
1073        assert_eq!(asm.into_cert().fingerprint(),
1074                   "E604 68CE 44D7 7C3F CE9F  D072 71DB C565 7FDE 65A7".parse()
1075                       .unwrap());
1076
1077
1078        // Create an ASM for testy-private.  Then decrypt it and make
1079        // sure the Cert, etc. survived the round trip.
1080        let cert =
1081            Cert::from_bytes(&include_bytes!("../tests/data/testy-private.pgp")[..])
1082            .unwrap();
1083
1084        let mut asm = AutocryptSetupMessage::new(cert)
1085            .set_prefer_encrypt("mutual");
1086        let mut buffer = Vec::new();
1087        asm.serialize(&mut buffer).unwrap();
1088
1089        let mut asm2 = AutocryptSetupMessage::from_bytes(&buffer[..]).unwrap();
1090        asm2.decrypt(asm.passcode().unwrap()).unwrap();
1091        let asm2 = asm2.parse().unwrap();
1092        assert_eq!(asm, asm2);
1093    }
1094
1095    #[test]
1096    fn autocrypt_header_new() {
1097        let p = &P::new();
1098
1099        let cert = Cert::from_bytes(&include_bytes!("../tests/data/testy.pgp")[..])
1100            .unwrap();
1101        let header = AutocryptHeader::new_sender(p, &cert, "testy@example.org",
1102                                                 "mutual").unwrap();
1103        let mut buf = Vec::new();
1104        write!(&mut buf, "Autocrypt: ").unwrap();
1105        header.serialize(&mut buf).unwrap();
1106
1107        let ac = AutocryptHeaders::from_bytes(&buf).unwrap();
1108
1109        // We expect exactly one Autocrypt header.
1110        assert_eq!(ac.headers.len(), 1);
1111
1112        assert_eq!(ac.headers[0].get("addr").unwrap().value,
1113                   "testy@example.org");
1114
1115        assert_eq!(ac.headers[0].get("prefer-encrypt").unwrap().value,
1116                   "mutual");
1117
1118        let cert = ac.headers[0].key.as_ref()
1119            .expect("Failed to parse key material.");
1120        assert_eq!(&cert.fingerprint().to_hex(),
1121                   "3E8877C877274692975189F5D03F6F865226FE8B");
1122        assert_eq!(cert.userids().len(), 1);
1123        assert_eq!(cert.keys().subkeys().count(), 1);
1124        assert_eq!(cert.userids().next().unwrap().userid().value(),
1125                   &b"Testy McTestface <testy@example.org>"[..]);
1126    }
1127
1128    #[test]
1129    fn autocrypt_header_new_address_mismatch() -> Result<()> {
1130        let p = &P::new();
1131
1132        let cert =
1133            Cert::from_bytes(&include_bytes!("../tests/data/testy.pgp")[..])?;
1134        let header = AutocryptHeader::new_sender(p, &cert,
1135                                                 "anna-lena@example.org",
1136                                                 "mutual")?;
1137        let mut buf = Vec::new();
1138        write!(&mut buf, "Autocrypt: ")?;
1139        header.serialize(&mut buf)?;
1140
1141        let ac = AutocryptHeaders::from_bytes(&buf)?;
1142
1143        // We expect exactly one Autocrypt header.
1144        assert_eq!(ac.headers.len(), 1);
1145
1146        assert_eq!(ac.headers[0].get("addr").unwrap().value,
1147                   "anna-lena@example.org");
1148
1149        assert_eq!(ac.headers[0].get("prefer-encrypt").unwrap().value,
1150                   "mutual");
1151
1152        let cert = ac.headers[0].key.as_ref()
1153            .expect("Failed to parse key material.");
1154        assert_eq!(&cert.fingerprint().to_hex(),
1155                   "3E8877C877274692975189F5D03F6F865226FE8B");
1156        assert_eq!(cert.userids().len(), 1);
1157        assert_eq!(cert.keys().subkeys().count(), 1);
1158        assert_eq!(cert.userids().next().unwrap().userid().value(),
1159                   &b"Testy McTestface <testy@example.org>"[..]);
1160        Ok(())
1161    }
1162
1163    /// Demonstrates a panic in the AutocryptHeader parser.
1164    #[test]
1165    fn issue_743() {
1166        let data: Vec<u8> = vec![
1167            0x41, 0x75, 0x02, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20,
1168            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x0a, 0xc4,
1169            0x83, 0x40, 0x39, 0x0a, 0x38, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
1170            0x20, 0x74, 0x6f, 0x63, 0x72, 0x79, 0x70, 0x74, 0x3a, 0x00, 0x00,
1171            0x0a, 0x0a, 0x0a, 0x0a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172            0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
1173            0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1174            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1175            0x00, 0x01, 0x35, 0x39, 0x33, 0x35, 0x38, 0x36, 0x34, 0x00, 0x00,
1176            0x01, 0x00, 0x00, 0x00, 0x3e, 0x3f, 0x00, 0x08, 0x00, 0x00, 0x00,
1177            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x3e, 0x08,
1178            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x01, 0x08, 0x00,
1179            0x00, 0x41, 0x75, 0x74, 0x6f, 0x63, 0x72, 0x79, 0x20, 0x02, 0x01,
1180            0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1181            0x00, 0x00, 0x00, 0x00, 0x01, 0x70,
1182        ];
1183        let _ = AutocryptHeaders::from_bytes(&data);
1184    }
1185
1186    #[test]
1187    fn issue_1012() {
1188        let data: Vec<u8> = vec![
1189            0x41, 0x75, 0x74, 0x6f, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2d, 0x47, 0x6f, 0x73, 0x73, 0x69,
1190            0x70, 0x3a, 0x20, 0xc8, 0x84, 0x01, 0x42, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x25, 0x25, 0x25,
1191            0x25, 0x42, 0x25, 0x3f, 0x21, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
1192            0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x00, 0x40, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
1193            0x25, 0x22, 0x6b, 0x25, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1194            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x25, 0x25, 0x25, 0x25,
1195            0x25, 0x25, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x25, 0x25, 0x25, 0x25, 0x25,
1196            0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
1197        ];
1198
1199        AutocryptHeaders::from_bytes(&data).expect("parses");
1200    }
1201}