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 15 #include <stdio.h> 16 #include <string.h> 17 18 #include <openssl/base64.h> 19 #include <openssl/crypto.h> 20 #include <openssl/err.h> 21 22 23 struct TestVector { 24 const char *decoded; 25 const char *encoded; 26 }; 27 28 // Test vectors from RFC 4648. 29 static const TestVector kTestVectors[] = { 30 { "", "" }, 31 { "f" , "Zg==" }, 32 { "fo", "Zm8=" }, 33 { "foo", "Zm9v" }, 34 { "foob", "Zm9vYg==" }, 35 { "fooba", "Zm9vYmE=" }, 36 { "foobar", "Zm9vYmFy" }, 37 }; 38 39 static const size_t kNumTests = sizeof(kTestVectors) / sizeof(kTestVectors[0]); 40 41 static bool TestEncode() { 42 for (size_t i = 0; i < kNumTests; i++) { 43 const TestVector *t = &kTestVectors[i]; 44 uint8_t out[9]; 45 size_t len = EVP_EncodeBlock(out, (const uint8_t*)t->decoded, 46 strlen(t->decoded)); 47 if (len != strlen(t->encoded) || 48 memcmp(out, t->encoded, len) != 0) { 49 fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n", 50 t->decoded, (int)len, (const char*)out, t->encoded); 51 return false; 52 } 53 } 54 return true; 55 } 56 57 static bool TestDecode() { 58 uint8_t out[6]; 59 size_t len; 60 61 for (size_t i = 0; i < kNumTests; i++) { 62 // Test the normal API. 63 const TestVector *t = &kTestVectors[i]; 64 size_t expected_len = strlen(t->decoded); 65 if (!EVP_DecodeBase64(out, &len, sizeof(out), 66 (const uint8_t*)t->encoded, strlen(t->encoded))) { 67 fprintf(stderr, "decode(\"%s\") failed\n", t->encoded); 68 return false; 69 } 70 if (len != strlen(t->decoded) || 71 memcmp(out, t->decoded, len) != 0) { 72 fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n", 73 t->encoded, (int)len, (const char*)out, t->decoded); 74 return false; 75 } 76 77 // Test that the padding behavior of the deprecated API is preserved. 78 int ret = EVP_DecodeBlock(out, (const uint8_t*)t->encoded, 79 strlen(t->encoded)); 80 if (ret < 0) { 81 fprintf(stderr, "decode(\"%s\") failed\n", t->encoded); 82 return false; 83 } 84 if (ret % 3 != 0) { 85 fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n"); 86 return false; 87 } 88 if (expected_len % 3 != 0) { 89 ret -= 3 - (expected_len % 3); 90 } 91 if (static_cast<size_t>(ret) != strlen(t->decoded) || 92 memcmp(out, t->decoded, ret) != 0) { 93 fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n", 94 t->encoded, ret, (const char*)out, t->decoded); 95 return false; 96 } 97 } 98 99 if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a!bc", 4)) { 100 fprintf(stderr, "Failed to reject invalid characters in the middle.\n"); 101 return false; 102 } 103 104 if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a=bc", 4)) { 105 fprintf(stderr, "Failed to reject invalid characters in the middle.\n"); 106 return false; 107 } 108 109 if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"abc", 4)) { 110 fprintf(stderr, "Failed to reject invalid input length.\n"); 111 return false; 112 } 113 114 return true; 115 } 116 117 int main(void) { 118 CRYPTO_library_init(); 119 ERR_load_crypto_strings(); 120 121 if (!TestEncode() || 122 !TestDecode()) { 123 return 1; 124 } 125 126 printf("PASS\n"); 127 return 0; 128 } 129