ffi-hydrogen 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +30 -0
  5. data/.travis.yml +10 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +72 -0
  9. data/Rakefile +46 -0
  10. data/bench/both.rb +86 -0
  11. data/bench/encode.rb +57 -0
  12. data/bench/encrypt.rb +80 -0
  13. data/bench/init.rb +5 -0
  14. data/bin/console +14 -0
  15. data/bin/setup +8 -0
  16. data/ffi-hydrogen.gemspec +31 -0
  17. data/lib/ffi/hydrogen.rb +216 -0
  18. data/vendor/.clang-format +2 -0
  19. data/vendor/.gitignore +3 -0
  20. data/vendor/README.md +2 -0
  21. data/vendor/libhydrogen/.clang-format +95 -0
  22. data/vendor/libhydrogen/.gitignore +32 -0
  23. data/vendor/libhydrogen/.travis.yml +22 -0
  24. data/vendor/libhydrogen/LICENSE +18 -0
  25. data/vendor/libhydrogen/Makefile +61 -0
  26. data/vendor/libhydrogen/Makefile.arduino +51 -0
  27. data/vendor/libhydrogen/README.md +29 -0
  28. data/vendor/libhydrogen/hydrogen.c +18 -0
  29. data/vendor/libhydrogen/hydrogen.h +317 -0
  30. data/vendor/libhydrogen/impl/common.h +316 -0
  31. data/vendor/libhydrogen/impl/core.h +220 -0
  32. data/vendor/libhydrogen/impl/gimli-core/portable.h +39 -0
  33. data/vendor/libhydrogen/impl/gimli-core/sse2.h +97 -0
  34. data/vendor/libhydrogen/impl/gimli-core.h +25 -0
  35. data/vendor/libhydrogen/impl/hash.h +138 -0
  36. data/vendor/libhydrogen/impl/hydrogen_p.h +83 -0
  37. data/vendor/libhydrogen/impl/kdf.h +20 -0
  38. data/vendor/libhydrogen/impl/kx.h +441 -0
  39. data/vendor/libhydrogen/impl/pwhash.h +281 -0
  40. data/vendor/libhydrogen/impl/random.h +376 -0
  41. data/vendor/libhydrogen/impl/secretbox.h +236 -0
  42. data/vendor/libhydrogen/impl/sign.h +207 -0
  43. data/vendor/libhydrogen/impl/x25519.h +383 -0
  44. data/vendor/libhydrogen/library.properties +10 -0
  45. data/vendor/libhydrogen/logo.png +0 -0
  46. data/vendor/libhydrogen/tests/tests.c +431 -0
  47. data/vendor/main.c +140 -0
  48. data/vendor/stringencoders/.gitignore +25 -0
  49. data/vendor/stringencoders/.travis.yml +13 -0
  50. data/vendor/stringencoders/AUTHORS +1 -0
  51. data/vendor/stringencoders/COPYING +2 -0
  52. data/vendor/stringencoders/ChangeLog +170 -0
  53. data/vendor/stringencoders/Doxyfile +276 -0
  54. data/vendor/stringencoders/INSTALL +119 -0
  55. data/vendor/stringencoders/LICENSE +22 -0
  56. data/vendor/stringencoders/Makefile.am +3 -0
  57. data/vendor/stringencoders/NEWS +3 -0
  58. data/vendor/stringencoders/README +2 -0
  59. data/vendor/stringencoders/README.md +32 -0
  60. data/vendor/stringencoders/bootstrap.sh +3 -0
  61. data/vendor/stringencoders/configure-gcc-hardened.sh +16 -0
  62. data/vendor/stringencoders/configure.ac +44 -0
  63. data/vendor/stringencoders/doxy/footer.html +34 -0
  64. data/vendor/stringencoders/doxy/header.html +85 -0
  65. data/vendor/stringencoders/indent.sh +9 -0
  66. data/vendor/stringencoders/javascript/base64-speed.html +43 -0
  67. data/vendor/stringencoders/javascript/base64-test.html +209 -0
  68. data/vendor/stringencoders/javascript/base64.html +18 -0
  69. data/vendor/stringencoders/javascript/base64.js +176 -0
  70. data/vendor/stringencoders/javascript/qunit.css +119 -0
  71. data/vendor/stringencoders/javascript/qunit.js +1062 -0
  72. data/vendor/stringencoders/javascript/urlparse-test.html +367 -0
  73. data/vendor/stringencoders/javascript/urlparse.js +328 -0
  74. data/vendor/stringencoders/make-ci.sh +13 -0
  75. data/vendor/stringencoders/makerelease.sh +16 -0
  76. data/vendor/stringencoders/python/b85.py +176 -0
  77. data/vendor/stringencoders/src/Makefile.am +134 -0
  78. data/vendor/stringencoders/src/arraytoc.c +85 -0
  79. data/vendor/stringencoders/src/arraytoc.h +43 -0
  80. data/vendor/stringencoders/src/extern_c_begin.h +3 -0
  81. data/vendor/stringencoders/src/extern_c_end.h +3 -0
  82. data/vendor/stringencoders/src/html_named_entities_generator.py +203 -0
  83. data/vendor/stringencoders/src/modp_ascii.c +159 -0
  84. data/vendor/stringencoders/src/modp_ascii.h +162 -0
  85. data/vendor/stringencoders/src/modp_ascii_data.h +84 -0
  86. data/vendor/stringencoders/src/modp_ascii_gen.c +55 -0
  87. data/vendor/stringencoders/src/modp_b16.c +125 -0
  88. data/vendor/stringencoders/src/modp_b16.h +148 -0
  89. data/vendor/stringencoders/src/modp_b16_data.h +104 -0
  90. data/vendor/stringencoders/src/modp_b16_gen.c +65 -0
  91. data/vendor/stringencoders/src/modp_b2.c +69 -0
  92. data/vendor/stringencoders/src/modp_b2.h +130 -0
  93. data/vendor/stringencoders/src/modp_b2_data.h +44 -0
  94. data/vendor/stringencoders/src/modp_b2_gen.c +36 -0
  95. data/vendor/stringencoders/src/modp_b36.c +108 -0
  96. data/vendor/stringencoders/src/modp_b36.h +170 -0
  97. data/vendor/stringencoders/src/modp_b64.c +254 -0
  98. data/vendor/stringencoders/src/modp_b64.h +236 -0
  99. data/vendor/stringencoders/src/modp_b64_data.h +477 -0
  100. data/vendor/stringencoders/src/modp_b64_gen.c +168 -0
  101. data/vendor/stringencoders/src/modp_b64r.c +254 -0
  102. data/vendor/stringencoders/src/modp_b64r.h +242 -0
  103. data/vendor/stringencoders/src/modp_b64r_data.h +477 -0
  104. data/vendor/stringencoders/src/modp_b64w.c +254 -0
  105. data/vendor/stringencoders/src/modp_b64w.h +231 -0
  106. data/vendor/stringencoders/src/modp_b64w_data.h +477 -0
  107. data/vendor/stringencoders/src/modp_b85.c +109 -0
  108. data/vendor/stringencoders/src/modp_b85.h +171 -0
  109. data/vendor/stringencoders/src/modp_b85_data.h +36 -0
  110. data/vendor/stringencoders/src/modp_b85_gen.c +65 -0
  111. data/vendor/stringencoders/src/modp_bjavascript.c +65 -0
  112. data/vendor/stringencoders/src/modp_bjavascript.h +105 -0
  113. data/vendor/stringencoders/src/modp_bjavascript_data.h +84 -0
  114. data/vendor/stringencoders/src/modp_bjavascript_gen.c +58 -0
  115. data/vendor/stringencoders/src/modp_burl.c +228 -0
  116. data/vendor/stringencoders/src/modp_burl.h +259 -0
  117. data/vendor/stringencoders/src/modp_burl_data.h +136 -0
  118. data/vendor/stringencoders/src/modp_burl_gen.c +121 -0
  119. data/vendor/stringencoders/src/modp_html.c +128 -0
  120. data/vendor/stringencoders/src/modp_html.h +53 -0
  121. data/vendor/stringencoders/src/modp_html_named_entities.h +9910 -0
  122. data/vendor/stringencoders/src/modp_json.c +315 -0
  123. data/vendor/stringencoders/src/modp_json.h +103 -0
  124. data/vendor/stringencoders/src/modp_json_data.h +57 -0
  125. data/vendor/stringencoders/src/modp_json_gen.py +60 -0
  126. data/vendor/stringencoders/src/modp_mainpage.h +120 -0
  127. data/vendor/stringencoders/src/modp_numtoa.c +350 -0
  128. data/vendor/stringencoders/src/modp_numtoa.h +100 -0
  129. data/vendor/stringencoders/src/modp_qsiter.c +76 -0
  130. data/vendor/stringencoders/src/modp_qsiter.h +71 -0
  131. data/vendor/stringencoders/src/modp_stdint.h +43 -0
  132. data/vendor/stringencoders/src/modp_utf8.c +88 -0
  133. data/vendor/stringencoders/src/modp_utf8.h +38 -0
  134. data/vendor/stringencoders/src/modp_xml.c +311 -0
  135. data/vendor/stringencoders/src/modp_xml.h +166 -0
  136. data/vendor/stringencoders/src/stringencoders.pc +10 -0
  137. data/vendor/stringencoders/src/stringencoders.pc.in +10 -0
  138. data/vendor/stringencoders/test/Makefile.am +113 -0
  139. data/vendor/stringencoders/test/apr_base64.c +262 -0
  140. data/vendor/stringencoders/test/apr_base64.h +120 -0
  141. data/vendor/stringencoders/test/cxx_test.cc +482 -0
  142. data/vendor/stringencoders/test/minunit.h +82 -0
  143. data/vendor/stringencoders/test/modp_ascii_test.c +281 -0
  144. data/vendor/stringencoders/test/modp_b16_test.c +288 -0
  145. data/vendor/stringencoders/test/modp_b2_test.c +250 -0
  146. data/vendor/stringencoders/test/modp_b64_test.c +266 -0
  147. data/vendor/stringencoders/test/modp_b85_test.c +130 -0
  148. data/vendor/stringencoders/test/modp_bjavascript_test.c +137 -0
  149. data/vendor/stringencoders/test/modp_burl_test.c +423 -0
  150. data/vendor/stringencoders/test/modp_html_test.c +296 -0
  151. data/vendor/stringencoders/test/modp_json_test.c +336 -0
  152. data/vendor/stringencoders/test/modp_numtoa_test.c +545 -0
  153. data/vendor/stringencoders/test/modp_qsiter_test.c +280 -0
  154. data/vendor/stringencoders/test/modp_utf8_test.c +188 -0
  155. data/vendor/stringencoders/test/modp_xml_test.c +339 -0
  156. data/vendor/stringencoders/test/speedtest.c +241 -0
  157. data/vendor/stringencoders/test/speedtest_ascii.c +345 -0
  158. data/vendor/stringencoders/test/speedtest_msg.c +78 -0
  159. data/vendor/stringencoders/test/speedtest_numtoa.c +276 -0
  160. metadata +314 -0
@@ -0,0 +1,108 @@
1
+ /**
2
+ * \file
3
+ * <PRE>
4
+ * MODP_B36 - High performance base36 encoder/decoder
5
+ * https://github.com/client9/stringencoders
6
+ *
7
+ * Copyright &copy; 2006-2016 Nick Galbreath
8
+ * All rights reserved.
9
+ *
10
+ * Released under MIT license. See LICENSE for details.
11
+ * </pre>
12
+ */
13
+
14
+ /* exported public header */
15
+ #include "modp_b36.h"
16
+ #include "modp_stdint.h"
17
+ /* private header */
18
+ #include "modp_b36_data.h"
19
+
20
+ /*
21
+ * Might need changing depending on platform
22
+ * we need htonl, and ntohl
23
+ */
24
+ #include <arpa/inet.h>
25
+
26
+ /**
27
+ * you can decode IN PLACE!
28
+ * no memory allocated
29
+ */
30
+ size_t modp_b36_decode(char* out, const char* data, size_t len)
31
+ {
32
+ size_t i;
33
+ int j;
34
+ const size_t buckets = len / 7;
35
+ const uint8_t* d2 = (const uint8_t*)data;
36
+ if (len % 7 != 0) {
37
+ return (size_t)-1;
38
+ }
39
+
40
+ uint32_t* o2 = (uint32_t*)out;
41
+ for (i = 0; i < buckets; ++i) {
42
+ uint32_t tmp = 0;
43
+ for (j = 0; j < 7; ++j) {
44
+ uint32_t digit = gsCharToInt[(uint32_t)*d2++];
45
+ if (digit >= 36) {
46
+ return (size_t)-1;
47
+ }
48
+ tmp = tmp * 36 + digit;
49
+ }
50
+ *o2++ = htonl(tmp);
51
+ }
52
+ return 4 * buckets;
53
+ }
54
+
55
+ /**
56
+ * src != out
57
+ */
58
+ size_t modp_b36_encode(char* out, const char* src, size_t len)
59
+ {
60
+ const uint32_t* sary = (const uint32_t*)src;
61
+ const size_t buckets = len / 4;
62
+ if (len % 4 != 0) {
63
+ return (size_t)-1;
64
+ }
65
+
66
+ size_t i;
67
+ for (i = 0; i < buckets; ++i) {
68
+ uint32_t tmp = *sary++;
69
+ tmp = htonl(tmp);
70
+
71
+ /* this crazy function */
72
+ #if 0
73
+ *out++ = (char)gsIntToChar[(tmp / 52200625)]; // don't need % 36 here, always < 36
74
+ *out++ = (char)gsIntToChar[(tmp / 614125) % 36];
75
+ *out++ = (char)gsIntToChar[(tmp / 7225) % 36];
76
+ *out++ = (char)gsIntToChar[(tmp / 36) % 36];
77
+ *out++ = (char)gsIntToChar[tmp % 36];
78
+ #else
79
+ /* is really this */
80
+ *(out + 6) = gsIntToChar[tmp % 36];
81
+ tmp /= 36;
82
+ *(out + 5) = gsIntToChar[tmp % 36];
83
+ tmp /= 36;
84
+ *(out + 4) = gsIntToChar[tmp % 36];
85
+ tmp /= 36;
86
+ *(out + 3) = gsIntToChar[tmp % 36];
87
+ tmp /= 36;
88
+ *(out + 2) = gsIntToChar[tmp % 36];
89
+ tmp /= 36;
90
+ *(out + 1) = gsIntToChar[tmp % 36];
91
+ tmp /= 36;
92
+ *out = gsIntToChar[tmp];
93
+ out += 7;
94
+ #endif
95
+ // NOTES
96
+ // Version 1 under -O3 is about 10-20 PERCENT faster than version 2
97
+ // BUT Version 1 is 10 TIMES SLOWER when used with -Os !!!
98
+ // Reason: gcc does a lot of tricks to remove the divisions
99
+ // op with multiplies and shift.
100
+ // In V1 with -O3 this works. Under -Os it reverts to very
101
+ // slow division.
102
+ // In V2 -O3 it does the same thing, but under Os, it's smart
103
+ // enough to know we want the quotient and remainder and only
104
+ // one div call per line.
105
+ }
106
+ *out = 0; // final null
107
+ return buckets * 7;
108
+ }
@@ -0,0 +1,170 @@
1
+ /**
2
+ * \file modp_b36.h
3
+ * \brief Base 36 encoding and decoding
4
+ *
5
+ * This provides a endian-safe base36 encode/decode operations. This
6
+ * means, the result will be the same on x86 or ibm/sparc chips.
7
+ */
8
+
9
+ /*
10
+ * <pre>
11
+ * High Performance Base36 Encoder / Decoder
12
+ *
13
+ * Copyright &copy; 2013-2016 Nick Galbreath
14
+ * All rights reserved.
15
+ *
16
+ * https://github.com/client9/stringencoders
17
+ *
18
+ * Released under MIT license. See LICENSE for details.
19
+ * </PRE>
20
+ *
21
+ * This provides a endian-safe base36 encode/decode operations. This
22
+ * means, the result will be the same on x86 or ibm/sparc chips.
23
+ *
24
+ * (Note: making it endian-specifc only results in a 5% savings in
25
+ * the decode operation, so why bother)
26
+ */
27
+
28
+ #ifndef COM_MODP_STRINGENCODERS_B36
29
+ #define COM_MODP_STRINGENCODERS_B36
30
+ #include "extern_c_begin.h"
31
+ #include "modp_stdint.h"
32
+
33
+ /**
34
+ * \brief base 36 encode
35
+ *
36
+ * \param[out] dest should have at least b36fast_encode_len memory allocated
37
+ * \param[in] src input string
38
+ * \param[in] len input string length, must be a multiple of 4
39
+ * \return the strlen of the destination, or -1 if error
40
+ *
41
+ */
42
+ size_t modp_b36_encode(char* dest, const char* src, size_t len);
43
+
44
+ /**
45
+ * \brief Base 36 decode
46
+ * \param[out] dest -- destination locations. May equal input.
47
+ * \param[in] src -- source b36data
48
+ * \param len -- length of source
49
+ * \return -1 on decoding error, length of output otherwise
50
+ * No ending null is added
51
+ */
52
+ size_t modp_b36_decode(char* dest, const char* src, size_t len);
53
+
54
+ /**
55
+ * \brief Returns the amount of memory to allocate for encoding the input
56
+ * string.
57
+ *
58
+ */
59
+ #define modp_b36_encode_len(A) ((A + 3) / 4 * 5 + 1)
60
+
61
+ /**
62
+ * \brief Return output strlen, without a NULL
63
+ */
64
+ #define modp_b36_encode_strlen(A) ((A + 3) / 4 * 5)
65
+
66
+ /**
67
+ * \brief Return the amount of memory to allocate for decoding a base 36
68
+ * encoded string.
69
+ *
70
+ */
71
+ #define modp_b36_decode_len(A) ((A + 4) / 5 * 4)
72
+
73
+ #include "extern_c_end.h"
74
+
75
+ #ifdef __cplusplus
76
+ #include <cstring>
77
+ #include <string>
78
+
79
+ namespace modp {
80
+
81
+ /**
82
+ *
83
+ * \param[in] s the input data
84
+ * \param[in] len the length of input
85
+ * \return b36 encoded string
86
+ */
87
+ inline std::string b36_encode(const char* s, size_t len)
88
+ {
89
+ std::string x(modp_b36_encode_len(len), '\0');
90
+ size_t d = modp_b36_encode(const_cast<char*>(x.data()), s, len);
91
+ if (d == (size_t)-1) {
92
+ x.clear();
93
+ } else {
94
+ x.erase(d, std::string::npos);
95
+ }
96
+ return x;
97
+ }
98
+
99
+ /**
100
+ * \param[in] null-terminated c-string input
101
+ * \return b36 encoded string
102
+ */
103
+ inline std::string b36_encode(const char* s)
104
+ {
105
+ return b36_encode(s, strlen(s));
106
+ }
107
+
108
+ /**
109
+ * /param[in,out] s the string to encode
110
+ * /return a reference to the input string, empty if error
111
+ */
112
+ inline std::string& b36_encode(std::string& s)
113
+ {
114
+ std::string x(b36_encode(s.data(), s.size()));
115
+ s.swap(x);
116
+ return s;
117
+ }
118
+
119
+ /**
120
+ * \param[in] s the input string
121
+ * \return base36 encoded string
122
+ */
123
+ inline std::string b36_encode(const std::string& s)
124
+ {
125
+ return b36_encode(s.data(), s.size());
126
+ }
127
+
128
+ /**
129
+ * Base36 decode a string.
130
+ * This function does not allocate memory.
131
+ *
132
+ * \param s the string to decode
133
+ * \return a reference to the input string. The string is empty
134
+ * if an error occurred.
135
+ */
136
+ inline std::string& b36_decode(std::string& s)
137
+ {
138
+ size_t d = modp_b36_decode(const_cast<char*>(s.data()), s.data(), s.size());
139
+ if (d == (size_t)-1) {
140
+ s.clear();
141
+ } else {
142
+ s.erase(d, std::string::npos);
143
+ }
144
+ return s;
145
+ }
146
+
147
+ inline std::string b36_decode(const std::string& s)
148
+ {
149
+ std::string x(s);
150
+ b36_decode(x);
151
+ return x;
152
+ }
153
+
154
+ inline std::string b36_decode(const char* s, size_t len)
155
+ {
156
+ std::string x(s, len);
157
+ return b36_decode(x);
158
+ }
159
+
160
+ inline std::string b36_decode(const char* s)
161
+ {
162
+ std::string x(s);
163
+ return b36_decode(x);
164
+ }
165
+
166
+ } /* namespace modp */
167
+
168
+ #endif /* ifdef __cplusplus */
169
+
170
+ #endif /* ifndef MODP_B36 */
@@ -0,0 +1,254 @@
1
+ /**
2
+ * \file modp_b64.c
3
+ * <PRE>
4
+ * MODP_B64 - High performance base64 encoder/decoder
5
+ * https://github.com/client9/stringencoders
6
+ *
7
+ * Copyright &copy; 2005-2016 Nick Galbreath
8
+ * All rights reserved.
9
+ * Released under MIT license. See LICENSE for details.
10
+ * </PRE>
11
+ */
12
+
13
+ /*
14
+ * If you are ripping this out of the library, comment out the next
15
+ * line and uncomment the next lines as approrpiate
16
+ */
17
+ // #include "config.h"
18
+
19
+ /* public header */
20
+ #include "modp_b64.h"
21
+
22
+ /* if on motorola, sun, ibm; uncomment this */
23
+ /* #define WORDS_BIGENDIAN 1 */
24
+ /* else for Intel, Amd; uncomment this */
25
+ /* #undef WORDS_BIGENDIAN */
26
+
27
+ #include "modp_b64_data.h"
28
+
29
+ #define BADCHAR 0x01FFFFFF
30
+
31
+ /**
32
+ * you can control if we use padding by commenting out this
33
+ * next line. However, I highly recommend you use padding and not
34
+ * using it should only be for compatibility with a 3rd party.
35
+ * Also, 'no padding' is not tested!
36
+ */
37
+ #define DOPAD 1
38
+
39
+ /*
40
+ * if we aren't doing padding
41
+ * set the pad character to NULL
42
+ */
43
+ #ifndef DOPAD
44
+ #undef CHARPAD
45
+ #define CHARPAD '\0'
46
+ #endif
47
+
48
+ size_t modp_b64_encode(char* dest, const char* str, size_t len)
49
+ {
50
+ size_t i = 0;
51
+ const uint8_t* s = (const uint8_t*)str;
52
+ uint8_t* p = (uint8_t*)dest;
53
+
54
+ /* unsigned here is important! */
55
+ /* uint8_t is fastest on G4, amd */
56
+ /* uint32_t is fastest on Intel */
57
+ uint32_t t1, t2, t3;
58
+
59
+ if (len > 2) {
60
+ for (i = 0; i < len - 2; i += 3) {
61
+ t1 = s[i];
62
+ t2 = s[i + 1];
63
+ t3 = s[i + 2];
64
+ *p++ = e0[t1];
65
+ *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
66
+ *p++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
67
+ *p++ = e2[t3];
68
+ }
69
+ }
70
+
71
+ switch (len - i) {
72
+ case 0:
73
+ break;
74
+ case 1:
75
+ t1 = s[i];
76
+ *p++ = e0[t1];
77
+ *p++ = e1[(t1 & 0x03) << 4];
78
+ *p++ = CHARPAD;
79
+ *p++ = CHARPAD;
80
+ break;
81
+ default: /* case 2 */
82
+ t1 = s[i];
83
+ t2 = s[i + 1];
84
+ *p++ = e0[t1];
85
+ *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
86
+ *p++ = e2[(t2 & 0x0F) << 2];
87
+ *p++ = CHARPAD;
88
+ }
89
+
90
+ *p = '\0';
91
+ return (size_t)(p - (uint8_t*)dest);
92
+ }
93
+
94
+ #ifdef WORDS_BIGENDIAN /* BIG ENDIAN -- SUN / IBM / MOTOROLA */
95
+ size_t modp_b64_decode(char* dest, const char* src, size_t len)
96
+ {
97
+ size_t i;
98
+ if (len == 0)
99
+ return 0;
100
+
101
+ #ifdef DOPAD
102
+ /* if padding is used, then the message must be at least
103
+ 4 chars and be a multiple of 4.
104
+ there can be at most 2 pad chars at the end */
105
+ if (len < 4 || (len % 4 != 0))
106
+ return -1;
107
+ if (src[len - 1] == CHARPAD) {
108
+ len--;
109
+ if (src[len - 1] == CHARPAD) {
110
+ len--;
111
+ }
112
+ }
113
+ #endif /* DOPAD */
114
+
115
+ size_t leftover = len % 4;
116
+ size_t chunks = (leftover == 0) ? len / 4 - 1 : len / 4;
117
+
118
+ uint8_t* p = (uint8_t*)dest;
119
+ uint32_t x = 0;
120
+ uint32_t* destInt = (uint32_t*)p;
121
+ uint32_t* srcInt = (uint32_t*)src;
122
+ uint32_t y = *srcInt++;
123
+ for (i = 0; i < chunks; ++i) {
124
+ x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] | d2[y >> 8 & 0xff] | d3[y & 0xff];
125
+
126
+ if (x >= BADCHAR)
127
+ return -1;
128
+ *destInt = x << 8;
129
+ p += 3;
130
+ destInt = (uint32_t*)p;
131
+ y = *srcInt++;
132
+ }
133
+
134
+ switch (leftover) {
135
+ case 0:
136
+ x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] | d2[y >> 8 & 0xff] | d3[y & 0xff];
137
+ if (x >= BADCHAR)
138
+ return -1;
139
+ *p++ = ((uint8_t*)&x)[1];
140
+ *p++ = ((uint8_t*)&x)[2];
141
+ *p = ((uint8_t*)&x)[3];
142
+ return (chunks + 1) * 3;
143
+ #ifndef DOPAD
144
+ case 1: /* with padding this is an impossible case */
145
+ x = d3[y >> 24];
146
+ *p = (uint8_t)x;
147
+ break;
148
+ #endif
149
+ case 2:
150
+ x = d3[y >> 24] * 64 + d3[(y >> 16) & 0xff];
151
+ *p = (uint8_t)(x >> 4);
152
+ break;
153
+ default: /* case 3 */
154
+ x = (d3[y >> 24] * 64 + d3[(y >> 16) & 0xff]) * 64 + d3[(y >> 8) & 0xff];
155
+ *p++ = (uint8_t)(x >> 10);
156
+ *p = (uint8_t)(x >> 2);
157
+ break;
158
+ }
159
+
160
+ if (x >= BADCHAR)
161
+ return -1;
162
+ return 3 * chunks + (6 * leftover) / 8;
163
+ }
164
+
165
+ #else /* LITTLE ENDIAN -- INTEL AND FRIENDS */
166
+
167
+ size_t modp_b64_decode(char* dest, const char* src, size_t len)
168
+ {
169
+ size_t i;
170
+ size_t leftover;
171
+ size_t chunks;
172
+
173
+ uint8_t* p;
174
+ uint32_t x;
175
+ uint32_t* destInt;
176
+ const uint32_t* srcInt = (const uint32_t*)src;
177
+ uint32_t y = *srcInt++;
178
+
179
+ if (len == 0)
180
+ return 0;
181
+
182
+ #ifdef DOPAD
183
+ /*
184
+ * if padding is used, then the message must be at least
185
+ * 4 chars and be a multiple of 4
186
+ */
187
+ if (len < 4 || (len % 4 != 0)) {
188
+ return (size_t)-1; /* error */
189
+ }
190
+ /* there can be at most 2 pad chars at the end */
191
+ if (src[len - 1] == CHARPAD) {
192
+ len--;
193
+ if (src[len - 1] == CHARPAD) {
194
+ len--;
195
+ }
196
+ }
197
+ #endif
198
+
199
+ leftover = len % 4;
200
+ chunks = (leftover == 0) ? len / 4 - 1 : len / 4;
201
+
202
+ p = (uint8_t*)dest;
203
+ x = 0;
204
+ destInt = (uint32_t*)p;
205
+ srcInt = (const uint32_t*)src;
206
+ y = *srcInt++;
207
+ for (i = 0; i < chunks; ++i) {
208
+ x = d0[y & 0xff] | d1[(y >> 8) & 0xff] | d2[(y >> 16) & 0xff] | d3[(y >> 24) & 0xff];
209
+
210
+ if (x >= BADCHAR) {
211
+ return (size_t)-1;
212
+ }
213
+ *destInt = x;
214
+ p += 3;
215
+ destInt = (uint32_t*)p;
216
+ y = *srcInt++;
217
+ }
218
+
219
+ switch (leftover) {
220
+ case 0:
221
+ x = d0[y & 0xff] | d1[(y >> 8) & 0xff] | d2[(y >> 16) & 0xff] | d3[(y >> 24) & 0xff];
222
+
223
+ if (x >= BADCHAR) {
224
+ return (size_t)-1;
225
+ }
226
+ *p++ = ((uint8_t*)(&x))[0];
227
+ *p++ = ((uint8_t*)(&x))[1];
228
+ *p = ((uint8_t*)(&x))[2];
229
+ return (chunks + 1) * 3;
230
+ #ifndef DOPAD
231
+ case 1: /* with padding this is an impossible case */
232
+ x = d0[y & 0xff];
233
+ *p = *((uint8_t*)(&x)); /* i.e. first char/byte in int */
234
+ break;
235
+ #endif
236
+ case 2: /* case 2, 1 output byte */
237
+ x = d0[y & 0xff] | d1[y >> 8 & 0xff];
238
+ *p = *((uint8_t*)(&x)); /* i.e. first char */
239
+ break;
240
+ default: /* case 3, 2 output bytes */
241
+ x = d0[y & 0xff] | d1[y >> 8 & 0xff] | d2[y >> 16 & 0xff]; /* 0x3c */
242
+ *p++ = ((uint8_t*)(&x))[0];
243
+ *p = ((uint8_t*)(&x))[1];
244
+ break;
245
+ }
246
+
247
+ if (x >= BADCHAR) {
248
+ return (size_t)-1;
249
+ }
250
+
251
+ return 3 * chunks + (6 * leftover) / 8;
252
+ }
253
+
254
+ #endif /* if bigendian / else / endif */