Line data Source code
1 : /** 2 : * The MIT License (MIT) 3 : * 4 : * Copyright (c) 2021 RSK Labs Ltd 5 : * 6 : * Permission is hereby granted, free of charge, to any person obtaining a copy 7 : * of this software and associated documentation files (the "Software"), to 8 : * deal in the Software without restriction, including without limitation the 9 : * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 : * sell copies of the Software, and to permit persons to whom the Software is 11 : * furnished to do so, subject to the following conditions: 12 : * 13 : * The above copyright notice and this permission notice shall be included in 14 : * all copies or substantial portions of the Software. 15 : * 16 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 : * IN THE SOFTWARE. 23 : */ 24 : 25 : #include "bc_mm.h" 26 : 27 : /* 28 : * Helper function: encode a RLP list prefix to the given buffer. 29 : * 30 : * @arg[in] list_size list size in bytes 31 : * @arg[out] buf pointer to destination buffer 32 : */ 33 691 : static uint8_t rlp_encode_list_prefix(uint16_t list_size, uint8_t* buf) { 34 : uint8_t prefix_size; 35 691 : if (list_size <= 55) { 36 0 : prefix_size = 1; 37 0 : buf[0] = (RLP_SHORT_LIST_BASE + list_size) & 0xFF; 38 : } else { 39 691 : prefix_size = 0; 40 691 : uint16_t remaining = list_size; 41 2073 : while (remaining > 0) { 42 1382 : prefix_size++; 43 1382 : remaining >>= 8; 44 : } 45 691 : buf[0] = RLP_LONG_LIST_BASE + prefix_size; 46 691 : remaining = list_size; 47 2073 : for (uint8_t i = 0; i < prefix_size; i++) { 48 1382 : buf[prefix_size - i] = remaining & 0xff; 49 1382 : remaining >>= 8; 50 : } 51 691 : prefix_size++; 52 : } 53 : 54 691 : return prefix_size; 55 : } 56 : 57 : /* 58 : * Helper function: encode a RLP str prefix to the given buffer. 59 : * 60 : * The first_str_byte para is ignored for "good" strings. Those 61 : * are strings whose length is greater than one. It is safe to 62 : * just pass a zero. If you have a "bad" single byte string, 63 : * pass 1 for str_size and the unique string byte in the 64 : * first_str_byte parameter. 65 : * 66 : * @arg[in] str_size string size in bytes 67 : * @arb[in] first_str_byte first byte of the string. 68 : * @arg[out] buf pointer to destination buffer 69 : */ 70 12106 : static uint8_t rlp_encode_str_prefix(uint16_t str_size, 71 : uint8_t first_str_byte, 72 : uint8_t* buf) { 73 : uint8_t prefix_size; 74 12106 : if (str_size == 1 && first_str_byte <= RLP_MAX_SINGLE_BYTE) { 75 1444 : prefix_size = 0; 76 10662 : } else if (str_size <= 55) { 77 9582 : prefix_size = 1; 78 9582 : buf[0] = (RLP_SHORT_STRING_BASE + str_size) & 0xff; 79 : } else { 80 1080 : prefix_size = 0; 81 1080 : uint16_t remaining = str_size; 82 2849 : while (remaining > 0) { 83 1769 : prefix_size++; 84 1769 : remaining >>= 8; 85 : } 86 1080 : buf[0] = RLP_LONG_STRING_BASE + prefix_size; 87 1080 : remaining = str_size; 88 2849 : for (uint8_t i = 0; i < prefix_size; i++) { 89 1769 : buf[prefix_size - i] = remaining & 0xff; 90 1769 : remaining >>= 8; 91 : } 92 1080 : prefix_size++; 93 : } 94 : 95 12106 : return prefix_size; 96 : } 97 : 98 : static uint8_t prefix_buf[MAX_RLP_PREFIX_SIZE]; 99 : 100 : /* 101 : * Hash a RLP prefix for a list of the given size. 102 : * 103 : * @arg[out] kctx Keccak context for hashing 104 : * @arg[in] list_size list size in bytes 105 : */ 106 691 : void mm_hash_rlp_list_prefix(keccak_ctx_t* kctx, uint16_t list_size) { 107 691 : uint8_t prefix_size = rlp_encode_list_prefix(list_size, prefix_buf); 108 691 : KECCAK_UPDATE(kctx, prefix_buf, prefix_size); 109 691 : } 110 : 111 : /* 112 : * Hash a RLP prefix for a "good" string of the given size. 113 : * A string is "good" if the RLP prefix can be determined 114 : * from the string length alone. This will be the case 115 : * any string with lenght greater than one. 116 : * 117 : * @arg[out] kctx Keccak context for hashing 118 : * @arg[in] str_size string size in bytes, must be greater than one 119 : */ 120 10662 : void mm_hash_good_rlp_str_prefix(keccak_ctx_t* kctx, uint16_t str_size) { 121 10662 : uint8_t prefix_size = rlp_encode_str_prefix(str_size, 0, prefix_buf); 122 10662 : KECCAK_UPDATE(kctx, prefix_buf, prefix_size); 123 10662 : } 124 : 125 : /* 126 : * Hash a RLP prefix for a "bad" string. Bad strings are one byte 127 : * long, and the prefix length is determined by the contexts of 128 : * the string's single byte. 129 : * 130 : * @arg[out] kctx Keccak context for hashing 131 : * @arg[in] str pointer to the bad string's single byte 132 : */ 133 1444 : void mm_hash_bad_rlp_str_prefix(keccak_ctx_t* kctx, const uint8_t* str) { 134 1444 : uint8_t prefix_size = rlp_encode_str_prefix(1, *str, prefix_buf); 135 1444 : KECCAK_UPDATE(kctx, prefix_buf, prefix_size); 136 1444 : }