/* * 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 != this->tag) { std::stringstream ss; ss << "ASN1_EAC_String tag mismatch, tag was " << std::hex << obj.type_tag << " expected " << std::hex << this->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), charset_is, LOCAL_CHARSET), obj.type_tag); } catch(Invalid_Argument inv_arg) { throw Decoding_Error(std::string("ASN1_EAC_String decoding failed: ") + inv_arg.what()); } }
Application_Layer_Protocol_Notification::Application_Layer_Protocol_Notification(TLS_Data_Reader& reader, u16bit extension_size) { if(extension_size == 0) return; // empty extension const u16bit name_bytes = reader.get_u16bit(); size_t bytes_remaining = extension_size - 2; if(name_bytes != bytes_remaining) throw Decoding_Error("Bad encoding of ALPN extension, bad length field"); while(bytes_remaining) { const std::string p = reader.get_string(1, 0, 255); if(bytes_remaining < p.size() + 1) throw Decoding_Error("Bad encoding of ALPN, length field too long"); bytes_remaining -= (p.size() + 1); m_protocols.push_back(p); } }
/* * 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 != this->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]); year = tmp_year + 2000; month = tmp_mon; day = tmp_day; } catch (Invalid_Argument) { throw Decoding_Error("EAC_Time decoding failed"); } }
/** * Deserialize a Certificate message */ Certificate::Certificate(const std::vector<byte>& buf) { if(buf.size() < 3) throw Decoding_Error("Certificate: Message malformed"); const size_t total_size = make_u32bit(0, buf[0], buf[1], buf[2]); if(total_size != buf.size() - 3) throw Decoding_Error("Certificate: Message malformed"); const byte* certs = buf.data() + 3; while(size_t remaining_bytes = buf.data() + buf.size() - certs) { if(remaining_bytes < 3) throw Decoding_Error("Certificate: Message malformed"); const size_t cert_size = make_u32bit(0, certs[0], certs[1], certs[2]); if(remaining_bytes < (3 + cert_size)) throw Decoding_Error("Certificate: Message malformed"); DataSource_Memory cert_buf(&certs[3], cert_size); m_certs.push_back(X509_Certificate(cert_buf)); certs += cert_size + 3; } }
/* * Read a PEM or BER X.509 object */ void X509_Object::init(DataSource& in, const std::string& labels) { m_PEM_labels_allowed = split_on(labels, '/'); if(m_PEM_labels_allowed.size() < 1) throw Invalid_Argument("Bad labels argument to X509_Object"); m_PEM_label_pref = m_PEM_labels_allowed[0]; std::sort(m_PEM_labels_allowed.begin(), m_PEM_labels_allowed.end()); try { if(ASN1::maybe_BER(in) && !PEM_Code::matches(in)) { BER_Decoder dec(in); decode_from(dec); } else { std::string got_label; DataSource_Memory ber(PEM_Code::decode(in, got_label)); if(!std::binary_search(m_PEM_labels_allowed.begin(), m_PEM_labels_allowed.end(), got_label)) throw Decoding_Error("Invalid PEM label: " + got_label); BER_Decoder dec(ber); decode_from(dec); } } catch(Decoding_Error& e) { throw Decoding_Error(m_PEM_label_pref + " decoding failed: " + e.what()); } }
Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, const secure_vector<byte>& key_bits, RandomNumberGenerator& rng) { const std::string alg_name = OIDS::lookup(alg_id.oid); if(alg_name == "") throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string()); #if defined(BOTAN_HAS_RSA) if(alg_name == "RSA") return new RSA_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_RW) if(alg_name == "RW") return new RW_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_DSA) if(alg_name == "DSA") return new DSA_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) if(alg_name == "DH") return new DH_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_NYBERG_RUEPPEL) if(alg_name == "NR") return new NR_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_ELGAMAL) if(alg_name == "ElGamal") return new ElGamal_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_ECDSA) if(alg_name == "ECDSA") return new ECDSA_PrivateKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_GOST_34_10_2001) if(alg_name == "GOST-34.10") return new GOST_3410_PrivateKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_ECDH) if(alg_name == "ECDH") return new ECDH_PrivateKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_CURVE_25519) if(alg_name == "Curve25519") return new Curve25519_PrivateKey(alg_id, key_bits, rng); #endif throw Decoding_Error("Unhandled PK algorithm " + alg_name); }
/* * Unpad with ANSI X9.23 Method */ size_t ANSI_X923_Padding::unpad(const byte block[], size_t size) const { size_t position = block[size-1]; if(position > size) throw Decoding_Error(name()); for(size_t j = size-position; j != size-1; ++j) if(block[j] != 0) throw Decoding_Error(name()); return (size-position); }
void Datagram_Handshake_IO::Handshake_Reassembly::add_fragment( const uint8_t fragment[], size_t fragment_length, size_t fragment_offset, uint16_t epoch, uint8_t msg_type, size_t msg_length) { if(complete()) return; // already have entire message, ignore this if(m_msg_type == HANDSHAKE_NONE) { m_epoch = epoch; m_msg_type = msg_type; m_msg_length = msg_length; } if(msg_type != m_msg_type || msg_length != m_msg_length || epoch != m_epoch) throw Decoding_Error("Inconsistent values in fragmented DTLS handshake header"); if(fragment_offset > m_msg_length) throw Decoding_Error("Fragment offset past end of message"); if(fragment_offset + fragment_length > m_msg_length) throw Decoding_Error("Fragment overlaps past end of message"); if(fragment_offset == 0 && fragment_length == m_msg_length) { m_fragments.clear(); m_message.assign(fragment, fragment+fragment_length); } else { /* * FIXME. This is a pretty lame way to do defragmentation, huge * overhead with a tree node per byte. * * Also should confirm that all overlaps have no changes, * otherwise we expose ourselves to the classic fingerprinting * and IDS evasion attacks on IP fragmentation. */ for(size_t i = 0; i != fragment_length; ++i) m_fragments[fragment_offset+i] = fragment[i]; if(m_fragments.size() == m_msg_length) { m_message.resize(m_msg_length); for(size_t i = 0; i != m_msg_length; ++i) m_message[i] = m_fragments[i]; m_fragments.clear(); } } }
/* * Split up and process handshake messages */ void TLS_Server::read_handshake(byte rec_type, const MemoryRegion<byte>& rec_buf) { if(rec_type == HANDSHAKE) { if(!state) state = new Handshake_State; state->queue.write(&rec_buf[0], rec_buf.size()); } while(true) { Handshake_Type type = HANDSHAKE_NONE; SecureVector<byte> contents; if(rec_type == HANDSHAKE) { if(state->queue.size() >= 4) { byte head[4] = { 0 }; state->queue.peek(head, 4); const size_t length = make_u32bit(0, head[1], head[2], head[3]); if(state->queue.size() >= length + 4) { type = static_cast<Handshake_Type>(head[0]); contents.resize(length); state->queue.read(head, 4); state->queue.read(&contents[0], contents.size()); } } } else if(rec_type == CHANGE_CIPHER_SPEC) { if(state->queue.size() == 0 && rec_buf.size() == 1 && rec_buf[0] == 1) type = HANDSHAKE_CCS; else throw Decoding_Error("Malformed ChangeCipherSpec message"); } else throw Decoding_Error("Unknown message type in handshake processing"); if(type == HANDSHAKE_NONE) break; process_handshake_msg(type, contents); if(type == HANDSHAKE_CCS || !state) break; } }
SRTP_Protection_Profiles::SRTP_Protection_Profiles(TLS_Data_Reader& reader, u16bit extension_size) { m_pp = reader.get_range<u16bit>(2, 0, 65535); const std::vector<byte> mki = reader.get_range<byte>(1, 0, 255); if(m_pp.size() * 2 + mki.size() + 3 != extension_size) throw Decoding_Error("Bad encoding for SRTP protection extension"); if(!mki.empty()) throw Decoding_Error("Unhandled non-empty MKI for SRTP protection extension"); }
/* * Deocde the CertificateRequestInfo */ void PKCS10_Request::force_decode() { BER_Decoder cert_req_info(m_tbs_bits); size_t version; cert_req_info.decode(version); if(version != 0) throw Decoding_Error("Unknown version code in PKCS #10 request: " + std::to_string(version)); X509_DN dn_subject; cert_req_info.decode(dn_subject); m_info.add(dn_subject.contents()); BER_Object public_key = cert_req_info.get_next_object(); if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED) throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for public key", public_key.type_tag, public_key.class_tag); m_info.add("X509.Certificate.public_key", PEM_Code::encode( ASN1::put_in_sequence(unlock(public_key.value)), "PUBLIC KEY" ) ); BER_Object attr_bits = cert_req_info.get_next_object(); if(attr_bits.type_tag == 0 && attr_bits.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) { BER_Decoder attributes(attr_bits.value); while(attributes.more_items()) { Attribute attr; attributes.decode(attr); handle_attribute(attr); } attributes.verify_end(); } else if(attr_bits.type_tag != NO_OBJECT) throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for attributes", attr_bits.type_tag, attr_bits.class_tag); cert_req_info.verify_end(); if(!this->check_signature(subject_public_key())) throw Decoding_Error("PKCS #10 request: Bad signature detected"); }
/* * Unpad with One and Zeros Method */ size_t OneAndZeros_Padding::unpad(const byte block[], size_t size) const { while(size) { if(block[size-1] == 0x80) break; if(block[size-1] != 0x00) throw Decoding_Error(name()); size--; } if(!size) throw Decoding_Error(name()); return (size-1); }
/** * Deserialize a Certificate Request message */ Certificate_Req::Certificate_Req(const std::vector<byte>& buf, Protocol_Version version) { if(buf.size() < 4) throw Decoding_Error("Certificate_Req: Bad certificate request"); TLS_Data_Reader reader("CertificateRequest", buf); std::vector<byte> cert_type_codes = reader.get_range_vector<byte>(1, 1, 255); for(size_t i = 0; i != cert_type_codes.size(); ++i) { const std::string cert_type_name = cert_type_code_to_name(cert_type_codes[i]); if(cert_type_name.empty()) // something we don't know continue; m_cert_key_types.push_back(cert_type_name); } if(version.supports_negotiable_signature_algorithms()) { std::vector<byte> sig_hash_algs = reader.get_range_vector<byte>(2, 2, 65534); if(sig_hash_algs.size() % 2 != 0) throw Decoding_Error("Bad length for signature IDs in certificate request"); for(size_t i = 0; i != sig_hash_algs.size(); i += 2) { std::string hash = Signature_Algorithms::hash_algo_name(sig_hash_algs[i]); std::string sig = Signature_Algorithms::sig_algo_name(sig_hash_algs[i+1]); m_supported_algos.push_back(std::make_pair(hash, sig)); } } const u16bit purported_size = reader.get_u16bit(); if(reader.remaining_bytes() != purported_size) throw Decoding_Error("Inconsistent length in certificate request"); while(reader.has_remaining()) { std::vector<byte> name_bits = reader.get_range_vector<byte>(2, 0, 65535); BER_Decoder decoder(name_bits.data(), name_bits.size()); X509_DN name; decoder.decode(name); m_names.push_back(name); } }
/* * Decompress Input with Gzip */ void Gzip_Decompression::write(const byte input_arr[], size_t length) { if(length) no_writes = false; // non-const needed by gzip api :( Bytef* input = reinterpret_cast<Bytef*>(const_cast<byte*>(input_arr)); gzip->stream.next_in = input; gzip->stream.avail_in = length; while(gzip->stream.avail_in != 0) { gzip->stream.next_out = reinterpret_cast<Bytef*>(&buffer[0]); gzip->stream.avail_out = buffer.size(); int rc = inflate(&(gzip->stream), Z_SYNC_FLUSH); if(rc != Z_OK && rc != Z_STREAM_END) { clear(); if(rc == Z_DATA_ERROR) throw Decoding_Error("Gzip_Decompression: Data integrity error"); else if(rc == Z_NEED_DICT) throw Decoding_Error("Gzip_Decompression: Need preset dictionary"); else if(rc == Z_MEM_ERROR) throw Memory_Exhaustion(); else throw std::runtime_error("Gzip decompression: Unknown error"); } send(&buffer[0], buffer.size() - gzip->stream.avail_out); if(rc == Z_STREAM_END) { size_t read_from_block = length - gzip->stream.avail_in; clear(); gzip = new Gzip_Stream; if(inflateInit2(&(gzip->stream), (raw_deflate ? -15 : (MAX_WBITS + 32))) != Z_OK) { throw Memory_Exhaustion(); } gzip->stream.next_in = input + read_from_block; gzip->stream.avail_in = length - read_from_block; input += read_from_block; length -= read_from_block; } } }
/* * Try to decode the actual information */ void X509_Object::do_decode() { try { force_decode(); } catch(Decoding_Error& e) { throw Decoding_Error(m_PEM_label_pref + " decoding failed (" + e.what() + ")"); } catch(Invalid_Argument& e) { throw Decoding_Error(m_PEM_label_pref + " decoding failed (" + e.what() + ")"); } }
Server_Name_Indicator::Server_Name_Indicator(TLS_Data_Reader& reader, u16bit extension_size) { /* * This is used by the server to confirm that it knew the name */ if(extension_size == 0) return; u16bit name_bytes = reader.get_u16bit(); if(name_bytes + 2 != extension_size) throw Decoding_Error("Bad encoding of SNI extension"); while(name_bytes) { byte name_type = reader.get_byte(); name_bytes--; if(name_type == 0) // DNS { m_sni_host_name = reader.get_string(2, 1, 65535); name_bytes -= (2 + m_sni_host_name.size()); } else // some other unknown name type { reader.discard_next(name_bytes); name_bytes = 0; } } }
/************************************************* * Convert a string into a time duration * *************************************************/ u32bit timespec_to_u32bit(const std::string& timespec) { if(timespec == "") return 0; const char suffix = timespec[timespec.size()-1]; std::string value = timespec.substr(0, timespec.size()-1); u32bit scale = 1; if(Charset::is_digit(suffix)) value += suffix; else if(suffix == 's') scale = 1; else if(suffix == 'm') scale = 60; else if(suffix == 'h') scale = 60 * 60; else if(suffix == 'd') scale = 24 * 60 * 60; else if(suffix == 'y') scale = 365 * 24 * 60 * 60; else throw Decoding_Error("timespec_to_u32bit: Bad input " + timespec); return scale * to_u32bit(value); }
Certificate_Status::Certificate_Status(const std::vector<uint8_t>& buf) { if(buf.size() < 5) throw Decoding_Error("Invalid Certificate_Status message: too small"); if(buf[0] != 1) // not OCSP throw Decoding_Error("Unexpected Certificate_Status message: unexpected response type"); size_t len = make_uint32(0, buf[1], buf[2], buf[3]); // Verify the redundant length field... if(buf.size() != len + 4) throw Decoding_Error("Invalid Certificate_Status: invalid length field"); m_response.assign(buf.begin() + 4, buf.end()); }
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, const secure_vector<byte>& key_bits) { m_domain_params = EC_Group(alg_id.parameters); m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; OID key_parameters; secure_vector<byte> public_key_bits; BER_Decoder(key_bits) .start_cons(SEQUENCE) .decode_and_check<size_t>(1, "Unknown version code for ECC key") .decode_octet_string_bigint(m_private_key) .decode_optional(key_parameters, ASN1_Tag(0), PRIVATE) .decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE) .end_cons(); if(!key_parameters.empty() && key_parameters != alg_id.oid) throw Decoding_Error("EC_PrivateKey - inner and outer OIDs did not match"); if(public_key_bits.empty()) { m_public_key = domain().get_base_point() * m_private_key; BOTAN_ASSERT(m_public_key.on_the_curve(), "Public point derived from loaded key was on the curve"); } else { m_public_key = OS2ECP(public_key_bits, domain().get_curve()); // OS2ECP verifies that the point is on the curve } }
Maximum_Fragment_Length::Maximum_Fragment_Length(TLS_Data_Reader& reader, u16bit extension_size) { if(extension_size != 1) throw Decoding_Error("Bad size for maximum fragment extension"); const byte val = reader.get_byte(); switch(val) { case 1: m_max_fragment = 512; break; case 2: m_max_fragment = 1024; break; case 3: m_max_fragment = 2048; break; case 4: m_max_fragment = 4096; break; default: throw TLS_Exception(Alert::ILLEGAL_PARAMETER, "Bad value " + std::to_string(val) + " for max fragment len"); } }
SRP6_Authenticator_File::SRP6_Authenticator_File(std::istream& in) { if(!in) return; // no entries while(in.good()) { std::string line; std::getline(in, line); std::vector<std::string> parts = split_on(line, ':'); if(parts.size() != 4) throw Decoding_Error("Invalid line in SRP authenticator file"); std::string username = parts[0]; BigInt v = BigInt::decode(base64_decode(parts[1])); std::vector<byte> salt = unlock(base64_decode(parts[2])); BigInt group_id_idx = BigInt::decode(base64_decode(parts[3])); std::string group_id; if(group_id_idx == 1) group_id = "modp/srp/1024"; else if(group_id_idx == 2) group_id = "modp/srp/1536"; else if(group_id_idx == 3) group_id = "modp/srp/2048"; else continue; // unknown group, ignored m_entries[username] = SRP6_Data(v, salt, group_id); } }
/** * Deserialize a Server Key Exchange message */ Server_Key_Exchange::Server_Key_Exchange(const std::vector<byte>& buf, const std::string& kex_algo, const std::string& sig_algo, Protocol_Version version) { TLS_Data_Reader reader("ServerKeyExchange", buf); /* * Here we are deserializing enough to find out what offset the * signature is at. All processing is done when the Client Key Exchange * is prepared. */ if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK") { reader.get_string(2, 0, 65535); // identity hint } if(kex_algo == "DH" || kex_algo == "DHE_PSK") { // 3 bigints, DH p, g, Y for(size_t i = 0; i != 3; ++i) { reader.get_range<byte>(2, 1, 65535); } } else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK") { reader.get_byte(); // curve type reader.get_u16bit(); // curve id reader.get_range<byte>(1, 1, 255); // public key } else if(kex_algo == "SRP_SHA") { // 2 bigints (N,g) then salt, then server B reader.get_range<byte>(2, 1, 65535); reader.get_range<byte>(2, 1, 65535); reader.get_range<byte>(1, 1, 255); reader.get_range<byte>(2, 1, 65535); } else if(kex_algo != "PSK") throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " + kex_algo); m_params.assign(buf.data(), buf.data() + reader.read_so_far()); if(sig_algo != "") { if(version.supports_negotiable_signature_algorithms()) { m_hash_algo = Signature_Algorithms::hash_algo_name(reader.get_byte()); m_sig_algo = Signature_Algorithms::sig_algo_name(reader.get_byte()); } m_signature = reader.get_range<byte>(2, 0, 65535); } reader.assert_done(); }
/* * Finish Decompressing with Gzip */ void Gzip_Decompression::end_msg() { if(no_writes) return; gzip->stream.next_in = 0; gzip->stream.avail_in = 0; int rc = Z_OK; while(rc != Z_STREAM_END) { gzip->stream.next_out = reinterpret_cast<Bytef*>(&buffer[0]); gzip->stream.avail_out = buffer.size(); rc = inflate(&(gzip->stream), Z_SYNC_FLUSH); if(rc != Z_OK && rc != Z_STREAM_END) { clear(); throw Decoding_Error("Gzip_Decompression: Error finalizing"); } send(&buffer[0], buffer.size() - gzip->stream.avail_out); } clear(); }
void Extensions::deserialize(TLS_Data_Reader& reader) { if(reader.has_remaining()) { const u16bit all_extn_size = reader.get_u16bit(); if(reader.remaining_bytes() != all_extn_size) throw Decoding_Error("Bad extension size"); while(reader.has_remaining()) { const u16bit extension_code = reader.get_u16bit(); const u16bit extension_size = reader.get_u16bit(); Extension* extn = make_extension(reader, extension_code, extension_size); if(extn) this->add(extn); else // unknown/unhandled extension reader.discard_next(extension_size); } } }
/* * 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(PEM_label_pref + " decoding failed (" + what + ")"); } catch(Invalid_Argument& e) { const std::string what = e.what(); throw Decoding_Error(PEM_label_pref + " decoding failed (" + what + ")"); } }
/* * Decompress a message */ void CMS_Decoder::decompress(BER_Decoder& decoder) { size_t version; AlgorithmIdentifier comp_algo; BER_Decoder comp_info = decoder.start_cons(SEQUENCE); comp_info.decode(version); if(version != 0) throw Decoding_Error("CMS: Unknown version for CompressedData"); comp_info.decode(comp_algo); read_econtent(comp_info); comp_info.end_cons(); Filter* decompressor = 0; info = comp_algo.oid.as_string(); #if defined(BOTAN_HAS_COMPRESSOR_ZLIB) if(comp_algo.oid == OIDS::lookup("Compression.Zlib")) { decompressor = new Zlib_Decompression; info = "Zlib"; } #endif if(!decompressor) status = FAILURE; Pipe pipe(decompressor); pipe.process_msg(data); data = pipe.read_all(); }
/* * Decode PKCS#5 PBES2 parameters */ void PBE_PKCS5v20::decode_params(DataSource& source) { AlgorithmIdentifier kdf_algo, enc_algo; BER_Decoder(source) .start_cons(SEQUENCE) .decode(kdf_algo) .decode(enc_algo) .verify_end() .end_cons(); if(kdf_algo.oid == OIDS::lookup("PKCS5.PBKDF2")) { BER_Decoder(kdf_algo.parameters) .start_cons(SEQUENCE) .decode(salt, OCTET_STRING) .decode(iterations) .decode_optional(key_length, INTEGER, UNIVERSAL) .verify_end() .end_cons(); } else throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " + kdf_algo.oid.as_string()); Algorithm_Factory& af = global_state().algorithm_factory(); std::string cipher = OIDS::lookup(enc_algo.oid); std::vector<std::string> cipher_spec = split_on(cipher, '/'); if(cipher_spec.size() != 2) throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher); if(!known_cipher(cipher_spec[0]) || cipher_spec[1] != "CBC") throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher); BER_Decoder(enc_algo.parameters).decode(iv, OCTET_STRING).verify_end(); block_cipher = af.make_block_cipher(cipher_spec[0]); hash_function = af.make_hash_function("SHA-160"); if(key_length == 0) key_length = block_cipher->maximum_keylength(); if(salt.size() < 8) throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small"); }
SRP_Identifier::SRP_Identifier(TLS_Data_Reader& reader, u16bit extension_size) { m_srp_identifier = reader.get_string(1, 1, 255); if(m_srp_identifier.size() + 1 != extension_size) throw Decoding_Error("Bad encoding for SRP identifier extension"); }
Renegotiation_Extension::Renegotiation_Extension(TLS_Data_Reader& reader, u16bit extension_size) { m_reneg_data = reader.get_range<byte>(1, 0, 255); if(m_reneg_data.size() + 1 != extension_size) throw Decoding_Error("Bad encoding for secure renegotiation extn"); }
Ed25519_PublicKey::Ed25519_PublicKey(const AlgorithmIdentifier&, const std::vector<uint8_t>& key_bits) { m_public = key_bits; if(m_public.size() != 32) throw Decoding_Error("Invalid size for Ed25519 public key"); }