tbase64.c - sick - sign and check files using ed25519
(HTM) git clone git://z3bra.org/sick
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
tbase64.c (2667B)
---
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <limits.h>
7
8 #include "base64.h"
9
10 #define BASE64_FOLD 76
11
12 int base64_index(const char *, char);
13
14 const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
15
16 /*
17 * Return the index of a base64 char in the table
18 */
19 int
20 base64_index(const char *base64, char ch)
21 {
22 uint8_t idx = 0;
23
24 for (idx = 0; idx < 64; idx++)
25 if (base64[idx] == ch)
26 return idx;
27
28 return ch == '=' ? 0 : -1;
29 }
30
31 /*
32 * Encode the given message in base64, allocate memory to store the encoded
33 * message, and return the size allocated.
34 */
35 size_t
36 base64_encode(char **buf, const unsigned char *msg, size_t len)
37 {
38 size_t i, j;
39 uint64_t b64;
40 size_t size;
41
42 /* calculate size needed for the base64 buffer */
43 size = (len / 3) * 4 + (len % 3 ? 4 : 0);
44
45 *buf = malloc(size);
46 memset(*buf, 0, size);
47
48 for (i = j = 0; i < len; i+=3) {
49 /* concatenate 3 bytes into one 24 bits quantum, or 0 */
50 b64 = 0;
51 b64 |= (msg[i]<<16);
52 b64 |= ((i+1 < len ? msg[i+1] : 0) << 8);
53 b64 |= i+2 < len ? msg[i+2] : 0;
54
55 /* extract 4 base64 values from it */
56 (*buf)[j++] = base64_table[63 & (b64>>18)];
57 (*buf)[j++] = base64_table[63 & (b64>>12)];
58 (*buf)[j++] = i+1 < len ? base64_table[63 & (b64>>6)] : '=';
59 (*buf)[j++] = i+2 < len ? base64_table[63 & b64] : '=';
60 }
61
62 return size;
63 }
64
65 /*
66 * Allocate size to decode a base64 message, decode it in the buffer and
67 * return the allocated size.
68 */
69 size_t
70 base64_decode(char **buf, const unsigned char *msg, size_t len)
71 {
72 uint64_t b64;
73 size_t size, i, j;
74
75 size = (len / 4) * 3;
76 size -= msg[len - 1] == '=' ? 1 : 0;
77 size -= msg[len - 2] == '=' ? 1 : 0;
78
79 *buf = malloc(size);
80 if (*buf == NULL)
81 return 0;
82 memset(*buf, 0, size);
83
84 for (i = j = 0; i < len; i+=4) {
85 b64 = 0;
86 b64 |= (base64_index(base64_table, msg[i])<<18);
87 b64 |= (base64_index(base64_table, msg[i+1])<<12);
88 b64 |= i + 2 < len ? (base64_index(base64_table, msg[i+2])<<6) : 0;
89 b64 |= i + 3 < len ? (base64_index(base64_table, msg[i+3])) : 0;
90
91 if (j < size)
92 (*buf)[j++] = 255 & (b64>>16);
93 if (j < size)
94 (*buf)[j++] = 255 & (b64>>8);
95 if (j < size)
96 (*buf)[j++] = 255 & (b64);
97 }
98
99 return size;
100 }
101
102 /*
103 * Write a base64 encoded message to the given file pointer, folded at the
104 * given width (defaults to BASE64_FOLD if specified width is 0).
105 */
106 size_t
107 base64_fold(FILE *fp, char *base64, size_t len, size_t fold)
108 {
109 size_t i;
110
111 fold = fold > 0 ? fold : BASE64_FOLD;
112
113 for (i = 0; i < len; i += BASE64_FOLD) {
114 fwrite(base64+i, 1, i+BASE64_FOLD>len?len-i:BASE64_FOLD, fp);
115 fwrite("\n", 1, 1, fp);
116 }
117
118 return fold;
119 }