diff options
Diffstat (limited to 'src/lib')
74 files changed, 1438 insertions, 2950 deletions
diff --git a/src/lib/asn1/oid_lookup/default.cpp b/src/lib/asn1/oid_lookup/default.cpp index 1f107ec86..937708be4 100644 --- a/src/lib/asn1/oid_lookup/default.cpp +++ b/src/lib/asn1/oid_lookup/default.cpp @@ -105,13 +105,6 @@ const char* default_oid_list() "2.16.840.1.101.3.4.3.1 = DSA/EMSA1(SHA-224)" "\n" "2.16.840.1.101.3.4.3.2 = DSA/EMSA1(SHA-256)" "\n" - "0.4.0.127.0.7.1.1.4.1.1 = ECDSA/EMSA1_BSI(SHA-160)" "\n" - "0.4.0.127.0.7.1.1.4.1.2 = ECDSA/EMSA1_BSI(SHA-224)" "\n" - "0.4.0.127.0.7.1.1.4.1.3 = ECDSA/EMSA1_BSI(SHA-256)" "\n" - "0.4.0.127.0.7.1.1.4.1.4 = ECDSA/EMSA1_BSI(SHA-384)" "\n" - "0.4.0.127.0.7.1.1.4.1.5 = ECDSA/EMSA1_BSI(SHA-512)" "\n" - "0.4.0.127.0.7.1.1.4.1.6 = ECDSA/EMSA1_BSI(RIPEMD-160)" "\n" - "1.2.840.10045.4.1 = ECDSA/EMSA1(SHA-160)" "\n" "1.2.840.10045.4.3.1 = ECDSA/EMSA1(SHA-224)" "\n" "1.2.840.10045.4.3.2 = ECDSA/EMSA1(SHA-256)" "\n" diff --git a/src/lib/cert/cvc/asn1_eac_str.cpp b/src/lib/cert/cvc/asn1_eac_str.cpp deleted file mode 100644 index 72ad24926..000000000 --- a/src/lib/cert/cvc/asn1_eac_str.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* -* Simple ASN.1 String Types -* (C) 2007 FlexSecure GmbH -* 2008-2011 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/eac_asn_obj.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/charset.h> -#include <botan/parsing.h> -#include <sstream> -#include <ios> - -namespace Botan { - -/* -* Create an ASN1_EAC_String -*/ -ASN1_EAC_String::ASN1_EAC_String(const std::string& str, ASN1_Tag t) : m_tag(t) - { - m_iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET); - - if(!sanity_check()) - throw Invalid_Argument("ASN1_EAC_String contains illegal characters"); - } - -/* -* Return this string in ISO 8859-1 encoding -*/ -std::string ASN1_EAC_String::iso_8859() const - { - return m_iso_8859_str; - } - -/* -* Return this string in local encoding -*/ -std::string ASN1_EAC_String::value() const - { - return Charset::transcode(m_iso_8859_str, LATIN1_CHARSET, LOCAL_CHARSET); - } - -/* -* Return the type of this string object -*/ -ASN1_Tag ASN1_EAC_String::tagging() const - { - return m_tag; - } - -/* -* DER encode an ASN1_EAC_String -*/ -void ASN1_EAC_String::encode_into(DER_Encoder& encoder) const - { - std::string value = iso_8859(); - encoder.add_object(tagging(), APPLICATION, value); - } - -/* -* Decode a BER encoded ASN1_EAC_String -*/ -void ASN1_EAC_String::decode_from(BER_Decoder& source) - { - BER_Object obj = source.get_next_object(); - - if(obj.type_tag != m_tag) - { - std::stringstream ss; - - ss << "ASN1_EAC_String tag mismatch, tag was " - << std::hex << obj.type_tag - << " expected " - << std::hex << m_tag; - - throw Decoding_Error(ss.str()); - } - - Character_Set charset_is; - charset_is = LATIN1_CHARSET; - - try - { - *this = ASN1_EAC_String( - Charset::transcode(ASN1::to_string(obj), LOCAL_CHARSET, charset_is), - obj.type_tag); - } - catch(Invalid_Argument& inv_arg) - { - throw Decoding_Error(std::string("ASN1_EAC_String decoding failed: ") + - inv_arg.what()); - } - } - -// checks for compliance to the alphabet defined in TR-03110 v1.10, 2007-08-20 -// p. 43 -bool ASN1_EAC_String::sanity_check() const - { - const byte* rep = reinterpret_cast<const byte*>(m_iso_8859_str.data()); - const size_t rep_len = m_iso_8859_str.size(); - - for(size_t i = 0; i != rep_len; ++i) - { - if((rep[i] < 0x20) || ((rep[i] >= 0x7F) && (rep[i] < 0xA0))) - return false; - } - - return true; - } - -bool operator==(const ASN1_EAC_String& lhs, const ASN1_EAC_String& rhs) - { - return (lhs.iso_8859() == rhs.iso_8859()); - } - -ASN1_Car::ASN1_Car(std::string const& str) - : ASN1_EAC_String(str, ASN1_Tag(2)) - {} - -ASN1_Chr::ASN1_Chr(std::string const& str) - : ASN1_EAC_String(str, ASN1_Tag(32)) - {} - -} diff --git a/src/lib/cert/cvc/asn1_eac_tm.cpp b/src/lib/cert/cvc/asn1_eac_tm.cpp deleted file mode 100644 index 9c65fcf6a..000000000 --- a/src/lib/cert/cvc/asn1_eac_tm.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* -* EAC Time Types -* (C) 2007 FlexSecure GmbH -* 2008-2009 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/eac_asn_obj.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/charset.h> -#include <botan/parsing.h> -#include <botan/internal/rounding.h> -#include <botan/calendar.h> -#include <sstream> -#include <iomanip> - -namespace Botan { - -namespace { - -std::vector<byte> enc_two_digit(u32bit in) - { - std::vector<byte> result; - in %= 100; - if(in < 10) - result.push_back(0x00); - else - { - u32bit y_first_pos = round_down<u32bit>(in, 10) / 10; - result.push_back(static_cast<byte>(y_first_pos)); - } - - u32bit y_sec_pos = in % 10; - result.push_back(static_cast<byte>(y_sec_pos)); - return result; - } - -u32bit dec_two_digit(byte b1, byte b2) - { - u32bit upper = b1; - u32bit lower = b2; - - if(upper > 9 || lower > 9) - throw Invalid_Argument("CVC dec_two_digit value too large"); - - return upper*10 + lower; - } - -} - -/* -* Create an EAC_Time -*/ -EAC_Time::EAC_Time(const std::chrono::system_clock::time_point& time, - ASN1_Tag t) : m_tag(t) - { - calendar_point cal = calendar_value(time); - - m_year = cal.year; - m_month = cal.month; - m_day = cal.day; - } - -/* -* Create an EAC_Time -*/ -EAC_Time::EAC_Time(const std::string& t_spec, ASN1_Tag t) : m_tag(t) - { - set_to(t_spec); - } - -/* -* Create an EAC_Time -*/ -EAC_Time::EAC_Time(u32bit y, u32bit m, u32bit d, ASN1_Tag t) : - m_year(y), m_month(m), m_day(d), m_tag(t) - { - } - -/* -* Set the time with a human readable string -*/ -void EAC_Time::set_to(const std::string& time_str) - { - if(time_str == "") - { - m_year = m_month = m_day = 0; - return; - } - - std::vector<std::string> params; - std::string current; - - for(u32bit j = 0; j != time_str.size(); ++j) - { - if(Charset::is_digit(time_str[j])) - current += time_str[j]; - else - { - if(current != "") - params.push_back(current); - current.clear(); - } - } - if(current != "") - params.push_back(current); - - if(params.size() != 3) - throw Invalid_Argument("Invalid time specification " + time_str); - - m_year = to_u32bit(params[0]); - m_month = to_u32bit(params[1]); - m_day = to_u32bit(params[2]); - - if(!passes_sanity_check()) - throw Invalid_Argument("Invalid time specification " + time_str); - } - - -/* -* DER encode a EAC_Time -*/ -void EAC_Time::encode_into(DER_Encoder& der) const - { - der.add_object(m_tag, APPLICATION, - encoded_eac_time()); - } - -/* -* Return a string representation of the time -*/ -std::string EAC_Time::as_string() const - { - if(time_is_set() == false) - throw Invalid_State("EAC_Time::as_string: No time set"); - - return std::to_string(m_year * 10000 + m_month * 100 + m_day); - } - -/* -* Return if the time has been set somehow -*/ -bool EAC_Time::time_is_set() const - { - return (m_year != 0); - } - -/* -* Return a human readable string representation -*/ -std::string EAC_Time::readable_string() const - { - if(time_is_set() == false) - throw Invalid_State("EAC_Time::readable_string: No time set"); - - // desired format: "%04d/%02d/%02d" - std::stringstream output; - output << std::setfill('0') - << std::setw(4) << m_year << "/" - << std::setw(2) << m_month << "/" - << std::setw(2) << m_day; - return output.str(); - } - -/* -* Do a general sanity check on the time -*/ -bool EAC_Time::passes_sanity_check() const - { - if(m_year < 2000 || m_year > 2099) - return false; - if(m_month == 0 || m_month > 12) - return false; - if(m_day == 0 || m_day > 31) - return false; - - return true; - } - -/* -* modification functions -*/ -void EAC_Time::add_years(u32bit years) - { - m_year += years; - } - -void EAC_Time::add_months(u32bit months) - { - m_year += months/12; - m_month += months % 12; - if(m_month > 12) - { - m_year += 1; - m_month -= 12; - } - } - -/* -* Compare this time against another -*/ -s32bit EAC_Time::cmp(const EAC_Time& other) const - { - if(time_is_set() == false) - throw Invalid_State("EAC_Time::cmp: No time set"); - - const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0; - - if(m_year < other.m_year) return EARLIER; - if(m_year > other.m_year) return LATER; - if(m_month < other.m_month) return EARLIER; - if(m_month > other.m_month) return LATER; - if(m_day < other.m_day) return EARLIER; - if(m_day > other.m_day) return LATER; - - return SAME_TIME; - } - -/* -* Compare two EAC_Times for in various ways -*/ -bool operator==(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) == 0); - } - -bool operator!=(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) != 0); - } - -bool operator<=(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) <= 0); - } - -bool operator>=(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) >= 0); - } - -bool operator>(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) > 0); - } - -bool operator<(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) < 0); - } - -/* -* Decode a BER encoded EAC_Time -*/ -void EAC_Time::decode_from(BER_Decoder& source) - { - BER_Object obj = source.get_next_object(); - - if(obj.type_tag != m_tag) - throw BER_Decoding_Error("Tag mismatch when decoding"); - - if(obj.value.size() != 6) - { - throw Decoding_Error("EAC_Time decoding failed"); - } - - try - { - u32bit tmp_year = dec_two_digit(obj.value[0], obj.value[1]); - u32bit tmp_mon = dec_two_digit(obj.value[2], obj.value[3]); - u32bit tmp_day = dec_two_digit(obj.value[4], obj.value[5]); - m_year = tmp_year + 2000; - m_month = tmp_mon; - m_day = tmp_day; - } - catch (Invalid_Argument) - { - throw Decoding_Error("EAC_Time decoding failed"); - } - - } - -/* -* make the value an octet string for encoding -*/ -std::vector<byte> EAC_Time::encoded_eac_time() const - { - std::vector<byte> result; - result += enc_two_digit(m_year); - result += enc_two_digit(m_month); - result += enc_two_digit(m_day); - return result; - } - -} diff --git a/src/lib/cert/cvc/cvc_ado.cpp b/src/lib/cert/cvc/cvc_ado.cpp deleted file mode 100644 index f803c6bf3..000000000 --- a/src/lib/cert/cvc/cvc_ado.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* -* CVC Certificate Constructor -* (C) 2007 FlexSecure GmbH -* 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/cvc_ado.h> -#include <fstream> - -namespace Botan { - -EAC1_1_ADO::EAC1_1_ADO(DataSource& in) - { - init(in); - do_decode(); - } - -EAC1_1_ADO::EAC1_1_ADO(const std::string& in) - { - DataSource_Stream stream(in, true); - init(stream); - do_decode(); - } - -void EAC1_1_ADO::force_decode() - { - std::vector<byte> inner_cert; - BER_Decoder(m_tbs_bits) - .start_cons(ASN1_Tag(33)) - .raw_bytes(inner_cert) - .end_cons() - .decode(m_car) - .verify_end(); - - std::vector<byte> req_bits = DER_Encoder() - .start_cons(ASN1_Tag(33), APPLICATION) - .raw_bytes(inner_cert) - .end_cons() - .get_contents_unlocked(); - - DataSource_Memory req_source(req_bits); - m_req = EAC1_1_Req(req_source); - m_sig_algo = m_req.m_sig_algo; - } - -std::vector<byte> EAC1_1_ADO::make_signed(PK_Signer& signer, - const std::vector<byte>& tbs_bits, - RandomNumberGenerator& rng) - { - const std::vector<byte> concat_sig = signer.sign_message(tbs_bits, rng); - - return DER_Encoder() - .start_cons(ASN1_Tag(7), APPLICATION) - .raw_bytes(tbs_bits) - .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons() - .get_contents_unlocked(); - } - -ASN1_Car EAC1_1_ADO::get_car() const - { - return m_car; - } - -void EAC1_1_ADO::decode_info(DataSource& source, - std::vector<byte> & res_tbs_bits, - ECDSA_Signature & res_sig) - { - std::vector<byte> concat_sig; - std::vector<byte> cert_inner_bits; - ASN1_Car car; - - BER_Decoder(source) - .start_cons(ASN1_Tag(7)) - .start_cons(ASN1_Tag(33)) - .raw_bytes(cert_inner_bits) - .end_cons() - .decode(car) - .decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons(); - - std::vector<byte> enc_cert = DER_Encoder() - .start_cons(ASN1_Tag(33), APPLICATION) - .raw_bytes(cert_inner_bits) - .end_cons() - .get_contents_unlocked(); - - res_tbs_bits = enc_cert; - res_tbs_bits += DER_Encoder().encode(car).get_contents(); - res_sig = decode_concatenation(concat_sig); - } - -void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const - { - if(encoding == PEM) - throw Invalid_Argument("EAC1_1_ADO::encode() cannot PEM encode an EAC object"); - - auto concat_sig = EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation(); - - out.write(DER_Encoder() - .start_cons(ASN1_Tag(7), APPLICATION) - .raw_bytes(m_tbs_bits) - .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons() - .get_contents()); - } - -std::vector<byte> EAC1_1_ADO::tbs_data() const - { - return m_tbs_bits; - } - -bool EAC1_1_ADO::operator==(EAC1_1_ADO const& rhs) const - { - return (this->get_concat_sig() == rhs.get_concat_sig() - && this->tbs_data() == rhs.tbs_data() - && this->get_car() == rhs.get_car()); - } - -EAC1_1_Req EAC1_1_ADO::get_request() const - { - return m_req; - } - -} diff --git a/src/lib/cert/cvc/cvc_ado.h b/src/lib/cert/cvc/cvc_ado.h deleted file mode 100644 index 4b861ec81..000000000 --- a/src/lib/cert/cvc/cvc_ado.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -* EAC1_1 CVC ADO -* (C) 2008 Falko Strenzke -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_CVC_ADO_H__ -#define BOTAN_EAC_CVC_ADO_H__ - -#include <botan/eac_obj.h> -#include <botan/eac_asn_obj.h> -#include <botan/cvc_req.h> -#include <string> - -namespace Botan { - -/** -* This class represents a TR03110 (EAC) v1.1 CVC ADO request -*/ - - // CRTP continuation from EAC1_1_obj -class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO> - { - public: - friend class EAC1_1_obj<EAC1_1_ADO>; - - /** - * Construct a CVC ADO request from a DER encoded CVC ADO request file. - * @param str the path to the DER encoded file - */ - EAC1_1_ADO(const std::string& str); - - /** - * Construct a CVC ADO request from a data source - * @param source the data source - */ - EAC1_1_ADO(DataSource& source); - - /** - * Create a signed CVC ADO request from to be signed (TBS) data - * @param signer the signer used to sign the CVC ADO request - * @param tbs_bits the TBS data to sign - * @param rng a random number generator - */ - static std::vector<byte> make_signed( - PK_Signer& signer, - const std::vector<byte>& tbs_bits, - RandomNumberGenerator& rng); - - /** - * Get the CAR of this CVC ADO request - * @result the CAR of this CVC ADO request - */ - ASN1_Car get_car() const; - - /** - * Get the CVC request contained in this object. - * @result the CVC request inside this CVC ADO request - */ - EAC1_1_Req get_request() const; - - /** - * Encode this object into a pipe. Only DER is supported. - * @param out the pipe to encode this object into - * @param encoding the encoding type to use, must be DER - */ - void encode(Pipe& out, X509_Encoding encoding) const; - - bool operator==(EAC1_1_ADO const& rhs) const; - - /** - * Get the TBS data of this CVC ADO request. - * @result the TBS data - */ - std::vector<byte> tbs_data() const; - - virtual ~EAC1_1_ADO() {} - private: - ASN1_Car m_car; - EAC1_1_Req m_req; - - void force_decode(); - static void decode_info(DataSource& source, - std::vector<byte> & res_tbs_bits, - ECDSA_Signature & res_sig); - }; - -inline bool operator!=(EAC1_1_ADO const& lhs, EAC1_1_ADO const& rhs) - { - return (!(lhs == rhs)); - } - -} - -#endif - - diff --git a/src/lib/cert/cvc/cvc_cert.cpp b/src/lib/cert/cvc/cvc_cert.cpp deleted file mode 100644 index 280a8acda..000000000 --- a/src/lib/cert/cvc/cvc_cert.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* -* (C) 2007 FlexSecure GmbH -* 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/cvc_cert.h> -#include <botan/oids.h> - -namespace Botan { - -ASN1_Car EAC1_1_CVC::get_car() const - { - return m_car; - } - -ASN1_Ced EAC1_1_CVC::get_ced() const - { - return m_ced; - } -ASN1_Cex EAC1_1_CVC::get_cex() const - { - return m_cex; - } -u32bit EAC1_1_CVC::get_chat_value() const - { - return m_chat_val; - } - -/* -* Decode the TBSCertificate data -*/ -void EAC1_1_CVC::force_decode() - { - std::vector<byte> enc_pk; - std::vector<byte> enc_chat_val; - size_t cpi; - BER_Decoder tbs_cert(m_tbs_bits); - tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION) - .decode(m_car) - .start_cons(ASN1_Tag(73)) - .raw_bytes(enc_pk) - .end_cons() - .decode(m_chr) - .start_cons(ASN1_Tag(76)) - .decode(m_chat_oid) - .decode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) - .end_cons() - .decode(m_ced) - .decode(m_cex) - .verify_end(); - - if(enc_chat_val.size() != 1) - throw Decoding_Error("CertificateHolderAuthorizationValue was not of length 1"); - - if(cpi != 0) - throw Decoding_Error("EAC1_1 certificate's cpi was not 0"); - - m_pk = decode_eac1_1_key(enc_pk, m_sig_algo); - - m_chat_val = enc_chat_val[0]; - - m_self_signed = (m_car.iso_8859() == m_chr.iso_8859()); - } - -/* -* CVC Certificate Constructor -*/ -EAC1_1_CVC::EAC1_1_CVC(DataSource& in) - { - init(in); - m_self_signed = false; - do_decode(); - } - -EAC1_1_CVC::EAC1_1_CVC(const std::string& in) - { - DataSource_Stream stream(in, true); - init(stream); - m_self_signed = false; - do_decode(); - } - -bool EAC1_1_CVC::operator==(EAC1_1_CVC const& rhs) const - { - return (tbs_data() == rhs.tbs_data() - && get_concat_sig() == rhs.get_concat_sig()); - } - -ECDSA_PublicKey* decode_eac1_1_key(const std::vector<byte>&, - AlgorithmIdentifier&) - { - throw Internal_Error("decode_eac1_1_key: Unimplemented"); - return 0; - } - -EAC1_1_CVC make_cvc_cert(PK_Signer& signer, - const std::vector<byte>& public_key, - ASN1_Car const& car, - ASN1_Chr const& chr, - byte holder_auth_templ, - ASN1_Ced ced, - ASN1_Cex cex, - RandomNumberGenerator& rng) - { - OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); - std::vector<byte> enc_chat_val; - enc_chat_val.push_back(holder_auth_templ); - - std::vector<byte> enc_cpi; - enc_cpi.push_back(0x00); - std::vector<byte> tbs = DER_Encoder() - .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi - .encode(car) - .raw_bytes(public_key) - .encode(chr) - .start_cons(ASN1_Tag(76), APPLICATION) - .encode(chat_oid) - .encode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) - .end_cons() - .encode(ced) - .encode(cex) - .get_contents_unlocked(); - - std::vector<byte> signed_cert = - EAC1_1_CVC::make_signed(signer, - EAC1_1_CVC::build_cert_body(tbs), - rng); - - DataSource_Memory source(signed_cert); - return EAC1_1_CVC(source); - } - -} diff --git a/src/lib/cert/cvc/cvc_cert.h b/src/lib/cert/cvc/cvc_cert.h deleted file mode 100644 index a45388550..000000000 --- a/src/lib/cert/cvc/cvc_cert.h +++ /dev/null @@ -1,116 +0,0 @@ -/* -* EAC1_1 CVC -* (C) 2008 Falko Strenzke -* 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_CVC_EAC_H__ -#define BOTAN_CVC_EAC_H__ - -#include <botan/cvc_gen_cert.h> -#include <botan/ecdsa.h> -#include <string> - -namespace Botan { - -/** -* This class represents TR03110 (EAC) v1.1 CV Certificates -*/ -class BOTAN_DLL EAC1_1_CVC : public EAC1_1_gen_CVC<EAC1_1_CVC>//Signed_Object - { - public: - friend class EAC1_1_obj<EAC1_1_CVC>; - - /** - * Get the CAR of the certificate. - * @result the CAR of the certificate - */ - ASN1_Car get_car() const; - - /** - * Get the CED of this certificate. - * @result the CED this certificate - */ - ASN1_Ced get_ced() const; - - /** - * Get the CEX of this certificate. - * @result the CEX this certificate - */ - ASN1_Cex get_cex() const; - - /** - * Get the CHAT value. - * @result the CHAT value - */ - u32bit get_chat_value() const; - - bool operator==(const EAC1_1_CVC&) const; - - /** - * Construct a CVC from a data source - * @param source the data source - */ - EAC1_1_CVC(DataSource& source); - - /** - * Construct a CVC from a file - * @param str the path to the certificate file - */ - EAC1_1_CVC(const std::string& str); - - virtual ~EAC1_1_CVC() {} - private: - void force_decode(); - EAC1_1_CVC() {} - - ASN1_Car m_car; - ASN1_Ced m_ced; - ASN1_Cex m_cex; - byte m_chat_val; - OID m_chat_oid; - }; - -/* -* Comparison -*/ -inline bool operator!=(EAC1_1_CVC const& lhs, EAC1_1_CVC const& rhs) - { - return !(lhs == rhs); - } - -/** -* Create an arbitrary EAC 1.1 CVC. -* The desired key encoding must be set within the key (if applicable). -* @param signer the signer used to sign the certificate -* @param public_key the DER encoded public key to appear in -* the certificate -* @param car the CAR of the certificate -* @param chr the CHR of the certificate -* @param holder_auth_templ the holder authorization value byte to -* appear in the CHAT of the certificate -* @param ced the CED to appear in the certificate -* @param cex the CEX to appear in the certificate -* @param rng a random number generator -*/ -EAC1_1_CVC BOTAN_DLL make_cvc_cert(PK_Signer& signer, - const std::vector<byte>& public_key, - ASN1_Car const& car, - ASN1_Chr const& chr, - byte holder_auth_templ, - ASN1_Ced ced, - ASN1_Cex cex, - RandomNumberGenerator& rng); - -/** -* Decode an EAC encoding ECDSA key -*/ -BOTAN_DLL ECDSA_PublicKey* decode_eac1_1_key(const std::vector<byte>& enc_key, - AlgorithmIdentifier& sig_algo); - -} - -#endif - diff --git a/src/lib/cert/cvc/cvc_gen_cert.h b/src/lib/cert/cvc/cvc_gen_cert.h deleted file mode 100644 index 2c3bca73d..000000000 --- a/src/lib/cert/cvc/cvc_gen_cert.h +++ /dev/null @@ -1,180 +0,0 @@ -/* -* EAC1_1 general CVC -* (C) 2008 Falko Strenzke -* 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_CVC_GEN_CERT_H__ -#define BOTAN_EAC_CVC_GEN_CERT_H__ - -#include <botan/eac_obj.h> -#include <botan/eac_asn_obj.h> -#include <botan/ecdsa.h> -#include <botan/pubkey.h> - -namespace Botan { - -/** -* This class represents TR03110 (EAC) v1.1 generalized CV Certificates -*/ -template<typename Derived> -class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1_1_obj - { - friend class EAC1_1_obj<EAC1_1_gen_CVC>; - - public: - - /** - * Get this certificates public key. - * @result this certificates public key - */ - Public_Key* subject_public_key() const; - - /** - * Find out whether this object is self signed. - * @result true if this object is self signed - */ - bool is_self_signed() const; - - /** - * Get the CHR of the certificate. - * @result the CHR of the certificate - */ - ASN1_Chr get_chr() const; - - /** - * Put the DER encoded version of this object into a pipe. PEM - * is not supported. - * @param out the pipe to push the DER encoded version into - * @param encoding the encoding to use. Must be DER. - */ - void encode(Pipe& out, X509_Encoding encoding) const; - - /** - * Get the to-be-signed (TBS) data of this object. - * @result the TBS data of this object - */ - std::vector<byte> tbs_data() const; - - /** - * Build the DER encoded certifcate body of an object - * @param tbs the data to be signed - * @result the correctly encoded body of the object - */ - static std::vector<byte> build_cert_body(const std::vector<byte>& tbs); - - /** - * Create a signed generalized CVC object. - * @param signer the signer used to sign this object - * @param tbs_bits the body the generalized CVC object to be signed - * @param rng a random number generator - * @result the DER encoded signed generalized CVC object - */ - static std::vector<byte> make_signed( - PK_Signer& signer, - const std::vector<byte>& tbs_bits, - RandomNumberGenerator& rng); - - EAC1_1_gen_CVC() { m_pk = nullptr; } - - virtual ~EAC1_1_gen_CVC<Derived>() - { delete m_pk; } - - protected: - ECDSA_PublicKey* m_pk; - ASN1_Chr m_chr; - bool m_self_signed; - - static void decode_info(DataSource& source, - std::vector<byte> & res_tbs_bits, - ECDSA_Signature & res_sig); - - }; - -template<typename Derived> ASN1_Chr EAC1_1_gen_CVC<Derived>::get_chr() const - { - return m_chr; - } - -template<typename Derived> bool EAC1_1_gen_CVC<Derived>::is_self_signed() const - { - return m_self_signed; - } - -template<typename Derived> -std::vector<byte> EAC1_1_gen_CVC<Derived>::make_signed( - PK_Signer& signer, - const std::vector<byte>& tbs_bits, - RandomNumberGenerator& rng) // static - { - const auto concat_sig = signer.sign_message(tbs_bits, rng); - - return DER_Encoder() - .start_cons(ASN1_Tag(33), APPLICATION) - .raw_bytes(tbs_bits) - .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons() - .get_contents_unlocked(); - } - -template<typename Derived> -Public_Key* EAC1_1_gen_CVC<Derived>::subject_public_key() const - { - return new ECDSA_PublicKey(*m_pk); - } - -template<typename Derived> std::vector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(const std::vector<byte>& tbs) - { - return DER_Encoder() - .start_cons(ASN1_Tag(78), APPLICATION) - .raw_bytes(tbs) - .end_cons().get_contents_unlocked(); - } - -template<typename Derived> std::vector<byte> EAC1_1_gen_CVC<Derived>::tbs_data() const - { - return build_cert_body(EAC1_1_obj<Derived>::m_tbs_bits); - } - -template<typename Derived> void EAC1_1_gen_CVC<Derived>::encode(Pipe& out, X509_Encoding encoding) const - { - std::vector<byte> concat_sig(EAC1_1_obj<Derived>::m_sig.get_concatenation()); - std::vector<byte> der = DER_Encoder() - .start_cons(ASN1_Tag(33), APPLICATION) - .start_cons(ASN1_Tag(78), APPLICATION) - .raw_bytes(EAC1_1_obj<Derived>::m_tbs_bits) - .end_cons() - .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons() - .get_contents_unlocked(); - - if (encoding == PEM) - throw Invalid_Argument("EAC1_1_gen_CVC::encode() cannot PEM encode an EAC object"); - else - out.write(der); - } - -template<typename Derived> -void EAC1_1_gen_CVC<Derived>::decode_info( - DataSource& source, - std::vector<byte> & res_tbs_bits, - ECDSA_Signature & res_sig) - { - std::vector<byte> concat_sig; - BER_Decoder(source) - .start_cons(ASN1_Tag(33)) - .start_cons(ASN1_Tag(78)) - .raw_bytes(res_tbs_bits) - .end_cons() - .decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons(); - res_sig = decode_concatenation(concat_sig); - } - -} - -#endif - - diff --git a/src/lib/cert/cvc/cvc_req.cpp b/src/lib/cert/cvc/cvc_req.cpp deleted file mode 100644 index 1cb6b50ac..000000000 --- a/src/lib/cert/cvc/cvc_req.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -* (C) 2007 FlexSecure GmbH -* 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/cvc_req.h> -#include <botan/cvc_cert.h> -#include <botan/ber_dec.h> - -namespace Botan { - -bool EAC1_1_Req::operator==(EAC1_1_Req const& rhs) const - { - return (this->tbs_data() == rhs.tbs_data() && - this->get_concat_sig() == rhs.get_concat_sig()); - } - -void EAC1_1_Req::force_decode() - { - std::vector<byte> enc_pk; - BER_Decoder tbs_cert(m_tbs_bits); - size_t cpi; - tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION) - .start_cons(ASN1_Tag(73)) - .raw_bytes(enc_pk) - .end_cons() - .decode(m_chr) - .verify_end(); - - if(cpi != 0) - throw Decoding_Error("EAC1_1 requests cpi was not 0"); - - m_pk = decode_eac1_1_key(enc_pk, m_sig_algo); - } - -EAC1_1_Req::EAC1_1_Req(DataSource& in) - { - init(in); - m_self_signed = true; - do_decode(); - } - -EAC1_1_Req::EAC1_1_Req(const std::string& in) - { - DataSource_Stream stream(in, true); - init(stream); - m_self_signed = true; - do_decode(); - } - -} diff --git a/src/lib/cert/cvc/cvc_req.h b/src/lib/cert/cvc/cvc_req.h deleted file mode 100644 index b71a8e764..000000000 --- a/src/lib/cert/cvc/cvc_req.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* EAC1_1 CVC Request -* (C) 2008 Falko Strenzke -* 2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_CVC_REQ_H__ -#define BOTAN_EAC_CVC_REQ_H__ - -#include <botan/cvc_gen_cert.h> - -namespace Botan { - -/** -* This class represents TR03110 v1.1 EAC CV Certificate Requests. -*/ -class BOTAN_DLL EAC1_1_Req : public EAC1_1_gen_CVC<EAC1_1_Req> - { - public: - friend class EAC1_1_ADO; - friend class EAC1_1_obj<EAC1_1_Req>; - - /** - * Compare for equality with other - * @param other compare for equality with this object - */ - bool operator==(const EAC1_1_Req& other) const; - - /** - * Construct a CVC request from a data source. - * @param source the data source - */ - EAC1_1_Req(DataSource& source); - - /** - * Construct a CVC request from a DER encoded CVC request file. - * @param str the path to the DER encoded file - */ - EAC1_1_Req(const std::string& str); - - virtual ~EAC1_1_Req(){} - private: - void force_decode(); - EAC1_1_Req() {} - }; - -/* -* Comparison Operator -*/ -inline bool operator!=(EAC1_1_Req const& lhs, EAC1_1_Req const& rhs) - { - return !(lhs == rhs); - } - -} - -#endif diff --git a/src/lib/cert/cvc/cvc_self.cpp b/src/lib/cert/cvc/cvc_self.cpp deleted file mode 100644 index fdc66bbfd..000000000 --- a/src/lib/cert/cvc/cvc_self.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* -* (C) 2007 FlexSecure GmbH -* 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/cvc_self.h> -#include <botan/ecc_key.h> -#include <botan/point_gfp.h> -#include <botan/oids.h> -#include <sstream> - -namespace Botan { - -namespace { - -/* -* cvc CHAT values -*/ -enum CHAT_values{ - CVCA = 0xC0, - DVCA_domestic = 0x80, - DVCA_foreign = 0x40, - IS = 0x00, - - IRIS = 0x02, - FINGERPRINT = 0x01 -}; - -void encode_eac_bigint(DER_Encoder& der, const BigInt& x, ASN1_Tag tag) - { - der.encode(BigInt::encode_1363(x, x.bytes()), OCTET_STRING, tag); - } - -std::vector<byte> eac_1_1_encoding(const EC_PublicKey* key, - const OID& sig_algo) - { - if(key->domain_format() == EC_DOMPAR_ENC_OID) - throw Encoding_Error("CVC encoder: cannot encode parameters by OID"); - - const EC_Group& domain = key->domain(); - - // This is why we can't have nice things - - DER_Encoder enc; - enc.start_cons(ASN1_Tag(73), APPLICATION) - .encode(sig_algo); - - if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT) - { - encode_eac_bigint(enc, domain.get_curve().get_p(), ASN1_Tag(1)); - encode_eac_bigint(enc, domain.get_curve().get_a(), ASN1_Tag(2)); - encode_eac_bigint(enc, domain.get_curve().get_b(), ASN1_Tag(3)); - - enc.encode(EC2OSP(domain.get_base_point(), PointGFp::UNCOMPRESSED), - OCTET_STRING, ASN1_Tag(4)); - - encode_eac_bigint(enc, domain.get_order(), ASN1_Tag(4)); - } - - enc.encode(EC2OSP(key->public_point(), PointGFp::UNCOMPRESSED), - OCTET_STRING, ASN1_Tag(6)); - - if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT) - encode_eac_bigint(enc, domain.get_cofactor(), ASN1_Tag(7)); - - enc.end_cons(); - - return enc.get_contents_unlocked(); - } - -std::string padding_and_hash_from_oid(OID const& oid) - { - std::string padding_and_hash = OIDS::lookup(oid); // use the hash - - if(padding_and_hash.substr(0,6) != "ECDSA/") - throw Invalid_State("CVC: Can only use ECDSA, not " + padding_and_hash); - - padding_and_hash.erase(0, padding_and_hash.find("/") + 1); - return padding_and_hash; - } - -} - -namespace CVC_EAC { - -EAC1_1_CVC create_self_signed_cert(Private_Key const& key, - EAC1_1_CVC_Options const& opt, - RandomNumberGenerator& rng) - { - // NOTE: we ignore the value of opt.chr - - const ECDSA_PrivateKey* priv_key = dynamic_cast<const ECDSA_PrivateKey*>(&key); - - if(priv_key == 0) - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - - ASN1_Chr chr(opt.car.value()); - - AlgorithmIdentifier sig_algo; - std::string padding_and_hash("EMSA1_BSI(" + opt.hash_alg + ")"); - sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash); - sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); - - PK_Signer signer(*priv_key, padding_and_hash); - - std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); - - return make_cvc_cert(signer, - enc_public_key, - opt.car, chr, - opt.holder_auth_templ, - opt.ced, opt.cex, rng); - } - -EAC1_1_Req create_cvc_req(Private_Key const& key, - ASN1_Chr const& chr, - std::string const& hash_alg, - RandomNumberGenerator& rng) - { - - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - AlgorithmIdentifier sig_algo; - std::string padding_and_hash("EMSA1_BSI(" + hash_alg + ")"); - sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash); - sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); - - PK_Signer signer(*priv_key, padding_and_hash); - - std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); - - std::vector<byte> enc_cpi; - enc_cpi.push_back(0x00); - std::vector<byte> tbs = DER_Encoder() - .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) - .raw_bytes(enc_public_key) - .encode(chr) - .get_contents_unlocked(); - - std::vector<byte> signed_cert = - EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(signer, - EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs), - rng); - - DataSource_Memory source(signed_cert); - return EAC1_1_Req(source); - } - -EAC1_1_ADO create_ado_req(Private_Key const& key, - EAC1_1_Req const& req, - ASN1_Car const& car, - RandomNumberGenerator& rng) - { - - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - - std::string padding_and_hash = padding_and_hash_from_oid(req.signature_algorithm().oid); - PK_Signer signer(*priv_key, padding_and_hash); - std::vector<byte> tbs_bits = req.BER_encode(); - tbs_bits += DER_Encoder().encode(car).get_contents(); - - std::vector<byte> signed_cert = - EAC1_1_ADO::make_signed(signer, tbs_bits, rng); - - DataSource_Memory source(signed_cert); - return EAC1_1_ADO(source); - } - -} // namespace CVC_EAC -namespace DE_EAC -{ - -EAC1_1_CVC create_cvca(Private_Key const& key, - std::string const& hash, - ASN1_Car const& car, bool iris, bool fingerpr, - u32bit cvca_validity_months, - RandomNumberGenerator& rng) - { - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - EAC1_1_CVC_Options opts; - opts.car = car; - - opts.ced = ASN1_Ced(std::chrono::system_clock::now()); - opts.cex = ASN1_Cex(opts.ced); - opts.cex.add_months(cvca_validity_months); - opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT)); - opts.hash_alg = hash; - return CVC_EAC::create_self_signed_cert(*priv_key, opts, rng); - } - - - -EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer, - Private_Key const& key, - EAC1_1_CVC const& signee, - RandomNumberGenerator& rng) - { - const ECDSA_PrivateKey* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - - if (priv_key == 0) - throw Invalid_Argument("link_cvca(): unsupported key type"); - - ASN1_Ced ced(std::chrono::system_clock::now()); - ASN1_Cex cex(signee.get_cex()); - if (*static_cast<EAC_Time*>(&ced) > *static_cast<EAC_Time*>(&cex)) - { - std::string detail("link_cvca(): validity periods of provided certificates don't overlap: currend time = ced = "); - detail += ced.as_string(); - detail += ", signee.cex = "; - detail += cex.as_string(); - throw Invalid_Argument(detail); - } - if (signer.signature_algorithm() != signee.signature_algorithm()) - { - throw Invalid_Argument("link_cvca(): signature algorithms of signer and signee don't match"); - } - AlgorithmIdentifier sig_algo = signer.signature_algorithm(); - std::string padding_and_hash = padding_and_hash_from_oid(sig_algo.oid); - PK_Signer pk_signer(*priv_key, padding_and_hash); - std::unique_ptr<Public_Key> pk(signee.subject_public_key()); - ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); - subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_EXPLICIT); - - std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); - - return make_cvc_cert(pk_signer, enc_public_key, - signer.get_car(), - signee.get_chr(), - signer.get_chat_value(), - ced, cex, - rng); - } - -EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, - Private_Key const& key, - EAC1_1_Req const& signee, - u32bit seqnr, - u32bit seqnr_len, - bool domestic, - u32bit dvca_validity_months, - u32bit ca_is_validity_months, - RandomNumberGenerator& rng) - { - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - std::string chr_str = signee.get_chr().value(); - - std::string seqnr_string = std::to_string(seqnr); - - while(seqnr_string.size() < seqnr_len) - seqnr_string = '0' + seqnr_string; - - chr_str += seqnr_string; - ASN1_Chr chr(chr_str); - std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid); - PK_Signer pk_signer(*priv_key, padding_and_hash); - std::unique_ptr<Public_Key> pk(signee.subject_public_key()); - ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); - std::unique_ptr<Public_Key> signer_pk(signer_cert.subject_public_key()); - - // for the case that the domain parameters are not set... - // (we use those from the signer because they must fit) - //subj_pk->set_domain_parameters(priv_key->domain_parameters()); - - subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - - AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm()); - - ASN1_Ced ced(std::chrono::system_clock::now()); - - u32bit chat_val; - u32bit chat_low = signer_cert.get_chat_value() & 0x3; // take the chat rights from signer - ASN1_Cex cex(ced); - if ((signer_cert.get_chat_value() & CVCA) == CVCA) - { - // we sign a dvca - cex.add_months(dvca_validity_months); - if (domestic) - chat_val = DVCA_domestic | chat_low; - else - chat_val = DVCA_foreign | chat_low; - } - else if ((signer_cert.get_chat_value() & DVCA_domestic) == DVCA_domestic || - (signer_cert.get_chat_value() & DVCA_foreign) == DVCA_foreign) - { - cex.add_months(ca_is_validity_months); - chat_val = IS | chat_low; - } - else - { - throw Invalid_Argument("sign_request(): encountered illegal value for CHAT"); - // (IS cannot sign certificates) - } - - std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); - - return make_cvc_cert(pk_signer, enc_public_key, - ASN1_Car(signer_cert.get_chr().iso_8859()), - chr, - chat_val, - ced, - cex, - rng); - } - -EAC1_1_Req create_cvc_req(Private_Key const& prkey, - ASN1_Chr const& chr, - std::string const& hash_alg, - RandomNumberGenerator& rng) - { - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&prkey); - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - ECDSA_PrivateKey key(*priv_key); - key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - return CVC_EAC::create_cvc_req(key, chr, hash_alg, rng); - } - -} // namespace DE_EAC - -} diff --git a/src/lib/cert/cvc/cvc_self.h b/src/lib/cert/cvc/cvc_self.h deleted file mode 100644 index d56e96c40..000000000 --- a/src/lib/cert/cvc/cvc_self.h +++ /dev/null @@ -1,180 +0,0 @@ -/* -* CVC Self-Signed Certificate -* (C) 2007 FlexSecure GmbH -* 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_CVC_EAC_SELF_H__ -#define BOTAN_CVC_EAC_SELF_H__ - -#include <botan/cvc_cert.h> -#include <botan/ecdsa.h> -#include <botan/asn1_obj.h> -#include <botan/cvc_req.h> -#include <botan/cvc_ado.h> - -namespace Botan { - -/** -* This class represents a set of options used for the creation of CVC certificates -*/ -class BOTAN_DLL EAC1_1_CVC_Options - { - public: - - // public member variable: - ASN1_Car car; - - // public member variable: - ASN1_Chr chr; - - // public member variable: - byte holder_auth_templ; - - // public member variable: - ASN1_Ced ced; - - // public member variable: - ASN1_Cex cex; - - // public member variable: - std::string hash_alg; - }; - -/** -* This namespace represents general EAC 1.1 convenience functions. -*/ -namespace CVC_EAC { - -/** -* Create a selfsigned CVCA -* @param rng the rng to use -* @param key the ECDSA private key to be used to sign the certificate -* @param opts used to set several parameters. Necessary are: -* car, holder_auth_templ, hash_alg, ced, cex and hash_alg -* @result the self signed certificate -*/ - -EAC1_1_CVC BOTAN_DLL create_self_signed_cert(Private_Key const& key, - EAC1_1_CVC_Options const& opts, - RandomNumberGenerator& rng); -/** -* Create a CVC request. The key encoding will be according to the provided private key. -* @param priv_key the private key associated with the requesting entity -* @param chr the chr to appear in the certificate (to be provided without -* sequence number) -* @param hash_alg the string defining the hash algorithm to be used for the creation -* of the signature -* @param rng the rng to use -* @result the new request -*/ -EAC1_1_Req BOTAN_DLL create_cvc_req(Private_Key const& priv_key, - ASN1_Chr const& chr, - std::string const& hash_alg, - RandomNumberGenerator& rng); - -/** -* Create an ADO from a request object. -* @param priv_key the private key used to sign the ADO -* @param req the request forming the body of the ADO -* @param car the CAR forming the body of the ADO, i.e. the -* CHR of the entity associated with the provided private key -* @param rng the rng to use -*/ -EAC1_1_ADO BOTAN_DLL create_ado_req(Private_Key const& priv_key, - EAC1_1_Req const& req, - ASN1_Car const& car, - RandomNumberGenerator& rng); -} -/** -* This namespace represents EAC 1.1 CVC convenience functions -* following the specific german requirements. -*/ - -namespace DE_EAC { - -/** -* Create a CVCA certificate. -* @param priv_key the private key associated with the CVCA certificate -* to be created -* @param hash the string identifying the hash algorithm to be used -* for signing the certificate to be created -* @param car the CAR of the certificate to be created -* @param iris indicates whether the entity associated with the certificate -* shall be entitled to read the biometrical iris image -* @param fingerpr indicates whether the entity associated with the certificate -* shall be entitled to read the biometrical fingerprint image -* @param cvca_validity_months length of time in months this will be valid -* @param rng a random number generator -* @result the CVCA certificate created -*/ -EAC1_1_CVC BOTAN_DLL create_cvca(Private_Key const& priv_key, - std::string const& hash, - ASN1_Car const& car, - bool iris, - bool fingerpr, - u32bit cvca_validity_months, - RandomNumberGenerator& rng); - -/** -* Create a link certificate between two CVCA certificates. The key -* encoding will be implicitCA. -* @param signer the cvca certificate associated with the signing -* entity -* @param priv_key the private key associated with the signer -* @param to_be_signed the certificate which whose CAR/CHR will be -* the holder of the link certificate -* @param rng a random number generator -*/ -EAC1_1_CVC BOTAN_DLL link_cvca(EAC1_1_CVC const& signer, - Private_Key const& priv_key, - EAC1_1_CVC const& to_be_signed, - RandomNumberGenerator& rng); - -/** -* Create a CVC request. The key encoding will be implicitCA. -* @param priv_key the private key associated with the requesting entity -* @param chr the chr to appear in the certificate (to be provided without -* sequence number) -* @param hash_alg the string defining the hash algorithm to be used for the creation -* of the signature -* @param rng a random number generator -* @result the new request -*/ -EAC1_1_Req BOTAN_DLL create_cvc_req(Private_Key const& priv_key, - ASN1_Chr const& chr, - std::string const& hash_alg, - RandomNumberGenerator& rng); - -/** -* Sign a CVC request. -* @param signer_cert the certificate of the signing entity -* @param priv_key the private key of the signing entity -* @param req the request to be signed -* @param seqnr the sequence number of the certificate to be created -* @param seqnr_len the number of digits the sequence number will be -* encoded in -* @param domestic indicates whether to sign a domestic or a foreign -* certificate: set to true for domestic -* @param dvca_validity_months validity period in months -* @param ca_is_validity_months validity period in months -* @param rng a random number generator -* @result the new certificate -* -**/ -EAC1_1_CVC BOTAN_DLL sign_request(EAC1_1_CVC const& signer_cert, - Private_Key const& priv_key, - EAC1_1_Req const& req, - u32bit seqnr, - u32bit seqnr_len, - bool domestic, - u32bit dvca_validity_months, - u32bit ca_is_validity_months, - RandomNumberGenerator& rng); -} - -} - -#endif diff --git a/src/lib/cert/cvc/eac_asn_obj.h b/src/lib/cert/cvc/eac_asn_obj.h deleted file mode 100644 index b4dcb6342..000000000 --- a/src/lib/cert/cvc/eac_asn_obj.h +++ /dev/null @@ -1,239 +0,0 @@ -/* -* EAC ASN.1 Objects -* (C) 2007-2008 FlexSecure GmbH -* 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_ASN1_OBJ_H__ -#define BOTAN_EAC_ASN1_OBJ_H__ - -#include <botan/asn1_obj.h> -#include <chrono> - -namespace Botan { - -/** -* This class represents CVC EAC Time objects. -* It only models year, month and day. Only limited sanity checks of -* the inputted date value are performed. -*/ -class BOTAN_DLL EAC_Time : public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - /** - * Get a this objects value as a string. - * @return date string - */ - std::string as_string() const; - - /** - * Get a this objects value as a readable formatted string. - * @return date string - */ - std::string readable_string() const; - - /** - * Find out whether this object's values have been set. - * @return true if this object's internal values are set - */ - bool time_is_set() const; - - /** - * Compare this to another EAC_Time object. - * @return -1 if this object's date is earlier than - * other, +1 in the opposite case, and 0 if both dates are - * equal. - */ - s32bit cmp(const EAC_Time& other) const; - - /** - * Set this' value by a string value. - * @param str a string in the format "yyyy mm dd", - * e.g. "2007 08 01" - */ - void set_to(const std::string& str); - - /** - * Add the specified number of years to this. - * @param years the number of years to add - */ - void add_years(u32bit years); - - /** - * Add the specified number of months to this. - * @param months the number of months to add - */ - void add_months(u32bit months); - - /** - * Get the year value of this objects. - * @return year value - */ - u32bit get_year() const { return m_year; } - - /** - * Get the month value of this objects. - * @return month value - */ - u32bit get_month() const { return m_month; } - - /** - * Get the day value of this objects. - * @return day value - */ - u32bit get_day() const { return m_day; } - - EAC_Time(const std::chrono::system_clock::time_point& time, - ASN1_Tag tag = ASN1_Tag(0)); - - EAC_Time(const std::string& yyyy_mm_dd, - ASN1_Tag tag = ASN1_Tag(0)); - - EAC_Time(u32bit year, u32bit month, u32bit day, - ASN1_Tag tag = ASN1_Tag(0)); - - virtual ~EAC_Time() {} - private: - std::vector<byte> encoded_eac_time() const; - bool passes_sanity_check() const; - u32bit m_year, m_month, m_day; - ASN1_Tag m_tag; - }; - -/** -* This class represents CVC CEDs. Only limited sanity checks of -* the inputted date value are performed. -*/ -class BOTAN_DLL ASN1_Ced : public EAC_Time - { - public: - /** - * Construct a CED from a string value. - * @param str a string in the format "yyyy mm dd", - * e.g. "2007 08 01" - */ - ASN1_Ced(const std::string& str = "") : - EAC_Time(str, ASN1_Tag(37)) {} - - /** - * Construct a CED from a time point - */ - ASN1_Ced(const std::chrono::system_clock::time_point& time) : - EAC_Time(time, ASN1_Tag(37)) {} - - /** - * Copy constructor (for general EAC_Time objects). - * @param other the object to copy from - */ - ASN1_Ced(const EAC_Time& other) : - EAC_Time(other.get_year(), other.get_month(), other.get_day(), - ASN1_Tag(37)) - {} - }; - -/** -* This class represents CVC CEXs. Only limited sanity checks of -* the inputted date value are performed. -*/ -class BOTAN_DLL ASN1_Cex : public EAC_Time - { - public: - /** - * Construct a CEX from a string value. - * @param str a string in the format "yyyy mm dd", - * e.g. "2007 08 01" - */ - ASN1_Cex(const std::string& str = "") : - EAC_Time(str, ASN1_Tag(36)) {} - - ASN1_Cex(const std::chrono::system_clock::time_point& time) : - EAC_Time(time, ASN1_Tag(36)) {} - - ASN1_Cex(const EAC_Time& other) : - EAC_Time(other.get_year(), other.get_month(), other.get_day(), - ASN1_Tag(36)) - {} - }; - -/** -* Base class for car/chr of cv certificates. -*/ -class BOTAN_DLL ASN1_EAC_String: public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - /** - * Get this objects string value. - * @return string value - */ - std::string value() const; - - /** - * Get this objects string value. - * @return string value in iso8859 encoding - */ - std::string iso_8859() const; - - ASN1_Tag tagging() const; - ASN1_EAC_String(const std::string& str, ASN1_Tag the_tag); - - virtual ~ASN1_EAC_String() {} - protected: - bool sanity_check() const; - private: - std::string m_iso_8859_str; - ASN1_Tag m_tag; - }; - -/** -* This class represents CARs of CVCs. (String tagged with 2) -*/ -class BOTAN_DLL ASN1_Car : public ASN1_EAC_String - { - public: - /** - * Create a CAR with the specified content. - * @param str the CAR value - */ - ASN1_Car(std::string const& str = ""); - }; - -/** -* This class represents CHRs of CVCs (tag 32) -*/ -class BOTAN_DLL ASN1_Chr : public ASN1_EAC_String - { - public: - /** - * Create a CHR with the specified content. - * @param str the CHR value - */ - ASN1_Chr(std::string const& str = ""); - }; - -/* -* Comparison Operations -*/ -bool BOTAN_DLL operator==(const EAC_Time&, const EAC_Time&); -bool BOTAN_DLL operator!=(const EAC_Time&, const EAC_Time&); -bool BOTAN_DLL operator<=(const EAC_Time&, const EAC_Time&); -bool BOTAN_DLL operator>=(const EAC_Time&, const EAC_Time&); -bool BOTAN_DLL operator>(const EAC_Time&, const EAC_Time&); -bool BOTAN_DLL operator<(const EAC_Time&, const EAC_Time&); - -bool BOTAN_DLL operator==(const ASN1_EAC_String&, const ASN1_EAC_String&); -inline bool operator!=(const ASN1_EAC_String& lhs, const ASN1_EAC_String& rhs) - { - return !(lhs == rhs); - } - -} - -#endif diff --git a/src/lib/cert/cvc/eac_obj.h b/src/lib/cert/cvc/eac_obj.h deleted file mode 100644 index a6e676076..000000000 --- a/src/lib/cert/cvc/eac_obj.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -* EAC1_1 objects -* (C) 2008 Falko Strenzke -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_OBJ_H__ -#define BOTAN_EAC_OBJ_H__ - -#include <botan/signed_obj.h> -#include <botan/ecdsa_sig.h> - -namespace Botan { - -/** -* TR03110 v1.1 EAC CV Certificate -*/ -template<typename Derived> // CRTP is used enable the call sequence: -class EAC1_1_obj : public EAC_Signed_Object - { - public: - /** - * Return the signature as a concatenation of the encoded parts. - * @result the concatenated signature - */ - std::vector<byte> get_concat_sig() const - { return m_sig.get_concatenation(); } - - bool check_signature(class Public_Key& key) const - { - return EAC_Signed_Object::check_signature(key, m_sig.DER_encode()); - } - - protected: - ECDSA_Signature m_sig; - - void init(DataSource& in) - { - try - { - Derived::decode_info(in, m_tbs_bits, m_sig); - } - catch(Decoding_Error) - { - throw Decoding_Error(m_PEM_label_pref + " decoding failed"); - } - } - - virtual ~EAC1_1_obj<Derived>(){} - }; - -} - -#endif diff --git a/src/lib/cert/cvc/ecdsa_sig.cpp b/src/lib/cert/cvc/ecdsa_sig.cpp deleted file mode 100644 index 5e85d7932..000000000 --- a/src/lib/cert/cvc/ecdsa_sig.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* -* ECDSA Signature -* (C) 2007 Falko Strenzke, FlexSecure GmbH -* (C) 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/ecdsa_sig.h> - -namespace Botan { - -ECDSA_Signature::ECDSA_Signature(const std::vector<byte>& ber) - { - BER_Decoder(ber) - .start_cons(SEQUENCE) - .decode(m_r) - .decode(m_s) - .end_cons() - .verify_end(); - } - -std::vector<byte> ECDSA_Signature::DER_encode() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(get_r()) - .encode(get_s()) - .end_cons() - .get_contents_unlocked(); - } - -std::vector<byte> ECDSA_Signature::get_concatenation() const - { - // use the larger - const size_t enc_len = m_r > m_s ? m_r.bytes() : m_s.bytes(); - - const auto sv_r = BigInt::encode_1363(m_r, enc_len); - const auto sv_s = BigInt::encode_1363(m_s, enc_len); - - secure_vector<byte> result(sv_r); - result += sv_s; - return unlock(result); - } - -ECDSA_Signature decode_concatenation(const std::vector<byte>& concat) - { - if(concat.size() % 2 != 0) - throw Invalid_Argument("Erroneous length of signature"); - - const size_t rs_len = concat.size() / 2; - - BigInt r = BigInt::decode(&concat[0], rs_len); - BigInt s = BigInt::decode(&concat[rs_len], rs_len); - - return ECDSA_Signature(r, s); - } - -} diff --git a/src/lib/cert/cvc/ecdsa_sig.h b/src/lib/cert/cvc/ecdsa_sig.h deleted file mode 100644 index 2845cbec9..000000000 --- a/src/lib/cert/cvc/ecdsa_sig.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -* ECDSA Signature -* (C) 2007 Falko Strenzke, FlexSecure GmbH -* (C) 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_ECDSA_SIGNATURE_H__ -#define BOTAN_ECDSA_SIGNATURE_H__ - -#include <botan/bigint.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> - -namespace Botan { - -/** -* Class representing an ECDSA signature -*/ -class BOTAN_DLL ECDSA_Signature - { - public: - friend class ECDSA_Signature_Decoder; - - ECDSA_Signature() {} - ECDSA_Signature(const BigInt& r, const BigInt& s) : - m_r(r), m_s(s) {} - - ECDSA_Signature(const std::vector<byte>& ber); - - const BigInt& get_r() const { return m_r; } - const BigInt& get_s() const { return m_s; } - - /** - * return the r||s - */ - std::vector<byte> get_concatenation() const; - - std::vector<byte> DER_encode() const; - - bool operator==(const ECDSA_Signature& other) const - { - return (get_r() == other.get_r() && get_s() == other.get_s()); - } - - private: - BigInt m_r; - BigInt m_s; - }; - -inline bool operator!=(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs) - { - return !(lhs == rhs); - } - -ECDSA_Signature decode_concatenation(const std::vector<byte>& concatenation); - -} - -#endif diff --git a/src/lib/cert/cvc/info.txt b/src/lib/cert/cvc/info.txt deleted file mode 100644 index e3da5435e..000000000 --- a/src/lib/cert/cvc/info.txt +++ /dev/null @@ -1,35 +0,0 @@ -define CARD_VERIFIABLE_CERTIFICATES 20131128 -load_on request - -<header:public> -cvc_ado.h -cvc_cert.h -cvc_gen_cert.h -cvc_req.h -cvc_self.h -eac_asn_obj.h -eac_obj.h -ecdsa_sig.h -signed_obj.h -</header:public> - -<source> -asn1_eac_str.cpp -asn1_eac_tm.cpp -ecdsa_sig.cpp -cvc_ado.cpp -cvc_cert.cpp -cvc_req.cpp -cvc_self.cpp -signed_obj.cpp -</source> - -<requires> -asn1 -bigint -ecdsa -filters -oid_lookup -pem -pubkey -</requires> diff --git a/src/lib/cert/cvc/signed_obj.cpp b/src/lib/cert/cvc/signed_obj.cpp deleted file mode 100644 index 1e3849663..000000000 --- a/src/lib/cert/cvc/signed_obj.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -* EAC SIGNED Object -* (C) 1999-2010 Jack Lloyd -* 2007 FlexSecure GmbH -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/signed_obj.h> -#include <botan/pubkey.h> -#include <botan/oids.h> - -namespace Botan { - -/* -* Return a BER encoded X.509 object -*/ -std::vector<byte> EAC_Signed_Object::BER_encode() const - { - Pipe ber; - ber.start_msg(); - encode(ber, RAW_BER); - ber.end_msg(); - return unlock(ber.read_all()); - } - -/* -* Return a PEM encoded X.509 object -*/ -std::string EAC_Signed_Object::PEM_encode() const - { - Pipe pem; - pem.start_msg(); - encode(pem, PEM); - pem.end_msg(); - return pem.read_all_as_string(); - } - -/* -* Return the algorithm used to sign this object -*/ -AlgorithmIdentifier EAC_Signed_Object::signature_algorithm() const - { - return m_sig_algo; - } - -bool EAC_Signed_Object::check_signature(Public_Key& pub_key, - const std::vector<byte>& sig) const - { - try - { - std::vector<std::string> sig_info = - split_on(OIDS::lookup(m_sig_algo.oid), '/'); - - if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) - { - return false; - } - - std::string padding = sig_info[1]; - Signature_Format format = - (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; - - std::vector<byte> to_sign = tbs_data(); - - PK_Verifier verifier(pub_key, padding, format); - return verifier.verify_message(to_sign, sig); - } - catch(...) - { - return false; - } - } - -/* -* Try to decode the actual information -*/ -void EAC_Signed_Object::do_decode() - { - try { - force_decode(); - } - catch(Decoding_Error& e) - { - const std::string what = e.what(); - throw Decoding_Error(m_PEM_label_pref + " decoding failed (" + what + ")"); - } - catch(Invalid_Argument& e) - { - const std::string what = e.what(); - throw Decoding_Error(m_PEM_label_pref + " decoding failed (" + what + ")"); - } - } - -} diff --git a/src/lib/cert/cvc/signed_obj.h b/src/lib/cert/cvc/signed_obj.h deleted file mode 100644 index b3fe20f31..000000000 --- a/src/lib/cert/cvc/signed_obj.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -* EAC SIGNED Object -* (C) 2007 FlexSecure GmbH -* 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_SIGNED_OBJECT_H__ -#define BOTAN_EAC_SIGNED_OBJECT_H__ - -#include <botan/asn1_obj.h> -#include <botan/x509_key.h> -#include <botan/pipe.h> -#include <vector> - -namespace Botan { - -/** -* This class represents abstract signed EAC object -*/ -class BOTAN_DLL EAC_Signed_Object - { - public: - /** - * Get the TBS (to-be-signed) data in this object. - * @return DER encoded TBS data of this object - */ - virtual std::vector<byte> tbs_data() const = 0; - - /** - * Get the signature of this object as a concatenation, i.e. if the - * signature consists of multiple parts (like in the case of ECDSA) - * these will be concatenated. - * @return signature as a concatenation of its parts - */ - - /* - NOTE: this is here only because abstract signature objects have - not yet been introduced - */ - virtual std::vector<byte> get_concat_sig() const = 0; - - /** - * Get the signature algorithm identifier used to sign this object. - * @result the signature algorithm identifier - */ - AlgorithmIdentifier signature_algorithm() const; - - /** - * Check the signature of this object. - * @param key the public key associated with this signed object - * @param sig the signature we are checking - * @return true if the signature was created by the private key - * associated with this public key - */ - bool check_signature(class Public_Key& key, - const std::vector<byte>& sig) const; - - /** - * Write this object DER encoded into a specified pipe. - * @param pipe the pipe to write the encoded object to - * @param encoding the encoding type to use - */ - virtual void encode(Pipe& pipe, - X509_Encoding encoding = PEM) const = 0; - - /** - * BER encode this object. - * @return result containing the BER representation of this object. - */ - std::vector<byte> BER_encode() const; - - /** - * PEM encode this object. - * @return result containing the PEM representation of this object. - */ - std::string PEM_encode() const; - - virtual ~EAC_Signed_Object() {} - protected: - void do_decode(); - EAC_Signed_Object() {} - - AlgorithmIdentifier m_sig_algo; - std::vector<byte> m_tbs_bits; - std::string m_PEM_label_pref; - std::vector<std::string> m_PEM_labels_allowed; - private: - virtual void force_decode() = 0; - }; - -} - -#endif diff --git a/src/lib/cert/x509/x509_ca.cpp b/src/lib/cert/x509/x509_ca.cpp index 46c8c65f2..147fdd6ad 100644 --- a/src/lib/cert/x509/x509_ca.cpp +++ b/src/lib/cert/x509/x509_ca.cpp @@ -234,10 +234,8 @@ PK_Signer* choose_sig_format(const Private_Key& key, std::string padding; if(algo_name == "RSA") padding = "EMSA3"; - else if(algo_name == "DSA") + else if(algo_name == "DSA" || algo_name == "ECDSA" ) padding = "EMSA1"; - else if(algo_name == "ECDSA") - padding = "EMSA1_BSI"; else throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name); diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp index 11084ae50..028b286b6 100644 --- a/src/lib/ffi/ffi.cpp +++ b/src/lib/ffi/ffi.cpp @@ -653,12 +653,13 @@ int botan_pbkdf_timed(const char* pbkdf_algo, int botan_kdf(const char* kdf_algo, uint8_t out[], size_t out_len, const uint8_t secret[], size_t secret_len, - const uint8_t salt[], size_t salt_len) + const uint8_t salt[], size_t salt_len, + const uint8_t label[], size_t label_len) { try { std::unique_ptr<Botan::KDF> kdf(Botan::get_kdf(kdf_algo)); - kdf->kdf(out, out_len, secret, secret_len, salt, salt_len); + kdf->kdf(out, out_len, secret, secret_len, salt, salt_len, label, label_len); return 0; } catch(std::exception& e) diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h index 6cbe56743..165554105 100644 --- a/src/lib/ffi/ffi.h +++ b/src/lib/ffi/ffi.h @@ -269,7 +269,8 @@ BOTAN_DLL int botan_pbkdf_timed(const char* pbkdf_algo, BOTAN_DLL int botan_kdf(const char* kdf_algo, uint8_t out[], size_t out_len, const uint8_t secret[], size_t secret_len, - const uint8_t salt[], size_t salt_len); + const uint8_t salt[], size_t salt_len, + const uint8_t label[], size_t label_len); /* * Bcrypt diff --git a/src/lib/kdf/hkdf/hkdf.cpp b/src/lib/kdf/hkdf/hkdf.cpp index 6f83853f9..56dc72f09 100644 --- a/src/lib/kdf/hkdf/hkdf.cpp +++ b/src/lib/kdf/hkdf/hkdf.cpp @@ -22,7 +22,8 @@ HKDF* HKDF::make(const Spec& spec) size_t HKDF::kdf(byte out[], size_t out_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { m_prf->set_key(secret, secret_len); @@ -33,6 +34,7 @@ size_t HKDF::kdf(byte out[], size_t out_len, while(offset != out_len && counter != 0) { m_prf->update(h); + m_prf->update(label, label_len); m_prf->update(salt, salt_len); m_prf->update(counter++); m_prf->final(h); diff --git a/src/lib/kdf/hkdf/hkdf.h b/src/lib/kdf/hkdf/hkdf.h index 3e3e2b73a..1dba82ee2 100644 --- a/src/lib/kdf/hkdf/hkdf.h +++ b/src/lib/kdf/hkdf/hkdf.h @@ -31,7 +31,8 @@ class BOTAN_DLL HKDF final : public KDF size_t kdf(byte out[], size_t out_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; private: std::unique_ptr<MessageAuthenticationCode> m_prf; diff --git a/src/lib/kdf/kdf.cpp b/src/lib/kdf/kdf.cpp index 7f4488d32..66296bf96 100644 --- a/src/lib/kdf/kdf.cpp +++ b/src/lib/kdf/kdf.cpp @@ -21,6 +21,10 @@ #include <botan/kdf2.h> #endif +#if defined(BOTAN_HAS_KDF1_18033) +#include <botan/kdf1_iso18033.h> +#endif + #if defined(BOTAN_HAS_TLS_V10_PRF) #include <botan/prf_tls.h> #endif @@ -89,6 +93,10 @@ BOTAN_REGISTER_KDF_1HASH(KDF1, "KDF1"); BOTAN_REGISTER_KDF_1HASH(KDF2, "KDF2"); #endif +#if defined(BOTAN_HAS_KDF1_18033) +BOTAN_REGISTER_KDF_1HASH( KDF1_18033, "KDF1-18033" ); +#endif + #if defined(BOTAN_HAS_TLS_V10_PRF) BOTAN_REGISTER_KDF_NOARGS(TLS_PRF, "TLS-PRF"); #endif diff --git a/src/lib/kdf/kdf.h b/src/lib/kdf/kdf.h index 88b50c8b8..3c8a7a013 100644 --- a/src/lib/kdf/kdf.h +++ b/src/lib/kdf/kdf.h @@ -40,7 +40,8 @@ class BOTAN_DLL KDF virtual size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const = 0; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const = 0; /** @@ -50,15 +51,19 @@ class BOTAN_DLL KDF * @param secret_len size of secret in bytes * @param salt a diversifier * @param salt_len size of salt in bytes + * @param label purpose for the derived keying material + * @param label_len size of label in bytes */ secure_vector<byte> derive_key(size_t key_len, const byte secret[], size_t secret_len, const byte salt[], - size_t salt_len) const + size_t salt_len, + const byte label[] = nullptr, + size_t label_len = 0) const { secure_vector<byte> key(key_len); - key.resize(kdf(key.data(), key.size(), secret, secret_len, salt, salt_len)); + key.resize(kdf(key.data(), key.size(), secret, secret_len, salt, salt_len, label, label_len)); return key; } @@ -67,14 +72,19 @@ class BOTAN_DLL KDF * @param key_len the desired output length in bytes * @param secret the secret input * @param salt a diversifier + * @param label purpose for the derived keying material */ secure_vector<byte> derive_key(size_t key_len, const secure_vector<byte>& secret, - const std::string& salt = "") const + const std::string& salt = "", + const std::string& label = "") const { return derive_key(key_len, secret.data(), secret.size(), reinterpret_cast<const byte*>(salt.data()), - salt.length()); + salt.length(), + reinterpret_cast<const byte*>(label.data()), + label.length()); + } /** @@ -82,15 +92,18 @@ class BOTAN_DLL KDF * @param key_len the desired output length in bytes * @param secret the secret input * @param salt a diversifier + * @param label purpose for the derived keying material */ - template<typename Alloc, typename Alloc2> + template<typename Alloc, typename Alloc2, typename Alloc3> secure_vector<byte> derive_key(size_t key_len, const std::vector<byte, Alloc>& secret, - const std::vector<byte, Alloc2>& salt) const + const std::vector<byte, Alloc2>& salt, + const std::vector<byte, Alloc3>& label) const { return derive_key(key_len, secret.data(), secret.size(), - salt.data(), salt.size()); + salt.data(), salt.size(), + label.data(), label.size()); } /** @@ -99,15 +112,19 @@ class BOTAN_DLL KDF * @param secret the secret input * @param salt a diversifier * @param salt_len size of salt in bytes + * @param label purpose for the derived keying material */ secure_vector<byte> derive_key(size_t key_len, const secure_vector<byte>& secret, const byte salt[], - size_t salt_len) const + size_t salt_len, + const std::string& label = "") const { return derive_key(key_len, secret.data(), secret.size(), - salt, salt_len); + salt, salt_len, + reinterpret_cast<const byte*>(label.data()), + label.size()); } /** @@ -116,15 +133,19 @@ class BOTAN_DLL KDF * @param secret the secret input * @param secret_len size of secret in bytes * @param salt a diversifier + * @param label purpose for the derived keying material */ secure_vector<byte> derive_key(size_t key_len, const byte secret[], size_t secret_len, - const std::string& salt = "") const + const std::string& salt = "", + const std::string& label = "") const { return derive_key(key_len, secret, secret_len, reinterpret_cast<const byte*>(salt.data()), - salt.length()); + salt.length(), + reinterpret_cast<const byte*>(label.data()), + label.length()); } virtual KDF* clone() const = 0; diff --git a/src/lib/kdf/kdf1/kdf1.cpp b/src/lib/kdf/kdf1/kdf1.cpp index c7ea3c37e..14dddc5f4 100644 --- a/src/lib/kdf/kdf1/kdf1.cpp +++ b/src/lib/kdf/kdf1/kdf1.cpp @@ -11,9 +11,11 @@ namespace Botan { size_t KDF1::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { m_hash->update(secret, secret_len); + m_hash->update(label, label_len); m_hash->update(salt, salt_len); if(key_len < m_hash->output_length()) diff --git a/src/lib/kdf/kdf1/kdf1.h b/src/lib/kdf/kdf1/kdf1.h index adaa84894..59bff4d8d 100644 --- a/src/lib/kdf/kdf1/kdf1.h +++ b/src/lib/kdf/kdf1/kdf1.h @@ -25,7 +25,8 @@ class BOTAN_DLL KDF1 final : public KDF size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; explicit KDF1(HashFunction* h) : m_hash(h) {} private: diff --git a/src/lib/kdf/kdf1_iso18033/info.txt b/src/lib/kdf/kdf1_iso18033/info.txt new file mode 100644 index 000000000..507a04561 --- /dev/null +++ b/src/lib/kdf/kdf1_iso18033/info.txt @@ -0,0 +1 @@ +define KDF1_18033 20160128 diff --git a/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp b/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp new file mode 100644 index 000000000..3ff717993 --- /dev/null +++ b/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.cpp @@ -0,0 +1,35 @@ +/* +* KDF1 from ISO 18033 +* (C) 2016 Philipp Weber +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/kdf1_iso18033.h> + +namespace Botan { + +size_t KDF1_18033::kdf(byte key[], size_t key_len, + const byte secret[], size_t secret_len, + const byte salt[], size_t salt_len) const + { + u32bit counter = 0; + secure_vector<byte> h; + + size_t offset = 0; + while(offset != key_len && counter != 0xFFFFFFFF) + { + m_hash->update(secret, secret_len); + m_hash->update_be(counter++); + m_hash->update(salt, salt_len); + m_hash->final(h); + + const size_t added = std::min(h.size(), key_len - offset); + copy_mem(&key[offset], h.data(), added); + offset += added; + } + + return offset; + } + +} diff --git a/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h b/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h new file mode 100644 index 000000000..6ec7ead8e --- /dev/null +++ b/src/lib/kdf/kdf1_iso18033/kdf1_iso18033.h @@ -0,0 +1,37 @@ +/* +* KDF1 from ISO 18033 +* (C) 2016 Philipp Weber +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_KDF1_18033_H__ +#define BOTAN_KDF1_18033_H__ + +#include <botan/kdf.h> +#include <botan/hash.h> + +namespace Botan { + +/** +* KDF1, from IEEE 1363 +*/ +class BOTAN_DLL KDF1_18033 : public KDF + { + public: + std::string name() const override { return "KDF1-18033(" + m_hash->name() + ")"; } + + KDF* clone() const override { return new KDF1_18033(m_hash->clone()); } + + size_t kdf(byte key[], size_t key_len, + const byte secret[], size_t secret_len, + const byte salt[], size_t salt_len) const override; + + KDF1_18033(HashFunction* h) : m_hash(h) {} + private: + std::unique_ptr<HashFunction> m_hash; + }; + +} + +#endif diff --git a/src/lib/kdf/kdf2/kdf2.cpp b/src/lib/kdf/kdf2/kdf2.cpp index df2b7a91c..760ebfc83 100644 --- a/src/lib/kdf/kdf2/kdf2.cpp +++ b/src/lib/kdf/kdf2/kdf2.cpp @@ -11,7 +11,8 @@ namespace Botan { size_t KDF2::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { u32bit counter = 1; secure_vector<byte> h; @@ -21,6 +22,7 @@ size_t KDF2::kdf(byte key[], size_t key_len, { m_hash->update(secret, secret_len); m_hash->update_be(counter++); + m_hash->update(label, label_len); m_hash->update(salt, salt_len); m_hash->final(h); diff --git a/src/lib/kdf/kdf2/kdf2.h b/src/lib/kdf/kdf2/kdf2.h index 7403df21c..600f7c91c 100644 --- a/src/lib/kdf/kdf2/kdf2.h +++ b/src/lib/kdf/kdf2/kdf2.h @@ -25,7 +25,8 @@ class BOTAN_DLL KDF2 final : public KDF size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; explicit KDF2(HashFunction* h) : m_hash(h) {} private: diff --git a/src/lib/kdf/prf_tls/prf_tls.cpp b/src/lib/kdf/prf_tls/prf_tls.cpp index 547b0c9c8..14b330901 100644 --- a/src/lib/kdf/prf_tls/prf_tls.cpp +++ b/src/lib/kdf/prf_tls/prf_tls.cpp @@ -73,23 +73,36 @@ void P_hash(byte out[], size_t out_len, size_t TLS_PRF::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { const size_t S1_len = (secret_len + 1) / 2, S2_len = (secret_len + 1) / 2; const byte* S1 = secret; const byte* S2 = secret + (secret_len - S2_len); + secure_vector<byte> msg; - P_hash(key, key_len, *m_hmac_md5, S1, S1_len, salt, salt_len); - P_hash(key, key_len, *m_hmac_sha1, S2, S2_len, salt, salt_len); + msg.reserve(label_len + salt_len); + msg += std::make_pair(label, label_len); + msg += std::make_pair(salt, salt_len); + + P_hash(key, key_len, *m_hmac_md5, S1, S1_len, msg.data(), msg.size()); + P_hash(key, key_len, *m_hmac_sha1, S2, S2_len, msg.data(), msg.size()); return key_len; } size_t TLS_12_PRF::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { - P_hash(key, key_len, *m_mac, secret, secret_len, salt, salt_len); + secure_vector<byte> msg; + + msg.reserve(label_len + salt_len); + msg += std::make_pair(label, label_len); + msg += std::make_pair(salt, salt_len); + + P_hash(key, key_len, *m_mac, secret, secret_len, msg.data(), msg.size()); return key_len; } diff --git a/src/lib/kdf/prf_tls/prf_tls.h b/src/lib/kdf/prf_tls/prf_tls.h index a51006d88..37a517125 100644 --- a/src/lib/kdf/prf_tls/prf_tls.h +++ b/src/lib/kdf/prf_tls/prf_tls.h @@ -25,7 +25,8 @@ class BOTAN_DLL TLS_PRF final : public KDF size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; TLS_PRF(); private: @@ -45,7 +46,8 @@ class BOTAN_DLL TLS_12_PRF final : public KDF size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; explicit TLS_12_PRF(MessageAuthenticationCode* mac) : m_mac(mac) {} diff --git a/src/lib/kdf/prf_x942/prf_x942.cpp b/src/lib/kdf/prf_x942/prf_x942.cpp index fb8de1e85..206cf6ce6 100644 --- a/src/lib/kdf/prf_x942/prf_x942.cpp +++ b/src/lib/kdf/prf_x942/prf_x942.cpp @@ -30,15 +30,21 @@ std::vector<byte> encode_x942_int(u32bit n) size_t X942_PRF::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-160")); const OID kek_algo(m_key_wrap_oid); secure_vector<byte> h; + secure_vector<byte> in; size_t offset = 0; u32bit counter = 1; + in.reserve(salt_len + label_len); + in += std::make_pair(label,label_len); + in += std::make_pair(salt,salt_len); + while(offset != key_len && counter) { hash->update(secret, secret_len); @@ -54,7 +60,7 @@ size_t X942_PRF::kdf(byte key[], size_t key_len, .encode_if(salt_len != 0, DER_Encoder() .start_explicit(0) - .encode(salt, salt_len, OCTET_STRING) + .encode(in, OCTET_STRING) .end_explicit() ) diff --git a/src/lib/kdf/prf_x942/prf_x942.h b/src/lib/kdf/prf_x942/prf_x942.h index c15be9845..afe56de80 100644 --- a/src/lib/kdf/prf_x942/prf_x942.h +++ b/src/lib/kdf/prf_x942/prf_x942.h @@ -24,7 +24,8 @@ class BOTAN_DLL X942_PRF final : public KDF size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; explicit X942_PRF(const std::string& oid); private: diff --git a/src/lib/kdf/sp800_108/sp800_108.cpp b/src/lib/kdf/sp800_108/sp800_108.cpp index 873db814c..aafb349b2 100644 --- a/src/lib/kdf/sp800_108/sp800_108.cpp +++ b/src/lib/kdf/sp800_108/sp800_108.cpp @@ -8,6 +8,8 @@ #include <botan/sp800_108.h> #include <botan/hmac.h> +#include <iterator> + namespace Botan { SP800_108_Counter* SP800_108_Counter::make(const Spec& spec) @@ -23,13 +25,18 @@ SP800_108_Counter* SP800_108_Counter::make(const Spec& spec) size_t SP800_108_Counter::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { const std::size_t prf_len = m_prf->output_length(); + const byte delim = 0; byte *p = key; uint32_t counter = 1; + uint32_t length = key_len * 8; + byte be_len[4] = { 0 }; secure_vector<byte> tmp; + store_be(length, be_len); m_prf->set_key(secret, secret_len); while(p < key + key_len && counter != 0) @@ -40,7 +47,10 @@ size_t SP800_108_Counter::kdf(byte key[], size_t key_len, store_be(counter, be_cnt); m_prf->update(be_cnt,4); - m_prf->update(salt, salt_len); + m_prf->update(label,label_len); + m_prf->update(delim); + m_prf->update(salt,salt_len); + m_prf->update(be_len,4); m_prf->final(tmp); std::move(tmp.begin(), tmp.begin() + to_copy, p); @@ -68,16 +78,21 @@ SP800_108_Feedback* SP800_108_Feedback::make(const Spec& spec) size_t SP800_108_Feedback::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { const std::size_t prf_len = m_prf->output_length(); const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0); + const byte delim = 0; byte *p = key; uint32_t counter = 1; + uint32_t length = key_len * 8; + byte be_len[4] = { 0 }; secure_vector< byte > prev(salt, salt + iv_len); secure_vector< byte > ctx(salt + iv_len, salt + salt_len); + store_be(length, be_len); m_prf->set_key(secret, secret_len); while(p < key + key_len && counter != 0) @@ -89,7 +104,10 @@ size_t SP800_108_Feedback::kdf(byte key[], size_t key_len, m_prf->update(prev); m_prf->update(be_cnt,4); + m_prf->update(label,label_len); + m_prf->update(delim); m_prf->update(ctx); + m_prf->update(be_len,4); m_prf->final(prev); std::copy(prev.begin(), prev.begin() + to_copy, p); @@ -117,15 +135,27 @@ SP800_108_Pipeline* SP800_108_Pipeline::make(const Spec& spec) size_t SP800_108_Pipeline::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { const std::size_t prf_len = m_prf->output_length(); + const byte delim = 0; + byte *p = key; uint32_t counter = 1; - secure_vector<byte> ai(salt, salt + salt_len), ki; + uint32_t length = key_len * 8; + byte be_len[4] = { 0 }; + secure_vector<byte> ai, ki; + store_be(length, be_len); m_prf->set_key(secret,secret_len); + // A(0) + std::copy(label,label + label_len,std::back_inserter(ai)); + ai.emplace_back(delim); + std::copy(salt,salt + salt_len,std::back_inserter(ai)); + std::copy(be_len,be_len + 4,std::back_inserter(ai)); + while(p < key + key_len && counter != 0) { // A(i) @@ -140,7 +170,10 @@ size_t SP800_108_Pipeline::kdf(byte key[], size_t key_len, m_prf->update(ai); m_prf->update(be_cnt,4); + m_prf->update(label, label_len); + m_prf->update(delim); m_prf->update(salt, salt_len); + m_prf->update(be_len,4); m_prf->final(ki); std::copy(ki.begin(), ki.begin() + to_copy, p); diff --git a/src/lib/kdf/sp800_108/sp800_108.h b/src/lib/kdf/sp800_108/sp800_108.h index 0acdfacf9..71a918c15 100644 --- a/src/lib/kdf/sp800_108/sp800_108.h +++ b/src/lib/kdf/sp800_108/sp800_108.h @@ -23,9 +23,27 @@ class BOTAN_DLL SP800_108_Counter : public KDF KDF* clone() const override { return new SP800_108_Counter(m_prf->clone()); } + /** + * Derive a key using the SP800-108 KDF in Counter mode. + * + * The implementation hard codes the length of [L]_2 + * and [i]_2 (the value r) to 32 bits. + * + * @param key resulting keying material + * @param key_len the desired output length in bytes + * @param secret K_I + * @param secret_len size of K_I in bytes + * @param salt Context + * @param salt_len size of Context in bytes + * @param label Label + * @param label_len size of Label in bytes + * + * @throws Invalid_Argument key_len > 2^32 + */ size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; SP800_108_Counter(MessageAuthenticationCode* mac) : m_prf(mac) {} @@ -44,9 +62,27 @@ class BOTAN_DLL SP800_108_Feedback : public KDF KDF* clone() const override { return new SP800_108_Feedback(m_prf->clone()); } + /** + * Derive a key using the SP800-108 KDF in Feedback mode. + * + * The implementation uses the optional counter i and hard + * codes the length of [L]_2 and [i]_2 (the value r) to 32 bits. + * + * @param key resulting keying material + * @param key_len the desired output length in bytes + * @param secret K_I + * @param secret_len size of K_I in bytes + * @param salt IV || Context + * @param salt_len size of Context plus IV in bytes + * @param label Label + * @param label_len size of Label in bytes + * + * @throws Invalid_Argument key_len > 2^32 + */ size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; SP800_108_Feedback(MessageAuthenticationCode* mac) : m_prf(mac) {} @@ -65,9 +101,27 @@ class BOTAN_DLL SP800_108_Pipeline : public KDF KDF* clone() const override { return new SP800_108_Pipeline(m_prf->clone()); } + /** + * Derive a key using the SP800-108 KDF in Double Pipeline mode. + * + * The implementation uses the optional counter i and hard + * codes the length of [L]_2 and [i]_2 (the value r) to 32 bits. + * + * @param key resulting keying material + * @param key_len the desired output length in bytes + * @param secret K_I + * @param secret_len size of K_I in bytes + * @param salt Context + * @param salt_len size of Context in bytes + * @param label Label + * @param label_len size of Label in bytes + * + * @throws Invalid_Argument key_len > 2^32 + */ size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; SP800_108_Pipeline(MessageAuthenticationCode* mac) : m_prf(mac) {} diff --git a/src/lib/kdf/sp800_56c/sp800_56c.cpp b/src/lib/kdf/sp800_56c/sp800_56c.cpp index 664d32b30..338feba2a 100644 --- a/src/lib/kdf/sp800_56c/sp800_56c.cpp +++ b/src/lib/kdf/sp800_56c/sp800_56c.cpp @@ -27,17 +27,18 @@ SP800_56C* SP800_56C::make(const Spec& spec) size_t SP800_56C::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const { // Randomness Extraction - secure_vector< byte > k_dk, context; + secure_vector< byte > k_dk; m_prf->set_key(salt, salt_len); m_prf->update(secret, secret_len); m_prf->final(k_dk); // Key Expansion - m_exp->kdf(key, key_len, k_dk.data(), k_dk.size(), context.data(), context.size()); + m_exp->kdf(key, key_len, k_dk.data(), k_dk.size(), nullptr, 0, label, label_len); return key_len; } diff --git a/src/lib/kdf/sp800_56c/sp800_56c.h b/src/lib/kdf/sp800_56c/sp800_56c.h index d1b6f39b5..1281ed314 100644 --- a/src/lib/kdf/sp800_56c/sp800_56c.h +++ b/src/lib/kdf/sp800_56c/sp800_56c.h @@ -23,9 +23,27 @@ class BOTAN_DLL SP800_56C : public KDF KDF* clone() const override { return new SP800_56C(m_prf->clone(), m_exp->clone()); } + /** + * Derive a key using the SP800-56C KDF. + * + * The implementation hard codes the context value for the + * expansion step to the empty string. + * + * @param key derived keying material K_M + * @param key_len the desired output length in bytes + * @param secret shared secret Z + * @param secret_len size of Z in bytes + * @param salt salt s of the extraction step + * @param salt_len size of s in bytes + * @param label label for the expansion step + * @param label_len size of label in bytes + * + * @throws Invalid_Argument key_len > 2^32 + */ size_t kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, - const byte salt[], size_t salt_len) const override; + const byte salt[], size_t salt_len, + const byte label[], size_t label_len) const override; SP800_56C(MessageAuthenticationCode* mac, KDF* exp) : m_prf(mac), m_exp(exp) {} diff --git a/src/lib/pk_pad/emsa.cpp b/src/lib/pk_pad/emsa.cpp index 91bf44cf8..4d4b96ad1 100644 --- a/src/lib/pk_pad/emsa.cpp +++ b/src/lib/pk_pad/emsa.cpp @@ -11,10 +11,6 @@ #include <botan/emsa1.h> #endif -#if defined(BOTAN_HAS_EMSA1_BSI) - #include <botan/emsa1_bsi.h> -#endif - #if defined(BOTAN_HAS_EMSA_X931) #include <botan/emsa_x931.h> #endif @@ -71,10 +67,6 @@ std::string hash_for_emsa(const std::string& algo_spec) BOTAN_REGISTER_EMSA_1HASH(EMSA1, "EMSA1"); #endif -#if defined(BOTAN_HAS_EMSA1_BSI) -BOTAN_REGISTER_EMSA_1HASH(EMSA1_BSI, "EMSA1_BSI"); -#endif - #if defined(BOTAN_HAS_EMSA_PKCS1) BOTAN_REGISTER_NAMED_T(EMSA, "EMSA_PKCS1", EMSA_PCS1v15, EMSA_PKCS1v15::make); #endif diff --git a/src/lib/pk_pad/emsa1_bsi/emsa1_bsi.cpp b/src/lib/pk_pad/emsa1_bsi/emsa1_bsi.cpp deleted file mode 100644 index 24f10b07e..000000000 --- a/src/lib/pk_pad/emsa1_bsi/emsa1_bsi.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* -* EMSA1 BSI -* (C) 1999-2008 Jack Lloyd -* 2008 Falko Strenzke, FlexSecure GmbH -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/emsa1_bsi.h> - -namespace Botan { - -EMSA* EMSA1_BSI::clone() - { - return new EMSA1_BSI(m_hash->clone()); - } - - -/* -* EMSA1 BSI Encode Operation -*/ -secure_vector<byte> EMSA1_BSI::encoding_of(const secure_vector<byte>& msg, - size_t output_bits, - RandomNumberGenerator&) - { - if(msg.size() != hash_output_length()) - throw Encoding_Error("EMSA1_BSI::encoding_of: Invalid size for input"); - - if(8*msg.size() <= output_bits) - return msg; - - throw Encoding_Error("EMSA1_BSI::encoding_of: max key input size exceeded"); - } - -} diff --git a/src/lib/pk_pad/emsa1_bsi/emsa1_bsi.h b/src/lib/pk_pad/emsa1_bsi/emsa1_bsi.h deleted file mode 100644 index ac351cd2f..000000000 --- a/src/lib/pk_pad/emsa1_bsi/emsa1_bsi.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -* EMSA1 BSI Variant -* (C) 1999-2008 Jack Lloyd -* 2007 FlexSecure GmbH -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EMSA1_BSI_H__ -#define BOTAN_EMSA1_BSI_H__ - -#include <botan/emsa1.h> - -namespace Botan { - -/** -* EMSA1_BSI is a variant of EMSA1 specified by the BSI. It accepts -* only hash values which are less or equal than the maximum key -* length. The implementation comes from InSiTo -*/ -class BOTAN_DLL EMSA1_BSI final : public EMSA1 - { - public: - /** - * @param hash the hash object to use - */ - explicit EMSA1_BSI(HashFunction* hash) : EMSA1(hash) {} - - EMSA* clone() override; - private: - secure_vector<byte> encoding_of(const secure_vector<byte>&, size_t, - RandomNumberGenerator& rng) override; - }; - -} - -#endif diff --git a/src/lib/pk_pad/emsa1_bsi/info.txt b/src/lib/pk_pad/emsa1_bsi/info.txt deleted file mode 100644 index 021c99720..000000000 --- a/src/lib/pk_pad/emsa1_bsi/info.txt +++ /dev/null @@ -1,5 +0,0 @@ -define EMSA1_BSI 20131128 - -<requires> -emsa1 -</requires> diff --git a/src/lib/prov/openssl/openssl_rc4.cpp b/src/lib/prov/openssl/openssl_rc4.cpp index e36535e08..070cdb14d 100644 --- a/src/lib/prov/openssl/openssl_rc4.cpp +++ b/src/lib/prov/openssl/openssl_rc4.cpp @@ -45,6 +45,11 @@ class OpenSSL_RC4 : public StreamCipher explicit OpenSSL_RC4(size_t skip = 0) : m_skip(skip) { clear(); } ~OpenSSL_RC4() { clear(); } + + void seek(u64bit) override + { + throw Exception("RC4 does not support seeking"); + } private: void cipher(const byte in[], byte out[], size_t length) override { diff --git a/src/lib/pubkey/dsa/dsa.cpp b/src/lib/pubkey/dsa/dsa.cpp index 6e0618fa2..c42e70914 100644 --- a/src/lib/pubkey/dsa/dsa.cpp +++ b/src/lib/pubkey/dsa/dsa.cpp @@ -70,7 +70,7 @@ bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const if(!strong) return true; - return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)"); + return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)"); } namespace { diff --git a/src/lib/pubkey/dsa/info.txt b/src/lib/pubkey/dsa/info.txt index 94802ed59..855363789 100644 --- a/src/lib/pubkey/dsa/info.txt +++ b/src/lib/pubkey/dsa/info.txt @@ -5,4 +5,6 @@ dl_algo dl_group keypair numbertheory +emsa1 +sha2_32 </requires> diff --git a/src/lib/pubkey/ecdsa/ecdsa.cpp b/src/lib/pubkey/ecdsa/ecdsa.cpp index 14f902c13..6fe7ce319 100644 --- a/src/lib/pubkey/ecdsa/ecdsa.cpp +++ b/src/lib/pubkey/ecdsa/ecdsa.cpp @@ -27,7 +27,7 @@ bool ECDSA_PrivateKey::check_key(RandomNumberGenerator& rng, if(!strong) return true; - return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)"); + return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)"); } namespace { diff --git a/src/lib/pubkey/ecdsa/info.txt b/src/lib/pubkey/ecdsa/info.txt index e98913897..3b12bff0d 100644 --- a/src/lib/pubkey/ecdsa/info.txt +++ b/src/lib/pubkey/ecdsa/info.txt @@ -7,4 +7,6 @@ ecc_key keypair numbertheory rng +emsa1 +sha2_32 </requires> diff --git a/src/lib/pubkey/ecgdsa/ecgdsa.cpp b/src/lib/pubkey/ecgdsa/ecgdsa.cpp index b28e3fe96..3e14aa8f4 100644 --- a/src/lib/pubkey/ecgdsa/ecgdsa.cpp +++ b/src/lib/pubkey/ecgdsa/ecgdsa.cpp @@ -20,7 +20,7 @@ bool ECGDSA_PrivateKey::check_key(RandomNumberGenerator& rng, if(!strong) return true; - return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)"); + return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)"); } namespace { diff --git a/src/lib/pubkey/ecgdsa/info.txt b/src/lib/pubkey/ecgdsa/info.txt index 6c18a1440..79dec3199 100644 --- a/src/lib/pubkey/ecgdsa/info.txt +++ b/src/lib/pubkey/ecgdsa/info.txt @@ -8,4 +8,6 @@ ecc_key keypair numbertheory rng +emsa1 +sha2_32 </requires> diff --git a/src/lib/pubkey/ecies/ecies.cpp b/src/lib/pubkey/ecies/ecies.cpp new file mode 100644 index 000000000..0efdc64e1 --- /dev/null +++ b/src/lib/pubkey/ecies/ecies.cpp @@ -0,0 +1,399 @@ +/* +* ECIES +* (C) 2016 Philipp Weber +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/ecies.h> +#include <botan/cipher_mode.h> +#include <botan/pipe.h> + +#include <botan/internal/ct_utils.h> +#include <botan/internal/pk_utils.h> + +namespace Botan { + +namespace { + +/** +* Private key type for ECIES_ECDH_KA_Operation +*/ +class ECIES_PrivateKey : public EC_PrivateKey, public PK_Key_Agreement_Key + { + public: + explicit ECIES_PrivateKey(const ECDH_PrivateKey& private_key) : + EC_PublicKey(private_key), + EC_PrivateKey(private_key), + PK_Key_Agreement_Key(), + m_key(private_key) + { + } + + std::vector<byte> public_value() const override + { + return m_key.public_value(); + } + + std::string algo_name() const override + { + return "ECIES"; + } + + size_t max_input_bits() const override + { + return m_key.max_input_bits(); + } + + private: + ECDH_PrivateKey m_key; + }; + +/** +* Implements ECDH key agreement without using the cofactor mode +*/ +class ECIES_ECDH_KA_Operation : public PK_Ops::Key_Agreement_with_KDF + { + public: + typedef ECIES_PrivateKey Key_Type; + + ECIES_ECDH_KA_Operation(const ECIES_PrivateKey& private_key, const std::string&) : + PK_Ops::Key_Agreement_with_KDF("Raw"), + m_key(private_key) + { + } + + secure_vector<byte> raw_agree(const byte w[], size_t w_len) override + { + const CurveGFp& curve = m_key.domain().get_curve(); + PointGFp point = OS2ECP(w, w_len, curve); + PointGFp S = point * m_key.private_value(); + BOTAN_ASSERT(S.on_the_curve(), "ECDH agreed value was on the curve"); + return BigInt::encode_1363(S.get_affine_x(), curve.get_p().bytes()); + } + + private: + ECIES_PrivateKey m_key; + }; + +/** +* Creates a PK_Key_Agreement instance for the given key and ecies_params +* Returns either ECIES_ECDH_KA_Operation or the default implementation for the given key, +* depending on the key and ecies_params +* @param private_key the private key used for the key agreement +* @param ecies_params settings for ecies +* @param for_encryption disable cofactor mode if the secret will be used for encryption +* (according to ISO 18033 cofactor mode is only used during decryption) +*/ +PK_Key_Agreement create_key_agreement(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params, + bool for_encryption) + { + const ECDH_PrivateKey* ecdh_key = dynamic_cast<const ECDH_PrivateKey*>(&private_key); + + if(ecdh_key == nullptr && (ecies_params.cofactor_mode() || ecies_params.old_cofactor_mode() + || ecies_params.check_mode())) + { + // assume we have a private key from an external provider (e.g. pkcs#11): + // there is no way to determine or control whether the provider uses cofactor mode or not. + // ISO 18033 does not allow cofactor mode in combination with old cofactor mode or check mode + // => disable cofactor mode, old cofactor mode and check mode for unknown keys/providers (as a precaution). + throw Invalid_Argument("ECIES: cofactor, old cofactor and check mode are only supported for ECDH_PrivateKey"); + } + + if(ecdh_key && (for_encryption || !ecies_params.cofactor_mode())) + { + // ECDH_KA_Operation uses cofactor mode: use own key agreement method if cofactor should not be used. + return PK_Key_Agreement(ECIES_PrivateKey(*ecdh_key), "Raw"); + } + + return PK_Key_Agreement(private_key, "Raw"); // use default implementation + } +} + +BOTAN_REGISTER_PK_KEY_AGREE_OP("ECIES", ECIES_ECDH_KA_Operation); + +ECIES_KA_Operation::ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params, + bool for_encryption) : + m_ka(create_key_agreement(private_key, ecies_params, for_encryption)), + m_params(ecies_params) + { + } + +/** +* ECIES secret derivation according to ISO 18033-2 +*/ +SymmetricKey ECIES_KA_Operation::derive_secret(const std::vector<byte>& eph_public_key_bin, + const PointGFp& other_public_key_point) const + { + if(other_public_key_point.is_zero()) + { + throw Invalid_Argument("ECIES: other public key point is zero"); + } + + std::unique_ptr<KDF> kdf = m_params.create_kdf(); + BOTAN_ASSERT(kdf != nullptr, "KDF is found"); + + PointGFp other_point = other_public_key_point; + + // ISO 18033: step b + if(m_params.old_cofactor_mode()) + { + other_point *= m_params.domain().get_cofactor(); + } + + secure_vector<byte> derivation_input; + + // ISO 18033: encryption step e / decryption step g + if(!m_params.single_hash_mode()) + { + derivation_input += eph_public_key_bin; + } + + // ISO 18033: encryption step f / decryption step h + secure_vector<byte> other_public_key_bin = EC2OSP(other_point, static_cast<byte>(m_params.compression_type())); + // Note: the argument `m_params.secret_length()` passed for `key_len` will only be used by providers because + // "Raw" is passed to the `PK_Key_Agreement` if the implementation of botan is used. + const SymmetricKey peh = m_ka.derive_key(m_params.domain().get_order().bytes(), other_public_key_bin.data(), other_public_key_bin.size()); + derivation_input.insert(derivation_input.end(), peh.begin(), peh.end()); + + // ISO 18033: encryption step g / decryption step i + return kdf->derive_key(m_params.secret_length(), derivation_input); + } + + +ECIES_KA_Params::ECIES_KA_Params(const EC_Group& domain, const std::string& kdf_spec, size_t length, + PointGFp::Compression_Type compression_type, ECIES_Flags flags) : + m_domain(domain), + m_kdf_spec(kdf_spec), + m_length(length), + m_compression_mode(compression_type), + m_flags(flags) + { + } + +std::unique_ptr<KDF> ECIES_KA_Params::create_kdf() const + { + std::unique_ptr<KDF> kdf = Botan::KDF::create(m_kdf_spec); + if(kdf == nullptr) + { + throw Algorithm_Not_Found(m_kdf_spec); + } + return kdf; + } + + +ECIES_System_Params::ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, + const std::string& dem_algo_spec, size_t dem_key_len, + const std::string& mac_spec, size_t mac_key_len, + PointGFp::Compression_Type compression_type, ECIES_Flags flags) : + ECIES_KA_Params(domain, kdf_spec, dem_key_len + mac_key_len, compression_type, flags), + m_dem_spec(dem_algo_spec), + m_dem_keylen(dem_key_len), + m_mac_spec(mac_spec), + m_mac_keylen(mac_key_len) + { + // ISO 18033: "At most one of CofactorMode, OldCofactorMode, and CheckMode may be 1." + if(cofactor_mode() + old_cofactor_mode() + check_mode() > 1) + { + throw Invalid_Argument("ECIES: only one of cofactor_mode, old_cofactor_mode and check_mode can be set"); + } + } + +ECIES_System_Params::ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, + const std::string& dem_algo_spec, size_t dem_key_len, + const std::string& mac_spec, size_t mac_key_len) : + ECIES_System_Params(domain, kdf_spec, dem_algo_spec, dem_key_len, mac_spec, mac_key_len, PointGFp::UNCOMPRESSED, + ECIES_Flags::NONE) + { + } + +std::unique_ptr<MessageAuthenticationCode> ECIES_System_Params::create_mac() const + { + std::unique_ptr<MessageAuthenticationCode> mac = Botan::MessageAuthenticationCode::create(m_mac_spec); + if(mac == nullptr) + { + throw Algorithm_Not_Found(m_mac_spec); + } + return mac; + } + +std::unique_ptr<Keyed_Filter> ECIES_System_Params::create_cipher(Botan::Cipher_Dir direction) const + { + Keyed_Filter* cipher = get_cipher(m_dem_spec, direction); + if(cipher == nullptr) + { + throw Algorithm_Not_Found(m_dem_spec); + } + return std::unique_ptr<Keyed_Filter>(cipher); + } + + +/* +* ECIES_Encryptor Constructor +*/ +ECIES_Encryptor::ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params) : + m_ka(private_key, ecies_params, true), + m_params(ecies_params), + m_eph_public_key_bin(private_key.public_value()), // returns the uncompressed public key, see conversion below + m_iv(), + m_other_point(), + m_label() + { + if(ecies_params.compression_type() != PointGFp::UNCOMPRESSED) + { + // ISO 18033: step d + // convert only if necessary; m_eph_public_key_bin has been initialized with the uncompressed format + m_eph_public_key_bin = unlock(EC2OSP(OS2ECP(m_eph_public_key_bin, m_params.domain().get_curve()), + static_cast<byte>(ecies_params.compression_type()))); + } + } + +/* +* ECIES_Encryptor Constructor +*/ +ECIES_Encryptor::ECIES_Encryptor(RandomNumberGenerator& rng, const ECIES_System_Params& ecies_params) : + ECIES_Encryptor(ECDH_PrivateKey(rng, ecies_params.domain()), ecies_params) + { + } + + +/* +* ECIES Encryption according to ISO 18033-2 +*/ +std::vector<byte> ECIES_Encryptor::enc(const byte data[], size_t length, RandomNumberGenerator&) const + { + if(m_other_point.is_zero()) + { + throw Invalid_State("ECIES: the other key is zero"); + } + + const SymmetricKey secret_key = m_ka.derive_secret(m_eph_public_key_bin, m_other_point); + + // encryption + std::unique_ptr<Keyed_Filter> cipher = m_params.create_cipher(ENCRYPTION); + BOTAN_ASSERT(cipher != nullptr, "Cipher is found"); + + cipher->set_key(SymmetricKey(secret_key.begin(), m_params.dem_keylen())); + if(m_iv.size() != 0) + { + cipher->set_iv(m_iv); + } + Pipe pipe(cipher.release()); + pipe.process_msg(data, length); + const secure_vector<byte> encrypted_data = pipe.read_all(0); + + // concat elements + std::unique_ptr<MessageAuthenticationCode> mac = m_params.create_mac(); + BOTAN_ASSERT(mac != nullptr, "MAC is found"); + + secure_vector<byte> out(m_eph_public_key_bin.size() + encrypted_data.size() + mac->output_length()); + buffer_insert(out, 0, m_eph_public_key_bin); + buffer_insert(out, m_eph_public_key_bin.size(), encrypted_data); + + // mac + mac->set_key(secret_key.begin() + m_params.dem_keylen(), m_params.mac_keylen()); + mac->update(encrypted_data); + if(!m_label.empty()) + { + mac->update(m_label); + } + mac->final(out.data() + m_eph_public_key_bin.size() + encrypted_data.size()); + + return unlock(out); + } + + +ECIES_Decryptor::ECIES_Decryptor(const PK_Key_Agreement_Key& key, const ECIES_System_Params& ecies_params) : + m_ka(key, ecies_params, false), + m_params(ecies_params), + m_iv(), + m_label() + { + // ISO 18033: "If v > 1 and CheckMode = 0, then we must have gcd(�, v) = 1." (v = index, � = order) + if(!ecies_params.check_mode()) + { + Botan::BigInt cofactor = m_params.domain().get_cofactor(); + if(cofactor > 1 && Botan::gcd(cofactor, m_params.domain().get_order()) != 1) + { + throw Invalid_Argument("ECIES: gcd of cofactor and order must be 1 if check_mode is 0"); + } + } + } + +/** +* ECIES Decryption according to ISO 18033-2 +*/ +secure_vector<byte> ECIES_Decryptor::do_decrypt(byte& valid_mask, const byte in[], size_t in_len) const + { + size_t point_size = m_params.domain().get_curve().get_p().bytes(); + if(m_params.compression_type() != PointGFp::COMPRESSED) + { + point_size *= 2; // uncompressed and hybrid contains x AND y + } + point_size += 1; // format byte + + std::unique_ptr<MessageAuthenticationCode> mac = m_params.create_mac(); + BOTAN_ASSERT(mac != nullptr, "MAC is found"); + + if(in_len < point_size + mac->output_length()) + { + throw Decoding_Error("ECIES decryption: ciphertext is too short"); + } + + // extract data + const std::vector<byte> other_public_key_bin(in, in + point_size); // the received (ephemeral) public key + const std::vector<byte> encrypted_data(in + point_size, in + in_len - mac->output_length()); + const std::vector<byte> mac_data(in + in_len - mac->output_length(), in + in_len); + + // ISO 18033: step a + PointGFp other_public_key = OS2ECP(other_public_key_bin, m_params.domain().get_curve()); + + // ISO 18033: step b + if(m_params.check_mode() && !other_public_key.on_the_curve()) + { + throw Decoding_Error("ECIES decryption: received public key is not on the curve"); + } + + // ISO 18033: step e (and step f because get_affine_x (called by ECDH_KA_Operation::raw_agree) + // throws Illegal_Transformation if the point is zero) + const SymmetricKey secret_key = m_ka.derive_secret(other_public_key_bin, other_public_key); + + // validate mac + mac->set_key(secret_key.begin() + m_params.dem_keylen(), m_params.mac_keylen()); + mac->update(encrypted_data); + if(!m_label.empty()) + { + mac->update(m_label); + } + const secure_vector<byte> calculated_mac = mac->final(); + valid_mask = CT::expand_mask<byte>(same_mem(mac_data.data(), calculated_mac.data(), mac_data.size())); + + if(valid_mask) + { + // decrypt data + std::unique_ptr<Keyed_Filter> cipher = m_params.create_cipher(DECRYPTION); + BOTAN_ASSERT(cipher != nullptr, "Cipher is found"); + + cipher->set_key(SymmetricKey(secret_key.begin(), m_params.dem_keylen())); + if(m_iv.size() != 0) + { + cipher->set_iv(m_iv); + } + + try + { + // the decryption can fail: + // e.g. Integrity_Failure is thrown if GCM is used and the message does not have a valid tag + Pipe pipe(cipher.release()); + pipe.process_msg(encrypted_data); + return pipe.read_all(0); + } + catch(...) + { + valid_mask = 0; + } + } + return secure_vector<byte>(); + } + +} diff --git a/src/lib/pubkey/ecies/ecies.h b/src/lib/pubkey/ecies/ecies.h new file mode 100644 index 000000000..07937556c --- /dev/null +++ b/src/lib/pubkey/ecies/ecies.h @@ -0,0 +1,293 @@ +/* +* ECIES +* (C) 2016 Philipp Weber +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_ECIES_H__ +#define BOTAN_ECIES_H__ + +#include <botan/ecdh.h> +#include <botan/ec_group.h> +#include <botan/kdf.h> +#include <botan/key_filt.h> +#include <botan/mac.h> +#include <botan/point_gfp.h> +#include <botan/pubkey.h> +#include <botan/secmem.h> +#include <botan/symkey.h> +#include <memory> +#include <string> +#include <vector> + +namespace Botan { + +class RandomNumberGenerator; + +enum class ECIES_Flags : uint32_t + { + NONE = 0, + + /// if set: prefix the input of the (ecdh) key agreement with the encoded (ephemeral) public key + SINGLE_HASH_MODE = 1, + + /// (decryption only) if set: use cofactor multiplication during (ecdh) key agreement + COFACTOR_MODE = 2, + + /// if set: use ecdhc instead of ecdh + OLD_COFACTOR_MODE = 4, + + /// (decryption only) if set: test if the (ephemeral) public key is on the curve + CHECK_MODE = 8 + }; + +inline ECIES_Flags operator |(ECIES_Flags a, ECIES_Flags b) + { + return static_cast<ECIES_Flags>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b)); + } + +inline ECIES_Flags operator &(ECIES_Flags a, ECIES_Flags b) + { + return static_cast<ECIES_Flags>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b)); + } + +/** +* Parameters for ecies secret derivation +*/ +class BOTAN_DLL ECIES_KA_Params + { + public: + /** + * @param domain ec domain parameters of the involved ec keys + * @param kdf_spec name of the key derivation function + * @param length length of the secret to be derived + * @param compression_type format of encoded keys (affects the secret derivation if single_hash_mode is used) + * @param flags options, see documentation of ECIES_Flags + */ + ECIES_KA_Params(const EC_Group& domain, const std::string& kdf_spec, size_t length, + PointGFp::Compression_Type compression_type, ECIES_Flags flags); + + virtual ~ECIES_KA_Params() = default; + + std::unique_ptr<KDF> create_kdf() const; + + inline const EC_Group& domain() const + { + return m_domain; + } + + inline size_t secret_length() const + { + return m_length; + } + + inline bool single_hash_mode() const + { + return (m_flags & ECIES_Flags::SINGLE_HASH_MODE) == ECIES_Flags::SINGLE_HASH_MODE; + } + + inline bool cofactor_mode() const + { + return (m_flags & ECIES_Flags::COFACTOR_MODE) == ECIES_Flags::COFACTOR_MODE; + } + + inline bool old_cofactor_mode() const + { + return (m_flags & ECIES_Flags::OLD_COFACTOR_MODE) == ECIES_Flags::OLD_COFACTOR_MODE; + } + + inline bool check_mode() const + { + return (m_flags & ECIES_Flags::CHECK_MODE) == ECIES_Flags::CHECK_MODE; + } + + inline PointGFp::Compression_Type compression_type() const + { + return m_compression_mode; + } + + private: + const EC_Group m_domain; + const std::string m_kdf_spec; + const size_t m_length; + const PointGFp::Compression_Type m_compression_mode; + const ECIES_Flags m_flags; + }; + + +class BOTAN_DLL ECIES_System_Params : public ECIES_KA_Params + { + public: + /** + * @param domain ec domain parameters of the involved ec keys + * @param kdf_spec name of the key derivation function + * @param dem_algo_spec name of the data encryption method + * @param dem_key_len length of the key used for the data encryption method + * @param mac_spec name of the message authentication code + * @param mac_key_len length of the key used for the message authentication code + * @param compression_type format of encoded keys (affects the secret derivation if single_hash_mode is used) + * @param flags options, see documentation of ECIES_Flags + */ + ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, const std::string& dem_algo_spec, + size_t dem_key_len, const std::string& mac_spec, size_t mac_key_len); + + /** + * @param domain ec domain parameters of the involved ec keys + * @param kdf_spec name of the key derivation function + * @param dem_algo_spec name of the data encryption method + * @param dem_key_len length of the key used for the data encryption method + * @param mac_spec name of the message authentication code + * @param mac_key_len length of the key used for the message authentication code + */ + ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, const std::string& dem_algo_spec, + size_t dem_key_len, const std::string& mac_spec, size_t mac_key_len, + PointGFp::Compression_Type compression_type, ECIES_Flags flags); + + virtual ~ECIES_System_Params() = default; + + /// creates an instance of the message authentication code + std::unique_ptr<MessageAuthenticationCode> create_mac() const; + + /// creates an instance of the data encryption method + std::unique_ptr<Keyed_Filter> create_cipher(Botan::Cipher_Dir direction) const; + + /// returns the length of the key used by the data encryption method + inline size_t dem_keylen() const + { + return m_dem_keylen; + } + + /// returns the length of the key used by the message authentication code + inline size_t mac_keylen() const + { + return m_mac_keylen; + } + + private: + const std::string m_dem_spec; + const size_t m_dem_keylen; + const std::string m_mac_spec; + const size_t m_mac_keylen; + }; + + +/** +* ECIES secret derivation according to ISO 18033-2 +*/ +class BOTAN_DLL ECIES_KA_Operation + { + public: + /** + * @param private_key the (ephemeral) private key which is used to derive the secret + * @param ecies_params settings for ecies + * @param for_encryption disable cofactor mode if the secret will be used for encryption + * (according to ISO 18033 cofactor mode is only used during decryption) + */ + ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params, + bool for_encryption); + + /** + * Performs a key agreement with the provided keys and derives the secret from the result + * @param eph_public_key_bin the encoded (ephemeral) public key which belongs to the used (ephemeral) private key + * @param other_public_key_point public key point of the other party + */ + SymmetricKey derive_secret(const std::vector<byte>& eph_public_key_bin, + const PointGFp& other_public_key_point) const; + + private: + const PK_Key_Agreement m_ka; + const ECIES_KA_Params m_params; + }; + + +/** +* ECIES Encryption according to ISO 18033-2 +*/ +class BOTAN_DLL ECIES_Encryptor : public PK_Encryptor + { + public: + /** + * @param private_key the (ephemeral) private key which is used for the key agreement + * @param ecies_params settings for ecies + */ + ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params); + + /** + * Creates an ephemeral private key which is used for the key agreement + * @param rng random generator used during private key generation + * @param ecies_params settings for ecies + */ + ECIES_Encryptor(RandomNumberGenerator& rng, const ECIES_System_Params& ecies_params); + + /// Set the public key of the other party + inline void set_other_key(const Botan::PointGFp& public_point) + { + m_other_point = public_point; + } + + /// Set the initialization vector for the data encryption method + inline void set_initialization_vector(const InitializationVector& iv) + { + m_iv = iv; + } + + /// Set the label which is appended to the input for the message authentication code + inline void set_label(const std::string& label) + { + m_label = std::vector<byte>(label.begin(), label.end()); + } + + private: + std::vector<byte> enc(const byte data[], size_t length, RandomNumberGenerator&) const override; + + inline size_t maximum_input_size() const override + { + return std::numeric_limits<size_t>::max(); + } + + const ECIES_KA_Operation m_ka; + const ECIES_System_Params m_params; + std::vector<byte> m_eph_public_key_bin; + InitializationVector m_iv; + PointGFp m_other_point; + std::vector<byte> m_label; + }; + + +/** +* ECIES Decryption according to ISO 18033-2 +*/ +class BOTAN_DLL ECIES_Decryptor : public PK_Decryptor + { + public: + /** + * @param private_key the private key which is used for the key agreement + * @param ecies_params settings for ecies + */ + ECIES_Decryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params); + + /// Set the initialization vector for the data encryption method + inline void set_initialization_vector(const InitializationVector& iv) + { + m_iv = iv; + } + + /// Set the label which is appended to the input for the message authentication code + inline void set_label(const std::string& label) + { + m_label = std::vector<byte>(label.begin(), label.end()); + } + + private: + secure_vector<byte> do_decrypt(byte& valid_mask, const byte in[], size_t in_len) const; + + const ECIES_KA_Operation m_ka; + const ECIES_System_Params m_params; + InitializationVector m_iv; + std::vector<byte> m_label; + }; + +} + +#endif diff --git a/src/lib/pubkey/ecies/info.txt b/src/lib/pubkey/ecies/info.txt new file mode 100644 index 000000000..dacefc88a --- /dev/null +++ b/src/lib/pubkey/ecies/info.txt @@ -0,0 +1,9 @@ +define ECIES 20160128 + +<requires> +kdf +mac +ecdh +modes +filters +</requires>
\ No newline at end of file diff --git a/src/lib/pubkey/rsa/info.txt b/src/lib/pubkey/rsa/info.txt index 264ff7c62..91eec565a 100644 --- a/src/lib/pubkey/rsa/info.txt +++ b/src/lib/pubkey/rsa/info.txt @@ -4,4 +4,6 @@ define RSA 20131128 if_algo keypair numbertheory +emsa_pssr +sha2_32 </requires> diff --git a/src/lib/pubkey/rsa/rsa.cpp b/src/lib/pubkey/rsa/rsa.cpp index e12586014..6a645ec88 100644 --- a/src/lib/pubkey/rsa/rsa.cpp +++ b/src/lib/pubkey/rsa/rsa.cpp @@ -58,7 +58,7 @@ bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const if((m_e * m_d) % lcm(m_p - 1, m_q - 1) != 1) return false; - return KeyPair::signature_consistency_check(rng, *this, "EMSA4(SHA-1)"); + return KeyPair::signature_consistency_check(rng, *this, "EMSA4(SHA-256)"); } namespace { diff --git a/src/lib/stream/chacha/chacha.cpp b/src/lib/stream/chacha/chacha.cpp index ac81fd70d..40da93029 100644 --- a/src/lib/stream/chacha/chacha.cpp +++ b/src/lib/stream/chacha/chacha.cpp @@ -12,8 +12,8 @@ namespace Botan { ChaCha::ChaCha(size_t rounds) : m_rounds(rounds) { - if(m_rounds != 12 && m_rounds != 20) - throw Invalid_Argument("ChaCha only supports 12 or 20 rounds"); + if(m_rounds != 8 && m_rounds != 12 && m_rounds != 20) + throw Invalid_Argument("ChaCha only supports 8, 12 or 20 rounds"); } namespace { @@ -67,7 +67,6 @@ void chacha(byte output[64], const u32bit input[16], size_t rounds) store_le(x14 + input[14], output + 4 * 14); store_le(x15 + input[15], output + 4 * 15); } - } /* @@ -173,4 +172,27 @@ std::string ChaCha::name() const return "ChaCha(" + std::to_string(m_rounds) + ")"; } +void ChaCha::seek(u64bit offset) + { + if (m_state.size() == 0 && m_buffer.size() == 0) + { + throw Invalid_State("You have to setup the stream cipher (key and iv)"); + } + + m_position = offset % m_buffer.size(); + + u64bit counter = offset / m_buffer.size(); + + byte out[8]; + + store_le(counter, out); + + m_state[12] = load_le<u32bit>(out, 0); + m_state[13] += load_le<u32bit>(out, 1); + + chacha(m_buffer.data(), m_state.data(), m_rounds); + + ++m_state[12]; + m_state[13] += (m_state[12] == 0); + } } diff --git a/src/lib/stream/chacha/chacha.h b/src/lib/stream/chacha/chacha.h index ba93d6260..f8f42e41d 100644 --- a/src/lib/stream/chacha/chacha.h +++ b/src/lib/stream/chacha/chacha.h @@ -21,7 +21,7 @@ class BOTAN_DLL ChaCha final : public StreamCipher StreamCipher* clone() const override { return new ChaCha(m_rounds); } /** - * Currently only 12 or 20 rounds are supported, all others + * Currently only 8, 12 or 20 rounds are supported, all others * will throw an exception */ ChaCha(size_t rounds); @@ -42,6 +42,8 @@ class BOTAN_DLL ChaCha final : public StreamCipher std::string name() const override; + void seek(u64bit offset) override; + private: void key_schedule(const byte key[], size_t key_len) override; diff --git a/src/lib/stream/ctr/ctr.cpp b/src/lib/stream/ctr/ctr.cpp index f5301c099..43609ba2d 100644 --- a/src/lib/stream/ctr/ctr.cpp +++ b/src/lib/stream/ctr/ctr.cpp @@ -125,4 +125,8 @@ void CTR_BE::increment_counter() m_pad_pos = 0; } +void CTR_BE::seek(u64bit) + { + throw Not_Implemented("CTR_BE::seek"); + } } diff --git a/src/lib/stream/ctr/ctr.h b/src/lib/stream/ctr/ctr.h index 003297b92..5d5556254 100644 --- a/src/lib/stream/ctr/ctr.h +++ b/src/lib/stream/ctr/ctr.h @@ -46,6 +46,8 @@ class BOTAN_DLL CTR_BE final : public StreamCipher explicit CTR_BE(BlockCipher* cipher); CTR_BE(BlockCipher* cipher, size_t ctr_size); + + void seek(u64bit offset) override; private: void key_schedule(const byte key[], size_t key_len) override; void increment_counter(); diff --git a/src/lib/stream/ofb/ofb.cpp b/src/lib/stream/ofb/ofb.cpp index e8cb463db..3337a0c14 100644 --- a/src/lib/stream/ofb/ofb.cpp +++ b/src/lib/stream/ofb/ofb.cpp @@ -73,4 +73,9 @@ void OFB::set_iv(const byte iv[], size_t iv_len) m_buf_pos = 0; } + +void OFB::seek(u64bit) + { + throw Exception("OFB does not support seeking"); + } } diff --git a/src/lib/stream/ofb/ofb.h b/src/lib/stream/ofb/ofb.h index fecd47d9d..127a06578 100644 --- a/src/lib/stream/ofb/ofb.h +++ b/src/lib/stream/ofb/ofb.h @@ -44,6 +44,8 @@ class BOTAN_DLL OFB final : public StreamCipher * @param cipher the underlying block cipher to use */ explicit OFB(BlockCipher* cipher); + + void seek(u64bit offset) override; private: void key_schedule(const byte key[], size_t key_len) override; diff --git a/src/lib/stream/rc4/rc4.cpp b/src/lib/stream/rc4/rc4.cpp index 895f38091..a4dea9e2b 100644 --- a/src/lib/stream/rc4/rc4.cpp +++ b/src/lib/stream/rc4/rc4.cpp @@ -113,4 +113,8 @@ void RC4::clear() */ RC4::RC4(size_t s) : m_SKIP(s) {} +void RC4::seek(u64bit) + { + throw Exception("RC4 does not support seeking"); + } } diff --git a/src/lib/stream/rc4/rc4.h b/src/lib/stream/rc4/rc4.h index f166a2772..88798fae6 100644 --- a/src/lib/stream/rc4/rc4.h +++ b/src/lib/stream/rc4/rc4.h @@ -39,6 +39,8 @@ class BOTAN_DLL RC4 final : public StreamCipher explicit RC4(size_t skip = 0); ~RC4() { clear(); } + + void seek(u64bit offset) override; private: void key_schedule(const byte[], size_t) override; void generate(); diff --git a/src/lib/stream/salsa20/salsa20.cpp b/src/lib/stream/salsa20/salsa20.cpp index 1d3fe3d28..f11fe5e59 100644 --- a/src/lib/stream/salsa20/salsa20.cpp +++ b/src/lib/stream/salsa20/salsa20.cpp @@ -227,4 +227,8 @@ void Salsa20::clear() m_position = 0; } +void Salsa20::seek(u64bit) + { + throw Not_Implemented("Salsa20::seek"); + } } diff --git a/src/lib/stream/salsa20/salsa20.h b/src/lib/stream/salsa20/salsa20.h index 7e75470da..8256ea4db 100644 --- a/src/lib/stream/salsa20/salsa20.h +++ b/src/lib/stream/salsa20/salsa20.h @@ -33,6 +33,8 @@ class BOTAN_DLL Salsa20 final : public StreamCipher void clear() override; std::string name() const override; StreamCipher* clone() const override { return new Salsa20; } + + void seek(u64bit offset) override; private: void key_schedule(const byte key[], size_t key_len) override; diff --git a/src/lib/stream/stream_cipher.h b/src/lib/stream/stream_cipher.h index bff1fd1a6..56bd2d5d9 100644 --- a/src/lib/stream/stream_cipher.h +++ b/src/lib/stream/stream_cipher.h @@ -80,6 +80,12 @@ class BOTAN_DLL StreamCipher : public SymmetricAlgorithm */ virtual StreamCipher* clone() const = 0; + /** + * Set the offset and the state used later to generate the keystream + * @param offset the offset where we begin to generate the keystream + */ + virtual void seek(u64bit offset) = 0; + StreamCipher(); virtual ~StreamCipher(); }; diff --git a/src/lib/tls/msg_finished.cpp b/src/lib/tls/msg_finished.cpp index 2d6b11995..3a2c88fb1 100644 --- a/src/lib/tls/msg_finished.cpp +++ b/src/lib/tls/msg_finished.cpp @@ -31,14 +31,15 @@ std::vector<byte> finished_compute_verify(const Handshake_State& state, std::unique_ptr<KDF> prf(state.protocol_specific_prf()); std::vector<byte> input; + std::vector<byte> label; if(side == CLIENT) - input += std::make_pair(TLS_CLIENT_LABEL, sizeof(TLS_CLIENT_LABEL)); + label += std::make_pair(TLS_CLIENT_LABEL, sizeof(TLS_CLIENT_LABEL)); else - input += std::make_pair(TLS_SERVER_LABEL, sizeof(TLS_SERVER_LABEL)); + label += std::make_pair(TLS_SERVER_LABEL, sizeof(TLS_SERVER_LABEL)); input += state.hash().final(state.version(), state.ciphersuite().prf_algo()); - return unlock(prf->derive_key(12, state.session_keys().master_secret(), input)); + return unlock(prf->derive_key(12, state.session_keys().master_secret(), input, label)); } } diff --git a/src/lib/tls/tls_channel.cpp b/src/lib/tls/tls_channel.cpp index 5afdd6074..f445eef99 100644 --- a/src/lib/tls/tls_channel.cpp +++ b/src/lib/tls/tls_channel.cpp @@ -621,7 +621,6 @@ SymmetricKey Channel::key_material_export(const std::string& label, active->session_keys().master_secret(); std::vector<byte> salt; - salt += to_byte_vector(label); salt += active->client_hello()->random(); salt += active->server_hello()->random(); @@ -635,7 +634,7 @@ SymmetricKey Channel::key_material_export(const std::string& label, salt += to_byte_vector(context); } - return prf->derive_key(length, master_secret, salt); + return prf->derive_key(length, master_secret, salt, to_byte_vector(label)); } else throw Exception("Channel::key_material_export connection not active"); diff --git a/src/lib/tls/tls_ciphersuite.cpp b/src/lib/tls/tls_ciphersuite.cpp index 20142adc5..1d5b9da40 100644 --- a/src/lib/tls/tls_ciphersuite.cpp +++ b/src/lib/tls/tls_ciphersuite.cpp @@ -48,46 +48,12 @@ const std::vector<Ciphersuite>& Ciphersuite::all_known_ciphersuites() return all_ciphersuites; } -Ciphersuite Ciphersuite::by_name(const std::string& name) - { - for(auto suite : all_known_ciphersuites()) - { - if(suite.to_string() == name) - return suite; - } - - return Ciphersuite(); // some unknown ciphersuite - } - bool Ciphersuite::is_scsv(u16bit suite) { // TODO: derive from IANA file in script return (suite == 0x00FF || suite == 0x5600); } -Ciphersuite::Ciphersuite(u16bit ciphersuite_code, - const char* sig_algo, - const char* kex_algo, - const char* cipher_algo, - size_t cipher_keylen, - size_t nonce_bytes_from_handshake, - size_t nonce_bytes_from_record, - const char* mac_algo, - size_t mac_keylen, - const char* prf_algo) : - m_ciphersuite_code(ciphersuite_code), - m_sig_algo(sig_algo), - m_kex_algo(kex_algo), - m_prf_algo(prf_algo), - m_cipher_algo(cipher_algo), - m_cipher_keylen(cipher_keylen), - m_nonce_bytes_from_handshake(nonce_bytes_from_handshake), - m_nonce_bytes_from_record(nonce_bytes_from_record), - m_mac_algo(mac_algo), - m_mac_keylen(mac_keylen) - { - } - bool Ciphersuite::psk_ciphersuite() const { return (kex_algo() == "PSK" || @@ -206,73 +172,6 @@ bool Ciphersuite::valid() const return true; } -std::string Ciphersuite::to_string() const - { - if(m_cipher_keylen == 0) - throw Exception("Ciphersuite::to_string - no value set"); - - std::ostringstream out; - - out << "TLS_"; - - if(kex_algo() != "RSA") - { - if(kex_algo() == "DH") - out << "DHE"; - else if(kex_algo() == "ECDH") - out << "ECDHE"; - else - out << kex_algo(); - - out << '_'; - } - - if(sig_algo() == "DSA") - out << "DSS_"; - else if(sig_algo() != "") - out << sig_algo() << '_'; - - out << "WITH_"; - - if(cipher_algo() == "RC4") - { - out << "RC4_128_"; - } - else if(cipher_algo() == "ChaCha20Poly1305") - { - out << "CHACHA20_POLY1305_"; - } - else - { - if(cipher_algo() == "3DES") - out << "3DES_EDE"; - else if(cipher_algo().find("Camellia") == 0) - out << "CAMELLIA_" << std::to_string(8*cipher_keylen()); - else - { - if(cipher_algo().find("OCB(12)") != std::string::npos) - out << replace_chars(cipher_algo().substr(0, cipher_algo().size() - 4), - {'-', '/'}, '_'); - else - out << replace_chars(cipher_algo(), {'-', '/'}, '_'); - } - - if(cipher_algo().find("/") != std::string::npos) - out << "_"; // some explicit mode already included - else - out << "_CBC_"; - } - - if(mac_algo() == "SHA-1") - out << "SHA"; - else if(mac_algo() == "AEAD") - out << erase_chars(prf_algo(), {'-'}); - else - out << erase_chars(mac_algo(), {'-'}); - - return out.str(); - } - } } diff --git a/src/lib/tls/tls_ciphersuite.h b/src/lib/tls/tls_ciphersuite.h index 355dd5a8f..1f646cc7e 100644 --- a/src/lib/tls/tls_ciphersuite.h +++ b/src/lib/tls/tls_ciphersuite.h @@ -31,17 +31,15 @@ class BOTAN_DLL Ciphersuite static std::vector<u16bit> all_known_ciphersuite_ids(); - /** - * Returns true iff this suite is a known SCSV + /* + * Returns the compiled in list of cipher suites. */ - static bool is_scsv(u16bit suite); + static const std::vector<Ciphersuite>& all_cipher_suites(); /** - * Lookup a ciphersuite by name - * @param name the name (eg TLS_RSA_WITH_RC4_128_SHA) - * @return ciphersuite object + * Returns true iff this suite is a known SCSV */ - static Ciphersuite by_name(const std::string& name); + static bool is_scsv(u16bit suite); /** * Generate a static list of all known ciphersuites and return it. @@ -54,7 +52,7 @@ class BOTAN_DLL Ciphersuite * Formats the ciphersuite back to an RFC-style ciphersuite string * @return RFC ciphersuite string identifier */ - std::string to_string() const; + std::string to_string() const { return m_iana_id; } /** * @return ciphersuite number @@ -74,26 +72,28 @@ class BOTAN_DLL Ciphersuite /** * @return key exchange algorithm used by this ciphersuite */ - const std::string& kex_algo() const { return m_kex_algo; } + std::string kex_algo() const { return m_kex_algo; } /** * @return signature algorithm used by this ciphersuite */ - const std::string& sig_algo() const { return m_sig_algo; } + std::string sig_algo() const { return m_sig_algo; } /** * @return symmetric cipher algorithm used by this ciphersuite */ - const std::string& cipher_algo() const { return m_cipher_algo; } + std::string cipher_algo() const { return m_cipher_algo; } /** * @return message authentication algorithm used by this ciphersuite */ - const std::string& mac_algo() const { return m_mac_algo; } + std::string mac_algo() const { return m_mac_algo; } - const std::string& prf_algo() const + std::string prf_algo() const { - return (!m_prf_algo.empty()) ? m_prf_algo : m_mac_algo; + if(m_prf_algo && *m_prf_algo) + return m_prf_algo; + return m_mac_algo; } /** @@ -116,7 +116,9 @@ class BOTAN_DLL Ciphersuite private: + Ciphersuite(u16bit ciphersuite_code, + const char* iana_id, const char* sig_algo, const char* kex_algo, const char* cipher_algo, @@ -125,20 +127,39 @@ class BOTAN_DLL Ciphersuite size_t nonce_bytes_from_record, const char* mac_algo, size_t mac_keylen, - const char* prf_algo = ""); + const char* prf_algo) : + m_ciphersuite_code(ciphersuite_code), + m_iana_id(iana_id), + m_sig_algo(sig_algo), + m_kex_algo(kex_algo), + m_prf_algo(prf_algo), + m_cipher_algo(cipher_algo), + m_mac_algo(mac_algo), + m_cipher_keylen(cipher_keylen), + m_nonce_bytes_from_handshake(nonce_bytes_from_handshake), + m_nonce_bytes_from_record(nonce_bytes_from_record), + m_mac_keylen(mac_keylen) + { + } u16bit m_ciphersuite_code = 0; - std::string m_sig_algo; - std::string m_kex_algo; - std::string m_prf_algo; + /* + All of these const char* strings are references to compile time + constants in tls_suite_info.cpp + */ + const char* m_iana_id; + + const char* m_sig_algo; + const char* m_kex_algo; + const char* m_prf_algo; + + const char* m_cipher_algo; + const char* m_mac_algo; - std::string m_cipher_algo; size_t m_cipher_keylen = 0; size_t m_nonce_bytes_from_handshake = 0; size_t m_nonce_bytes_from_record = 0; - - std::string m_mac_algo; size_t m_mac_keylen = 0; }; diff --git a/src/lib/tls/tls_session_key.cpp b/src/lib/tls/tls_session_key.cpp index 0e796aa23..193af8d9f 100644 --- a/src/lib/tls/tls_session_key.cpp +++ b/src/lib/tls/tls_session_key.cpp @@ -48,28 +48,30 @@ Session_Keys::Session_Keys(const Handshake_State* state, else { secure_vector<byte> salt; + secure_vector<byte> label; if(extended_master_secret) { - salt += std::make_pair(EXT_MASTER_SECRET_MAGIC, sizeof(EXT_MASTER_SECRET_MAGIC)); + label += std::make_pair(EXT_MASTER_SECRET_MAGIC, sizeof(EXT_MASTER_SECRET_MAGIC)); salt += state->hash().final(state->version(), state->ciphersuite().prf_algo()); } else { - salt += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC)); + label += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC)); salt += state->client_hello()->random(); salt += state->server_hello()->random(); } - m_master_sec = prf->derive_key(48, pre_master_secret, salt); + m_master_sec = prf->derive_key(48, pre_master_secret, salt, label); } secure_vector<byte> salt; - salt += std::make_pair(KEY_GEN_MAGIC, sizeof(KEY_GEN_MAGIC)); + secure_vector<byte> label; + label += std::make_pair(KEY_GEN_MAGIC, sizeof(KEY_GEN_MAGIC)); salt += state->server_hello()->random(); salt += state->client_hello()->random(); - SymmetricKey keyblock = prf->derive_key(prf_gen, m_master_sec, salt); + SymmetricKey keyblock = prf->derive_key(prf_gen, m_master_sec, salt, label); const byte* key_data = keyblock.begin(); diff --git a/src/lib/tls/tls_suite_info.cpp b/src/lib/tls/tls_suite_info.cpp index 0d08710e8..24f9584c8 100644 --- a/src/lib/tls/tls_suite_info.cpp +++ b/src/lib/tls/tls_suite_info.cpp @@ -2,8 +2,8 @@ * TLS cipher suite information * * This file was automatically generated from the IANA assignments -* (tls-parameters.txt hash fe280cb8b13bfdd306a975ab39fda238f77ae3bc) -* by ./src/scripts/tls_suite_info.py on 2016-04-04 +* (tls-parameters.txt hash 9f03ae0e3c6b9931e49b8a6259461fa19f4c145a) +* by ./src/scripts/tls_suite_info.py on 2016-06-09 * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -184,485 +184,485 @@ Ciphersuite Ciphersuite::by_id(u16bit suite) { switch(suite) { - case 0x000A: // RSA_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0x000A, "RSA", "RSA", "3DES", 24, 8, 0, "SHA-1", 20); + case 0x000A: + return Ciphersuite(0x000A, "RSA_WITH_3DES_EDE_CBC_SHA", "RSA", "RSA", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0x0013: // DHE_DSS_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0x0013, "DSA", "DH", "3DES", 24, 8, 0, "SHA-1", 20); + case 0x0013: + return Ciphersuite(0x0013, "DHE_DSS_WITH_3DES_EDE_CBC_SHA", "DSA", "DH", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0x0016: // DHE_RSA_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0x0016, "RSA", "DH", "3DES", 24, 8, 0, "SHA-1", 20); + case 0x0016: + return Ciphersuite(0x0016, "DHE_RSA_WITH_3DES_EDE_CBC_SHA", "RSA", "DH", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0x001B: // DH_anon_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0x001B, "", "DH", "3DES", 24, 8, 0, "SHA-1", 20); + case 0x001B: + return Ciphersuite(0x001B, "DH_anon_WITH_3DES_EDE_CBC_SHA", "", "DH", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0x002F: // RSA_WITH_AES_128_CBC_SHA - return Ciphersuite(0x002F, "RSA", "RSA", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0x002F: + return Ciphersuite(0x002F, "RSA_WITH_AES_128_CBC_SHA", "RSA", "RSA", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0x0032: // DHE_DSS_WITH_AES_128_CBC_SHA - return Ciphersuite(0x0032, "DSA", "DH", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0x0032: + return Ciphersuite(0x0032, "DHE_DSS_WITH_AES_128_CBC_SHA", "DSA", "DH", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0x0033: // DHE_RSA_WITH_AES_128_CBC_SHA - return Ciphersuite(0x0033, "RSA", "DH", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0x0033: + return Ciphersuite(0x0033, "DHE_RSA_WITH_AES_128_CBC_SHA", "RSA", "DH", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0x0034: // DH_anon_WITH_AES_128_CBC_SHA - return Ciphersuite(0x0034, "", "DH", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0x0034: + return Ciphersuite(0x0034, "DH_anon_WITH_AES_128_CBC_SHA", "", "DH", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0x0035: // RSA_WITH_AES_256_CBC_SHA - return Ciphersuite(0x0035, "RSA", "RSA", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0x0035: + return Ciphersuite(0x0035, "RSA_WITH_AES_256_CBC_SHA", "RSA", "RSA", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0x0038: // DHE_DSS_WITH_AES_256_CBC_SHA - return Ciphersuite(0x0038, "DSA", "DH", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0x0038: + return Ciphersuite(0x0038, "DHE_DSS_WITH_AES_256_CBC_SHA", "DSA", "DH", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0x0039: // DHE_RSA_WITH_AES_256_CBC_SHA - return Ciphersuite(0x0039, "RSA", "DH", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0x0039: + return Ciphersuite(0x0039, "DHE_RSA_WITH_AES_256_CBC_SHA", "RSA", "DH", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0x003A: // DH_anon_WITH_AES_256_CBC_SHA - return Ciphersuite(0x003A, "", "DH", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0x003A: + return Ciphersuite(0x003A, "DH_anon_WITH_AES_256_CBC_SHA", "", "DH", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0x003C: // RSA_WITH_AES_128_CBC_SHA256 - return Ciphersuite(0x003C, "RSA", "RSA", "AES-128", 16, 16, 0, "SHA-256", 32); + case 0x003C: + return Ciphersuite(0x003C, "RSA_WITH_AES_128_CBC_SHA256", "RSA", "RSA", "AES-128", 16, 16, 0, "SHA-256", 32, ""); - case 0x003D: // RSA_WITH_AES_256_CBC_SHA256 - return Ciphersuite(0x003D, "RSA", "RSA", "AES-256", 32, 16, 0, "SHA-256", 32); + case 0x003D: + return Ciphersuite(0x003D, "RSA_WITH_AES_256_CBC_SHA256", "RSA", "RSA", "AES-256", 32, 16, 0, "SHA-256", 32, ""); - case 0x0040: // DHE_DSS_WITH_AES_128_CBC_SHA256 - return Ciphersuite(0x0040, "DSA", "DH", "AES-128", 16, 16, 0, "SHA-256", 32); + case 0x0040: + return Ciphersuite(0x0040, "DHE_DSS_WITH_AES_128_CBC_SHA256", "DSA", "DH", "AES-128", 16, 16, 0, "SHA-256", 32, ""); - case 0x0041: // RSA_WITH_CAMELLIA_128_CBC_SHA - return Ciphersuite(0x0041, "RSA", "RSA", "Camellia-128", 16, 16, 0, "SHA-1", 20); + case 0x0041: + return Ciphersuite(0x0041, "RSA_WITH_CAMELLIA_128_CBC_SHA", "RSA", "RSA", "Camellia-128", 16, 16, 0, "SHA-1", 20, ""); - case 0x0044: // DHE_DSS_WITH_CAMELLIA_128_CBC_SHA - return Ciphersuite(0x0044, "DSA", "DH", "Camellia-128", 16, 16, 0, "SHA-1", 20); + case 0x0044: + return Ciphersuite(0x0044, "DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", "DSA", "DH", "Camellia-128", 16, 16, 0, "SHA-1", 20, ""); - case 0x0045: // DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - return Ciphersuite(0x0045, "RSA", "DH", "Camellia-128", 16, 16, 0, "SHA-1", 20); + case 0x0045: + return Ciphersuite(0x0045, "DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", "RSA", "DH", "Camellia-128", 16, 16, 0, "SHA-1", 20, ""); - case 0x0046: // DH_anon_WITH_CAMELLIA_128_CBC_SHA - return Ciphersuite(0x0046, "", "DH", "Camellia-128", 16, 16, 0, "SHA-1", 20); + case 0x0046: + return Ciphersuite(0x0046, "DH_anon_WITH_CAMELLIA_128_CBC_SHA", "", "DH", "Camellia-128", 16, 16, 0, "SHA-1", 20, ""); - case 0x0067: // DHE_RSA_WITH_AES_128_CBC_SHA256 - return Ciphersuite(0x0067, "RSA", "DH", "AES-128", 16, 16, 0, "SHA-256", 32); + case 0x0067: + return Ciphersuite(0x0067, "DHE_RSA_WITH_AES_128_CBC_SHA256", "RSA", "DH", "AES-128", 16, 16, 0, "SHA-256", 32, ""); - case 0x006A: // DHE_DSS_WITH_AES_256_CBC_SHA256 - return Ciphersuite(0x006A, "DSA", "DH", "AES-256", 32, 16, 0, "SHA-256", 32); + case 0x006A: + return Ciphersuite(0x006A, "DHE_DSS_WITH_AES_256_CBC_SHA256", "DSA", "DH", "AES-256", 32, 16, 0, "SHA-256", 32, ""); - case 0x006B: // DHE_RSA_WITH_AES_256_CBC_SHA256 - return Ciphersuite(0x006B, "RSA", "DH", "AES-256", 32, 16, 0, "SHA-256", 32); + case 0x006B: + return Ciphersuite(0x006B, "DHE_RSA_WITH_AES_256_CBC_SHA256", "RSA", "DH", "AES-256", 32, 16, 0, "SHA-256", 32, ""); - case 0x006C: // DH_anon_WITH_AES_128_CBC_SHA256 - return Ciphersuite(0x006C, "", "DH", "AES-128", 16, 16, 0, "SHA-256", 32); + case 0x006C: + return Ciphersuite(0x006C, "DH_anon_WITH_AES_128_CBC_SHA256", "", "DH", "AES-128", 16, 16, 0, "SHA-256", 32, ""); - case 0x006D: // DH_anon_WITH_AES_256_CBC_SHA256 - return Ciphersuite(0x006D, "", "DH", "AES-256", 32, 16, 0, "SHA-256", 32); + case 0x006D: + return Ciphersuite(0x006D, "DH_anon_WITH_AES_256_CBC_SHA256", "", "DH", "AES-256", 32, 16, 0, "SHA-256", 32, ""); - case 0x0084: // RSA_WITH_CAMELLIA_256_CBC_SHA - return Ciphersuite(0x0084, "RSA", "RSA", "Camellia-256", 32, 16, 0, "SHA-1", 20); + case 0x0084: + return Ciphersuite(0x0084, "RSA_WITH_CAMELLIA_256_CBC_SHA", "RSA", "RSA", "Camellia-256", 32, 16, 0, "SHA-1", 20, ""); - case 0x0087: // DHE_DSS_WITH_CAMELLIA_256_CBC_SHA - return Ciphersuite(0x0087, "DSA", "DH", "Camellia-256", 32, 16, 0, "SHA-1", 20); + case 0x0087: + return Ciphersuite(0x0087, "DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", "DSA", "DH", "Camellia-256", 32, 16, 0, "SHA-1", 20, ""); - case 0x0088: // DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - return Ciphersuite(0x0088, "RSA", "DH", "Camellia-256", 32, 16, 0, "SHA-1", 20); + case 0x0088: + return Ciphersuite(0x0088, "DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", "RSA", "DH", "Camellia-256", 32, 16, 0, "SHA-1", 20, ""); - case 0x0089: // DH_anon_WITH_CAMELLIA_256_CBC_SHA - return Ciphersuite(0x0089, "", "DH", "Camellia-256", 32, 16, 0, "SHA-1", 20); + case 0x0089: + return Ciphersuite(0x0089, "DH_anon_WITH_CAMELLIA_256_CBC_SHA", "", "DH", "Camellia-256", 32, 16, 0, "SHA-1", 20, ""); - case 0x008B: // PSK_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0x008B, "", "PSK", "3DES", 24, 8, 0, "SHA-1", 20); + case 0x008B: + return Ciphersuite(0x008B, "PSK_WITH_3DES_EDE_CBC_SHA", "", "PSK", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0x008C: // PSK_WITH_AES_128_CBC_SHA - return Ciphersuite(0x008C, "", "PSK", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0x008C: + return Ciphersuite(0x008C, "PSK_WITH_AES_128_CBC_SHA", "", "PSK", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0x008D: // PSK_WITH_AES_256_CBC_SHA - return Ciphersuite(0x008D, "", "PSK", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0x008D: + return Ciphersuite(0x008D, "PSK_WITH_AES_256_CBC_SHA", "", "PSK", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0x008F: // DHE_PSK_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0x008F, "", "DHE_PSK", "3DES", 24, 8, 0, "SHA-1", 20); + case 0x008F: + return Ciphersuite(0x008F, "DHE_PSK_WITH_3DES_EDE_CBC_SHA", "", "DHE_PSK", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0x0090: // DHE_PSK_WITH_AES_128_CBC_SHA - return Ciphersuite(0x0090, "", "DHE_PSK", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0x0090: + return Ciphersuite(0x0090, "DHE_PSK_WITH_AES_128_CBC_SHA", "", "DHE_PSK", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0x0091: // DHE_PSK_WITH_AES_256_CBC_SHA - return Ciphersuite(0x0091, "", "DHE_PSK", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0x0091: + return Ciphersuite(0x0091, "DHE_PSK_WITH_AES_256_CBC_SHA", "", "DHE_PSK", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0x0096: // RSA_WITH_SEED_CBC_SHA - return Ciphersuite(0x0096, "RSA", "RSA", "SEED", 16, 16, 0, "SHA-1", 20); + case 0x0096: + return Ciphersuite(0x0096, "RSA_WITH_SEED_CBC_SHA", "RSA", "RSA", "SEED", 16, 16, 0, "SHA-1", 20, ""); - case 0x0099: // DHE_DSS_WITH_SEED_CBC_SHA - return Ciphersuite(0x0099, "DSA", "DH", "SEED", 16, 16, 0, "SHA-1", 20); + case 0x0099: + return Ciphersuite(0x0099, "DHE_DSS_WITH_SEED_CBC_SHA", "DSA", "DH", "SEED", 16, 16, 0, "SHA-1", 20, ""); - case 0x009A: // DHE_RSA_WITH_SEED_CBC_SHA - return Ciphersuite(0x009A, "RSA", "DH", "SEED", 16, 16, 0, "SHA-1", 20); + case 0x009A: + return Ciphersuite(0x009A, "DHE_RSA_WITH_SEED_CBC_SHA", "RSA", "DH", "SEED", 16, 16, 0, "SHA-1", 20, ""); - case 0x009B: // DH_anon_WITH_SEED_CBC_SHA - return Ciphersuite(0x009B, "", "DH", "SEED", 16, 16, 0, "SHA-1", 20); + case 0x009B: + return Ciphersuite(0x009B, "DH_anon_WITH_SEED_CBC_SHA", "", "DH", "SEED", 16, 16, 0, "SHA-1", 20, ""); - case 0x009C: // RSA_WITH_AES_128_GCM_SHA256 - return Ciphersuite(0x009C, "RSA", "RSA", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0x009C: + return Ciphersuite(0x009C, "RSA_WITH_AES_128_GCM_SHA256", "RSA", "RSA", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0x009D: // RSA_WITH_AES_256_GCM_SHA384 - return Ciphersuite(0x009D, "RSA", "RSA", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0x009D: + return Ciphersuite(0x009D, "RSA_WITH_AES_256_GCM_SHA384", "RSA", "RSA", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0x009E: // DHE_RSA_WITH_AES_128_GCM_SHA256 - return Ciphersuite(0x009E, "RSA", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0x009E: + return Ciphersuite(0x009E, "DHE_RSA_WITH_AES_128_GCM_SHA256", "RSA", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0x009F: // DHE_RSA_WITH_AES_256_GCM_SHA384 - return Ciphersuite(0x009F, "RSA", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0x009F: + return Ciphersuite(0x009F, "DHE_RSA_WITH_AES_256_GCM_SHA384", "RSA", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0x00A2: // DHE_DSS_WITH_AES_128_GCM_SHA256 - return Ciphersuite(0x00A2, "DSA", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0x00A2: + return Ciphersuite(0x00A2, "DHE_DSS_WITH_AES_128_GCM_SHA256", "DSA", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0x00A3: // DHE_DSS_WITH_AES_256_GCM_SHA384 - return Ciphersuite(0x00A3, "DSA", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0x00A3: + return Ciphersuite(0x00A3, "DHE_DSS_WITH_AES_256_GCM_SHA384", "DSA", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0x00A6: // DH_anon_WITH_AES_128_GCM_SHA256 - return Ciphersuite(0x00A6, "", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0x00A6: + return Ciphersuite(0x00A6, "DH_anon_WITH_AES_128_GCM_SHA256", "", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0x00A7: // DH_anon_WITH_AES_256_GCM_SHA384 - return Ciphersuite(0x00A7, "", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0x00A7: + return Ciphersuite(0x00A7, "DH_anon_WITH_AES_256_GCM_SHA384", "", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0x00A8: // PSK_WITH_AES_128_GCM_SHA256 - return Ciphersuite(0x00A8, "", "PSK", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0x00A8: + return Ciphersuite(0x00A8, "PSK_WITH_AES_128_GCM_SHA256", "", "PSK", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0x00A9: // PSK_WITH_AES_256_GCM_SHA384 - return Ciphersuite(0x00A9, "", "PSK", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0x00A9: + return Ciphersuite(0x00A9, "PSK_WITH_AES_256_GCM_SHA384", "", "PSK", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0x00AA: // DHE_PSK_WITH_AES_128_GCM_SHA256 - return Ciphersuite(0x00AA, "", "DHE_PSK", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0x00AA: + return Ciphersuite(0x00AA, "DHE_PSK_WITH_AES_128_GCM_SHA256", "", "DHE_PSK", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0x00AB: // DHE_PSK_WITH_AES_256_GCM_SHA384 - return Ciphersuite(0x00AB, "", "DHE_PSK", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0x00AB: + return Ciphersuite(0x00AB, "DHE_PSK_WITH_AES_256_GCM_SHA384", "", "DHE_PSK", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0x00AE: // PSK_WITH_AES_128_CBC_SHA256 - return Ciphersuite(0x00AE, "", "PSK", "AES-128", 16, 16, 0, "SHA-256", 32); + case 0x00AE: + return Ciphersuite(0x00AE, "PSK_WITH_AES_128_CBC_SHA256", "", "PSK", "AES-128", 16, 16, 0, "SHA-256", 32, ""); - case 0x00AF: // PSK_WITH_AES_256_CBC_SHA384 - return Ciphersuite(0x00AF, "", "PSK", "AES-256", 32, 16, 0, "SHA-384", 48); + case 0x00AF: + return Ciphersuite(0x00AF, "PSK_WITH_AES_256_CBC_SHA384", "", "PSK", "AES-256", 32, 16, 0, "SHA-384", 48, ""); - case 0x00B2: // DHE_PSK_WITH_AES_128_CBC_SHA256 - return Ciphersuite(0x00B2, "", "DHE_PSK", "AES-128", 16, 16, 0, "SHA-256", 32); + case 0x00B2: + return Ciphersuite(0x00B2, "DHE_PSK_WITH_AES_128_CBC_SHA256", "", "DHE_PSK", "AES-128", 16, 16, 0, "SHA-256", 32, ""); - case 0x00B3: // DHE_PSK_WITH_AES_256_CBC_SHA384 - return Ciphersuite(0x00B3, "", "DHE_PSK", "AES-256", 32, 16, 0, "SHA-384", 48); + case 0x00B3: + return Ciphersuite(0x00B3, "DHE_PSK_WITH_AES_256_CBC_SHA384", "", "DHE_PSK", "AES-256", 32, 16, 0, "SHA-384", 48, ""); - case 0x00BA: // RSA_WITH_CAMELLIA_128_CBC_SHA256 - return Ciphersuite(0x00BA, "RSA", "RSA", "Camellia-128", 16, 16, 0, "SHA-256", 32); + case 0x00BA: + return Ciphersuite(0x00BA, "RSA_WITH_CAMELLIA_128_CBC_SHA256", "RSA", "RSA", "Camellia-128", 16, 16, 0, "SHA-256", 32, ""); - case 0x00BD: // DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 - return Ciphersuite(0x00BD, "DSA", "DH", "Camellia-128", 16, 16, 0, "SHA-256", 32); + case 0x00BD: + return Ciphersuite(0x00BD, "DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", "DSA", "DH", "Camellia-128", 16, 16, 0, "SHA-256", 32, ""); - case 0x00BE: // DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - return Ciphersuite(0x00BE, "RSA", "DH", "Camellia-128", 16, 16, 0, "SHA-256", 32); + case 0x00BE: + return Ciphersuite(0x00BE, "DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", "RSA", "DH", "Camellia-128", 16, 16, 0, "SHA-256", 32, ""); - case 0x00BF: // DH_anon_WITH_CAMELLIA_128_CBC_SHA256 - return Ciphersuite(0x00BF, "", "DH", "Camellia-128", 16, 16, 0, "SHA-256", 32); + case 0x00BF: + return Ciphersuite(0x00BF, "DH_anon_WITH_CAMELLIA_128_CBC_SHA256", "", "DH", "Camellia-128", 16, 16, 0, "SHA-256", 32, ""); - case 0x00C0: // RSA_WITH_CAMELLIA_256_CBC_SHA256 - return Ciphersuite(0x00C0, "RSA", "RSA", "Camellia-256", 32, 16, 0, "SHA-256", 32); + case 0x00C0: + return Ciphersuite(0x00C0, "RSA_WITH_CAMELLIA_256_CBC_SHA256", "RSA", "RSA", "Camellia-256", 32, 16, 0, "SHA-256", 32, ""); - case 0x00C3: // DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 - return Ciphersuite(0x00C3, "DSA", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32); + case 0x00C3: + return Ciphersuite(0x00C3, "DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", "DSA", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32, ""); - case 0x00C4: // DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - return Ciphersuite(0x00C4, "RSA", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32); + case 0x00C4: + return Ciphersuite(0x00C4, "DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", "RSA", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32, ""); - case 0x00C5: // DH_anon_WITH_CAMELLIA_256_CBC_SHA256 - return Ciphersuite(0x00C5, "", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32); + case 0x00C5: + return Ciphersuite(0x00C5, "DH_anon_WITH_CAMELLIA_256_CBC_SHA256", "", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32, ""); - case 0xC008: // ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0xC008, "ECDSA", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20); + case 0xC008: + return Ciphersuite(0xC008, "ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "ECDSA", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0xC009: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA - return Ciphersuite(0xC009, "ECDSA", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0xC009: + return Ciphersuite(0xC009, "ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "ECDSA", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0xC00A: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA - return Ciphersuite(0xC00A, "ECDSA", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0xC00A: + return Ciphersuite(0xC00A, "ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "ECDSA", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0xC012: // ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0xC012, "RSA", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20); + case 0xC012: + return Ciphersuite(0xC012, "ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "RSA", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0xC013: // ECDHE_RSA_WITH_AES_128_CBC_SHA - return Ciphersuite(0xC013, "RSA", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0xC013: + return Ciphersuite(0xC013, "ECDHE_RSA_WITH_AES_128_CBC_SHA", "RSA", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0xC014: // ECDHE_RSA_WITH_AES_256_CBC_SHA - return Ciphersuite(0xC014, "RSA", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0xC014: + return Ciphersuite(0xC014, "ECDHE_RSA_WITH_AES_256_CBC_SHA", "RSA", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0xC017: // ECDH_anon_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0xC017, "", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20); + case 0xC017: + return Ciphersuite(0xC017, "ECDH_anon_WITH_3DES_EDE_CBC_SHA", "", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0xC018: // ECDH_anon_WITH_AES_128_CBC_SHA - return Ciphersuite(0xC018, "", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0xC018: + return Ciphersuite(0xC018, "ECDH_anon_WITH_AES_128_CBC_SHA", "", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0xC019: // ECDH_anon_WITH_AES_256_CBC_SHA - return Ciphersuite(0xC019, "", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0xC019: + return Ciphersuite(0xC019, "ECDH_anon_WITH_AES_256_CBC_SHA", "", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0xC01A: // SRP_SHA_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0xC01A, "", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20); + case 0xC01A: + return Ciphersuite(0xC01A, "SRP_SHA_WITH_3DES_EDE_CBC_SHA", "", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0xC01B: // SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0xC01B, "RSA", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20); + case 0xC01B: + return Ciphersuite(0xC01B, "SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", "RSA", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0xC01C: // SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0xC01C, "DSA", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20); + case 0xC01C: + return Ciphersuite(0xC01C, "SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", "DSA", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0xC01D: // SRP_SHA_WITH_AES_128_CBC_SHA - return Ciphersuite(0xC01D, "", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0xC01D: + return Ciphersuite(0xC01D, "SRP_SHA_WITH_AES_128_CBC_SHA", "", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0xC01E: // SRP_SHA_RSA_WITH_AES_128_CBC_SHA - return Ciphersuite(0xC01E, "RSA", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0xC01E: + return Ciphersuite(0xC01E, "SRP_SHA_RSA_WITH_AES_128_CBC_SHA", "RSA", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0xC01F: // SRP_SHA_DSS_WITH_AES_128_CBC_SHA - return Ciphersuite(0xC01F, "DSA", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0xC01F: + return Ciphersuite(0xC01F, "SRP_SHA_DSS_WITH_AES_128_CBC_SHA", "DSA", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0xC020: // SRP_SHA_WITH_AES_256_CBC_SHA - return Ciphersuite(0xC020, "", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0xC020: + return Ciphersuite(0xC020, "SRP_SHA_WITH_AES_256_CBC_SHA", "", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0xC021: // SRP_SHA_RSA_WITH_AES_256_CBC_SHA - return Ciphersuite(0xC021, "RSA", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0xC021: + return Ciphersuite(0xC021, "SRP_SHA_RSA_WITH_AES_256_CBC_SHA", "RSA", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0xC022: // SRP_SHA_DSS_WITH_AES_256_CBC_SHA - return Ciphersuite(0xC022, "DSA", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0xC022: + return Ciphersuite(0xC022, "SRP_SHA_DSS_WITH_AES_256_CBC_SHA", "DSA", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0xC023: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - return Ciphersuite(0xC023, "ECDSA", "ECDH", "AES-128", 16, 16, 0, "SHA-256", 32); + case 0xC023: + return Ciphersuite(0xC023, "ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "ECDSA", "ECDH", "AES-128", 16, 16, 0, "SHA-256", 32, ""); - case 0xC024: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - return Ciphersuite(0xC024, "ECDSA", "ECDH", "AES-256", 32, 16, 0, "SHA-384", 48); + case 0xC024: + return Ciphersuite(0xC024, "ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "ECDSA", "ECDH", "AES-256", 32, 16, 0, "SHA-384", 48, ""); - case 0xC027: // ECDHE_RSA_WITH_AES_128_CBC_SHA256 - return Ciphersuite(0xC027, "RSA", "ECDH", "AES-128", 16, 16, 0, "SHA-256", 32); + case 0xC027: + return Ciphersuite(0xC027, "ECDHE_RSA_WITH_AES_128_CBC_SHA256", "RSA", "ECDH", "AES-128", 16, 16, 0, "SHA-256", 32, ""); - case 0xC028: // ECDHE_RSA_WITH_AES_256_CBC_SHA384 - return Ciphersuite(0xC028, "RSA", "ECDH", "AES-256", 32, 16, 0, "SHA-384", 48); + case 0xC028: + return Ciphersuite(0xC028, "ECDHE_RSA_WITH_AES_256_CBC_SHA384", "RSA", "ECDH", "AES-256", 32, 16, 0, "SHA-384", 48, ""); - case 0xC02B: // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - return Ciphersuite(0xC02B, "ECDSA", "ECDH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC02B: + return Ciphersuite(0xC02B, "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "ECDSA", "ECDH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC02C: // ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - return Ciphersuite(0xC02C, "ECDSA", "ECDH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0xC02C: + return Ciphersuite(0xC02C, "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "ECDSA", "ECDH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0xC02F: // ECDHE_RSA_WITH_AES_128_GCM_SHA256 - return Ciphersuite(0xC02F, "RSA", "ECDH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC02F: + return Ciphersuite(0xC02F, "ECDHE_RSA_WITH_AES_128_GCM_SHA256", "RSA", "ECDH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC030: // ECDHE_RSA_WITH_AES_256_GCM_SHA384 - return Ciphersuite(0xC030, "RSA", "ECDH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0xC030: + return Ciphersuite(0xC030, "ECDHE_RSA_WITH_AES_256_GCM_SHA384", "RSA", "ECDH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0xC034: // ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - return Ciphersuite(0xC034, "", "ECDHE_PSK", "3DES", 24, 8, 0, "SHA-1", 20); + case 0xC034: + return Ciphersuite(0xC034, "ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", "", "ECDHE_PSK", "3DES", 24, 8, 0, "SHA-1", 20, ""); - case 0xC035: // ECDHE_PSK_WITH_AES_128_CBC_SHA - return Ciphersuite(0xC035, "", "ECDHE_PSK", "AES-128", 16, 16, 0, "SHA-1", 20); + case 0xC035: + return Ciphersuite(0xC035, "ECDHE_PSK_WITH_AES_128_CBC_SHA", "", "ECDHE_PSK", "AES-128", 16, 16, 0, "SHA-1", 20, ""); - case 0xC036: // ECDHE_PSK_WITH_AES_256_CBC_SHA - return Ciphersuite(0xC036, "", "ECDHE_PSK", "AES-256", 32, 16, 0, "SHA-1", 20); + case 0xC036: + return Ciphersuite(0xC036, "ECDHE_PSK_WITH_AES_256_CBC_SHA", "", "ECDHE_PSK", "AES-256", 32, 16, 0, "SHA-1", 20, ""); - case 0xC037: // ECDHE_PSK_WITH_AES_128_CBC_SHA256 - return Ciphersuite(0xC037, "", "ECDHE_PSK", "AES-128", 16, 16, 0, "SHA-256", 32); + case 0xC037: + return Ciphersuite(0xC037, "ECDHE_PSK_WITH_AES_128_CBC_SHA256", "", "ECDHE_PSK", "AES-128", 16, 16, 0, "SHA-256", 32, ""); - case 0xC038: // ECDHE_PSK_WITH_AES_256_CBC_SHA384 - return Ciphersuite(0xC038, "", "ECDHE_PSK", "AES-256", 32, 16, 0, "SHA-384", 48); + case 0xC038: + return Ciphersuite(0xC038, "ECDHE_PSK_WITH_AES_256_CBC_SHA384", "", "ECDHE_PSK", "AES-256", 32, 16, 0, "SHA-384", 48, ""); - case 0xC072: // ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - return Ciphersuite(0xC072, "ECDSA", "ECDH", "Camellia-128", 16, 16, 0, "SHA-256", 32); + case 0xC072: + return Ciphersuite(0xC072, "ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", "ECDSA", "ECDH", "Camellia-128", 16, 16, 0, "SHA-256", 32, ""); - case 0xC073: // ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - return Ciphersuite(0xC073, "ECDSA", "ECDH", "Camellia-256", 32, 16, 0, "SHA-384", 48); + case 0xC073: + return Ciphersuite(0xC073, "ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", "ECDSA", "ECDH", "Camellia-256", 32, 16, 0, "SHA-384", 48, ""); - case 0xC076: // ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - return Ciphersuite(0xC076, "RSA", "ECDH", "Camellia-128", 16, 16, 0, "SHA-256", 32); + case 0xC076: + return Ciphersuite(0xC076, "ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", "RSA", "ECDH", "Camellia-128", 16, 16, 0, "SHA-256", 32, ""); - case 0xC077: // ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 - return Ciphersuite(0xC077, "RSA", "ECDH", "Camellia-256", 32, 16, 0, "SHA-384", 48); + case 0xC077: + return Ciphersuite(0xC077, "ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384", "RSA", "ECDH", "Camellia-256", 32, 16, 0, "SHA-384", 48, ""); - case 0xC07A: // RSA_WITH_CAMELLIA_128_GCM_SHA256 - return Ciphersuite(0xC07A, "RSA", "RSA", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC07A: + return Ciphersuite(0xC07A, "RSA_WITH_CAMELLIA_128_GCM_SHA256", "RSA", "RSA", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC07B: // RSA_WITH_CAMELLIA_256_GCM_SHA384 - return Ciphersuite(0xC07B, "RSA", "RSA", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0xC07B: + return Ciphersuite(0xC07B, "RSA_WITH_CAMELLIA_256_GCM_SHA384", "RSA", "RSA", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0xC07C: // DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - return Ciphersuite(0xC07C, "RSA", "DH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC07C: + return Ciphersuite(0xC07C, "DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", "RSA", "DH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC07D: // DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - return Ciphersuite(0xC07D, "RSA", "DH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0xC07D: + return Ciphersuite(0xC07D, "DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", "RSA", "DH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0xC080: // DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 - return Ciphersuite(0xC080, "DSA", "DH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC080: + return Ciphersuite(0xC080, "DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256", "DSA", "DH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC081: // DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 - return Ciphersuite(0xC081, "DSA", "DH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0xC081: + return Ciphersuite(0xC081, "DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384", "DSA", "DH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0xC084: // DH_anon_WITH_CAMELLIA_128_GCM_SHA256 - return Ciphersuite(0xC084, "", "DH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC084: + return Ciphersuite(0xC084, "DH_anon_WITH_CAMELLIA_128_GCM_SHA256", "", "DH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC085: // DH_anon_WITH_CAMELLIA_256_GCM_SHA384 - return Ciphersuite(0xC085, "", "DH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0xC085: + return Ciphersuite(0xC085, "DH_anon_WITH_CAMELLIA_256_GCM_SHA384", "", "DH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0xC086: // ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - return Ciphersuite(0xC086, "ECDSA", "ECDH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC086: + return Ciphersuite(0xC086, "ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", "ECDSA", "ECDH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC087: // ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - return Ciphersuite(0xC087, "ECDSA", "ECDH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0xC087: + return Ciphersuite(0xC087, "ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", "ECDSA", "ECDH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0xC08A: // ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - return Ciphersuite(0xC08A, "RSA", "ECDH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC08A: + return Ciphersuite(0xC08A, "ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", "RSA", "ECDH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC08B: // ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - return Ciphersuite(0xC08B, "RSA", "ECDH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0xC08B: + return Ciphersuite(0xC08B, "ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", "RSA", "ECDH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0xC08E: // PSK_WITH_CAMELLIA_128_GCM_SHA256 - return Ciphersuite(0xC08E, "", "PSK", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC08E: + return Ciphersuite(0xC08E, "PSK_WITH_CAMELLIA_128_GCM_SHA256", "", "PSK", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC08F: // PSK_WITH_CAMELLIA_256_GCM_SHA384 - return Ciphersuite(0xC08F, "", "PSK", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0xC08F: + return Ciphersuite(0xC08F, "PSK_WITH_CAMELLIA_256_GCM_SHA384", "", "PSK", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0xC090: // DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 - return Ciphersuite(0xC090, "", "DHE_PSK", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC090: + return Ciphersuite(0xC090, "DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256", "", "DHE_PSK", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC091: // DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 - return Ciphersuite(0xC091, "", "DHE_PSK", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); + case 0xC091: + return Ciphersuite(0xC091, "DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384", "", "DHE_PSK", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); - case 0xC094: // PSK_WITH_CAMELLIA_128_CBC_SHA256 - return Ciphersuite(0xC094, "", "PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32); + case 0xC094: + return Ciphersuite(0xC094, "PSK_WITH_CAMELLIA_128_CBC_SHA256", "", "PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32, ""); - case 0xC095: // PSK_WITH_CAMELLIA_256_CBC_SHA384 - return Ciphersuite(0xC095, "", "PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48); + case 0xC095: + return Ciphersuite(0xC095, "PSK_WITH_CAMELLIA_256_CBC_SHA384", "", "PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48, ""); - case 0xC096: // DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - return Ciphersuite(0xC096, "", "DHE_PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32); + case 0xC096: + return Ciphersuite(0xC096, "DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", "", "DHE_PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32, ""); - case 0xC097: // DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - return Ciphersuite(0xC097, "", "DHE_PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48); + case 0xC097: + return Ciphersuite(0xC097, "DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", "", "DHE_PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48, ""); - case 0xC09A: // ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - return Ciphersuite(0xC09A, "", "ECDHE_PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32); + case 0xC09A: + return Ciphersuite(0xC09A, "ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", "", "ECDHE_PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32, ""); - case 0xC09B: // ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - return Ciphersuite(0xC09B, "", "ECDHE_PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48); + case 0xC09B: + return Ciphersuite(0xC09B, "ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", "", "ECDHE_PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48, ""); - case 0xC09C: // RSA_WITH_AES_128_CCM - return Ciphersuite(0xC09C, "RSA", "RSA", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC09C: + return Ciphersuite(0xC09C, "RSA_WITH_AES_128_CCM", "RSA", "RSA", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC09D: // RSA_WITH_AES_256_CCM - return Ciphersuite(0xC09D, "RSA", "RSA", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC09D: + return Ciphersuite(0xC09D, "RSA_WITH_AES_256_CCM", "RSA", "RSA", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC09E: // DHE_RSA_WITH_AES_128_CCM - return Ciphersuite(0xC09E, "RSA", "DH", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC09E: + return Ciphersuite(0xC09E, "DHE_RSA_WITH_AES_128_CCM", "RSA", "DH", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC09F: // DHE_RSA_WITH_AES_256_CCM - return Ciphersuite(0xC09F, "RSA", "DH", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC09F: + return Ciphersuite(0xC09F, "DHE_RSA_WITH_AES_256_CCM", "RSA", "DH", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0A0: // RSA_WITH_AES_128_CCM_8 - return Ciphersuite(0xC0A0, "RSA", "RSA", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0A0: + return Ciphersuite(0xC0A0, "RSA_WITH_AES_128_CCM_8", "RSA", "RSA", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0A1: // RSA_WITH_AES_256_CCM_8 - return Ciphersuite(0xC0A1, "RSA", "RSA", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0A1: + return Ciphersuite(0xC0A1, "RSA_WITH_AES_256_CCM_8", "RSA", "RSA", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0A2: // DHE_RSA_WITH_AES_128_CCM_8 - return Ciphersuite(0xC0A2, "RSA", "DH", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0A2: + return Ciphersuite(0xC0A2, "DHE_RSA_WITH_AES_128_CCM_8", "RSA", "DH", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0A3: // DHE_RSA_WITH_AES_256_CCM_8 - return Ciphersuite(0xC0A3, "RSA", "DH", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0A3: + return Ciphersuite(0xC0A3, "DHE_RSA_WITH_AES_256_CCM_8", "RSA", "DH", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0A4: // PSK_WITH_AES_128_CCM - return Ciphersuite(0xC0A4, "", "PSK", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0A4: + return Ciphersuite(0xC0A4, "PSK_WITH_AES_128_CCM", "", "PSK", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0A5: // PSK_WITH_AES_256_CCM - return Ciphersuite(0xC0A5, "", "PSK", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0A5: + return Ciphersuite(0xC0A5, "PSK_WITH_AES_256_CCM", "", "PSK", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0A6: // DHE_PSK_WITH_AES_128_CCM - return Ciphersuite(0xC0A6, "", "DHE_PSK", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0A6: + return Ciphersuite(0xC0A6, "DHE_PSK_WITH_AES_128_CCM", "", "DHE_PSK", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0A7: // DHE_PSK_WITH_AES_256_CCM - return Ciphersuite(0xC0A7, "", "DHE_PSK", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0A7: + return Ciphersuite(0xC0A7, "DHE_PSK_WITH_AES_256_CCM", "", "DHE_PSK", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0A8: // PSK_WITH_AES_128_CCM_8 - return Ciphersuite(0xC0A8, "", "PSK", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0A8: + return Ciphersuite(0xC0A8, "PSK_WITH_AES_128_CCM_8", "", "PSK", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0A9: // PSK_WITH_AES_256_CCM_8 - return Ciphersuite(0xC0A9, "", "PSK", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0A9: + return Ciphersuite(0xC0A9, "PSK_WITH_AES_256_CCM_8", "", "PSK", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0AA: // PSK_DHE_WITH_AES_128_CCM_8 - return Ciphersuite(0xC0AA, "", "DHE_PSK", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0AA: + return Ciphersuite(0xC0AA, "PSK_DHE_WITH_AES_128_CCM_8", "", "DHE_PSK", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0AB: // PSK_DHE_WITH_AES_256_CCM_8 - return Ciphersuite(0xC0AB, "", "DHE_PSK", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0AB: + return Ciphersuite(0xC0AB, "PSK_DHE_WITH_AES_256_CCM_8", "", "DHE_PSK", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0AC: // ECDHE_ECDSA_WITH_AES_128_CCM - return Ciphersuite(0xC0AC, "ECDSA", "ECDH", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0AC: + return Ciphersuite(0xC0AC, "ECDHE_ECDSA_WITH_AES_128_CCM", "ECDSA", "ECDH", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0AD: // ECDHE_ECDSA_WITH_AES_256_CCM - return Ciphersuite(0xC0AD, "ECDSA", "ECDH", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0AD: + return Ciphersuite(0xC0AD, "ECDHE_ECDSA_WITH_AES_256_CCM", "ECDSA", "ECDH", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0AE: // ECDHE_ECDSA_WITH_AES_128_CCM_8 - return Ciphersuite(0xC0AE, "ECDSA", "ECDH", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0AE: + return Ciphersuite(0xC0AE, "ECDHE_ECDSA_WITH_AES_128_CCM_8", "ECDSA", "ECDH", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); - case 0xC0AF: // ECDHE_ECDSA_WITH_AES_256_CCM_8 - return Ciphersuite(0xC0AF, "ECDSA", "ECDH", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); + case 0xC0AF: + return Ciphersuite(0xC0AF, "ECDHE_ECDSA_WITH_AES_256_CCM_8", "ECDSA", "ECDH", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); - case 0xCC13: // ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - return Ciphersuite(0xCC13, "RSA", "ECDH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256"); + case 0xCC13: + return Ciphersuite(0xCC13, "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "RSA", "ECDH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256"); - case 0xCC14: // ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 - return Ciphersuite(0xCC14, "ECDSA", "ECDH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256"); + case 0xCC14: + return Ciphersuite(0xCC14, "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "ECDSA", "ECDH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256"); - case 0xCC15: // DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - return Ciphersuite(0xCC15, "RSA", "DH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256"); + case 0xCC15: + return Ciphersuite(0xCC15, "DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "RSA", "DH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256"); - case 0xCCA8: // ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - return Ciphersuite(0xCCA8, "RSA", "ECDH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xCCA8: + return Ciphersuite(0xCCA8, "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "RSA", "ECDH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xCCA9: // ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 - return Ciphersuite(0xCCA9, "ECDSA", "ECDH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xCCA9: + return Ciphersuite(0xCCA9, "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "ECDSA", "ECDH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xCCAA: // DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - return Ciphersuite(0xCCAA, "RSA", "DH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xCCAA: + return Ciphersuite(0xCCAA, "DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "RSA", "DH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xCCAB: // PSK_WITH_CHACHA20_POLY1305_SHA256 - return Ciphersuite(0xCCAB, "", "PSK", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xCCAB: + return Ciphersuite(0xCCAB, "PSK_WITH_CHACHA20_POLY1305_SHA256", "", "PSK", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xCCAC: // ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 - return Ciphersuite(0xCCAC, "", "ECDHE_PSK", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xCCAC: + return Ciphersuite(0xCCAC, "ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", "", "ECDHE_PSK", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xCCAD: // DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 - return Ciphersuite(0xCCAD, "", "DHE_PSK", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xCCAD: + return Ciphersuite(0xCCAD, "DHE_PSK_WITH_CHACHA20_POLY1305_SHA256", "", "DHE_PSK", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFC0: // DHE_RSA_WITH_AES_128_OCB_SHA256 - return Ciphersuite(0xFFC0, "RSA", "DH", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFC0: + return Ciphersuite(0xFFC0, "DHE_RSA_WITH_AES_128_OCB_SHA256", "RSA", "DH", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFC1: // DHE_RSA_WITH_AES_256_OCB_SHA256 - return Ciphersuite(0xFFC1, "RSA", "DH", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFC1: + return Ciphersuite(0xFFC1, "DHE_RSA_WITH_AES_256_OCB_SHA256", "RSA", "DH", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFC2: // ECDHE_RSA_WITH_AES_128_OCB_SHA256 - return Ciphersuite(0xFFC2, "RSA", "ECDH", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFC2: + return Ciphersuite(0xFFC2, "ECDHE_RSA_WITH_AES_128_OCB_SHA256", "RSA", "ECDH", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFC3: // ECDHE_RSA_WITH_AES_256_OCB_SHA256 - return Ciphersuite(0xFFC3, "RSA", "ECDH", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFC3: + return Ciphersuite(0xFFC3, "ECDHE_RSA_WITH_AES_256_OCB_SHA256", "RSA", "ECDH", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFC4: // ECDHE_ECDSA_WITH_AES_128_OCB_SHA256 - return Ciphersuite(0xFFC4, "ECDSA", "ECDH", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFC4: + return Ciphersuite(0xFFC4, "ECDHE_ECDSA_WITH_AES_128_OCB_SHA256", "ECDSA", "ECDH", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFC5: // ECDHE_ECDSA_WITH_AES_256_OCB_SHA256 - return Ciphersuite(0xFFC5, "ECDSA", "ECDH", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFC5: + return Ciphersuite(0xFFC5, "ECDHE_ECDSA_WITH_AES_256_OCB_SHA256", "ECDSA", "ECDH", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFC6: // PSK_WITH_AES_128_OCB_SHA256 - return Ciphersuite(0xFFC6, "", "PSK", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFC6: + return Ciphersuite(0xFFC6, "PSK_WITH_AES_128_OCB_SHA256", "", "PSK", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFC7: // PSK_WITH_AES_256_OCB_SHA256 - return Ciphersuite(0xFFC7, "", "PSK", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFC7: + return Ciphersuite(0xFFC7, "PSK_WITH_AES_256_OCB_SHA256", "", "PSK", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFC8: // DHE_PSK_WITH_AES_128_OCB_SHA256 - return Ciphersuite(0xFFC8, "", "DHE_PSK", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFC8: + return Ciphersuite(0xFFC8, "DHE_PSK_WITH_AES_128_OCB_SHA256", "", "DHE_PSK", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFC9: // DHE_PSK_WITH_AES_256_OCB_SHA256 - return Ciphersuite(0xFFC9, "", "DHE_PSK", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFC9: + return Ciphersuite(0xFFC9, "DHE_PSK_WITH_AES_256_OCB_SHA256", "", "DHE_PSK", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFCA: // ECDHE_PSK_WITH_AES_128_OCB_SHA256 - return Ciphersuite(0xFFCA, "", "ECDHE_PSK", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFCA: + return Ciphersuite(0xFFCA, "ECDHE_PSK_WITH_AES_128_OCB_SHA256", "", "ECDHE_PSK", "AES-128/OCB(12)", 16, 12, 0, "AEAD", 0, "SHA-256"); - case 0xFFCB: // ECDHE_PSK_WITH_AES_256_OCB_SHA256 - return Ciphersuite(0xFFCB, "", "ECDHE_PSK", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); + case 0xFFCB: + return Ciphersuite(0xFFCB, "ECDHE_PSK_WITH_AES_256_OCB_SHA256", "", "ECDHE_PSK", "AES-256/OCB(12)", 32, 12, 0, "AEAD", 0, "SHA-256"); } |