Botan
1.11.15
|
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 }