Git fork
1#ifndef HASH_H
2#define HASH_H
3
4#if defined(SHA1_APPLE)
5#define SHA1_BACKEND "SHA1_APPLE (No collision detection)"
6#include <CommonCrypto/CommonDigest.h>
7#elif defined(SHA1_OPENSSL)
8# define SHA1_BACKEND "SHA1_OPENSSL (No collision detection)"
9# include <openssl/sha.h>
10# if defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL >= 3
11# define SHA1_NEEDS_CLONE_HELPER
12# include "sha1/openssl.h"
13# endif
14#elif defined(SHA1_DC)
15#define SHA1_BACKEND "SHA1_DC"
16#include "sha1dc_git.h"
17#else /* SHA1_BLK */
18#define SHA1_BACKEND "SHA1_BLK (No collision detection)"
19#include "block-sha1/sha1.h"
20#endif
21
22#if defined(SHA1_APPLE_UNSAFE)
23# define SHA1_UNSAFE_BACKEND "SHA1_APPLE_UNSAFE"
24# include <CommonCrypto/CommonDigest.h>
25# define platform_SHA_CTX_unsafe CC_SHA1_CTX
26# define platform_SHA1_Init_unsafe CC_SHA1_Init
27# define platform_SHA1_Update_unsafe CC_SHA1_Update
28# define platform_SHA1_Final_unsafe CC_SHA1_Final
29#elif defined(SHA1_OPENSSL_UNSAFE)
30# define SHA1_UNSAFE_BACKEND "SHA1_OPENSSL_UNSAFE"
31# include <openssl/sha.h>
32# if defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL >= 3
33# define SHA1_NEEDS_CLONE_HELPER_UNSAFE
34# include "sha1/openssl.h"
35# define platform_SHA_CTX_unsafe openssl_SHA1_CTX
36# define platform_SHA1_Init_unsafe openssl_SHA1_Init
37# define platform_SHA1_Clone_unsafe openssl_SHA1_Clone
38# define platform_SHA1_Update_unsafe openssl_SHA1_Update
39# define platform_SHA1_Final_unsafe openssl_SHA1_Final
40# else
41# define platform_SHA_CTX_unsafe SHA_CTX
42# define platform_SHA1_Init_unsafe SHA1_Init
43# define platform_SHA1_Update_unsafe SHA1_Update
44# define platform_SHA1_Final_unsafe SHA1_Final
45# endif
46#elif defined(SHA1_BLK_UNSAFE)
47# define SHA1_UNSAFE_BACKEND "SHA1_BLK_UNSAFE"
48# include "block-sha1/sha1.h"
49# define platform_SHA_CTX_unsafe blk_SHA_CTX
50# define platform_SHA1_Init_unsafe blk_SHA1_Init
51# define platform_SHA1_Update_unsafe blk_SHA1_Update
52# define platform_SHA1_Final_unsafe blk_SHA1_Final
53#endif
54
55#if defined(SHA256_NETTLE)
56#define SHA256_BACKEND "SHA256_NETTLE"
57#include "sha256/nettle.h"
58#elif defined(SHA256_GCRYPT)
59#define SHA256_BACKEND "SHA256_GCRYPT"
60#define SHA256_NEEDS_CLONE_HELPER
61#include "sha256/gcrypt.h"
62#elif defined(SHA256_OPENSSL)
63# define SHA256_BACKEND "SHA256_OPENSSL"
64# include <openssl/sha.h>
65# if defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL >= 3
66# define SHA256_NEEDS_CLONE_HELPER
67# include "sha256/openssl.h"
68# endif
69#else
70#define SHA256_BACKEND "SHA256_BLK"
71#include "sha256/block/sha256.h"
72#endif
73
74#ifndef platform_SHA_CTX
75/*
76 * platform's underlying implementation of SHA-1; could be OpenSSL,
77 * blk_SHA, Apple CommonCrypto, etc... Note that the relevant
78 * SHA-1 header may have already defined platform_SHA_CTX for our
79 * own implementations like block-sha1, so we list
80 * the default for OpenSSL compatible SHA-1 implementations here.
81 */
82#define platform_SHA_CTX SHA_CTX
83#define platform_SHA1_Init SHA1_Init
84#define platform_SHA1_Update SHA1_Update
85#define platform_SHA1_Final SHA1_Final
86#endif
87
88#ifndef platform_SHA_CTX_unsafe
89# define platform_SHA_CTX_unsafe platform_SHA_CTX
90# define platform_SHA1_Init_unsafe platform_SHA1_Init
91# define platform_SHA1_Update_unsafe platform_SHA1_Update
92# define platform_SHA1_Final_unsafe platform_SHA1_Final
93# ifdef platform_SHA1_Clone
94# define platform_SHA1_Clone_unsafe platform_SHA1_Clone
95# endif
96# ifdef SHA1_NEEDS_CLONE_HELPER
97# define SHA1_NEEDS_CLONE_HELPER_UNSAFE
98# endif
99#endif
100
101#define git_SHA_CTX platform_SHA_CTX
102#define git_SHA1_Init platform_SHA1_Init
103#define git_SHA1_Update platform_SHA1_Update
104#define git_SHA1_Final platform_SHA1_Final
105
106#define git_SHA_CTX_unsafe platform_SHA_CTX_unsafe
107#define git_SHA1_Init_unsafe platform_SHA1_Init_unsafe
108#define git_SHA1_Update_unsafe platform_SHA1_Update_unsafe
109#define git_SHA1_Final_unsafe platform_SHA1_Final_unsafe
110
111#ifdef platform_SHA1_Clone
112#define git_SHA1_Clone platform_SHA1_Clone
113#endif
114#ifdef platform_SHA1_Clone_unsafe
115# define git_SHA1_Clone_unsafe platform_SHA1_Clone_unsafe
116#endif
117
118#ifndef platform_SHA256_CTX
119#define platform_SHA256_CTX SHA256_CTX
120#define platform_SHA256_Init SHA256_Init
121#define platform_SHA256_Update SHA256_Update
122#define platform_SHA256_Final SHA256_Final
123#endif
124
125#define git_SHA256_CTX platform_SHA256_CTX
126#define git_SHA256_Init platform_SHA256_Init
127#define git_SHA256_Update platform_SHA256_Update
128#define git_SHA256_Final platform_SHA256_Final
129
130#ifdef platform_SHA256_Clone
131#define git_SHA256_Clone platform_SHA256_Clone
132#endif
133
134#ifdef SHA1_MAX_BLOCK_SIZE
135#include "compat/sha1-chunked.h"
136#undef git_SHA1_Update
137#define git_SHA1_Update git_SHA1_Update_Chunked
138#endif
139
140#ifndef SHA1_NEEDS_CLONE_HELPER
141static inline void git_SHA1_Clone(git_SHA_CTX *dst, const git_SHA_CTX *src)
142{
143 memcpy(dst, src, sizeof(*dst));
144}
145#endif
146#ifndef SHA1_NEEDS_CLONE_HELPER_UNSAFE
147static inline void git_SHA1_Clone_unsafe(git_SHA_CTX_unsafe *dst,
148 const git_SHA_CTX_unsafe *src)
149{
150 memcpy(dst, src, sizeof(*dst));
151}
152#endif
153
154#ifndef SHA256_NEEDS_CLONE_HELPER
155static inline void git_SHA256_Clone(git_SHA256_CTX *dst, const git_SHA256_CTX *src)
156{
157 memcpy(dst, src, sizeof(*dst));
158}
159#endif
160
161/*
162 * Note that these constants are suitable for indexing the hash_algos array and
163 * comparing against each other, but are otherwise arbitrary, so they should not
164 * be exposed to the user or serialized to disk. To know whether a
165 * git_hash_algo struct points to some usable hash function, test the format_id
166 * field for being non-zero. Use the name field for user-visible situations and
167 * the format_id field for fixed-length fields on disk.
168 */
169/* An unknown hash function. */
170#define GIT_HASH_UNKNOWN 0
171/* SHA-1 */
172#define GIT_HASH_SHA1 1
173/* SHA-256 */
174#define GIT_HASH_SHA256 2
175/* Number of algorithms supported (including unknown). */
176#define GIT_HASH_NALGOS (GIT_HASH_SHA256 + 1)
177
178/* Default hash algorithm if unspecified. */
179#ifdef WITH_BREAKING_CHANGES
180# define GIT_HASH_DEFAULT GIT_HASH_SHA256
181#else
182# define GIT_HASH_DEFAULT GIT_HASH_SHA1
183#endif
184
185/* Legacy hash algorithm. Implied for older data formats which don't specify. */
186#define GIT_HASH_SHA1_LEGACY GIT_HASH_SHA1
187
188/* "sha1", big-endian */
189#define GIT_SHA1_FORMAT_ID 0x73686131
190
191/* The length in bytes and in hex digits of an object name (SHA-1 value). */
192#define GIT_SHA1_RAWSZ 20
193#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
194/* The block size of SHA-1. */
195#define GIT_SHA1_BLKSZ 64
196
197/* "s256", big-endian */
198#define GIT_SHA256_FORMAT_ID 0x73323536
199
200/* The length in bytes and in hex digits of an object name (SHA-256 value). */
201#define GIT_SHA256_RAWSZ 32
202#define GIT_SHA256_HEXSZ (2 * GIT_SHA256_RAWSZ)
203/* The block size of SHA-256. */
204#define GIT_SHA256_BLKSZ 64
205
206/* The length in byte and in hex digits of the largest possible hash value. */
207#define GIT_MAX_RAWSZ GIT_SHA256_RAWSZ
208#define GIT_MAX_HEXSZ GIT_SHA256_HEXSZ
209/* The largest possible block size for any supported hash. */
210#define GIT_MAX_BLKSZ GIT_SHA256_BLKSZ
211
212struct object_id {
213 unsigned char hash[GIT_MAX_RAWSZ];
214 int algo; /* XXX requires 4-byte alignment */
215};
216
217#define GET_OID_QUIETLY 01
218#define GET_OID_COMMIT 02
219#define GET_OID_COMMITTISH 04
220#define GET_OID_TREE 010
221#define GET_OID_TREEISH 020
222#define GET_OID_BLOB 040
223#define GET_OID_FOLLOW_SYMLINKS 0100
224#define GET_OID_RECORD_PATH 0200
225#define GET_OID_ONLY_TO_DIE 04000
226#define GET_OID_REQUIRE_PATH 010000
227#define GET_OID_HASH_ANY 020000
228#define GET_OID_SKIP_AMBIGUITY_CHECK 040000
229#define GET_OID_GENTLY 0100000
230
231#define GET_OID_DISAMBIGUATORS \
232 (GET_OID_COMMIT | GET_OID_COMMITTISH | \
233 GET_OID_TREE | GET_OID_TREEISH | \
234 GET_OID_BLOB)
235
236enum get_oid_result {
237 FOUND = 0,
238 MISSING_OBJECT = -1, /* The requested object is missing */
239 SHORT_NAME_AMBIGUOUS = -2,
240 /* The following only apply when symlinks are followed */
241 DANGLING_SYMLINK = -4, /*
242 * The initial symlink is there, but
243 * (transitively) points to a missing
244 * in-tree file
245 */
246 SYMLINK_LOOP = -5,
247 NOT_DIR = -6, /*
248 * Somewhere along the symlink chain, a path is
249 * requested which contains a file as a
250 * non-final element.
251 */
252};
253
254#ifdef USE_THE_REPOSITORY_VARIABLE
255# include "repository.h"
256# define the_hash_algo the_repository->hash_algo
257#endif
258
259/* A suitably aligned type for stack allocations of hash contexts. */
260struct git_hash_ctx {
261 const struct git_hash_algo *algop;
262 union {
263 git_SHA_CTX sha1;
264 git_SHA_CTX_unsafe sha1_unsafe;
265 git_SHA256_CTX sha256;
266 } state;
267};
268
269typedef void (*git_hash_init_fn)(struct git_hash_ctx *ctx);
270typedef void (*git_hash_clone_fn)(struct git_hash_ctx *dst, const struct git_hash_ctx *src);
271typedef void (*git_hash_update_fn)(struct git_hash_ctx *ctx, const void *in, size_t len);
272typedef void (*git_hash_final_fn)(unsigned char *hash, struct git_hash_ctx *ctx);
273typedef void (*git_hash_final_oid_fn)(struct object_id *oid, struct git_hash_ctx *ctx);
274
275struct git_hash_algo {
276 /*
277 * The name of the algorithm, as appears in the config file and in
278 * messages.
279 */
280 const char *name;
281
282 /* A four-byte version identifier, used in pack indices. */
283 uint32_t format_id;
284
285 /* The length of the hash in binary. */
286 size_t rawsz;
287
288 /* The length of the hash in hex characters. */
289 size_t hexsz;
290
291 /* The block size of the hash. */
292 size_t blksz;
293
294 /* The hash initialization function. */
295 git_hash_init_fn init_fn;
296
297 /* The hash context cloning function. */
298 git_hash_clone_fn clone_fn;
299
300 /* The hash update function. */
301 git_hash_update_fn update_fn;
302
303 /* The hash finalization function. */
304 git_hash_final_fn final_fn;
305
306 /* The hash finalization function for object IDs. */
307 git_hash_final_oid_fn final_oid_fn;
308
309 /* The OID of the empty tree. */
310 const struct object_id *empty_tree;
311
312 /* The OID of the empty blob. */
313 const struct object_id *empty_blob;
314
315 /* The all-zeros OID. */
316 const struct object_id *null_oid;
317
318 /* The unsafe variant of this hash function, if one exists. */
319 const struct git_hash_algo *unsafe;
320};
321extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS];
322
323static inline void git_hash_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src)
324{
325 src->algop->clone_fn(dst, src);
326}
327
328static inline void git_hash_update(struct git_hash_ctx *ctx, const void *in, size_t len)
329{
330 ctx->algop->update_fn(ctx, in, len);
331}
332
333static inline void git_hash_final(unsigned char *hash, struct git_hash_ctx *ctx)
334{
335 ctx->algop->final_fn(hash, ctx);
336}
337
338static inline void git_hash_final_oid(struct object_id *oid, struct git_hash_ctx *ctx)
339{
340 ctx->algop->final_oid_fn(oid, ctx);
341}
342
343/*
344 * Return a GIT_HASH_* constant based on the name. Returns GIT_HASH_UNKNOWN if
345 * the name doesn't match a known algorithm.
346 */
347int hash_algo_by_name(const char *name);
348/* Identical, except based on the format ID. */
349int hash_algo_by_id(uint32_t format_id);
350/* Identical, except based on the length. */
351int hash_algo_by_length(size_t len);
352/* Identical, except for a pointer to struct git_hash_algo. */
353static inline int hash_algo_by_ptr(const struct git_hash_algo *p)
354{
355 size_t i;
356 for (i = 0; i < GIT_HASH_NALGOS; i++) {
357 const struct git_hash_algo *algop = &hash_algos[i];
358 if (p == algop)
359 return i;
360 }
361 return GIT_HASH_UNKNOWN;
362}
363
364const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop);
365
366const struct object_id *null_oid(const struct git_hash_algo *algop);
367
368static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)
369{
370 /*
371 * Teach the compiler that there are only two possibilities of hash size
372 * here, so that it can optimize for this case as much as possible.
373 */
374 if (algop->rawsz == GIT_MAX_RAWSZ)
375 return memcmp(sha1, sha2, GIT_MAX_RAWSZ);
376 return memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
377}
378
379static inline int hasheq(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop)
380{
381 /*
382 * We write this here instead of deferring to hashcmp so that the
383 * compiler can properly inline it and avoid calling memcmp.
384 */
385 if (algop->rawsz == GIT_MAX_RAWSZ)
386 return !memcmp(sha1, sha2, GIT_MAX_RAWSZ);
387 return !memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
388}
389
390static inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src,
391 const struct git_hash_algo *algop)
392{
393 memcpy(sha_dst, sha_src, algop->rawsz);
394}
395
396static inline void hashclr(unsigned char *hash, const struct git_hash_algo *algop)
397{
398 memset(hash, 0, algop->rawsz);
399}
400
401static inline int oidcmp(const struct object_id *oid1, const struct object_id *oid2)
402{
403 return memcmp(oid1->hash, oid2->hash, GIT_MAX_RAWSZ);
404}
405
406static inline int oideq(const struct object_id *oid1, const struct object_id *oid2)
407{
408 return !memcmp(oid1->hash, oid2->hash, GIT_MAX_RAWSZ);
409}
410
411static inline void oidcpy(struct object_id *dst, const struct object_id *src)
412{
413 memcpy(dst->hash, src->hash, GIT_MAX_RAWSZ);
414 dst->algo = src->algo;
415}
416
417static inline void oidread(struct object_id *oid, const unsigned char *hash,
418 const struct git_hash_algo *algop)
419{
420 memcpy(oid->hash, hash, algop->rawsz);
421 if (algop->rawsz < GIT_MAX_RAWSZ)
422 memset(oid->hash + algop->rawsz, 0, GIT_MAX_RAWSZ - algop->rawsz);
423 oid->algo = hash_algo_by_ptr(algop);
424}
425
426static inline void oidclr(struct object_id *oid,
427 const struct git_hash_algo *algop)
428{
429 memset(oid->hash, 0, GIT_MAX_RAWSZ);
430 oid->algo = hash_algo_by_ptr(algop);
431}
432
433static inline struct object_id *oiddup(const struct object_id *src)
434{
435 struct object_id *dst = xmalloc(sizeof(struct object_id));
436 oidcpy(dst, src);
437 return dst;
438}
439
440static inline void oid_set_algo(struct object_id *oid, const struct git_hash_algo *algop)
441{
442 oid->algo = hash_algo_by_ptr(algop);
443}
444
445/*
446 * Converts a cryptographic hash (e.g. SHA-1) into an int-sized hash code
447 * for use in hash tables. Cryptographic hashes are supposed to have
448 * uniform distribution, so in contrast to `memhash()`, this just copies
449 * the first `sizeof(int)` bytes without shuffling any bits. Note that
450 * the results will be different on big-endian and little-endian
451 * platforms, so they should not be stored or transferred over the net.
452 */
453static inline unsigned int oidhash(const struct object_id *oid)
454{
455 /*
456 * Equivalent to 'return *(unsigned int *)oid->hash;', but safe on
457 * platforms that don't support unaligned reads.
458 */
459 unsigned int hash;
460 memcpy(&hash, oid->hash, sizeof(hash));
461 return hash;
462}
463
464static inline int is_null_oid(const struct object_id *oid)
465{
466 static const unsigned char null_hash[GIT_MAX_RAWSZ];
467 return !memcmp(oid->hash, null_hash, GIT_MAX_RAWSZ);
468}
469
470const char *empty_tree_oid_hex(const struct git_hash_algo *algop);
471
472static inline int is_empty_blob_oid(const struct object_id *oid,
473 const struct git_hash_algo *algop)
474{
475 return oideq(oid, algop->empty_blob);
476}
477
478static inline int is_empty_tree_oid(const struct object_id *oid,
479 const struct git_hash_algo *algop)
480{
481 return oideq(oid, algop->empty_tree);
482}
483
484#endif