summaryrefslogtreecommitdiff
path: root/src/hash/libwebidoidc-hash.c
blob: 75d7da91888e5732c48997c3f695146c61969531 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <utilities.h>
#include <nettle/sha2.h>

#define _(s) dgettext (PACKAGE, s)

SCM_SYMBOL (sha256, "SHA-256");
SCM_SYMBOL (sha384, "SHA-384");
SCM_SYMBOL (sha512, "SHA-512");

SCM_SYMBOL (unsupported_alg, "unsupported-alg");

SCM_DEFINE (webidoidc_hash_g, "hash", 2, 0, 0, (SCM alg, SCM payload),
	    "Hash something with @var{alg}, which must be @code{'SHA-256}, @code{'SHA-384} or @code{'SHA-512}.")
{
  size_t payload_size;
  uint8_t *c_payload;
  if (scm_is_string (payload))
    {
      return webidoidc_hash_g (alg, scm_string_to_utf8 (payload));
    }
  payload_size = scm_c_bytevector_length (payload);
  c_payload = scm_gc_malloc_pointerless (payload_size, "To hash");
  memcpy (c_payload, SCM_BYTEVECTOR_CONTENTS (payload), payload_size);
  if (scm_is_eq (alg, sha256))
    {
      struct sha256_ctx hash;
      uint8_t digest[SHA256_DIGEST_SIZE];
      sha256_init (&hash);
      sha256_update (&hash, payload_size, c_payload);
      sha256_digest (&hash, SHA256_DIGEST_SIZE, digest);
      return wrap_bytevector (SHA256_DIGEST_SIZE, digest);
    }
  else if (scm_is_eq (alg, sha384))
    {
      struct sha384_ctx hash;
      uint8_t digest[SHA384_DIGEST_SIZE];
      sha384_init (&hash);
      sha384_update (&hash, payload_size, c_payload);
      sha384_digest (&hash, SHA384_DIGEST_SIZE, digest);
      return wrap_bytevector (SHA384_DIGEST_SIZE, digest);
    }
  else if (scm_is_eq (alg, sha512))
    {
      struct sha512_ctx hash;
      uint8_t digest[SHA512_DIGEST_SIZE];
      sha512_init (&hash);
      sha512_update (&hash, payload_size, c_payload);
      sha512_digest (&hash, SHA512_DIGEST_SIZE, digest);
      return wrap_bytevector (SHA512_DIGEST_SIZE, digest);
    }
  else
    {
      scm_throw (unsupported_alg, scm_list_1 (alg));
    }
  return SCM_UNDEFINED;
}

void
init_webidoidc_hash (void)
{
#ifndef SCM_MAGIC_SNARFER
#include "libwebidoidc-hash.x"
#endif /* not SCM_MAGIC_SNARFER */
}