Git fork
at reftables-rust 277 lines 7.7 kB view raw
1#include "git-compat-util.h" 2#include "hash.h" 3#include "hex.h" 4 5static const struct object_id empty_tree_oid = { 6 .hash = { 7 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60, 8 0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 9 }, 10 .algo = GIT_HASH_SHA1, 11}; 12static const struct object_id empty_blob_oid = { 13 .hash = { 14 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b, 15 0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 16 }, 17 .algo = GIT_HASH_SHA1, 18}; 19static const struct object_id null_oid_sha1 = { 20 .hash = {0}, 21 .algo = GIT_HASH_SHA1, 22}; 23static const struct object_id empty_tree_oid_sha256 = { 24 .hash = { 25 0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1, 26 0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5, 27 0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc, 28 0x53, 0x21 29 }, 30 .algo = GIT_HASH_SHA256, 31}; 32static const struct object_id empty_blob_oid_sha256 = { 33 .hash = { 34 0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2, 35 0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43, 36 0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72, 37 0x18, 0x13 38 }, 39 .algo = GIT_HASH_SHA256, 40}; 41static const struct object_id null_oid_sha256 = { 42 .hash = {0}, 43 .algo = GIT_HASH_SHA256, 44}; 45 46static void git_hash_sha1_init(struct git_hash_ctx *ctx) 47{ 48 ctx->algop = &hash_algos[GIT_HASH_SHA1]; 49 git_SHA1_Init(&ctx->state.sha1); 50} 51 52static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) 53{ 54 dst->algop = src->algop; 55 git_SHA1_Clone(&dst->state.sha1, &src->state.sha1); 56} 57 58static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len) 59{ 60 git_SHA1_Update(&ctx->state.sha1, data, len); 61} 62 63static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx) 64{ 65 git_SHA1_Final(hash, &ctx->state.sha1); 66} 67 68static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) 69{ 70 git_SHA1_Final(oid->hash, &ctx->state.sha1); 71 memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); 72 oid->algo = GIT_HASH_SHA1; 73} 74 75static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx) 76{ 77 ctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]); 78 git_SHA1_Init_unsafe(&ctx->state.sha1_unsafe); 79} 80 81static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src) 82{ 83 dst->algop = src->algop; 84 git_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe); 85} 86 87static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data, 88 size_t len) 89{ 90 git_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len); 91} 92 93static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx) 94{ 95 git_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe); 96} 97 98static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx) 99{ 100 git_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe); 101 memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); 102 oid->algo = GIT_HASH_SHA1; 103} 104 105static void git_hash_sha256_init(struct git_hash_ctx *ctx) 106{ 107 ctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]); 108 git_SHA256_Init(&ctx->state.sha256); 109} 110 111static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) 112{ 113 dst->algop = src->algop; 114 git_SHA256_Clone(&dst->state.sha256, &src->state.sha256); 115} 116 117static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len) 118{ 119 git_SHA256_Update(&ctx->state.sha256, data, len); 120} 121 122static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx) 123{ 124 git_SHA256_Final(hash, &ctx->state.sha256); 125} 126 127static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) 128{ 129 git_SHA256_Final(oid->hash, &ctx->state.sha256); 130 /* 131 * This currently does nothing, so the compiler should optimize it out, 132 * but keep it in case we extend the hash size again. 133 */ 134 memset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ); 135 oid->algo = GIT_HASH_SHA256; 136} 137 138static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED) 139{ 140 BUG("trying to init unknown hash"); 141} 142 143static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED, 144 const struct git_hash_ctx *src UNUSED) 145{ 146 BUG("trying to clone unknown hash"); 147} 148 149static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED, 150 const void *data UNUSED, 151 size_t len UNUSED) 152{ 153 BUG("trying to update unknown hash"); 154} 155 156static void git_hash_unknown_final(unsigned char *hash UNUSED, 157 struct git_hash_ctx *ctx UNUSED) 158{ 159 BUG("trying to finalize unknown hash"); 160} 161 162static void git_hash_unknown_final_oid(struct object_id *oid UNUSED, 163 struct git_hash_ctx *ctx UNUSED) 164{ 165 BUG("trying to finalize unknown hash"); 166} 167 168static const struct git_hash_algo sha1_unsafe_algo = { 169 .name = "sha1", 170 .format_id = GIT_SHA1_FORMAT_ID, 171 .rawsz = GIT_SHA1_RAWSZ, 172 .hexsz = GIT_SHA1_HEXSZ, 173 .blksz = GIT_SHA1_BLKSZ, 174 .init_fn = git_hash_sha1_init_unsafe, 175 .clone_fn = git_hash_sha1_clone_unsafe, 176 .update_fn = git_hash_sha1_update_unsafe, 177 .final_fn = git_hash_sha1_final_unsafe, 178 .final_oid_fn = git_hash_sha1_final_oid_unsafe, 179 .empty_tree = &empty_tree_oid, 180 .empty_blob = &empty_blob_oid, 181 .null_oid = &null_oid_sha1, 182}; 183 184const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { 185 { 186 .name = NULL, 187 .format_id = 0x00000000, 188 .rawsz = 0, 189 .hexsz = 0, 190 .blksz = 0, 191 .init_fn = git_hash_unknown_init, 192 .clone_fn = git_hash_unknown_clone, 193 .update_fn = git_hash_unknown_update, 194 .final_fn = git_hash_unknown_final, 195 .final_oid_fn = git_hash_unknown_final_oid, 196 .empty_tree = NULL, 197 .empty_blob = NULL, 198 .null_oid = NULL, 199 }, 200 { 201 .name = "sha1", 202 .format_id = GIT_SHA1_FORMAT_ID, 203 .rawsz = GIT_SHA1_RAWSZ, 204 .hexsz = GIT_SHA1_HEXSZ, 205 .blksz = GIT_SHA1_BLKSZ, 206 .init_fn = git_hash_sha1_init, 207 .clone_fn = git_hash_sha1_clone, 208 .update_fn = git_hash_sha1_update, 209 .final_fn = git_hash_sha1_final, 210 .final_oid_fn = git_hash_sha1_final_oid, 211 .unsafe = &sha1_unsafe_algo, 212 .empty_tree = &empty_tree_oid, 213 .empty_blob = &empty_blob_oid, 214 .null_oid = &null_oid_sha1, 215 }, 216 { 217 .name = "sha256", 218 .format_id = GIT_SHA256_FORMAT_ID, 219 .rawsz = GIT_SHA256_RAWSZ, 220 .hexsz = GIT_SHA256_HEXSZ, 221 .blksz = GIT_SHA256_BLKSZ, 222 .init_fn = git_hash_sha256_init, 223 .clone_fn = git_hash_sha256_clone, 224 .update_fn = git_hash_sha256_update, 225 .final_fn = git_hash_sha256_final, 226 .final_oid_fn = git_hash_sha256_final_oid, 227 .empty_tree = &empty_tree_oid_sha256, 228 .empty_blob = &empty_blob_oid_sha256, 229 .null_oid = &null_oid_sha256, 230 } 231}; 232 233const struct object_id *null_oid(const struct git_hash_algo *algop) 234{ 235 return algop->null_oid; 236} 237 238const char *empty_tree_oid_hex(const struct git_hash_algo *algop) 239{ 240 static char buf[GIT_MAX_HEXSZ + 1]; 241 return oid_to_hex_r(buf, algop->empty_tree); 242} 243 244int hash_algo_by_name(const char *name) 245{ 246 if (!name) 247 return GIT_HASH_UNKNOWN; 248 for (size_t i = 1; i < GIT_HASH_NALGOS; i++) 249 if (!strcmp(name, hash_algos[i].name)) 250 return i; 251 return GIT_HASH_UNKNOWN; 252} 253 254int hash_algo_by_id(uint32_t format_id) 255{ 256 for (size_t i = 1; i < GIT_HASH_NALGOS; i++) 257 if (format_id == hash_algos[i].format_id) 258 return i; 259 return GIT_HASH_UNKNOWN; 260} 261 262int hash_algo_by_length(size_t len) 263{ 264 for (size_t i = 1; i < GIT_HASH_NALGOS; i++) 265 if (len == hash_algos[i].rawsz) 266 return i; 267 return GIT_HASH_UNKNOWN; 268} 269 270const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop) 271{ 272 /* If we have a faster "unsafe" implementation, use that. */ 273 if (algop->unsafe) 274 return algop->unsafe; 275 /* Otherwise use the default one. */ 276 return algop; 277}