aboutsummaryrefslogtreecommitdiffstats
path: root/ext/util.c
blob: 7e59abcaee19ae2f141dd7474d2d301c3d3ecdec (plain) (blame)
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
89
90
91
92
93
#include <ctype.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/random.h>

#include "util.h"

int bin2hex(char *hex, size_t hexsize, const uint8_t *bin, size_t binlen)
{
    static const char hex_chars[] = "0123456789abcdef";

    if (hex == NULL || bin == NULL || hexsize == 0)
        return -1;

    if (hexsize < (binlen * 2 + 1))
        return -2;

    for (size_t i = 0; i < binlen; ++i) {
        hex[2 * i + 0] = hex_chars[(bin[i] >> 4) & 0xF];
        hex[2 * i + 1] = hex_chars[(bin[i] >> 0) & 0xF];
    }

    hex[binlen * 2] = '\0';
    return 0;
}

int hex2bin(uint8_t *bin, size_t binsize, const char *hex, size_t hexlen)
{
    size_t ibin = 0;

    const int hi_reset = -1;
    int hi = hi_reset;

    for (size_t ihex = 0; ihex < hexlen; ihex++) {
        char c = hex[ihex];

        if (isspace((unsigned char) c))
            continue;

        /* invalid character */
        if (!isxdigit((unsigned char) c))
            return -1;

        /* hex char encountered after bin is full */
        if (ibin >= binsize)
            return -2;

        uint8_t val = (uint8_t) (isdigit(c) ? c - '0' : (tolower(c) - 'a' + 10));

        if (hi < 0) {
            /* process hi nibble */
            hi = val;
        } else {
            /* process lo nibble, complete byte, reset hi nibble */
            bin[ibin++] = (hi << 4) | val;
            hi = hi_reset;
        }
    }

    /* odd number of hex chars */
    if (hi != hi_reset)
        return -3;

    return (int) ibin;
}

void randombytes(uint8_t *buf, uint64_t n)
{
    while (n > 0) {
        ssize_t nbread;

        do {
            nbread = getrandom(buf, n, 0);
        } while (nbread == -1 && errno == EINTR);

        if (nbread < 0)
            exit(1);

        buf += nbread;
        n -= nbread;
    }
}

void memzero(void *ptr, size_t num)
{
    volatile unsigned char *volatile ptr_ = (volatile unsigned char *volatile) ptr;
    size_t i = (size_t) 0U;

    while (i < num)
        ptr_[i++] = 0U;
}