+ SSL OPTION DESCRIPTIONS - CLIENT SIDE
+
+ Options described here are client specific or has a slightly different
+diff --git a/lib/ssl/src/dtls_record.erl b/lib/ssl/src/dtls_record.erl
+index a7bbb6b..ae35dd7 100644
+--- a/lib/ssl/src/dtls_record.erl
++++ b/lib/ssl/src/dtls_record.erl
+@@ -1,7 +1,7 @@
+ %%
+ %% %CopyrightBegin%
+ %%
+-%% Copyright Ericsson AB 2013-2014. All Rights Reserved.
++%% Copyright Ericsson AB 2013-2015. All Rights Reserved.
+ %%
+ %% The contents of this file are subject to the Erlang Public License,
+ %% Version 1.1, (the "License"); you may not use this file except in
+@@ -146,7 +146,7 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
+ = ConnnectionStates0) ->
+ CompressAlg = SecParams#security_parameters.compression_algorithm,
+ {PlainFragment, Mac, ReadState1} = ssl_record:decipher(dtls_v1:corresponding_tls_version(Version),
+- CipherFragment, ReadState0),
++ CipherFragment, ReadState0, true),
+ MacHash = calc_mac_hash(ReadState1, Type, Version, Epoch, Seq, PlainFragment),
+ case ssl_record:is_correct_mac(Mac, MacHash) of
+ true ->
+diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
+index b4bea25..4b7f495 100644
+--- a/lib/ssl/src/ssl.erl
++++ b/lib/ssl/src/ssl.erl
+@@ -1,7 +1,7 @@
+ %%
+ %% %CopyrightBegin%
+ %%
+-%% Copyright Ericsson AB 1999-2014. All Rights Reserved.
++%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
+ %%
+ %% The contents of this file are subject to the Erlang Public License,
+ %% Version 1.1, (the "License"); you may not use this file except in
+@@ -656,7 +656,8 @@ handle_options(Opts0) ->
+ log_alert = handle_option(log_alert, Opts, true),
+ server_name_indication = handle_option(server_name_indication, Opts, undefined),
+ honor_cipher_order = handle_option(honor_cipher_order, Opts, false),
+- protocol = proplists:get_value(protocol, Opts, tls)
++ protocol = proplists:get_value(protocol, Opts, tls),
++ padding_check = proplists:get_value(padding_check, Opts, true)
+ },
+
+ CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed, tcp_error}),
+@@ -669,7 +670,7 @@ handle_options(Opts0) ->
+ cb_info, renegotiate_at, secure_renegotiate, hibernate_after,
+ erl_dist, next_protocols_advertised,
+ client_preferred_next_protocols, log_alert,
+- server_name_indication, honor_cipher_order],
++ server_name_indication, honor_cipher_order, padding_check],
+
+ SockOpts = lists:foldl(fun(Key, PropList) ->
+ proplists:delete(Key, PropList)
+@@ -847,6 +848,8 @@ validate_option(server_name_indication, undefined) ->
+ undefined;
+ validate_option(honor_cipher_order, Value) when is_boolean(Value) ->
+ Value;
++validate_option(padding_check, Value) when is_boolean(Value) ->
++ Value;
+ validate_option(Opt, Value) ->
+ throw({error, {options, {Opt, Value}}}).
+
+diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
+index 72467ea..ff9c618 100644
+--- a/lib/ssl/src/ssl_cipher.erl
++++ b/lib/ssl/src/ssl_cipher.erl
+@@ -1,7 +1,7 @@
+ %%
+ %% %CopyrightBegin%
+ %%
+-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
++%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
+ %%
+ %% The contents of this file are subject to the Erlang Public License,
+ %% Version 1.1, (the "License"); you may not use this file except in
+@@ -33,8 +33,7 @@
+ -include_lib("public_key/include/public_key.hrl").
+
+ -export([security_parameters/2, security_parameters/3, suite_definition/1,
+- decipher/5, cipher/5,
+- suite/1, suites/1, all_suites/1,
++ decipher/6, cipher/5, suite/1, suites/1, all_suites/1,
+ ec_keyed_suites/0, anonymous_suites/0, psk_suites/1, srp_suites/0,
+ openssl_suite/1, openssl_suite_name/1, filter/2, filter_suites/1,
+ hash_algorithm/1, sign_algorithm/1, is_acceptable_hash/2]).
+@@ -143,17 +142,18 @@ block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
+ {T, CS0#cipher_state{iv=NextIV}}.
+
+ %%--------------------------------------------------------------------
+--spec decipher(cipher_enum(), integer(), #cipher_state{}, binary(), ssl_record:ssl_version()) ->
++-spec decipher(cipher_enum(), integer(), #cipher_state{}, binary(),
++ ssl_record:ssl_version(), boolean()) ->
+ {binary(), binary(), #cipher_state{}} | #alert{}.
+ %%
+ %% Description: Decrypts the data and the MAC using cipher described
+ %% by cipher_enum() and updating the cipher state.
+ %%-------------------------------------------------------------------
+-decipher(?NULL, _HashSz, CipherState, Fragment, _) ->
++decipher(?NULL, _HashSz, CipherState, Fragment, _, _) ->
+ {Fragment, <<>>, CipherState};
+-decipher(?RC4, HashSz, CipherState, Fragment, _) ->
++decipher(?RC4, HashSz, CipherState, Fragment, _, _) ->
+ State0 = case CipherState#cipher_state.state of
+- undefined -> crypto:stream_init(rc4, CipherState#cipher_state.key);
++ undefined -> crypto:stream_init(rc4, CipherState#cipher_state.key);
+ S -> S
+ end,
+ try crypto:stream_decrypt(State0, Fragment) of
+@@ -171,23 +171,23 @@ decipher(?RC4, HashSz, CipherState, Fragment, _) ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end;
+
+-decipher(?DES, HashSz, CipherState, Fragment, Version) ->
++decipher(?DES, HashSz, CipherState, Fragment, Version, PaddingCheck) ->
+ block_decipher(fun(Key, IV, T) ->
+ crypto:block_decrypt(des_cbc, Key, IV, T)
+- end, CipherState, HashSz, Fragment, Version);
+-decipher(?'3DES', HashSz, CipherState, Fragment, Version) ->
++ end, CipherState, HashSz, Fragment, Version, PaddingCheck);
++decipher(?'3DES', HashSz, CipherState, Fragment, Version, PaddingCheck) ->
+ block_decipher(fun(<>, IV, T) ->
+ crypto:block_decrypt(des3_cbc, [K1, K2, K3], IV, T)
+- end, CipherState, HashSz, Fragment, Version);
+-decipher(?AES, HashSz, CipherState, Fragment, Version) ->
++ end, CipherState, HashSz, Fragment, Version, PaddingCheck);
++decipher(?AES, HashSz, CipherState, Fragment, Version, PaddingCheck) ->
+ block_decipher(fun(Key, IV, T) when byte_size(Key) =:= 16 ->
+ crypto:block_decrypt(aes_cbc128, Key, IV, T);
+ (Key, IV, T) when byte_size(Key) =:= 32 ->
+ crypto:block_decrypt(aes_cbc256, Key, IV, T)
+- end, CipherState, HashSz, Fragment, Version).
++ end, CipherState, HashSz, Fragment, Version, PaddingCheck).
+
+ block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
+- HashSz, Fragment, Version) ->
++ HashSz, Fragment, Version, PaddingCheck) ->
+ try
+ Text = Fun(Key, IV, Fragment),
+ NextIV = next_iv(Fragment, IV),
+@@ -195,7 +195,7 @@ block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
+ Content = GBC#generic_block_cipher.content,
+ Mac = GBC#generic_block_cipher.mac,
+ CipherState1 = CipherState0#cipher_state{iv=GBC#generic_block_cipher.next_iv},
+- case is_correct_padding(GBC, Version) of
++ case is_correct_padding(GBC, Version, PaddingCheck) of
+ true ->
+ {Content, Mac, CipherState1};
+ false ->
+@@ -1288,16 +1288,18 @@ generic_stream_cipher_from_bin(T, HashSz) ->
+ #generic_stream_cipher{content=Content,
+ mac=Mac}.
+
+-%% For interoperability reasons we do not check the padding content in
+-%% SSL 3.0 and TLS 1.0 as it is not strictly required and breaks
+-%% interopability with for instance Google.
+ is_correct_padding(#generic_block_cipher{padding_length = Len,
+- padding = Padding}, {3, N})
+- when N == 0; N == 1 ->
+- Len == byte_size(Padding);
+-%% Padding must be check in TLS 1.1 and after
++ padding = Padding}, {3, 0}, _) ->
++ Len == byte_size(Padding); %% Only length check is done in SSL 3.0 spec
++%% For interoperability reasons it is possible to disable
++%% the padding check when using TLS 1.0, as it is not strictly required
++%% in the spec (only recommended), howerver this makes TLS 1.0 vunrable to the Poodle attack
++%% so by default this clause will not match
++is_correct_padding(GenBlockCipher, {3, 1}, false) ->
++ is_correct_padding(GenBlockCipher, {3, 0}, false);
++%% Padding must be checked in TLS 1.1 and after
+ is_correct_padding(#generic_block_cipher{padding_length = Len,
+- padding = Padding}, _) ->
++ padding = Padding}, _, _) ->
+ Len == byte_size(Padding) andalso
+ list_to_binary(lists:duplicate(Len, Len)) == Padding.
+
+diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
+index 155fa81..1250b50 100644
+--- a/lib/ssl/src/ssl_internal.hrl
++++ b/lib/ssl/src/ssl_internal.hrl
+@@ -1,7 +1,7 @@
+ %%
+ %% %CopyrightBegin%
+ %%
+-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
++%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
+ %%
+ %% The contents of this file are subject to the Erlang Public License,
+ %% Version 1.1, (the "License"); you may not use this file except in
+@@ -117,7 +117,8 @@
+ server_name_indication = undefined,
+ %% Should the server prefer its own cipher order over the one provided by
+ %% the client?
+- honor_cipher_order = false
++ honor_cipher_order = false,
++ padding_check = true
+ }).
+
+ -record(socket_options,
+diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
+index 7337225..025a46b 100644
+--- a/lib/ssl/src/ssl_record.erl
++++ b/lib/ssl/src/ssl_record.erl
+@@ -1,7 +1,7 @@
+ %%
+ %% %CopyrightBegin%
+ %%
+-%% Copyright Ericsson AB 2013-2014. All Rights Reserved.
++%% Copyright Ericsson AB 2013-2015. All Rights Reserved.
+ %%
+ %% The contents of this file are subject to the Erlang Public License,
+ %% Version 1.1, (the "License"); you may not use this file except in
+@@ -48,7 +48,7 @@
+ -export([compress/3, uncompress/3, compressions/0]).
+
+ %% Payload encryption/decryption
+--export([cipher/4, decipher/3, is_correct_mac/2]).
++-export([cipher/4, decipher/4, is_correct_mac/2]).
+
+ -export_type([ssl_version/0, ssl_atom_version/0]).
+
+@@ -376,8 +376,9 @@ cipher(Version, Fragment,
+ {CipherFragment, CipherS1} =
+ ssl_cipher:cipher(BulkCipherAlgo, CipherS0, MacHash, Fragment, Version),
+ {CipherFragment, WriteState0#connection_state{cipher_state = CipherS1}}.
++
+ %%--------------------------------------------------------------------
+--spec decipher(ssl_version(), binary(), #connection_state{}) -> {binary(), binary(), #connection_state{}} | #alert{}.
++-spec decipher(ssl_version(), binary(), #connection_state{}, boolean()) -> {binary(), binary(), #connection_state{}} | #alert{}.
+ %%
+ %% Description: Payload decryption
+ %%--------------------------------------------------------------------
+@@ -387,8 +388,8 @@ decipher(Version, CipherFragment,
+ BulkCipherAlgo,
+ hash_size = HashSz},
+ cipher_state = CipherS0
+- } = ReadState) ->
+- case ssl_cipher:decipher(BulkCipherAlgo, HashSz, CipherS0, CipherFragment, Version) of
++ } = ReadState, PaddingCheck) ->
++ case ssl_cipher:decipher(BulkCipherAlgo, HashSz, CipherS0, CipherFragment, Version, PaddingCheck) of
+ {PlainFragment, Mac, CipherS1} ->
+ CS1 = ReadState#connection_state{cipher_state = CipherS1},
+ {PlainFragment, Mac, CS1};
+diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
+index 7df73fb..77d3aa7 100644
+--- a/lib/ssl/src/tls_connection.erl
++++ b/lib/ssl/src/tls_connection.erl
+@@ -1,7 +1,7 @@
+ %%
+ %% %CopyrightBegin%
+ %%
+-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
++%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
+ %%
+ %% The contents of this file are subject to the Erlang Public License,
+ %% Version 1.1, (the "License"); you may not use this file except in
+@@ -482,8 +482,9 @@ next_record(#state{protocol_buffers = #protocol_buffers{tls_packets = [], tls_ci
+ next_record(#state{protocol_buffers =
+ #protocol_buffers{tls_packets = [], tls_cipher_texts = [CT | Rest]}
+ = Buffers,
+- connection_states = ConnStates0} = State) ->
+- case tls_record:decode_cipher_text(CT, ConnStates0) of
++ connection_states = ConnStates0,
++ ssl_options = #ssl_options{padding_check = Check}} = State) ->
++ case tls_record:decode_cipher_text(CT, ConnStates0, Check) of
+ {Plain, ConnStates} ->
+ {Plain, State#state{protocol_buffers =
+ Buffers#protocol_buffers{tls_cipher_texts = Rest},
+diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
+index aa4fc8d..bb7a701 100644
+--- a/lib/ssl/src/tls_record.erl
++++ b/lib/ssl/src/tls_record.erl
+@@ -1,7 +1,7 @@
+ %%
+ %% %CopyrightBegin%
+ %%
+-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
++%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
+ %%
+ %% The contents of this file are subject to the Erlang Public License,
+ %% Version 1.1, (the "License"); you may not use this file except in
+@@ -34,7 +34,7 @@
+ -export([get_tls_records/2]).
+
+ %% Decoding
+--export([decode_cipher_text/2]).
++-export([decode_cipher_text/3]).
+
+ %% Encoding
+ -export([encode_plain_text/4]).
+@@ -142,19 +142,21 @@ encode_plain_text(Type, Version, Data,
+ {CipherText, ConnectionStates#connection_states{current_write = WriteState#connection_state{sequence_number = Seq +1}}}.
+
+ %%--------------------------------------------------------------------
+--spec decode_cipher_text(#ssl_tls{}, #connection_states{}) ->
++-spec decode_cipher_text(#ssl_tls{}, #connection_states{}, boolean()) ->
+ {#ssl_tls{}, #connection_states{}}| #alert{}.
+ %%
+ %% Description: Decode cipher text
+ %%--------------------------------------------------------------------
+ decode_cipher_text(#ssl_tls{type = Type, version = Version,
+- fragment = CipherFragment} = CipherText, ConnnectionStates0) ->
+- ReadState0 = ConnnectionStates0#connection_states.current_read,
+- #connection_state{compression_state = CompressionS0,
+- sequence_number = Seq,
+- security_parameters = SecParams} = ReadState0,
+- CompressAlg = SecParams#security_parameters.compression_algorithm,
+- case ssl_record:decipher(Version, CipherFragment, ReadState0) of
++ fragment = CipherFragment} = CipherText,
++ #connection_states{current_read =
++ #connection_state{
++ compression_state = CompressionS0,
++ sequence_number = Seq,
++ security_parameters=
++ #security_parameters{compression_algorithm = CompressAlg}
++ } = ReadState0} = ConnnectionStates0, PaddingCheck) ->
++ case ssl_record:decipher(Version, CipherFragment, ReadState0, PaddingCheck) of
+ {PlainFragment, Mac, ReadState1} ->
+ MacHash = calc_mac_hash(Type, Version, PlainFragment, ReadState1),
+ case ssl_record:is_correct_mac(Mac, MacHash) of
+diff --git a/lib/ssl/test/ssl_cipher_SUITE.erl b/lib/ssl/test/ssl_cipher_SUITE.erl
+index 45e9178..0e48b67 100644
+--- a/lib/ssl/test/ssl_cipher_SUITE.erl
++++ b/lib/ssl/test/ssl_cipher_SUITE.erl
+@@ -1,7 +1,7 @@
+ %%
+ %% %CopyrightBegin%
+ %%
+-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
++%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
+ %%
+ %% The contents of this file are subject to the Erlang Public License,
+ %% Version 1.1, (the "License"); you may not use this file except in
+@@ -38,7 +38,7 @@
+ suite() -> [{ct_hooks,[ts_install_cth]}].
+
+ all() ->
+- [aes_decipher_good, aes_decipher_good_tls11, aes_decipher_fail, aes_decipher_fail_tls11].
++ [aes_decipher_good, aes_decipher_fail, padding_test].
+
+ groups() ->
+ [].
+@@ -73,93 +73,123 @@ end_per_testcase(_TestCase, Config) ->
+ %% Test Cases --------------------------------------------------------
+ %%--------------------------------------------------------------------
+ aes_decipher_good() ->
+- [{doc,"Decipher a known cryptotext."}].
++ [{doc,"Decipher a known cryptotext using a correct key"}].
+
+ aes_decipher_good(Config) when is_list(Config) ->
+ HashSz = 32,
+- CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+- key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,148>>},
+- Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+- 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+- 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+- 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+- Content = <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56, "HELLO\n">>,
+- Mac = <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>,
+- Version = {3,0},
+- {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+- Version1 = {3,1},
+- {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
+- ok.
+-
+-%%--------------------------------------------------------------------
+-
+-aes_decipher_good_tls11() ->
+- [{doc,"Decipher a known TLS 1.1 cryptotext."}].
+-
+-%% the fragment is actuall a TLS 1.1 record, with
+-%% Version = TLS 1.1, we get the correct NextIV in #cipher_state
+-aes_decipher_good_tls11(Config) when is_list(Config) ->
+- HashSz = 32,
+- CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+- key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,148>>},
+- Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+- 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+- 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+- 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+- Content = <<"HELLO\n">>,
+- NextIV = <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56>>,
+- Mac = <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>,
+- Version = {3,2},
+- {Content, Mac, #cipher_state{iv = NextIV}} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+- Version1 = {3,2},
+- {Content, Mac, #cipher_state{iv = NextIV}} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
+- ok.
++ CipherState = correct_cipher_state(),
++ decipher_check_good(HashSz, CipherState, {3,0}),
++ decipher_check_good(HashSz, CipherState, {3,1}),
++ decipher_check_good(HashSz, CipherState, {3,2}),
++ decipher_check_good(HashSz, CipherState, {3,3}).
+
+ %%--------------------------------------------------------------------
+
+ aes_decipher_fail() ->
+- [{doc,"Decipher a known cryptotext."}].
++ [{doc,"Decipher a known cryptotext using a incorrect key"}].
+
+-%% same as above, last byte of key replaced
+ aes_decipher_fail(Config) when is_list(Config) ->
+ HashSz = 32,
+- CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+- key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,254>>},
+- Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+- 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+- 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+- 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+- Version = {3,0},
+- {Content, Mac, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+- 32 = byte_size(Content),
+- 32 = byte_size(Mac),
+- Version1 = {3,1},
+- {Content1, Mac1, _} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
+- 32 = byte_size(Content1),
+- 32 = byte_size(Mac1),
+- ok.
+
+-%%--------------------------------------------------------------------
+-
+-aes_decipher_fail_tls11() ->
+- [{doc,"Decipher a known TLS 1.1 cryptotext."}].
+-
+-%% same as above, last byte of key replaced
+-%% stricter padding checks in TLS 1.1 mean we get an alert instead
+-aes_decipher_fail_tls11(Config) when is_list(Config) ->
+- HashSz = 32,
+- CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+- key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,254>>},
+- Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+- 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+- 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+- 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+- Version = {3,2},
+- #alert{level = ?FATAL, description = ?BAD_RECORD_MAC} =
+- ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+- Version1 = {3,3},
+- #alert{level = ?FATAL, description = ?BAD_RECORD_MAC} =
+- ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1),
+- ok.
++ CipherState = incorrect_cipher_state(),
++ decipher_check_fail(HashSz, CipherState, {3,0}),
++ decipher_check_fail(HashSz, CipherState, {3,1}),
++ decipher_check_fail(HashSz, CipherState, {3,2}),
++ decipher_check_fail(HashSz, CipherState, {3,3}).
+
+ %%--------------------------------------------------------------------
++padding_test(Config) when is_list(Config) ->
++ HashSz = 16,
++ CipherState = correct_cipher_state(),
++ pad_test(HashSz, CipherState, {3,0}),
++ pad_test(HashSz, CipherState, {3,1}),
++ pad_test(HashSz, CipherState, {3,2}),
++ pad_test(HashSz, CipherState, {3,3}).
++
++%%--------------------------------------------------------------------
++% Internal functions --------------------------------------------------------
++%%--------------------------------------------------------------------
++decipher_check_good(HashSz, CipherState, Version) ->
++ {Content, NextIV, Mac} = content_nextiv_mac(Version),
++ {Content, Mac, #cipher_state{iv = NextIV}} =
++ ssl_cipher:decipher(?AES, HashSz, CipherState, aes_fragment(Version), Version, true).
++
++decipher_check_fail(HashSz, CipherState, Version) ->
++ {Content, NextIV, Mac} = content_nextiv_mac(Version),
++ true = {Content, Mac, #cipher_state{iv = NextIV}} =/=
++ ssl_cipher:decipher(?AES, HashSz, CipherState, aes_fragment(Version), Version, true).
++
++pad_test(HashSz, CipherState, {3,0} = Version) ->
++ %% 3.0 does not have padding test
++ {Content, NextIV, Mac} = badpad_content_nextiv_mac(Version),
++ {Content, Mac, #cipher_state{iv = NextIV}} =
++ ssl_cipher:decipher(?AES, HashSz, CipherState, badpad_aes_fragment({3,0}), {3,0}, true),
++ {Content, Mac, #cipher_state{iv = NextIV}} =
++ ssl_cipher:decipher(?AES, HashSz, CipherState, badpad_aes_fragment({3,0}), {3,0}, false);
++pad_test(HashSz, CipherState, {3,1} = Version) ->
++ %% 3.1 should have padding test, but may be disabled
++ {Content, NextIV, Mac} = badpad_content_nextiv_mac(Version),
++ BadCont = badpad_content(Content),
++ {Content, Mac, #cipher_state{iv = NextIV}} =
++ ssl_cipher:decipher(?AES, HashSz, CipherState, badpad_aes_fragment({3,1}) , {3,1}, false),
++ {BadCont, Mac, #cipher_state{iv = NextIV}} =
++ ssl_cipher:decipher(?AES, HashSz, CipherState, badpad_aes_fragment({3,1}), {3,1}, true);
++pad_test(HashSz, CipherState, Version) ->
++ %% 3.2 and 3.3 must have padding test
++ {Content, NextIV, Mac} = badpad_content_nextiv_mac(Version),
++ BadCont = badpad_content(Content),
++ {BadCont, Mac, #cipher_state{iv = NextIV}} = ssl_cipher:decipher(?AES, HashSz, CipherState,
++ badpad_aes_fragment(Version), Version, false),
++ {BadCont, Mac, #cipher_state{iv = NextIV}} = ssl_cipher:decipher(?AES, HashSz, CipherState,
++ badpad_aes_fragment(Version), Version, true).
++
++aes_fragment({3,N}) when N == 0; N == 1->
++ <<197,9,6,109,242,87,80,154,85,250,110,81,119,95,65,185,53,206,216,153,246,169,
++ 119,177,178,238,248,174,253,220,242,81,33,0,177,251,91,44,247,53,183,198,165,
++ 63,20,194,159,107>>;
++
++aes_fragment(_) ->
++ <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
++ 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
++ 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
++ 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>.
++
++badpad_aes_fragment({3,N}) when N == 0; N == 1 ->
++ <<186,139,125,10,118,21,26,248,120,108,193,104,87,118,145,79,225,55,228,10,105,
++ 30,190,37,1,88,139,243,210,99,65,41>>;
++badpad_aes_fragment(_) ->
++ <<137,31,14,77,228,80,76,103,183,125,55,250,68,190,123,131,117,23,229,180,207,
++ 94,121,137,117,157,109,99,113,61,190,138,131,229,201,120,142,179,172,48,77,
++ 234,19,240,33,38,91,93>>.
++
++content_nextiv_mac({3,N}) when N == 0; N == 1 ->
++ {<<"HELLO\n">>,
++ <<33,0, 177,251, 91,44, 247,53, 183,198, 165,63, 20,194, 159,107>>,
++ <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>};
++content_nextiv_mac(_) ->
++ {<<"HELLO\n">>,
++ <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56>>,
++ <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>}.
++
++badpad_content_nextiv_mac({3,N}) when N == 0; N == 1 ->
++ {<<"HELLO\n">>,
++ <<225,55,228,10,105,30,190,37,1,88,139,243,210,99,65,41>>,
++ <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56>>
++ };
++badpad_content_nextiv_mac(_) ->
++ {<<"HELLO\n">>,
++ <<133,211,45,189,179,229,56,86,11,178,239,159,14,160,253,140>>,
++ <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56>>
++ }.
++
++badpad_content(Content) ->
++ %% BadContent will fail mac test
++ <<16#F0, Content/binary>>.
++
++correct_cipher_state() ->
++ #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
++ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,148>>}.
++
++incorrect_cipher_state() ->
++ #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
++ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,254>>}.
diff --git a/otp-0011-Quickfix-for-cmpxchg8b-inline-asm-when-pic-and-gcc-5.patch b/otp-0011-Quickfix-for-cmpxchg8b-inline-asm-when-pic-and-gcc-5.patch
new file mode 100644
index 0000000..35d248e
--- /dev/null
+++ b/otp-0011-Quickfix-for-cmpxchg8b-inline-asm-when-pic-and-gcc-5.patch
@@ -0,0 +1,27 @@
+From: Rickard Green
+Date: Tue, 9 Feb 2016 18:23:26 +0100
+Subject: [PATCH] Quickfix for cmpxchg8b inline asm when pic and gcc >= 5.0 is
+ used
+
+
+diff --git a/erts/include/internal/i386/ethr_dw_atomic.h b/erts/include/internal/i386/ethr_dw_atomic.h
+index 9fb89bb..89f32f7 100644
+--- a/erts/include/internal/i386/ethr_dw_atomic.h
++++ b/erts/include/internal/i386/ethr_dw_atomic.h
+@@ -114,6 +114,8 @@ ethr_native_dw_atomic_addr(ethr_native_dw_atomic_t *var)
+ return (ethr_sint_t *) ETHR_DW_NATMC_MEM__(var);
+ }
+
++#if !ETHR_AT_LEAST_GCC_VSN__(5, 0, 0)
++
+ #if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
+ /*
+ * When position independent code is used in 32-bit mode, the EBX register
+@@ -137,6 +139,7 @@ ethr_native_dw_atomic_addr(ethr_native_dw_atomic_t *var)
+ # endif
+ #endif
+
++#endif /* < gcc-5.0 */
+
+ #define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_MB
+
diff --git a/otp-get-patches.sh b/otp-get-patches.sh
index 75d4a54..033db0e 100755
--- a/otp-get-patches.sh
+++ b/otp-get-patches.sh
@@ -17,6 +17,18 @@
#
# # start of autogenerated patch tag list
# # end of autogenerated patch tag list
+# # start of autogenerated prep patch list
+# # end of autogenerated prep patch list
+#
+# The following special comment lines in the git commit messages
+# will be interpreted:
+#
+# Fedora-Spec-Comment: This patch only applies to EL6 builds
+# Fedora-Spec-Before: %if 0%?el6}
+# Fedora-Spec-After: %endif
+#
+# If there is no "Fedora-Spec-Comment:" line, we will use
+# "Fedora specific patch".
# Command line parsing
otp_dir="${1:?'Fatal: otp git repo dir required'}"
@@ -37,29 +49,44 @@ test -s "$tmpdir/patch-list.txt"
# Process patch files
echo "# start of autogenerated patch tag list" > "$tmpdir/patch-list-tags.txt"
+echo "# start of autogenerated prep patch list" > "$tmpdir/patch-list-prep.txt"
n=1
while read patch
do
otppatch="$(dirname "$patch")/otp-$(basename "$patch")"
${SED-sed} -e '1d' -e '/^-- $/,$d' "$patch" > "$otppatch"
rm -f "$patch"
+ comment="$(sed -n 's/^Fedora-Spec-Comment:\s*//p' "$otppatch")"
+ if test "x$comment" = "x"; then comment="Fedora specific patch"; fi
+ echo "# ${comment}" >> "$tmpdir/patch-list-tags.txt"
+ echo "# $(sed -n 's/^Subject: \[PATCH\] //p' "$otppatch")" >> "$tmpdir/patch-list-tags.txt"
echo "Patch$n: $(basename "$otppatch")" >> "$tmpdir/patch-list-tags.txt"
+ base="$(basename "$patch" ".patch" | sed 's/^00[0-9][0-9]-//')"
+ backupext=".$(echo -n "$base" | tr -c -s '[:alnum:]' '_')"
+ sed -n 's/^Fedora-Spec-Before:\s*//p' "$otppatch" >> "$tmpdir/patch-list-prep.txt"
+ echo "%patch$n -p1 -b ${backupext}" >> "$tmpdir/patch-list-prep.txt"
+ sed -n 's/^Fedora-Spec-After:\s*//p' "$otppatch" >> "$tmpdir/patch-list-prep.txt"
n=$(($n + 1))
done < "$tmpdir/patch-list.txt"
echo "# end of autogenerated patch tag list" >> "$tmpdir/patch-list-tags.txt"
+echo "# end of autogenerated prep patch list" >> "$tmpdir/patch-list-prep.txt"
# Create updated spec file
specfile="erlang.spec"
newspec1="${tmpdir}/${specfile}.new1"
+newspec2="${tmpdir}/${specfile}.new2"
sed '/^# start of autogenerated patch tag list$/,$d' "$specfile" > "$newspec1"
cat "$tmpdir/patch-list-tags.txt" >> "$newspec1"
sed '1,/^# end of autogenerated patch tag list/d' "$specfile" >> "$newspec1"
+sed '/^# start of autogenerated prep patch list$/,$d' "$newspec1" > "$newspec2"
+cat "$tmpdir/patch-list-prep.txt" >> "$newspec2"
+sed '1,/^# end of autogenerated prep patch list/d' "$newspec1" >> "$newspec2"
# Actually put all changes into git index
git rm -f otp-00*.patch
mv "$tmpdir/otp-00"*.patch .
git add otp-00*.patch
-mv -f "$newspec1" "$specfile"
+mv -f "$newspec2" "$specfile"
git add "$specfile"
rm -rf "$tmpdir"
diff --git a/otp-make-subpackages.py b/otp-make-subpackages.py
deleted file mode 100644
index fd9df5e..0000000
--- a/otp-make-subpackages.py
+++ /dev/null
@@ -1,174 +0,0 @@
-import glob
-import os
-import re
-import rpm
-import sys
-
-ts = rpm.TransactionSet()
-
-packages = []
-for arg in sys.argv[1:]:
- packages += glob.glob(arg)
-
-erlang_provides = {}
-erlang_requires = {}
-
-package_names = []
-package_headers = {}
-
-##
-## Custom tweaks begins here
-##
-
-# These packages should be marked as noarch
-package_noarch = [
- "emacs-erlang",
- "emacs-erlang-el",
- "erlang-doc"]
-
-# These are additional Requires which cannot be picked up automatically (yet).
-# TODO these should be added automatically
-package_additional_requires = {
- "emacs-erlang": ["emacs-common-erlang = %{version}-%{release}", "emacs(bin) >= %{_emacs_version}" ],
- "emacs-erlang-el": ["emacs-erlang = %{version}-%{release}"],
- "erlang-dialyzer": ["graphviz"],
- "erlang-erl_interface": ["%{name}-erts%{?_isa} = %{version}-%{release}"],
- # This library (lksctp-tools) is dlopened so it can't be picked
- # up automatically by the RPM dependency checker
- "erlang-erts": ["lksctp-tools"],
- "erlang-gs": ["tk"],
- # Stores files/links in /usr/share/java so has to depend on jpackage-utils
- "erlang-ic": ["jpackage-utils"],
- # Stores files/links in /usr/share/java so has to depend on jpackage-utils
- "erlang-jinterface": ["%{name}-erts%{?_isa} = %{version}-%{release}", "jpackage-utils"],
- "erlang-wx": ["mesa-libGL", "mesa-libGLU"],
- }
-
-package_additional_buildrequires = {
- "emacs-erlang": ["emacs", "emacs-el"],
- "erlang-crypto": ["openssl-devel"],
- "erlang-diameter": ["ed"],
-
- # BEWARE. No fop for EPEL5, and only for x86/x86_64 in EPEL6,
- # so we cannot regenerate docs here. (Un)Fortunately we dropped
- # support for EPEL6 and older versions.
- # FIXME add bootstrap condition first.
- "erlang-doc": ["fop", "libxslt"],
-
- "erlang-erts": ["lksctp-tools-devel", "m4", "ncurses-devel", "zlib-devel"],
- "erlang-gs": ["tcl-devel", "tk-devel"],
-
- # in EPEL6 on arches different from %{ix86} x86_64 we have to
- # use java-devel-gcj, so technically this requirement makes it
- # impossible to build Java support there. (Un)Fortunately we
- # already dropped full support for EPEL6 and older versions.
- "erlang-ic": ["java-devel"],
- "erlang-jinterface": ["java-devel"],
-
- "erlang-odbc": ["unixODBC-devel"],
- }
-
-package_additional_obsoletes = {
- "erlang-erts": [
- "erlang-appmon",
- "erlang-docbuilder",
- "erlang-inviso",
- "erlang-pman",
- "erlang-toolbar",
- "erlang-tv"],
- }
-
-##
-## Custom tweaks ends here
-##
-
-# To match 'erlang(asn1ct_eval_ext:transform_to_EXTERNAL1994/1)'
-prog = re.compile("^erlang(.*:.*/\d+)")
-rpmmask = re.compile(".*\.rpm")
-
-# iterate over all rpms
-for package in sorted([p for p in packages if rpmmask.match(p)]):
-
- # A tricky part. We are processing packages, rebuilt with
- # %{__erlang_provides_requires}. Otherwise we won't get information
- # about imports/exports (until we learn how to parse Erlang BEAM file
- # headers with Python.
- fd = os.open(package, os.O_RDONLY)
- h = ts.hdrFromFdno(fd)
- os.close(fd)
-
- rpm_name = h[rpm.RPMTAG_NAME]
-
- # Let's calculate provides
- # We'll create dictionary to speedup future use
- # FIXME duplicate provides
- local_provides = [p for p in h[rpm.RPMTAG_PROVIDENAME] if prog.match(p)]
- erlang_provides.update({k: rpm_name for k in local_provides})
-
- # Let's calculate requires
- erlang_requires.update({rpm_name: [r for r in h[rpm.RPMTAG_REQUIRENAME] if prog.match(r) and not r in local_provides]})
-
- package_headers.update({rpm_name: h})
-
- package_names.append(rpm_name)
-
-namemask = re.compile("^erlang-[a-zA-Z0-9_]*$")
-
-print "### BEGIN OF AUTOGENERATED LIST ###"
-print ""
-
-for name in package_names:
- h = package_headers[name]
-
- if name == "erlang-doc":
- # Additional ifdef just for this sub-package (see below)
- print "%if %{with doc}"
-
- if namemask.match(name):
- print "%%package %s" % name.replace("erlang-", "")
- else:
- print "%%package -n %s" % name
-
- print "Summary: %s" % h[rpm.RPMTAG_SUMMARY]
- print "Group: %s" % h[rpm.RPMTAG_GROUP]
-
- rawdeps = [erlang_provides.get(r, "Error: missing requires: %s" % r) for r in erlang_requires[name]]
-
- deps = set()
- dependency_add = deps.add
- [x for x in rawdeps if not (x in deps or dependency_add(x))]
-
- # Additional BuildRequires (if any):
- for br in package_additional_buildrequires.get(name, []):
- print "BuildRequires: %s" % br
-
- # Add basic autogenerated Requires:
- for r in sorted(deps):
- #Requires: %{name}-stdlib%{?_isa} = %{version}-%{release}
- print "Requires: %s%%{?_isa} = %%{version}-%%{release}" % r.replace("erlang-", "%{name}-")
-
- # Add custom additional Requires (if any):
- for r in package_additional_requires.get(name, []):
- print "Requires: %s" % r
-
- # Add custom additional Obsoletes (if any):
- for os in package_additional_obsoletes.get(name, []):
- print "Obsoletes: %s" % os
-
- if name in package_noarch:
- print "BuildArch: noarch"
-
- print ""
- if namemask.match(name):
- print "%%description %s" % name.replace("erlang-", "")
- else:
- print "%%description -n %s" % name
- print "%s" % h[rpm.RPMTAG_DESCRIPTION]
-
- if name == "erlang-doc":
- # Additional ifdef just for this sub-package (see above)
- print "%endif"
-
- print ""
-
-print "### END OF AUTOGENERATED LIST ###"
diff --git a/sources b/sources
index 674a546..b22e8a6 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (otp-OTP-26.2.5.16.tar.gz) = 4e973be7e8ccad196d59759108a521535b0f046268eb0406f789a50f411fa27c9c11fcfb61a7218605bf1b32921bb52c52fc7c99917e1acfc0d3ed09437129b2
+0d06e7d3802d63992535116e4d37c1a4 otp-OTP-17.4.tar.gz