hash: add an SHA-256 implementation using OpenSSL
[gitweb.git] / sha1-file.c
index 97b74238483e00c3f07bd5ab0879eb84bf5c8dfa..66ba3dadb9b48d9e28ce16e130332b1f45fc6355 100644 (file)
 #define EMPTY_TREE_SHA1_BIN_LITERAL \
         "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \
         "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04"
+#define EMPTY_TREE_SHA256_BIN_LITERAL \
+       "\x6e\xf1\x9b\x41\x22\x5c\x53\x69\xf1\xc1" \
+       "\x04\xd4\x5d\x8d\x85\xef\xa9\xb0\x57\xb5" \
+       "\x3b\x14\xb4\xb9\xb9\x39\xdd\x74\xde\xcc" \
+       "\x53\x21"
 
 #define EMPTY_BLOB_SHA1_BIN_LITERAL \
        "\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b" \
        "\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91"
+#define EMPTY_BLOB_SHA256_BIN_LITERAL \
+       "\x47\x3a\x0f\x4c\x3b\xe8\xa9\x36\x81\xa2" \
+       "\x67\xe3\xb1\xe9\xa7\xdc\xda\x11\x85\x43" \
+       "\x6f\xe1\x41\xf7\x74\x91\x20\xa3\x03\x72" \
+       "\x18\x13"
 
 const unsigned char null_sha1[GIT_MAX_RAWSZ];
 const struct object_id null_oid;
@@ -53,6 +63,12 @@ static const struct object_id empty_tree_oid = {
 static const struct object_id empty_blob_oid = {
        EMPTY_BLOB_SHA1_BIN_LITERAL
 };
+static const struct object_id empty_tree_oid_sha256 = {
+       EMPTY_TREE_SHA256_BIN_LITERAL
+};
+static const struct object_id empty_blob_oid_sha256 = {
+       EMPTY_BLOB_SHA256_BIN_LITERAL
+};
 
 static void git_hash_sha1_init(git_hash_ctx *ctx)
 {
@@ -69,6 +85,22 @@ static void git_hash_sha1_final(unsigned char *hash, git_hash_ctx *ctx)
        git_SHA1_Final(hash, &ctx->sha1);
 }
 
+
+static void git_hash_sha256_init(git_hash_ctx *ctx)
+{
+       git_SHA256_Init(&ctx->sha256);
+}
+
+static void git_hash_sha256_update(git_hash_ctx *ctx, const void *data, size_t len)
+{
+       git_SHA256_Update(&ctx->sha256, data, len);
+}
+
+static void git_hash_sha256_final(unsigned char *hash, git_hash_ctx *ctx)
+{
+       git_SHA256_Final(hash, &ctx->sha256);
+}
+
 static void git_hash_unknown_init(git_hash_ctx *ctx)
 {
        BUG("trying to init unknown hash");
@@ -90,6 +122,7 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
                0x00000000,
                0,
                0,
+               0,
                git_hash_unknown_init,
                git_hash_unknown_update,
                git_hash_unknown_final,
@@ -97,17 +130,31 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
                NULL,
        },
        {
-               "sha-1",
+               "sha1",
                /* "sha1", big-endian */
                0x73686131,
                GIT_SHA1_RAWSZ,
                GIT_SHA1_HEXSZ,
+               GIT_SHA1_BLKSZ,
                git_hash_sha1_init,
                git_hash_sha1_update,
                git_hash_sha1_final,
                &empty_tree_oid,
                &empty_blob_oid,
        },
+       {
+               "sha256",
+               /* "s256", big-endian */
+               0x73323536,
+               GIT_SHA256_RAWSZ,
+               GIT_SHA256_HEXSZ,
+               GIT_SHA256_BLKSZ,
+               git_hash_sha256_init,
+               git_hash_sha256_update,
+               git_hash_sha256_final,
+               &empty_tree_oid_sha256,
+               &empty_blob_oid_sha256,
+       }
 };
 
 const char *empty_tree_oid_hex(void)
@@ -122,6 +169,27 @@ const char *empty_blob_oid_hex(void)
        return oid_to_hex_r(buf, the_hash_algo->empty_blob);
 }
 
+int hash_algo_by_name(const char *name)
+{
+       int i;
+       if (!name)
+               return GIT_HASH_UNKNOWN;
+       for (i = 1; i < GIT_HASH_NALGOS; i++)
+               if (!strcmp(name, hash_algos[i].name))
+                       return i;
+       return GIT_HASH_UNKNOWN;
+}
+
+int hash_algo_by_id(uint32_t format_id)
+{
+       int i;
+       for (i = 1; i < GIT_HASH_NALGOS; i++)
+               if (format_id == hash_algos[i].format_id)
+                       return i;
+       return GIT_HASH_UNKNOWN;
+}
+
+
 /*
  * This is meant to hold a *small* number of objects that you would
  * want read_sha1_file() to be able to return, but yet you do not want
@@ -149,10 +217,10 @@ static struct cached_object *find_cached_object(const struct object_id *oid)
        struct cached_object *co = cached_objects;
 
        for (i = 0; i < cached_object_nr; i++, co++) {
-               if (!oidcmp(&co->oid, oid))
+               if (oideq(&co->oid, oid))
                        return co;
        }
-       if (!oidcmp(oid, the_hash_algo->empty_tree))
+       if (oideq(oid, the_hash_algo->empty_tree))
                return &empty_tree;
        return NULL;
 }
@@ -825,7 +893,7 @@ int check_object_signature(const struct object_id *oid, void *map,
 
        if (map) {
                hash_object_file(map, size, type, &real_oid);
-               return oidcmp(oid, &real_oid) ? -1 : 0;
+               return !oideq(oid, &real_oid) ? -1 : 0;
        }
 
        st = open_istream(oid, &obj_type, &size, NULL);
@@ -852,7 +920,7 @@ int check_object_signature(const struct object_id *oid, void *map,
        }
        the_hash_algo->final_fn(real_oid.hash, &c);
        close_istream(st);
-       return oidcmp(oid, &real_oid) ? -1 : 0;
+       return !oideq(oid, &real_oid) ? -1 : 0;
 }
 
 int git_open_cloexec(const char *name, int flags)
@@ -1317,7 +1385,7 @@ int oid_object_info_extended(struct repository *r, const struct object_id *oid,
                         * TODO Pass a repository struct through fetch_object,
                         * such that arbitrary repositories work.
                         */
-                       fetch_object(repository_format_partial_clone, real->hash);
+                       fetch_objects(repository_format_partial_clone, real, 1);
                        already_retried = 1;
                        continue;
                }
@@ -1671,7 +1739,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
                die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid),
                    ret);
        the_hash_algo->final_fn(parano_oid.hash, &c);
-       if (oidcmp(oid, &parano_oid) != 0)
+       if (!oideq(oid, &parano_oid))
                die(_("confused by unstable object source data for %s"),
                    oid_to_hex(oid));
 
@@ -2213,7 +2281,7 @@ static int check_stream_sha1(git_zstream *stream,
        }
 
        the_hash_algo->final_fn(real_sha1, &c);
-       if (hashcmp(expected_sha1, real_sha1)) {
+       if (!hasheq(expected_sha1, real_sha1)) {
                error(_("sha1 mismatch for %s (expected %s)"), path,
                      sha1_to_hex(expected_sha1));
                return -1;