aboutsummaryrefslogtreecommitdiffstats
path: root/src/codec/openpgp
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec/openpgp')
-rw-r--r--src/codec/openpgp/modinfo.txt8
-rw-r--r--src/codec/openpgp/openpgp.cpp194
-rw-r--r--src/codec/openpgp/openpgp.h32
3 files changed, 234 insertions, 0 deletions
diff --git a/src/codec/openpgp/modinfo.txt b/src/codec/openpgp/modinfo.txt
new file mode 100644
index 000000000..32a18fa4f
--- /dev/null
+++ b/src/codec/openpgp/modinfo.txt
@@ -0,0 +1,8 @@
+realname "OpenPGP Codec"
+
+define OPENPGP_CODEC
+
+<add>
+openpgp.cpp
+openpgp.h
+</add>
diff --git a/src/codec/openpgp/openpgp.cpp b/src/codec/openpgp/openpgp.cpp
new file mode 100644
index 000000000..2a84b037e
--- /dev/null
+++ b/src/codec/openpgp/openpgp.cpp
@@ -0,0 +1,194 @@
+/*************************************************
+* OpenPGP Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/openpgp.h>
+#include <botan/filters.h>
+#include <botan/charset.h>
+
+namespace Botan {
+
+namespace OpenPGP {
+
+/*************************************************
+* OpenPGP Base64 encoding *
+*************************************************/
+std::string encode(const byte input[], u32bit length,
+ const std::string& label,
+ const std::map<std::string, std::string>& headers)
+ {
+ const std::string PGP_HEADER = "-----BEGIN PGP " + label + "-----\n";
+ const std::string PGP_TRAILER = "-----END PGP " + label + "-----\n";
+ const u32bit PGP_WIDTH = 64;
+
+ std::string pgp_encoded = PGP_HEADER;
+
+ if(headers.find("Version") != headers.end())
+ pgp_encoded += "Version: " + headers.find("Version")->second + '\n';
+
+ std::map<std::string, std::string>::const_iterator i = headers.begin();
+ while(i != headers.end())
+ {
+ if(i->first != "Version")
+ pgp_encoded += i->first + ": " + i->second + '\n';
+ ++i;
+ }
+ pgp_encoded += '\n';
+
+ Pipe pipe(new Fork(
+ new Base64_Encoder(true, PGP_WIDTH),
+ new Chain(new Hash_Filter("CRC24"), new Base64_Encoder)
+ )
+ );
+
+ pipe.process_msg(input, length);
+
+ pgp_encoded += pipe.read_all_as_string(0);
+ pgp_encoded += '=' + pipe.read_all_as_string(1) + '\n';
+ pgp_encoded += PGP_TRAILER;
+
+ return pgp_encoded;
+ }
+
+/*************************************************
+* OpenPGP Base64 encoding *
+*************************************************/
+std::string encode(const byte input[], u32bit length,
+ const std::string& type)
+ {
+ std::map<std::string, std::string> empty;
+ return encode(input, length, type, empty);
+ }
+
+/*************************************************
+* OpenPGP Base64 decoding *
+*************************************************/
+SecureVector<byte> decode(DataSource& source, std::string& label,
+ std::map<std::string, std::string>& headers)
+ {
+ const u32bit RANDOM_CHAR_LIMIT = 5;
+
+ const std::string PGP_HEADER1 = "-----BEGIN PGP ";
+ const std::string PGP_HEADER2 = "-----";
+ u32bit position = 0;
+
+ while(position != PGP_HEADER1.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: No PGP header found");
+ if(b == PGP_HEADER1[position])
+ ++position;
+ else if(position >= RANDOM_CHAR_LIMIT)
+ throw Decoding_Error("PGP: Malformed PGP header");
+ else
+ position = 0;
+ }
+ position = 0;
+ while(position != PGP_HEADER2.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: No PGP header found");
+ if(b == PGP_HEADER2[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PGP: Malformed PGP header");
+
+ if(position == 0)
+ label += static_cast<char>(b);
+ }
+
+ headers.clear();
+ bool end_of_headers = false;
+ while(!end_of_headers)
+ {
+ std::string this_header;
+ byte b = 0;
+ while(b != '\n')
+ {
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: Bad armor header");
+ if(b != '\n')
+ this_header += static_cast<char>(b);
+ }
+
+ end_of_headers = true;
+ for(u32bit j = 0; j != this_header.length(); ++j)
+ if(!Charset::is_space(this_header[j]))
+ end_of_headers = false;
+
+ if(!end_of_headers)
+ {
+ std::string::size_type pos = this_header.find(": ");
+ if(pos == std::string::npos)
+ throw Decoding_Error("OpenPGP: Bad headers");
+
+ std::string key = this_header.substr(0, pos);
+ std::string value = this_header.substr(pos + 2, std::string::npos);
+ headers[key] = value;
+ }
+ }
+
+ Pipe base64(new Base64_Decoder,
+ new Fork(0,
+ new Chain(new Hash_Filter("CRC24"),
+ new Base64_Encoder)
+ )
+ );
+ base64.start_msg();
+
+ const std::string PGP_TRAILER = "-----END PGP " + label + "-----";
+ position = 0;
+ bool newline_seen = 0;
+ std::string crc;
+ while(position != PGP_TRAILER.length())
+ {
+ byte b;
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: No PGP trailer found");
+ if(b == PGP_TRAILER[position])
+ ++position;
+ else if(position)
+ throw Decoding_Error("PGP: Malformed PGP trailer");
+
+ if(b == '=' && newline_seen)
+ {
+ while(b != '\n')
+ {
+ if(!source.read_byte(b))
+ throw Decoding_Error("PGP: Bad CRC tail");
+ if(b != '\n')
+ crc += static_cast<char>(b);
+ }
+ }
+ else if(b == '\n')
+ newline_seen = true;
+ else if(position == 0)
+ {
+ base64.write(b);
+ newline_seen = false;
+ }
+ }
+ base64.end_msg();
+
+ if(crc != "" && crc != base64.read_all_as_string(1))
+ throw Decoding_Error("PGP: Corrupt CRC");
+
+ return base64.read_all();
+ }
+
+/*************************************************
+* OpenPGP Base64 decoding *
+*************************************************/
+SecureVector<byte> decode(DataSource& source, std::string& label)
+ {
+ std::map<std::string, std::string> ignored;
+ return decode(source, label, ignored);
+ }
+
+}
+
+}
+
diff --git a/src/codec/openpgp/openpgp.h b/src/codec/openpgp/openpgp.h
new file mode 100644
index 000000000..1a078a630
--- /dev/null
+++ b/src/codec/openpgp/openpgp.h
@@ -0,0 +1,32 @@
+/*************************************************
+* OpenPGP Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_OPENPGP_H__
+#define BOTAN_OPENPGP_H__
+
+#include <botan/data_src.h>
+#include <string>
+#include <map>
+
+namespace Botan {
+
+namespace OpenPGP {
+
+/*************************************************
+* OpenPGP Base64 encoding/decoding *
+*************************************************/
+BOTAN_DLL std::string encode(const byte[], u32bit, const std::string&,
+ const std::map<std::string, std::string>&);
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&,
+ std::map<std::string, std::string>&);
+
+BOTAN_DLL std::string encode(const byte[], u32bit, const std::string&);
+BOTAN_DLL SecureVector<byte> decode(DataSource&, std::string&);
+
+}
+
+}
+
+#endif