aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2010-03-19 17:59:40 +0000
committerlloyd <[email protected]>2010-03-19 17:59:40 +0000
commitdab16b79c89e54e9551d30dcf54ca89432932dce (patch)
treefcd4ccce7e442006f8075f8c8a9b298aab5167b3
parent8fa0099ce0f2f488ca4c5046c6d019125d1d3b68 (diff)
Add a couple of new helper functions to BER_Decoder:
decode_and_check takes an expected value; if the decoded value does not match, a Decoding_Error with a specified string is thrown. Useful for checking embedded version codes. decode_octet_string_bigint is for decoding INTEGER values that are stored as OCTET STRINGs. Totally obnoxious and useless, but common especially in the ECC standards.
-rw-r--r--src/asn1/ber_dec.cpp8
-rw-r--r--src/asn1/ber_dec.h25
-rw-r--r--src/pubkey/ec_dompar/ec_dompar.cpp27
-rw-r--r--src/pubkey/ecc_key/ecc_key.cpp14
-rw-r--r--src/pubkey/if_algo/if_algo.cpp7
-rw-r--r--src/pubkey/pkcs8.cpp7
6 files changed, 42 insertions, 46 deletions
diff --git a/src/asn1/ber_dec.cpp b/src/asn1/ber_dec.cpp
index 66a27dd4e..ea0334202 100644
--- a/src/asn1/ber_dec.cpp
+++ b/src/asn1/ber_dec.cpp
@@ -355,6 +355,14 @@ BER_Decoder& BER_Decoder::decode(BigInt& out)
return decode(out, INTEGER, UNIVERSAL);
}
+BER_Decoder& BER_Decoder::decode_octet_string_bigint(BigInt& out)
+ {
+ SecureVector<byte> out_vec;
+ decode(out_vec, OCTET_STRING);
+ out = BigInt::decode(&out_vec[0], out_vec.size());
+ return (*this);
+ }
+
/*
* Decode a BER encoded BOOLEAN
*/
diff --git a/src/asn1/ber_dec.h b/src/asn1/ber_dec.h
index 2e38af301..3658aeba4 100644
--- a/src/asn1/ber_dec.h
+++ b/src/asn1/ber_dec.h
@@ -1,6 +1,6 @@
/*
* BER Decoder
-* (C) 1999-2008 Jack Lloyd
+* (C) 1999-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -46,11 +46,30 @@ class BOTAN_DLL BER_Decoder
BER_Decoder& decode(class ASN1_Object&);
+ BER_Decoder& decode_octet_string_bigint(class BigInt&);
+
+ template<typename T>
+ BER_Decoder& decode_optional(T& out,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag,
+ const T& default_value = T());
+
template<typename T>
- BER_Decoder& decode_optional(T&, ASN1_Tag, ASN1_Tag, const T& = T());
+ BER_Decoder& decode_list(std::vector<T>& out,
+ bool clear_out = true);
template<typename T>
- BER_Decoder& decode_list(std::vector<T>&, bool = true);
+ BER_Decoder& decode_and_check(const T& expected,
+ const std::string& error_msg)
+ {
+ T actual;
+ decode(actual);
+
+ if(actual != expected)
+ throw Decoding_Error(error_msg);
+
+ return (*this);
+ }
BER_Decoder& decode_optional_string(MemoryRegion<byte>&,
ASN1_Tag, u16bit);
diff --git a/src/pubkey/ec_dompar/ec_dompar.cpp b/src/pubkey/ec_dompar/ec_dompar.cpp
index 42ae9211e..3512060d1 100644
--- a/src/pubkey/ec_dompar/ec_dompar.cpp
+++ b/src/pubkey/ec_dompar/ec_dompar.cpp
@@ -54,23 +54,20 @@ EC_Domain_Params::EC_Domain_Params(const MemoryRegion<byte>& ber_data)
}
else if(obj.type_tag == SEQUENCE)
{
- BigInt ecpVers1(1);
- OID curve_type;
- SecureVector<byte> sv_a;
- SecureVector<byte> sv_b;
- BigInt p;
+ BigInt p, a, b;
SecureVector<byte> sv_base_point;
BER_Decoder(ber_data)
.start_cons(SEQUENCE)
- .decode(ecpVers1)
+ .decode_and_check<u32bit>(1, "Unknown ECC param version code")
.start_cons(SEQUENCE)
- .decode(curve_type)
+ .decode_and_check(OID("1.2.840.10045.1.1"),
+ "Only prime ECC fields supported")
.decode(p)
.end_cons()
.start_cons(SEQUENCE)
- .decode(sv_a, OCTET_STRING)
- .decode(sv_b, OCTET_STRING)
+ .decode_octet_string_bigint(a)
+ .decode_octet_string_bigint(b)
.end_cons()
.decode(sv_base_point, OCTET_STRING)
.decode(order)
@@ -78,17 +75,7 @@ EC_Domain_Params::EC_Domain_Params(const MemoryRegion<byte>& ber_data)
.end_cons()
.verify_end();
- if(ecpVers1 != 1)
- throw Decoding_Error("EC_Domain_Params: Unknown version code");
-
- // Only prime curves supported
- if(curve_type.as_string() != "1.2.840.10045.1.1")
- throw Decoding_Error("Unexpected curve type " + curve_type.as_string());
-
- curve = CurveGFp(p,
- BigInt::decode(sv_a, sv_a.size()),
- BigInt::decode(sv_b, sv_b.size()));
-
+ curve = CurveGFp(p, a, b);
base_point = OS2ECP(sv_base_point, curve);
base_point.check_invariants();
}
diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp
index a4bd9b635..fdb29b29f 100644
--- a/src/pubkey/ecc_key/ecc_key.cpp
+++ b/src/pubkey/ecc_key/ecc_key.cpp
@@ -125,7 +125,7 @@ MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const
{
return DER_Encoder()
.start_cons(SEQUENCE)
- .encode(BigInt(1))
+ .encode(static_cast<u32bit>(1))
.encode(BigInt::encode_1363(private_key, private_key.bytes()),
OCTET_STRING)
.end_cons()
@@ -138,21 +138,13 @@ EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
domain_params = EC_Domain_Params(alg_id.parameters);
domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
- u32bit version;
- SecureVector<byte> octstr_secret;
-
BER_Decoder(key_bits)
.start_cons(SEQUENCE)
- .decode(version)
- .decode(octstr_secret, OCTET_STRING)
+ .decode_and_check<u32bit>(1, "Unknown version code for ECC key")
+ .decode_octet_string_bigint(private_key)
.verify_end()
.end_cons();
- if(version != 1)
- throw Decoding_Error("Wrong key format version for EC key");
-
- private_key = BigInt::decode(octstr_secret, octstr_secret.size());
-
public_key = domain().get_base_point() * private_key;
try
diff --git a/src/pubkey/if_algo/if_algo.cpp b/src/pubkey/if_algo/if_algo.cpp
index 759c30c61..82722d489 100644
--- a/src/pubkey/if_algo/if_algo.cpp
+++ b/src/pubkey/if_algo/if_algo.cpp
@@ -60,11 +60,9 @@ IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
const AlgorithmIdentifier&,
const MemoryRegion<byte>& key_bits)
{
- u32bit version;
-
BER_Decoder(key_bits)
.start_cons(SEQUENCE)
- .decode(version)
+ .decode_and_check<u32bit>(0, "Unknown PKCS #1 key format version")
.decode(n)
.decode(e)
.decode(d)
@@ -75,9 +73,6 @@ IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng,
.decode(c)
.end_cons();
- if(version != 0)
- throw Decoding_Error("Unknown PKCS #1 key format version");
-
load_check(rng);
}
diff --git a/src/pubkey/pkcs8.cpp b/src/pubkey/pkcs8.cpp
index 400fdbb48..35ff7f206 100644
--- a/src/pubkey/pkcs8.cpp
+++ b/src/pubkey/pkcs8.cpp
@@ -105,19 +105,14 @@ SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
key = decryptor.read_all();
}
- u32bit version;
-
BER_Decoder(key)
.start_cons(SEQUENCE)
- .decode(version)
+ .decode_and_check<u32bit>(0, "Unknown PKCS #8 version number")
.decode(pk_alg_id)
.decode(key, OCTET_STRING)
.discard_remaining()
.end_cons();
- if(version != 0)
- throw Decoding_Error("PKCS #8: Unknown version number");
-
break;
}
catch(Decoding_Error)