1 /*
2 * OpenPGP Codec
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/openpgp.h>
9 #include <botan/filters.h>
10 #include <botan/basefilt.h>
11 #include <botan/charset.h>
12 #include <botan/crc24.h>
13 
14 namespace Botan {
15 
16 /*
17 * OpenPGP Base64 encoding
18 */
PGP_encode(const byte input[],size_t length,const std::string & label,const std::map<std::string,std::string> & headers)19 std::string PGP_encode(
20    const byte input[], size_t length,
21    const std::string& label,
22    const std::map<std::string, std::string>& headers)
23    {
24    const std::string PGP_HEADER = "-----BEGIN PGP " + label + "-----\n";
25    const std::string PGP_TRAILER = "-----END PGP " + label + "-----\n";
26    const size_t PGP_WIDTH = 64;
27 
28    std::string pgp_encoded = PGP_HEADER;
29 
30    if(headers.find("Version") != headers.end())
31       pgp_encoded += "Version: " + headers.find("Version")->second + '\n';
32 
33    std::map<std::string, std::string>::const_iterator i = headers.begin();
34    while(i != headers.end())
35       {
36       if(i->first != "Version")
37          pgp_encoded += i->first + ": " + i->second + '\n';
38       ++i;
39       }
40    pgp_encoded += '\n';
41 
42    Pipe pipe(new Fork(
43                 new Base64_Encoder(true, PGP_WIDTH),
44                 new Chain(new Hash_Filter(new CRC24), new Base64_Encoder)
45                 )
46       );
47 
48    pipe.process_msg(input, length);
49 
50    pgp_encoded += pipe.read_all_as_string(0);
51    pgp_encoded += '=' + pipe.read_all_as_string(1) + '\n';
52    pgp_encoded += PGP_TRAILER;
53 
54    return pgp_encoded;
55    }
56 
57 /*
58 * OpenPGP Base64 encoding
59 */
PGP_encode(const byte input[],size_t length,const std::string & type)60 std::string PGP_encode(const byte input[], size_t length,
61                        const std::string& type)
62    {
63    std::map<std::string, std::string> empty;
64    return PGP_encode(input, length, type, empty);
65    }
66 
67 /*
68 * OpenPGP Base64 decoding
69 */
PGP_decode(DataSource & source,std::string & label,std::map<std::string,std::string> & headers)70 SecureVector<byte> PGP_decode(DataSource& source,
71                               std::string& label,
72                               std::map<std::string, std::string>& headers)
73    {
74    const size_t RANDOM_CHAR_LIMIT = 5;
75 
76    const std::string PGP_HEADER1 = "-----BEGIN PGP ";
77    const std::string PGP_HEADER2 = "-----";
78    size_t position = 0;
79 
80    while(position != PGP_HEADER1.length())
81       {
82       byte b;
83       if(!source.read_byte(b))
84          throw Decoding_Error("PGP: No PGP header found");
85       if(b == PGP_HEADER1[position])
86          ++position;
87       else if(position >= RANDOM_CHAR_LIMIT)
88          throw Decoding_Error("PGP: Malformed PGP header");
89       else
90          position = 0;
91       }
92    position = 0;
93    while(position != PGP_HEADER2.length())
94       {
95       byte b;
96       if(!source.read_byte(b))
97          throw Decoding_Error("PGP: No PGP header found");
98       if(b == PGP_HEADER2[position])
99          ++position;
100       else if(position)
101          throw Decoding_Error("PGP: Malformed PGP header");
102 
103       if(position == 0)
104          label += static_cast<char>(b);
105       }
106 
107    headers.clear();
108    bool end_of_headers = false;
109    while(!end_of_headers)
110       {
111       std::string this_header;
112       byte b = 0;
113       while(b != '\n')
114          {
115          if(!source.read_byte(b))
116             throw Decoding_Error("PGP: Bad armor header");
117          if(b != '\n')
118             this_header += static_cast<char>(b);
119          }
120 
121       end_of_headers = true;
122       for(size_t j = 0; j != this_header.length(); ++j)
123          if(!Charset::is_space(this_header[j]))
124             end_of_headers = false;
125 
126       if(!end_of_headers)
127          {
128          std::string::size_type pos = this_header.find(": ");
129          if(pos == std::string::npos)
130             throw Decoding_Error("OpenPGP: Bad headers");
131 
132          std::string key = this_header.substr(0, pos);
133          std::string value = this_header.substr(pos + 2, std::string::npos);
134          headers[key] = value;
135          }
136       }
137 
138    Pipe base64(new Base64_Decoder,
139                new Fork(0,
140                         new Chain(new Hash_Filter(new CRC24),
141                                   new Base64_Encoder)
142                   )
143       );
144    base64.start_msg();
145 
146    const std::string PGP_TRAILER = "-----END PGP " + label + "-----";
147    position = 0;
148    bool newline_seen = 0;
149    std::string crc;
150    while(position != PGP_TRAILER.length())
151       {
152       byte b;
153       if(!source.read_byte(b))
154          throw Decoding_Error("PGP: No PGP trailer found");
155       if(b == PGP_TRAILER[position])
156          ++position;
157       else if(position)
158          throw Decoding_Error("PGP: Malformed PGP trailer");
159 
160       if(b == '=' && newline_seen)
161          {
162          while(b != '\n')
163             {
164             if(!source.read_byte(b))
165                throw Decoding_Error("PGP: Bad CRC tail");
166             if(b != '\n')
167                crc += static_cast<char>(b);
168             }
169          }
170       else if(b == '\n')
171          newline_seen = true;
172       else if(position == 0)
173          {
174          base64.write(b);
175          newline_seen = false;
176          }
177       }
178    base64.end_msg();
179 
180    if(crc != "" && crc != base64.read_all_as_string(1))
181       throw Decoding_Error("PGP: Corrupt CRC");
182 
183    return base64.read_all();
184    }
185 
186 /*
187 * OpenPGP Base64 decoding
188 */
PGP_decode(DataSource & source,std::string & label)189 SecureVector<byte> PGP_decode(DataSource& source, std::string& label)
190    {
191    std::map<std::string, std::string> ignored;
192    return PGP_decode(source, label, ignored);
193    }
194 
195 }
196 
197