summaryrefslogtreecommitdiff
path: root/src/utilities.h
blob: b5b91f91e014f35d61b358f27a3acebee09ee8b3 (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
83
84
85
86
87
88
#ifndef H_UTILITIES_INCLUDED
#define H_UTILITIES_INCLUDED

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */

#include <libguile.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <nettle/base64.h>
#include <nettle/ecc.h>
#include <nettle/ecdsa.h>
#include <nettle/rsa.h>
#include <nettle/ecc-curve.h>
#include <nettle/yarrow.h>
#include <gettext.h>
#include <stdio.h>
#include <unistd.h>

/* Return a base64 encoding of some raw data. */
static SCM wrap_bytevector (size_t length, uint8_t * data);

/* Decode a base64 of binary data. */
static uint8_t *get_as_bytevector (SCM data, size_t *size, int throw_if_fail);

static inline SCM
wrap_bytevector (size_t length, uint8_t * data)
{
  char *head;
  char tail[BASE64_ENCODE_FINAL_LENGTH];
  size_t head_size, tail_size;
  char *full;
  struct base64_encode_ctx encoder;
  SCM ret;
  base64url_encode_init (&encoder);
  scm_dynwind_begin (0);
  head = scm_malloc (BASE64_ENCODE_LENGTH (length));
  scm_dynwind_free (head);
  head_size = base64_encode_update (&encoder, head, length, data);
  tail_size = base64_encode_final (&encoder, tail);
  while (tail_size != 0 && tail[tail_size - 1] == '=')
    {
      tail_size--;
    }
  full = scm_malloc (head_size + tail_size);
  memcpy (full, head, head_size);
  memcpy (full + head_size, tail, tail_size);
  ret = scm_from_utf8_stringn (full, head_size + tail_size);
  scm_dynwind_end ();
  return ret;
}

static inline uint8_t *
get_as_bytevector (SCM data, size_t *size, int throw_if_fail)
{
  uint8_t *ret = NULL;
  size_t data_length;
  char *data_str = NULL;
  struct base64_decode_ctx decoder;
  int ok = 1;
  if (!scm_is_bytevector (data) && !throw_if_fail)
    {
      return NULL;
    }
  base64url_decode_init (&decoder);
  scm_dynwind_begin (0);
  data_str = scm_to_utf8_stringn (data, &data_length);
  scm_dynwind_free (data_str);
  ret = scm_malloc (BASE64_DECODE_LENGTH (data_length));
  /* Not protected! Nothing will throw until scm_dynwind_end. */
  ok = base64_decode_update (&decoder, size, ret, data_length, data_str);
  scm_dynwind_end ();
  if (!ok)
    {
      ret = NULL;
      if (throw_if_fail)
	{
	  SCM base64_decoding_error =
	    scm_from_utf8_symbol ("base64-decoding-error");
	  scm_throw (base64_decoding_error, scm_list_1 (data));
	}
    }
  return ret;
}

#endif /* not H_UTILITIES_INCLUDED */