Botan  1.11.15
src/lib/pubkey/ec_group/ec_group.cpp
Go to the documentation of this file.
00001 /*
00002 * ECC Domain Parameters
00003 *
00004 * (C) 2007 Falko Strenzke, FlexSecure GmbH
00005 *     2008 Jack Lloyd
00006 *
00007 * Botan is released under the Simplified BSD License (see license.txt)
00008 */
00009 
00010 #include <botan/ec_group.h>
00011 #include <botan/ber_dec.h>
00012 #include <botan/der_enc.h>
00013 #include <botan/oids.h>
00014 #include <botan/pem.h>
00015 
00016 namespace Botan {
00017 
00018 EC_Group::EC_Group(const OID& domain_oid)
00019    {
00020    const char* pem = PEM_for_named_group(OIDS::lookup(domain_oid));
00021 
00022    if(!pem)
00023       throw Lookup_Error("No ECC domain data for " + domain_oid.as_string());
00024 
00025    *this = EC_Group(pem);
00026    oid = domain_oid.as_string();
00027    }
00028 
00029 EC_Group::EC_Group(const std::string& str)
00030    {
00031    if(str == "")
00032       return; // no initialization / uninitialized
00033 
00034    try
00035       {
00036       std::vector<byte> ber =
00037          unlock(PEM_Code::decode_check_label(str, "EC PARAMETERS"));
00038 
00039       *this = EC_Group(ber);
00040       }
00041    catch(Decoding_Error) // hmm, not PEM?
00042       {
00043       *this = EC_Group(OIDS::lookup(str));
00044       }
00045    }
00046 
00047 EC_Group::EC_Group(const std::vector<byte>& ber_data)
00048    {
00049    BER_Decoder ber(ber_data);
00050    BER_Object obj = ber.get_next_object();
00051 
00052    if(obj.type_tag == NULL_TAG)
00053       throw Decoding_Error("Cannot handle ImplicitCA ECDSA parameters");
00054    else if(obj.type_tag == OBJECT_ID)
00055       {
00056       OID dom_par_oid;
00057       BER_Decoder(ber_data).decode(dom_par_oid);
00058       *this = EC_Group(dom_par_oid);
00059       }
00060    else if(obj.type_tag == SEQUENCE)
00061       {
00062       BigInt p, a, b;
00063       std::vector<byte> sv_base_point;
00064 
00065       BER_Decoder(ber_data)
00066          .start_cons(SEQUENCE)
00067            .decode_and_check<size_t>(1, "Unknown ECC param version code")
00068            .start_cons(SEQUENCE)
00069             .decode_and_check(OID("1.2.840.10045.1.1"),
00070                               "Only prime ECC fields supported")
00071              .decode(p)
00072            .end_cons()
00073            .start_cons(SEQUENCE)
00074              .decode_octet_string_bigint(a)
00075              .decode_octet_string_bigint(b)
00076            .end_cons()
00077            .decode(sv_base_point, OCTET_STRING)
00078            .decode(order)
00079            .decode(cofactor)
00080          .end_cons()
00081          .verify_end();
00082 
00083       curve = CurveGFp(p, a, b);
00084       base_point = OS2ECP(sv_base_point, curve);
00085       }
00086    else
00087       throw Decoding_Error("Unexpected tag while decoding ECC domain params");
00088    }
00089 
00090 std::vector<byte>
00091 EC_Group::DER_encode(EC_Group_Encoding form) const
00092    {
00093    if(form == EC_DOMPAR_ENC_EXPLICIT)
00094       {
00095       const size_t ecpVers1 = 1;
00096       OID curve_type("1.2.840.10045.1.1");
00097 
00098       const size_t p_bytes = curve.get_p().bytes();
00099 
00100       return DER_Encoder()
00101          .start_cons(SEQUENCE)
00102             .encode(ecpVers1)
00103             .start_cons(SEQUENCE)
00104                .encode(curve_type)
00105                .encode(curve.get_p())
00106             .end_cons()
00107             .start_cons(SEQUENCE)
00108                .encode(BigInt::encode_1363(curve.get_a(), p_bytes),
00109                        OCTET_STRING)
00110                .encode(BigInt::encode_1363(curve.get_b(), p_bytes),
00111                        OCTET_STRING)
00112             .end_cons()
00113             .encode(EC2OSP(base_point, PointGFp::UNCOMPRESSED), OCTET_STRING)
00114             .encode(order)
00115             .encode(cofactor)
00116          .end_cons()
00117          .get_contents_unlocked();
00118       }
00119    else if(form == EC_DOMPAR_ENC_OID)
00120       return DER_Encoder().encode(OID(get_oid())).get_contents_unlocked();
00121    else if(form == EC_DOMPAR_ENC_IMPLICITCA)
00122       return DER_Encoder().encode_null().get_contents_unlocked();
00123    else
00124       throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
00125    }
00126 
00127 std::string EC_Group::PEM_encode() const
00128    {
00129    const std::vector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT);
00130    return PEM_Code::encode(der, "EC PARAMETERS");
00131    }
00132 
00133 }