Botan  1.11.15
src/lib/asn1/asn1_str.cpp
Go to the documentation of this file.
00001 /*
00002 * Simple ASN.1 String Types
00003 * (C) 1999-2007 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/asn1_str.h>
00009 #include <botan/der_enc.h>
00010 #include <botan/ber_dec.h>
00011 #include <botan/charset.h>
00012 #include <botan/parsing.h>
00013 
00014 namespace Botan {
00015 
00016 namespace {
00017 
00018 /*
00019 * Choose an encoding for the string
00020 */
00021 ASN1_Tag choose_encoding(const std::string& str,
00022                          const std::string& type)
00023    {
00024    static const byte IS_PRINTABLE[256] = {
00025       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00026       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00027       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
00028       0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
00029       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
00030       0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
00031       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
00032       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
00033       0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
00034       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
00035       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00036       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00037       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00038       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00039       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00040       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00041       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00042       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00043       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00044       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00045       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00046       0x00, 0x00, 0x00, 0x00 };
00047 
00048    for(size_t i = 0; i != str.size(); ++i)
00049       {
00050       if(!IS_PRINTABLE[static_cast<byte>(str[i])])
00051          {
00052          if(type == "utf8")   return UTF8_STRING;
00053          if(type == "latin1") return T61_STRING;
00054          throw Invalid_Argument("choose_encoding: Bad string type " + type);
00055          }
00056       }
00057    return PRINTABLE_STRING;
00058    }
00059 
00060 }
00061 
00062 /*
00063 * Create an ASN1_String
00064 */
00065 ASN1_String::ASN1_String(const std::string& str, ASN1_Tag t) : tag(t)
00066    {
00067    iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET);
00068 
00069    if(tag == DIRECTORY_STRING)
00070       tag = choose_encoding(iso_8859_str, "latin1");
00071 
00072    if(tag != NUMERIC_STRING &&
00073       tag != PRINTABLE_STRING &&
00074       tag != VISIBLE_STRING &&
00075       tag != T61_STRING &&
00076       tag != IA5_STRING &&
00077       tag != UTF8_STRING &&
00078       tag != BMP_STRING)
00079       throw Invalid_Argument("ASN1_String: Unknown string type " +
00080                              std::to_string(tag));
00081    }
00082 
00083 /*
00084 * Create an ASN1_String
00085 */
00086 ASN1_String::ASN1_String(const std::string& str)
00087    {
00088    iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET);
00089    tag = choose_encoding(iso_8859_str, "latin1");
00090    }
00091 
00092 /*
00093 * Return this string in ISO 8859-1 encoding
00094 */
00095 std::string ASN1_String::iso_8859() const
00096    {
00097    return iso_8859_str;
00098    }
00099 
00100 /*
00101 * Return this string in local encoding
00102 */
00103 std::string ASN1_String::value() const
00104    {
00105    return Charset::transcode(iso_8859_str, LATIN1_CHARSET, LOCAL_CHARSET);
00106    }
00107 
00108 /*
00109 * Return the type of this string object
00110 */
00111 ASN1_Tag ASN1_String::tagging() const
00112    {
00113    return tag;
00114    }
00115 
00116 /*
00117 * DER encode an ASN1_String
00118 */
00119 void ASN1_String::encode_into(DER_Encoder& encoder) const
00120    {
00121    std::string value = iso_8859();
00122    if(tagging() == UTF8_STRING)
00123       value = Charset::transcode(value, LATIN1_CHARSET, UTF8_CHARSET);
00124    encoder.add_object(tagging(), UNIVERSAL, value);
00125    }
00126 
00127 /*
00128 * Decode a BER encoded ASN1_String
00129 */
00130 void ASN1_String::decode_from(BER_Decoder& source)
00131    {
00132    BER_Object obj = source.get_next_object();
00133 
00134    Character_Set charset_is;
00135 
00136    if(obj.type_tag == BMP_STRING)
00137       charset_is = UCS2_CHARSET;
00138    else if(obj.type_tag == UTF8_STRING)
00139       charset_is = UTF8_CHARSET;
00140    else
00141       charset_is = LATIN1_CHARSET;
00142 
00143    *this = ASN1_String(
00144       Charset::transcode(ASN1::to_string(obj), charset_is, LOCAL_CHARSET),
00145       obj.type_tag);
00146    }
00147 
00148 }