/* * PEM Encoding/Decoding * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #include namespace Botan { namespace PEM_Code { /* * PEM encode BER/DER-encoded objects */ std::string encode(const byte der[], u32bit length, const std::string& label, u32bit width) { const std::string PEM_HEADER = "-----BEGIN " + label + "-----\n"; const std::string PEM_TRAILER = "-----END " + label + "-----\n"; Pipe pipe(new Base64_Encoder(true, width)); pipe.process_msg(der, length); return (PEM_HEADER + pipe.read_all_as_string() + PEM_TRAILER); } /* * PEM encode BER/DER-encoded objects */ std::string encode(const MemoryRegion& data, const std::string& label, u32bit width) { return encode(data, data.size(), label, width); } /* * Decode PEM down to raw BER/DER */ SecureVector decode_check_label(DataSource& source, const std::string& label_want) { std::string label_got; SecureVector ber = decode(source, label_got); if(label_got != label_want) throw Decoding_Error("PEM: Label mismatch, wanted " + label_want + ", got " + label_got); return ber; } /* * Decode PEM down to raw BER/DER */ SecureVector decode(DataSource& source, std::string& label) { const u32bit RANDOM_CHAR_LIMIT = 8; const std::string PEM_HEADER1 = "-----BEGIN "; const std::string PEM_HEADER2 = "-----"; u32bit position = 0; while(position != PEM_HEADER1.length()) { byte b; if(!source.read_byte(b)) throw Decoding_Error("PEM: No PEM header found"); if(b == PEM_HEADER1[position]) ++position; else if(position >= RANDOM_CHAR_LIMIT) throw Decoding_Error("PEM: Malformed PEM header"); else position = 0; } position = 0; while(position != PEM_HEADER2.length()) { byte b; if(!source.read_byte(b)) throw Decoding_Error("PEM: No PEM header found"); if(b == PEM_HEADER2[position]) ++position; else if(position) throw Decoding_Error("PEM: Malformed PEM header"); if(position == 0) label += static_cast(b); } Pipe base64(new Base64_Decoder); base64.start_msg(); const std::string PEM_TRAILER = "-----END " + label + "-----"; position = 0; while(position != PEM_TRAILER.length()) { byte b; if(!source.read_byte(b)) throw Decoding_Error("PEM: No PEM trailer found"); if(b == PEM_TRAILER[position]) ++position; else if(position) throw Decoding_Error("PEM: Malformed PEM trailer"); if(position == 0) base64.write(b); } base64.end_msg(); return base64.read_all(); } /* * Search for a PEM signature */ bool matches(DataSource& source, const std::string& extra, u32bit search_range) { const std::string PEM_HEADER = "-----BEGIN " + extra; SecureVector search_buf(search_range); u32bit got = source.peek(search_buf, search_buf.size(), 0); if(got < PEM_HEADER.length()) return false; u32bit index = 0; for(u32bit j = 0; j != got; ++j) { if(search_buf[j] == PEM_HEADER[index]) ++index; else index = 0; if(index == PEM_HEADER.size()) return true; } return false; } } }