aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-07-09 16:24:14 +0000
committerlloyd <[email protected]>2012-07-09 16:24:14 +0000
commit4e43080954be57e362feb1cc8202bfd42117e286 (patch)
treeffcefbd2b2b78ddee4285e8dd4d2d90e112acb93 /src
parent38f7ed8efb6621d55a705bb7af4ba5a21495113a (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.h2
-rw-r--r--src/asn1/asn1_oid.h2
-rw-r--r--src/asn1/ber_dec.cpp37
-rw-r--r--src/asn1/ber_dec.h34
-rw-r--r--src/pubkey/ecc_key/ecc_key.cpp22
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
+ }
}
}