/* * Copyright (c) 2018 Stefan Sperling * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include "got_object.h" #include "got_lib_hash.h" int got_parse_xdigit(uint8_t *val, const char *hex) { char *ep; long lval; errno = 0; lval = strtol(hex, &ep, 16); if (hex[0] == '\0' || *ep != '\0') return 0; if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) return 0; *val = (uint8_t)lval; return 1; } int got_parse_sha1_digest(uint8_t *digest, const char *line) { uint8_t b = 0; char hex[3] = {'\0', '\0', '\0'}; int i, j; for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { if (line[0] == '\0' || line[1] == '\0') return 0; for (j = 0; j < 2; j++) { hex[j] = *line; line++; } if (!got_parse_xdigit(&b, hex)) return 0; digest[i] = b; } return 1; } char * got_sha1_digest_to_str(const uint8_t *digest, char *buf, size_t size) { char *p = buf; char hex[3]; int i; if (size < SHA1_DIGEST_STRING_LENGTH) return NULL; for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { snprintf(hex, sizeof(hex), "%.2x", digest[i]); p[0] = hex[0]; p[1] = hex[1]; p += 2; } p[0] = '\0'; return buf; } int got_parse_sha256_digest(uint8_t *digest, const char *line) { uint8_t b = 0; char hex[3] = {'\0', '\0', '\0'}; int i, j; for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { if (line[0] == '\0' || line[1] == '\0') return 0; for (j = 0; j < 2; j++) { hex[j] = *line; line++; } if (!got_parse_xdigit(&b, hex)) return 0; digest[i] = b; } return 1; } char * got_sha256_digest_to_str(const uint8_t *digest, char *buf, size_t size) { char *p = buf; char hex[3]; int i; if (size < SHA256_DIGEST_STRING_LENGTH) return NULL; for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { snprintf(hex, sizeof(hex), "%.2x", digest[i]); p[0] = hex[0]; p[1] = hex[1]; p += 2; } p[0] = '\0'; return buf; } int got_parse_hash_digest(uint8_t *digest, const char *line, enum got_hash_algorithm algo) { switch (algo) { case GOT_HASH_SHA1: return got_parse_sha1_digest(digest, line); case GOT_HASH_SHA256: return got_parse_sha256_digest(digest, line); default: return 0; } } char * got_hash_digest_to_str(const uint8_t *digest, char *buf, size_t size, enum got_hash_algorithm algo) { switch (algo) { case GOT_HASH_SHA1: return got_sha1_digest_to_str(digest, buf, size); case GOT_HASH_SHA256: return got_sha256_digest_to_str(digest, buf, size); default: return NULL; } } size_t got_hash_digest_length(enum got_hash_algorithm algo) { switch (algo) { case GOT_HASH_SHA1: return SHA1_DIGEST_LENGTH; case GOT_HASH_SHA256: return SHA256_DIGEST_LENGTH; default: return 0; } } size_t got_hash_digest_string_length(enum got_hash_algorithm algo) { switch (algo) { case GOT_HASH_SHA1: return SHA1_DIGEST_STRING_LENGTH; case GOT_HASH_SHA256: return SHA256_DIGEST_STRING_LENGTH; default: return 0; } } void got_hash_init(struct got_hash *hash, enum got_hash_algorithm algo) { memset(hash, 0, sizeof(*hash)); hash->algo = algo; if (algo == GOT_HASH_SHA1) SHA1Init(&hash->sha1_ctx); else if (algo == GOT_HASH_SHA256) SHA256Init(&hash->sha256_ctx); } void got_hash_update(struct got_hash *hash, const void *data, size_t len) { if (hash->algo == GOT_HASH_SHA1) SHA1Update(&hash->sha1_ctx, data, len); else if (hash->algo == GOT_HASH_SHA256) SHA256Update(&hash->sha256_ctx, data, len); } void got_hash_final(struct got_hash *hash, uint8_t *out) { if (hash->algo == GOT_HASH_SHA1) SHA1Final(out, &hash->sha1_ctx); else if (hash->algo == GOT_HASH_SHA256) SHA256Final(out, &hash->sha256_ctx); } int got_hash_cmp(struct got_hash *hash, uint8_t *orig, uint8_t *target) { if (hash->algo == GOT_HASH_SHA1) return memcmp(orig, target, SHA1_DIGEST_LENGTH); else if (hash->algo == GOT_HASH_SHA256) return memcmp(orig, target, SHA256_DIGEST_LENGTH); return -1; }