選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

base64_test.cc 12 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /* Copyright (c) 2014, Google Inc.
  2. *
  3. * Permission to use, copy, modify, and/or distribute this software for any
  4. * purpose with or without fee is hereby granted, provided that the above
  5. * copyright notice and this permission notice appear in all copies.
  6. *
  7. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <string>
  17. #include <vector>
  18. #include <openssl/base64.h>
  19. #include <openssl/crypto.h>
  20. #include <openssl/err.h>
  21. #include "../internal.h"
  22. enum encoding_relation {
  23. // canonical indicates that the encoding is the expected encoding of the
  24. // input.
  25. canonical,
  26. // valid indicates that the encoding is /a/ valid encoding of the input, but
  27. // need not be the canonical one.
  28. valid,
  29. // invalid indicates that the encoded data is valid.
  30. invalid,
  31. };
  32. struct TestVector {
  33. enum encoding_relation relation;
  34. const char *decoded;
  35. const char *encoded;
  36. };
  37. // Test vectors from RFC 4648.
  38. static const TestVector kTestVectors[] = {
  39. {canonical, "", ""},
  40. {canonical, "f", "Zg==\n"},
  41. {canonical, "fo", "Zm8=\n"},
  42. {canonical, "foo", "Zm9v\n"},
  43. {canonical, "foob", "Zm9vYg==\n"},
  44. {canonical, "fooba", "Zm9vYmE=\n"},
  45. {canonical, "foobar", "Zm9vYmFy\n"},
  46. {valid, "foobar", "Zm9vYmFy\n\n"},
  47. {valid, "foobar", " Zm9vYmFy\n\n"},
  48. {valid, "foobar", " Z m 9 v Y m F y\n\n"},
  49. {invalid, "", "Zm9vYmFy=\n"},
  50. {invalid, "", "Zm9vYmFy==\n"},
  51. {invalid, "", "Zm9vYmFy===\n"},
  52. {invalid, "", "Z"},
  53. {invalid, "", "Z\n"},
  54. {invalid, "", "ab!c"},
  55. {invalid, "", "ab=c"},
  56. {invalid, "", "abc"},
  57. {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  58. "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\n"},
  59. {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  60. "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA\n==\n"},
  61. {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  62. "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n=\n"},
  63. {invalid, "",
  64. "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n==\n"},
  65. {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  66. "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh"
  67. "4eHh4eHh4\n"},
  68. {canonical,
  69. "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  70. "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh"
  71. "4eHh4eHh4eHh4eA==\n"},
  72. {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  73. "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh\n4eHh4eHh"
  74. "4eHh4eHh4eHh4eA==\n"},
  75. {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  76. "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e"
  77. "Hh4eHh4eHh4eA==\n"},
  78. {invalid, "",
  79. "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=="
  80. "\neHh4eHh4eHh4eHh4eHh4eHh4\n"},
  81. // A '-' has traditionally been treated as the end of the data by OpenSSL
  82. // and anything following would be ignored. BoringSSL does not accept this
  83. // non-standard extension.
  84. {invalid, "", "Zm9vYmFy-anythinggoes"},
  85. {invalid, "", "Zm9vYmFy\n-anythinggoes"},
  86. // CVE-2015-0292
  87. {invalid, "",
  88. "ZW5jb2RlIG1lCg==========================================================="
  89. "=======\n"},
  90. };
  91. static const size_t kNumTests = OPENSSL_ARRAY_SIZE(kTestVectors);
  92. // RemoveNewlines returns a copy of |in| with all '\n' characters removed.
  93. static std::string RemoveNewlines(const char *in) {
  94. std::string ret;
  95. const size_t in_len = strlen(in);
  96. for (size_t i = 0; i < in_len; i++) {
  97. if (in[i] != '\n') {
  98. ret.push_back(in[i]);
  99. }
  100. }
  101. return ret;
  102. }
  103. static bool TestEncodeBlock() {
  104. for (unsigned i = 0; i < kNumTests; i++) {
  105. const TestVector *t = &kTestVectors[i];
  106. if (t->relation != canonical) {
  107. continue;
  108. }
  109. const size_t decoded_len = strlen(t->decoded);
  110. size_t max_encoded_len;
  111. if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
  112. fprintf(stderr, "#%u: EVP_EncodedLength failed\n", i);
  113. return false;
  114. }
  115. std::vector<uint8_t> out_vec(max_encoded_len);
  116. uint8_t *out = out_vec.data();
  117. size_t len = EVP_EncodeBlock(out, (const uint8_t *)t->decoded, decoded_len);
  118. std::string encoded(RemoveNewlines(t->encoded));
  119. if (len != encoded.size() ||
  120. memcmp(out, encoded.data(), len) != 0) {
  121. fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n",
  122. t->decoded, (int)len, (const char*)out, encoded.c_str());
  123. return false;
  124. }
  125. }
  126. return true;
  127. }
  128. static bool TestDecodeBase64() {
  129. size_t len;
  130. for (unsigned i = 0; i < kNumTests; i++) {
  131. const TestVector *t = &kTestVectors[i];
  132. if (t->relation == valid) {
  133. // The non-canonical encodings will generally have odd whitespace etc
  134. // that |EVP_DecodeBase64| will reject.
  135. continue;
  136. }
  137. const std::string encoded(RemoveNewlines(t->encoded));
  138. std::vector<uint8_t> out_vec(encoded.size());
  139. uint8_t *out = out_vec.data();
  140. int ok = EVP_DecodeBase64(out, &len, out_vec.size(),
  141. (const uint8_t *)encoded.data(), encoded.size());
  142. if (t->relation == invalid) {
  143. if (ok) {
  144. fprintf(stderr, "decode(\"%s\") didn't fail but should have\n",
  145. encoded.c_str());
  146. return false;
  147. }
  148. } else if (t->relation == canonical) {
  149. if (!ok) {
  150. fprintf(stderr, "decode(\"%s\") failed\n", encoded.c_str());
  151. return false;
  152. }
  153. if (len != strlen(t->decoded) ||
  154. memcmp(out, t->decoded, len) != 0) {
  155. fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
  156. encoded.c_str(), (int)len, (const char*)out, t->decoded);
  157. return false;
  158. }
  159. }
  160. }
  161. return true;
  162. }
  163. static bool TestDecodeBlock() {
  164. for (unsigned i = 0; i < kNumTests; i++) {
  165. const TestVector *t = &kTestVectors[i];
  166. if (t->relation != canonical) {
  167. continue;
  168. }
  169. std::string encoded(RemoveNewlines(t->encoded));
  170. std::vector<uint8_t> out_vec(encoded.size());
  171. uint8_t *out = out_vec.data();
  172. // Test that the padding behavior of the deprecated API is preserved.
  173. int ret =
  174. EVP_DecodeBlock(out, (const uint8_t *)encoded.data(), encoded.size());
  175. if (ret < 0) {
  176. fprintf(stderr, "EVP_DecodeBlock(\"%s\") failed\n", t->encoded);
  177. return false;
  178. }
  179. if (ret % 3 != 0) {
  180. fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n");
  181. return false;
  182. }
  183. size_t expected_len = strlen(t->decoded);
  184. if (expected_len % 3 != 0) {
  185. ret -= 3 - (expected_len % 3);
  186. }
  187. if (static_cast<size_t>(ret) != strlen(t->decoded) ||
  188. memcmp(out, t->decoded, ret) != 0) {
  189. fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
  190. t->encoded, ret, (const char*)out, t->decoded);
  191. return false;
  192. }
  193. }
  194. return true;
  195. }
  196. static bool TestEncodeDecode() {
  197. for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
  198. const TestVector *t = &kTestVectors[test_num];
  199. EVP_ENCODE_CTX ctx;
  200. const size_t decoded_len = strlen(t->decoded);
  201. if (t->relation == canonical) {
  202. size_t max_encoded_len;
  203. if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
  204. fprintf(stderr, "#%u: EVP_EncodedLength failed\n", test_num);
  205. return false;
  206. }
  207. // EVP_EncodeUpdate will output new lines every 64 bytes of output so we
  208. // need slightly more than |EVP_EncodedLength| returns. */
  209. max_encoded_len += (max_encoded_len + 63) >> 6;
  210. std::vector<uint8_t> out_vec(max_encoded_len);
  211. uint8_t *out = out_vec.data();
  212. EVP_EncodeInit(&ctx);
  213. int out_len;
  214. EVP_EncodeUpdate(&ctx, out, &out_len,
  215. reinterpret_cast<const uint8_t *>(t->decoded),
  216. decoded_len);
  217. size_t total = out_len;
  218. EVP_EncodeFinal(&ctx, out + total, &out_len);
  219. total += out_len;
  220. if (total != strlen(t->encoded) || memcmp(out, t->encoded, total) != 0) {
  221. fprintf(stderr, "#%u: EVP_EncodeUpdate produced different output: '%s' (%u)\n",
  222. test_num, out, static_cast<unsigned>(total));
  223. return false;
  224. }
  225. }
  226. std::vector<uint8_t> out_vec(strlen(t->encoded));
  227. uint8_t *out = out_vec.data();
  228. EVP_DecodeInit(&ctx);
  229. int out_len;
  230. size_t total = 0;
  231. int ret = EVP_DecodeUpdate(&ctx, out, &out_len,
  232. reinterpret_cast<const uint8_t *>(t->encoded),
  233. strlen(t->encoded));
  234. if (ret != -1) {
  235. total = out_len;
  236. ret = EVP_DecodeFinal(&ctx, out + total, &out_len);
  237. total += out_len;
  238. }
  239. switch (t->relation) {
  240. case canonical:
  241. case valid:
  242. if (ret == -1) {
  243. fprintf(stderr, "#%u: EVP_DecodeUpdate failed\n", test_num);
  244. return false;
  245. }
  246. if (total != decoded_len || memcmp(out, t->decoded, decoded_len)) {
  247. fprintf(stderr, "#%u: EVP_DecodeUpdate produced incorrect output\n",
  248. test_num);
  249. return false;
  250. }
  251. break;
  252. case invalid:
  253. if (ret != -1) {
  254. fprintf(stderr, "#%u: EVP_DecodeUpdate was successful but shouldn't have been\n", test_num);
  255. return false;
  256. }
  257. break;
  258. }
  259. }
  260. return true;
  261. }
  262. static bool TestDecodeUpdateStreaming() {
  263. for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
  264. const TestVector *t = &kTestVectors[test_num];
  265. if (t->relation == invalid) {
  266. continue;
  267. }
  268. const size_t encoded_len = strlen(t->encoded);
  269. std::vector<uint8_t> out(encoded_len);
  270. for (size_t chunk_size = 1; chunk_size <= encoded_len; chunk_size++) {
  271. size_t out_len = 0;
  272. EVP_ENCODE_CTX ctx;
  273. EVP_DecodeInit(&ctx);
  274. for (size_t i = 0; i < encoded_len;) {
  275. size_t todo = encoded_len - i;
  276. if (todo > chunk_size) {
  277. todo = chunk_size;
  278. }
  279. int bytes_written;
  280. int ret = EVP_DecodeUpdate(
  281. &ctx, out.data() + out_len, &bytes_written,
  282. reinterpret_cast<const uint8_t *>(t->encoded + i), todo);
  283. i += todo;
  284. switch (ret) {
  285. case -1:
  286. fprintf(stderr, "#%u: EVP_DecodeUpdate returned error\n", test_num);
  287. return 0;
  288. case 0:
  289. out_len += bytes_written;
  290. if (i == encoded_len ||
  291. (i + 1 == encoded_len && t->encoded[i] == '\n') ||
  292. /* If there was an '-' in the input (which means “EOF”) then
  293. * this loop will continue to test that |EVP_DecodeUpdate| will
  294. * ignore the remainder of the input. */
  295. strchr(t->encoded, '-') != nullptr) {
  296. break;
  297. }
  298. fprintf(stderr,
  299. "#%u: EVP_DecodeUpdate returned zero before end of "
  300. "encoded data\n",
  301. test_num);
  302. return 0;
  303. default:
  304. out_len += bytes_written;
  305. }
  306. }
  307. int bytes_written;
  308. int ret = EVP_DecodeFinal(&ctx, out.data() + out_len, &bytes_written);
  309. if (ret == -1) {
  310. fprintf(stderr, "#%u: EVP_DecodeFinal returned error\n", test_num);
  311. return 0;
  312. }
  313. out_len += bytes_written;
  314. if (out_len != strlen(t->decoded) ||
  315. memcmp(out.data(), t->decoded, out_len) != 0) {
  316. fprintf(stderr, "#%u: incorrect output\n", test_num);
  317. return 0;
  318. }
  319. }
  320. }
  321. return true;
  322. }
  323. int main(void) {
  324. CRYPTO_library_init();
  325. if (!TestEncodeBlock() ||
  326. !TestDecodeBase64() ||
  327. !TestDecodeBlock() ||
  328. !TestDecodeUpdateStreaming() ||
  329. !TestEncodeDecode()) {
  330. return 1;
  331. }
  332. printf("PASS\n");
  333. return 0;
  334. }