Botan  1.11.15
src/lib/misc/pem/pem.cpp
Go to the documentation of this file.
00001 /*
00002 * PEM Encoding/Decoding
00003 * (C) 1999-2007 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/pem.h>
00009 #include <botan/filters.h>
00010 #include <botan/parsing.h>
00011 
00012 namespace Botan {
00013 
00014 namespace PEM_Code {
00015 
00016 /*
00017 * PEM encode BER/DER-encoded objects
00018 */
00019 std::string encode(const byte der[], size_t length, const std::string& label,
00020                    size_t width)
00021    {
00022    const std::string PEM_HEADER = "-----BEGIN " + label + "-----\n";
00023    const std::string PEM_TRAILER = "-----END " + label + "-----\n";
00024 
00025    Pipe pipe(new Base64_Encoder(true, width));
00026    pipe.process_msg(der, length);
00027    return (PEM_HEADER + pipe.read_all_as_string() + PEM_TRAILER);
00028    }
00029 
00030 /*
00031 * Decode PEM down to raw BER/DER
00032 */
00033 secure_vector<byte> decode_check_label(DataSource& source,
00034                                       const std::string& label_want)
00035    {
00036    std::string label_got;
00037    secure_vector<byte> ber = decode(source, label_got);
00038    if(label_got != label_want)
00039       throw Decoding_Error("PEM: Label mismatch, wanted " + label_want +
00040                            ", got " + label_got);
00041    return ber;
00042    }
00043 
00044 /*
00045 * Decode PEM down to raw BER/DER
00046 */
00047 secure_vector<byte> decode(DataSource& source, std::string& label)
00048    {
00049    const size_t RANDOM_CHAR_LIMIT = 8;
00050 
00051    const std::string PEM_HEADER1 = "-----BEGIN ";
00052    const std::string PEM_HEADER2 = "-----";
00053    size_t position = 0;
00054 
00055    while(position != PEM_HEADER1.length())
00056       {
00057       byte b;
00058       if(!source.read_byte(b))
00059          throw Decoding_Error("PEM: No PEM header found");
00060       if(b == PEM_HEADER1[position])
00061          ++position;
00062       else if(position >= RANDOM_CHAR_LIMIT)
00063          throw Decoding_Error("PEM: Malformed PEM header");
00064       else
00065          position = 0;
00066       }
00067    position = 0;
00068    while(position != PEM_HEADER2.length())
00069       {
00070       byte b;
00071       if(!source.read_byte(b))
00072          throw Decoding_Error("PEM: No PEM header found");
00073       if(b == PEM_HEADER2[position])
00074          ++position;
00075       else if(position)
00076          throw Decoding_Error("PEM: Malformed PEM header");
00077 
00078       if(position == 0)
00079          label += static_cast<char>(b);
00080       }
00081 
00082    Pipe base64(new Base64_Decoder);
00083    base64.start_msg();
00084 
00085    const std::string PEM_TRAILER = "-----END " + label + "-----";
00086    position = 0;
00087    while(position != PEM_TRAILER.length())
00088       {
00089       byte b;
00090       if(!source.read_byte(b))
00091          throw Decoding_Error("PEM: No PEM trailer found");
00092       if(b == PEM_TRAILER[position])
00093          ++position;
00094       else if(position)
00095          throw Decoding_Error("PEM: Malformed PEM trailer");
00096 
00097       if(position == 0)
00098          base64.write(b);
00099       }
00100    base64.end_msg();
00101    return base64.read_all();
00102    }
00103 
00104 secure_vector<byte> decode_check_label(const std::string& pem,
00105                                       const std::string& label_want)
00106    {
00107    DataSource_Memory src(pem);
00108    return decode_check_label(src, label_want);
00109    }
00110 
00111 secure_vector<byte> decode(const std::string& pem, std::string& label)
00112    {
00113    DataSource_Memory src(pem);
00114    return decode(src, label);
00115    }
00116 
00117 /*
00118 * Search for a PEM signature
00119 */
00120 bool matches(DataSource& source, const std::string& extra,
00121              size_t search_range)
00122    {
00123    const std::string PEM_HEADER = "-----BEGIN " + extra;
00124 
00125    secure_vector<byte> search_buf(search_range);
00126    size_t got = source.peek(&search_buf[0], search_buf.size(), 0);
00127 
00128    if(got < PEM_HEADER.length())
00129       return false;
00130 
00131    size_t index = 0;
00132 
00133    for(size_t j = 0; j != got; ++j)
00134       {
00135       if(search_buf[j] == PEM_HEADER[index])
00136          ++index;
00137       else
00138          index = 0;
00139       if(index == PEM_HEADER.size())
00140          return true;
00141       }
00142    return false;
00143    }
00144 
00145 }
00146 
00147 }