OpenVPN 3 Core Library
Loading...
Searching...
No Matches
test_b64.cpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12
13
14#include "test_common.hpp"
15
16#include <iostream>
17#include <memory>
18
21
22using namespace openvpn;
23
24
25#ifdef USE_OPENSSL
26#include <openssl/bio.h>
27#include <openssl/evp.h>
28#include <openssl/buffer.h>
29#include <stdint.h>
30
31#include <cstdlib>
32
33std::string ssllib_b64enc(const char *text, size_t textlen)
34{
35 BIO *bio, *b64;
36
37 b64 = BIO_new(BIO_f_base64());
38 bio = BIO_new(BIO_s_mem());
39 bio = BIO_push(b64, bio);
40
41 BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); // Ignore newlines - write everything in one line
42 BIO_write(bio, text, (int)textlen);
43 EXPECT_TRUE(BIO_flush(bio) == 1);
44 const char *encdata;
45 long len = BIO_get_mem_data(bio, &encdata);
46
47 /* If there is nothing to encode OpenSSL gives back a nullptr */
48 if (len == 0)
49 encdata = "";
50
51 std::string ret(encdata, (size_t)len);
52 BIO_free_all(bio);
53
54 return ret;
55}
56#else
57#include <mbedtls/base64.h>
58
59std::string ssllib_b64enc(const char *text, size_t textlen)
60{
61 size_t olen, outlen;
62
63 // make a pessimistic assumption about length always calculate 3 padding bytes
64 outlen = 3 + 4 * (textlen + 3) / 3;
65
66 char *dst = new char[outlen];
67
68 EXPECT_EQ(mbedtls_base64_encode(reinterpret_cast<unsigned char *>(dst),
69 outlen,
70 &olen,
71 reinterpret_cast<const unsigned char *>(text),
72 textlen),
73 0);
74 std::string ret(dst, olen);
75 delete[] dst;
76 return ret;
77}
78#endif
79
80
81void b64_test(const Base64 &b64, const std::string &text)
82{
83 const std::string enc = b64.encode(text);
84 std::string dec = b64.decode(enc);
85 std::string libenc = ssllib_b64enc(text.c_str(), text.size());
86
87 EXPECT_EQ(text, dec) << "Encode/Decode results differ";
88 EXPECT_EQ(enc, libenc) << "Encode differs from Crypto lib result";
89}
90
91void b64_test_binary(const Base64 &b64, const char *data, unsigned int len)
92{
93 auto enc = b64.encode(data, len);
94
95 std::unique_ptr<char[]> decdata(new char[len]);
96 size_t decode_len = b64.decode(decdata.get(), len, enc);
97 std::string libenc = ssllib_b64enc(data, len);
98
99 EXPECT_EQ(enc, libenc) << "Encode differs from Crypto lib result";
100
101 ASSERT_EQ(decode_len, len) << "Encode/decode length differs";
102 ASSERT_EQ(std::vector<uint8_t>(decdata.get(), decdata.get() + decode_len),
103 std::vector<uint8_t>(data, data + len))
104 << "Encode/Decode results differ";
105}
106
107TEST(Base64, tooshortdest)
108{
109 const Base64 b64;
110 auto enc = b64.encode(std::string("abc"));
111
112 char buf[2];
113 EXPECT_THROW(b64.decode(buf, 2, enc), Base64::base64_decode_out_of_bound_error);
114}
115
116void b64_test_bad_decode(const Base64 &b64, const std::string &text)
117{
118 std::string dec;
119 EXPECT_THROW(b64.decode(dec, text), Base64::base64_decode_error);
120}
121
122TEST(Base64, baddecode)
123{
124 const Base64 b64;
125
126 b64_test_bad_decode(b64, "!@#$%^&*()_");
127 b64_test_bad_decode(b64, "plausible deniability");
128 b64_test_bad_decode(b64, "plausible != deniability");
129 b64_test_bad_decode(b64, "x");
130 b64_test_bad_decode(b64, "====");
131 b64_test_bad_decode(b64, "xxxx=");
132 b64_test_bad_decode(b64, "01*=");
133}
134
135TEST(Base64, encode)
136{
137 const Base64 b64;
138
139 b64_test(b64, "Hello world!");
140 b64_test(b64, "привет!");
141 b64_test(b64, "ûmbrellaûmbrella");
142 b64_test(b64, "一旦在一个蓝色的月亮");
143 b64_test(b64, "x");
144 b64_test(b64, "one two three");
145 b64_test(b64, "aa");
146 b64_test(b64, "get your kicks on ... route 66");
147 b64_test(b64, "fight the future");
148 b64_test(b64, "");
149 b64_test(b64, "I want to believe...");
150 b64_test(b64, "it was a weather balloon");
151 b64_test(b64, "hyperspatial bypass");
152 b64_test(b64, "ode to a vogon");
153 b64_test(b64, "Acme Travel");
154 b64_test(b64, "there's no sunshine when she's gone");
155 b64_test(b64, "??????????????????????");
156 b64_test(b64, "???????????????????????");
157 b64_test(b64, "????????????????????????");
158 b64_test(b64, "???x>>>>>>>>>?????????????");
159 b64_test(b64, "???x>>>>>>>>>??????????????");
160 b64_test(b64, "???x>>>>>>>>>?????????????x>>");
161}
162
163TEST(Base64, binary_data)
164{
165
166 const Base64 b64;
167 std::srand(0);
168 for (unsigned int i = 0; i < 20; i++)
169 {
170 char *data = new char[i];
171 for (unsigned int j = 0; j < i; j++)
172 {
173 data[j] = (char)(std::rand() & 0xff);
174 }
175 b64_test_binary(b64, data, i);
176 delete[] data;
177 }
178}
std::string encode(const V &data) const
Definition base64.hpp:139
size_t decode(void *data, size_t len, const std::string &str) const
Definition base64.hpp:186
void b64_test_binary(const Base64 &b64, const char *data, unsigned int len)
Definition test_b64.cpp:91
TEST(Base64, tooshortdest)
Definition test_b64.cpp:107
void b64_test_bad_decode(const Base64 &b64, const std::string &text)
Definition test_b64.cpp:116
void b64_test(const Base64 &b64, const std::string &text)
Definition test_b64.cpp:81
std::string ssllib_b64enc(const char *text, size_t textlen)
Definition test_b64.cpp:59
std::string ret