diff options
author | lloyd <[email protected]> | 2012-07-09 16:24:14 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-07-09 16:24:14 +0000 |
commit | 4e43080954be57e362feb1cc8202bfd42117e286 (patch) | |
tree | ffcefbd2b2b78ddee4285e8dd4d2d90e112acb93 /src | |
parent | 38f7ed8efb6621d55a705bb7af4ba5a21495113a (diff) |
Fix for bug 209. Required some reworking of the ASN.1 bytestring
decoding code but seems an improvement.
Diffstat (limited to 'src')
-rw-r--r-- | src/asn1/asn1_int.h | 2 | ||||
-rw-r--r-- | src/asn1/asn1_oid.h | 2 | ||||
-rw-r--r-- | src/asn1/ber_dec.cpp | 37 | ||||
-rw-r--r-- | src/asn1/ber_dec.h | 34 | ||||
-rw-r--r-- | src/pubkey/ecc_key/ecc_key.cpp | 22 |
5 files changed, 50 insertions, 47 deletions
diff --git a/src/asn1/asn1_int.h b/src/asn1/asn1_int.h index 6d254e4db..564f4ecdb 100644 --- a/src/asn1/asn1_int.h +++ b/src/asn1/asn1_int.h @@ -23,6 +23,8 @@ enum ASN1_Tag { CONSTRUCTED = 0x20, + PRIVATE = CONSTRUCTED | CONTEXT_SPECIFIC, + EOC = 0x00, BOOLEAN = 0x01, INTEGER = 0x02, diff --git a/src/asn1/asn1_oid.h b/src/asn1/asn1_oid.h index 85e863907..9d712b256 100644 --- a/src/asn1/asn1_oid.h +++ b/src/asn1/asn1_oid.h @@ -27,7 +27,7 @@ class BOTAN_DLL OID : public ASN1_Object * Find out whether this OID is empty * @return true is no OID value is set */ - bool is_empty() const { return id.size() == 0; } + bool empty() const { return id.size() == 0; } /** * Get this OID as list (vector) of its components. diff --git a/src/asn1/ber_dec.cpp b/src/asn1/ber_dec.cpp index 25c412600..81b2e34f6 100644 --- a/src/asn1/ber_dec.cpp +++ b/src/asn1/ber_dec.cpp @@ -558,41 +558,4 @@ BER_Decoder& BER_Decoder::decode(std::vector<byte>& buffer, return (*this); } -/* -* Decode an OPTIONAL string type -*/ -BER_Decoder& BER_Decoder::decode_optional_string(secure_vector<byte>& out, - ASN1_Tag real_type, - u16bit type_no) - { - BER_Object obj = get_next_object(); - - ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no); - - out.clear(); - push_back(obj); - - if(obj.type_tag == type_tag && obj.class_tag == CONTEXT_SPECIFIC) - decode(out, real_type, type_tag, CONTEXT_SPECIFIC); - - return (*this); - } - -BER_Decoder& BER_Decoder::decode_optional_string(std::vector<byte>& out, - ASN1_Tag real_type, - u16bit type_no) - { - BER_Object obj = get_next_object(); - - ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no); - - out.clear(); - push_back(obj); - - if(obj.type_tag == type_tag && obj.class_tag == CONTEXT_SPECIFIC) - decode(out, real_type, type_tag, CONTEXT_SPECIFIC); - - return (*this); - } - } diff --git a/src/asn1/ber_dec.h b/src/asn1/ber_dec.h index 0d0d0ec72..ebfa91c85 100644 --- a/src/asn1/ber_dec.h +++ b/src/asn1/ber_dec.h @@ -123,13 +123,37 @@ class BOTAN_DLL BER_Decoder return (*this); } - BER_Decoder& decode_optional_string(std::vector<byte>& out, + /* + * Decode an OPTIONAL string type + */ + template<typename Alloc> + BER_Decoder& decode_optional_string(std::vector<byte, Alloc>& out, ASN1_Tag real_type, - u16bit type_no); + u16bit type_no, + ASN1_Tag class_tag = CONTEXT_SPECIFIC) + { + BER_Object obj = get_next_object(); + + ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no); + + if(obj.type_tag == type_tag && obj.class_tag == class_tag) + { + if((class_tag & CONSTRUCTED) && (class_tag & CONTEXT_SPECIFIC)) + BER_Decoder(obj.value).decode(out, real_type).verify_end(); + else + { + push_back(obj); + decode(out, real_type, type_tag, class_tag); + } + } + else + { + out.clear(); + push_back(obj); + } - BER_Decoder& decode_optional_string(secure_vector<byte>& out, - ASN1_Tag real_type, - u16bit type_no); + return (*this); + } BER_Decoder& operator=(const BER_Decoder&) = delete; diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp index ead129ec6..2b6deea44 100644 --- a/src/pubkey/ecc_key/ecc_key.cpp +++ b/src/pubkey/ecc_key/ecc_key.cpp @@ -113,17 +113,31 @@ EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, domain_params = EC_Group(alg_id.parameters); domain_encoding = EC_DOMPAR_ENC_EXPLICIT; + OID key_parameters; + secure_vector<byte> public_key_bits; + BER_Decoder(key_bits) .start_cons(SEQUENCE) .decode_and_check<size_t>(1, "Unknown version code for ECC key") .decode_octet_string_bigint(private_key) - .verify_end() + .decode_optional(key_parameters, ASN1_Tag(0), PRIVATE) + .decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE) .end_cons(); - public_key = domain().get_base_point() * private_key; + if(!key_parameters.empty() && key_parameters != alg_id.oid) + throw Decoding_Error("EC_PrivateKey - inner and outer OIDs did not match"); - BOTAN_ASSERT(public_key.on_the_curve(), - "Loaded ECC private key not on the curve"); + if(public_key_bits.empty()) + { + public_key = domain().get_base_point() * private_key; + BOTAN_ASSERT(public_key.on_the_curve(), + "Public key derived from private key was on the curve"); + } + else + { + public_key = OS2ECP(public_key_bits, domain().get_curve()); + // OS2ECP verifies that the point is on the curve + } } } |