@@ -818,14 +818,15 @@ struct onionreply *create_onionreply(const tal_t *ctx,
818
818
towire (& reply -> contents , payload , tal_count (payload ));
819
819
tal_free (payload );
820
820
821
+ reply -> attr_data = NULL ;
821
822
return reply ;
822
823
}
823
824
824
825
struct onionreply * wrap_onionreply (const tal_t * ctx ,
825
826
const struct secret * shared_secret ,
826
827
const struct onionreply * reply )
827
828
{
828
- struct secret key ;
829
+ struct secret key , attr_key ;
829
830
struct onionreply * result = tal (ctx , struct onionreply );
830
831
831
832
/* BOLT #4:
@@ -839,9 +840,109 @@ struct onionreply *wrap_onionreply(const tal_t *ctx,
839
840
subkey_from_hmac ("ammag" , shared_secret , & key );
840
841
result -> contents = tal_dup_talarr (result , u8 , reply -> contents );
841
842
xor_cipher_stream (result -> contents , & key , tal_bytelen (result -> contents ));
843
+
844
+ if (reply -> attr_data ) {
845
+ result -> attr_data = tal (ctx , struct attribution_data );
846
+ subkey_from_hmac ("ammagext" , shared_secret , & attr_key );
847
+ result -> attr_data -> htlc_hold_time = tal_dup_talarr (result , u8 , reply -> attr_data -> htlc_hold_time );
848
+ xor_cipher_stream_off (& attr_key , 0 , result -> attr_data -> htlc_hold_time , tal_bytelen (result -> attr_data -> htlc_hold_time ));
849
+ result -> attr_data -> truncated_hmac = tal_dup_talarr (result , u8 , reply -> attr_data -> truncated_hmac );
850
+ xor_cipher_stream_off (& attr_key ,
851
+ tal_bytelen (result -> attr_data -> htlc_hold_time ),
852
+ result -> attr_data -> truncated_hmac ,
853
+ tal_bytelen (result -> attr_data -> truncated_hmac ));
854
+ } else {
855
+ result -> attr_data = NULL ;
856
+ }
857
+
842
858
return result ;
843
859
}
844
860
861
+ static void write_downstream_hmacs (struct crypto_auth_hmacsha256_state * state , int pos , u8 * truncated_hmac ) {
862
+ int hmac_idx = MAX_HOPS + MAX_HOPS - pos - 1 ;
863
+ for (int i = 0 ; i < pos ; i ++ ) {
864
+ hmac_update (state , truncated_hmac + (hmac_idx * TRUNC_HMAC_LEN ), TRUNC_HMAC_LEN );
865
+ int block_size = MAX_HOPS - i - 1 ;
866
+ hmac_idx += block_size ;
867
+ }
868
+ }
869
+
870
+ static void add_hmacs_to_attribution_data (struct onionreply * failonion , struct secret * shared_secret ) {
871
+ struct secret um_key ;
872
+ subkey_from_hmac ("um" , shared_secret , & um_key );
873
+ for (int i = 0 ; i < MAX_HOPS ; i ++ ) {
874
+ struct crypto_auth_hmacsha256_state state ;
875
+ struct hmac hmac ;
876
+ int pos = MAX_HOPS - i - 1 ;
877
+ hmac_start (& state , um_key .data , sizeof (um_key .data ));
878
+ hmac_update (& state , failonion -> contents , tal_bytelen (failonion -> contents ));
879
+ hmac_update (& state , failonion -> attr_data -> htlc_hold_time , (pos + 1 ) * HOLD_TIME_LEN );
880
+ write_downstream_hmacs (& state , pos , failonion -> attr_data -> truncated_hmac );
881
+ hmac_done (& state , & hmac );
882
+ memcpy (failonion -> attr_data -> truncated_hmac + (i * TRUNC_HMAC_LEN ), hmac .bytes , TRUNC_HMAC_LEN );
883
+ }
884
+
885
+ }
886
+
887
+ void update_attributable_data (struct onionreply * failonion , u32 hold_times , struct secret * shared_secret ) {
888
+ if (!failonion -> attr_data ) {
889
+ failonion -> attr_data = tal (failonion , struct attribution_data );
890
+ failonion -> attr_data -> htlc_hold_time = tal_arrz (failonion , u8 , 80 );
891
+ failonion -> attr_data -> truncated_hmac = tal_arrz (failonion , u8 , 840 );
892
+ } else {
893
+ /* Right shift */
894
+ memmove (& failonion -> attr_data -> htlc_hold_time [HOLD_TIME_LEN ], failonion -> attr_data -> htlc_hold_time , HOLD_TIME_LEN * (MAX_HOPS - 1 ));
895
+ int src_index = HMAC_COUNT - 2 ;
896
+ int dest_index = HMAC_COUNT - 1 ;
897
+ int copy_len = 1 ;
898
+
899
+ for (int i = 0 ; i < MAX_HOPS - 1 ; i ++ ) {
900
+ memmove (& failonion -> attr_data -> truncated_hmac [dest_index * TRUNC_HMAC_LEN ],
901
+ & failonion -> attr_data -> truncated_hmac [src_index * TRUNC_HMAC_LEN ],
902
+ copy_len * TRUNC_HMAC_LEN );
903
+ if (i == MAX_HOPS - 2 )
904
+ break ;
905
+
906
+ copy_len += 1 ;
907
+ src_index -= copy_len + 1 ;
908
+ dest_index -= copy_len ;
909
+ }
910
+ }
911
+ u8 * hold_times_be = tal_arr (failonion , u8 , 0 );
912
+ towire_u32 (& hold_times_be , hold_times );
913
+ memcpy (failonion -> attr_data -> htlc_hold_time , hold_times_be , HOLD_TIME_LEN );
914
+ add_hmacs_to_attribution_data (failonion , shared_secret );
915
+ }
916
+
917
+ static u8 * verify_attr_data (struct onionreply * reply ,
918
+ int pos ,
919
+ const struct secret * shared_secret )
920
+ {
921
+ struct secret um_key ;
922
+ struct hmac hmac ;
923
+ struct crypto_auth_hmacsha256_state state ;
924
+ u8 expected_hmac [4 ], actual_hmac [4 ];
925
+
926
+ subkey_from_hmac ("um" , shared_secret , & um_key );
927
+
928
+ hmac_start (& state , um_key .data , sizeof (um_key .data ));
929
+ hmac_update (& state , reply -> contents , tal_bytelen (reply -> contents ));
930
+ hmac_update (& state , reply -> attr_data -> htlc_hold_time , (pos + 1 ) * HOLD_TIME_LEN );
931
+ write_downstream_hmacs (& state , pos , reply -> attr_data -> truncated_hmac );
932
+ hmac_done (& state , & hmac );
933
+ memcpy (expected_hmac , hmac .bytes , TRUNC_HMAC_LEN );
934
+
935
+ /* Compare with actual index. */
936
+ int hmac_idx = MAX_HOPS - pos - 1 ;
937
+ memcpy (actual_hmac , reply -> attr_data -> truncated_hmac + hmac_idx * TRUNC_HMAC_LEN , TRUNC_HMAC_LEN );
938
+
939
+ if (memcmp (actual_hmac , expected_hmac , 4 ) != 0 ) {
940
+ return NULL ;
941
+ }
942
+
943
+ return tal_dup_arr (reply , u8 , reply -> attr_data -> htlc_hold_time , 4 , 0 );
944
+ }
945
+
845
946
u8 * unwrap_onionreply (const tal_t * ctx ,
846
947
const struct secret * shared_secrets ,
847
948
const int numhops ,
@@ -852,9 +953,9 @@ u8 *unwrap_onionreply(const tal_t *ctx,
852
953
const u8 * cursor ;
853
954
size_t max ;
854
955
u16 msglen ;
855
-
856
- r = new_onionreply (tmpctx , reply -> contents );
956
+ r = new_onionreply (tmpctx , reply -> contents , reply -> attr_data );
857
957
* origin_index = -1 ;
958
+ int attr_hop_count = numhops > 20 ? 20 : numhops ;
858
959
859
960
for (int i = 0 ; i < numhops ; i ++ ) {
860
961
struct secret key ;
@@ -871,6 +972,36 @@ u8 *unwrap_onionreply(const tal_t *ctx,
871
972
cursor = r -> contents ;
872
973
max = tal_count (r -> contents );
873
974
975
+ /* Check attribution error HMACs, If present. */
976
+ if (r -> attr_data ) {
977
+ if (i < attr_hop_count ) {
978
+ int pos = attr_hop_count - i - 1 ;
979
+ u8 * hop_time = verify_attr_data (r , pos , & shared_secrets [i ]);
980
+ if (hop_time ) {
981
+ /* Shift Left */
982
+ memmove (r -> attr_data -> htlc_hold_time , & r -> attr_data -> htlc_hold_time [HOLD_TIME_LEN ], HOLD_TIME_LEN * (MAX_HOPS - 1 ));
983
+
984
+ int src_index = MAX_HOPS ;
985
+ int dest_index = 1 ;
986
+ int copy_len = MAX_HOPS - 1 ;
987
+
988
+ for (int i = 0 ; i < MAX_HOPS - 1 ; i ++ ) {
989
+ memmove (& r -> attr_data -> truncated_hmac [dest_index * TRUNC_HMAC_LEN ],
990
+ & r -> attr_data -> truncated_hmac [src_index * TRUNC_HMAC_LEN ],
991
+ copy_len * TRUNC_HMAC_LEN );
992
+
993
+ src_index += copy_len ;
994
+ dest_index += copy_len + 1 ;
995
+ copy_len -= 1 ;
996
+ }
997
+ // printf("Hop time at position %d: %s \n", i, tal_hexstr(tmpctx, hop_time, 4));
998
+ } else {
999
+ /* FIXME: Add logging */
1000
+ // printf("Invalid HMAC at pos: %d", i);
1001
+ }
1002
+ }
1003
+ }
1004
+
874
1005
fromwire_hmac (& cursor , & max , & hmac );
875
1006
/* Too short. */
876
1007
if (!cursor )
0 commit comments