summaryrefslogtreecommitdiff
path: root/src/hash/libwebidoidc-hash.c
blob: a9876d1ddf294558ca0a305d18fc31f6a21ce012 (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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
  webid-oidc, implementation of the Solid specification
  Copyright (C) 2020, 2021  Vivien Kraus

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as
  published by the Free Software Foundation, either version 3 of the
  License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License
  along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#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 */
}