{
BYTE *base64;
int length;
- crypto_base64_decode((BYTE *) (arg->Value),
- (int) strlen(arg->Value), &base64, &length);
+ crypto_base64_decode((const char *) (arg->Value), (int) strlen(arg->Value),
+ &base64, &length);
if ((base64 != NULL) && (length == sizeof(ARC_SC_PRIVATE_PACKET)))
{
memcpy(settings->ServerAutoReconnectCookie, base64, length);
FREERDP_API void crypto_nonce(BYTE* nonce, int size);
FREERDP_API char* crypto_base64_encode(const BYTE* data, int length);
-FREERDP_API void crypto_base64_decode(const BYTE* enc_data, int length, BYTE** dec_data, int* res_length);
+FREERDP_API void crypto_base64_decode(const char* enc_data, int length, BYTE** dec_data, int* res_length);
#endif /* FREERDP_CRYPTO_H */
goto out;
ntlm_token_data = NULL;
- crypto_base64_decode((BYTE*) token64, strlen(token64), &ntlm_token_data, &ntlm_token_length);
+ crypto_base64_decode(token64, strlen(token64), &ntlm_token_data, &ntlm_token_length);
}
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
if (http_response && ListDictionary_Contains(http_response->Authenticates, "NTLM"))
{
char *token64 = ListDictionary_GetItemValue(http_response->Authenticates, "NTLM");
- crypto_base64_decode((BYTE*) token64, strlen(token64), &ntlm_token_data, &ntlm_token_length);
+ crypto_base64_decode(token64, strlen(token64), &ntlm_token_data, &ntlm_token_length);
}
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
+
+if(BUILD_TESTING)
+ add_subdirectory(test)
+endif()
char* p;
char* ret;
int i = 0;
+ int blocks;
q = data;
p = ret = (char*) malloc((length + 3) * 4 / 3 + 1);
if (!p)
return NULL;
- while (i < length)
+ /* b1, b2, b3 are input bytes
+ *
+ * 0 1 2
+ * 012345678901234567890123
+ * | b1 | b2 | b3 |
+ *
+ * [ c1 ] [ c3 ]
+ * [ c2 ] [ c4 ]
+ *
+ * c1, c2, c3, c4 are output chars in base64
+ */
+
+ /* first treat complete blocks */
+ blocks = length - (length % 3);
+ for (i = 0; i < blocks; i += 3, q += 3)
{
- c = q[i++];
-
- c <<= 8;
- if (i < length)
- c += q[i];
- i++;
-
- c <<= 8;
- if (i < length)
- c += q[i];
- i++;
+ c = (q[0] << 16) + (q[1] << 8) + q[2];
*p++ = base64[(c & 0x00FC0000) >> 18];
*p++ = base64[(c & 0x0003F000) >> 12];
+ *p++ = base64[(c & 0x00000FC0) >> 6];
+ *p++ = base64[c & 0x0000003F];
+ }
- if (i > length + 1)
- *p++ = '=';
- else
- *p++ = base64[(c & 0x00000FC0) >> 6];
-
- if (i > length)
- *p++ = '=';
- else
- *p++ = base64[c & 0x0000003F];
+ /* then remainder */
+ switch (length % 3)
+ {
+ case 0:
+ break;
+ case 1:
+ c = (q[0] << 16);
+ *p++ = base64[(c & 0x00FC0000) >> 18];
+ *p++ = base64[(c & 0x0003F000) >> 12];
+ *p++ = '=';
+ *p++ = '=';
+ break;
+ case 2:
+ c = (q[0] << 16) + (q[1] << 8);
+ *p++ = base64[(c & 0x00FC0000) >> 18];
+ *p++ = base64[(c & 0x0003F000) >> 12];
+ *p++ = base64[(c & 0x00000FC0) >> 6];
+ *p++ = '=';
+ break;
}
*p = 0;
return -1;
}
-static void* base64_decode(const BYTE* s, int length, int* data_len)
+static void* base64_decode(const char* s, int length, int* data_len)
{
- char* p;
int n[4];
BYTE* q;
BYTE* data;
+ int nBlocks, i, outputLen;
if (length % 4)
return NULL;
- n[0] = n[1] = n[2] = n[3] = 0;
q = data = (BYTE*) malloc(length / 4 * 3);
- for (p = (char*) s; *p; )
+ /* first treat complete blocks */
+ nBlocks = (length / 4);
+ outputLen = 0;
+
+ for (i = 0; i < nBlocks-1; i++, q += 3)
{
- n[0] = base64_decode_char(*p++);
- n[1] = base64_decode_char(*p++);
- n[2] = base64_decode_char(*p++);
- n[3] = base64_decode_char(*p++);
-
- if ((n[0] == -1) || (n[1] == -1))
- {
- free(data);
- return NULL;
- }
-
- if ((n[2] == -1) && (n[3] != -1))
- {
- free(data);
- return NULL;
- }
+ n[0] = base64_decode_char(*s++);
+ n[1] = base64_decode_char(*s++);
+ n[2] = base64_decode_char(*s++);
+ n[3] = base64_decode_char(*s++);
+
+ if ((n[0] == -1) || (n[1] == -1) || (n[2] == -1) || (n[3] == -1))
+ goto out_free;
q[0] = (n[0] << 2) + (n[1] >> 4);
+ q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
+ q[2] = ((n[2] & 3) << 6) + n[3];
+ outputLen += 3;
+ }
- if (n[2] != -1)
- q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
+ /* treat last block */
+ n[0] = base64_decode_char(*s++);
+ n[1] = base64_decode_char(*s++);
+ if ((n[0] == -1) || (n[1] == -1))
+ goto out_free;
+ n[2] = base64_decode_char(*s++);
+ n[3] = base64_decode_char(*s++);
+
+ q[0] = (n[0] << 2) + (n[1] >> 4);
+ if (n[2] == -1)
+ {
+ /* XX== */
+ outputLen += 1;
if (n[3] != -1)
- q[2] = ((n[2] & 3) << 6) + n[3];
+ goto out_free;
- q += 3;
+ q[1] = ((n[1] & 15) << 4);
+ }
+ else if (n[3] == -1)
+ {
+ /* yyy= */
+ outputLen += 2;
+ q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
+ q[2] = ((n[2] & 3) << 6);
+ }
+ else
+ {
+ /* XXXX */
+ outputLen += 3;
+ q[0] = (n[0] << 2) + (n[1] >> 4);
+ q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
+ q[2] = ((n[2] & 3) << 6) + n[3];
}
- *data_len = q - data - (n[2] == -1) - (n[3] == -1);
+ *data_len = outputLen;
return data;
+out_free:
+ free(data);
+ return NULL;
}
-void crypto_base64_decode(const BYTE* enc_data, int length, BYTE** dec_data, int* res_length)
+void crypto_base64_decode(const char* enc_data, int length, BYTE** dec_data, int* res_length)
{
*dec_data = base64_decode(enc_data, length, res_length);
}
--- /dev/null
+
+set(MODULE_NAME "TestFreeRDPCrypto")
+set(MODULE_PREFIX "TEST_FREERDP_CRYPTO")
+
+set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
+
+set(${MODULE_PREFIX}_TESTS
+ TestBase64.c)
+
+create_test_sourcelist(${MODULE_PREFIX}_SRCS
+ ${${MODULE_PREFIX}_DRIVER}
+ ${${MODULE_PREFIX}_TESTS})
+
+add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
+
+set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
+ MONOLITHIC ${MONOLITHIC_BUILD}
+ MODULE freerdp
+ MODULES freerdp-crypto)
+
+target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+
+set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
+
+foreach(test ${${MODULE_PREFIX}_TESTS})
+ get_filename_component(TestName ${test} NAME_WE)
+ add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
+endforeach()
+
+set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Test")
+
--- /dev/null
+/**
+ * Copyright © 2014 Thincast Technologies GmbH
+ * Copyright © 2014 Hardening <contact@hardening-consulting.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <freerdp/crypto/crypto.h>
+
+struct Encode64test {
+ const char *input;
+ int len;
+ const char *output;
+};
+
+struct Encode64test encodeTests[] = {
+ {"\x00", 1, "AA=="},
+ {"\x00\x00", 2, "AAA="},
+ {"\x00\x00\x00", 3, "AAAA"},
+ {"0123456", 7, "MDEyMzQ1Ng=="},
+ {"90123456", 8, "OTAxMjM0NTY="},
+ {"890123456", 9, "ODkwMTIzNDU2"},
+ {"7890123456", 10, "Nzg5MDEyMzQ1Ng=="},
+
+ {NULL, -1, NULL}, /* /!\ last one /!\ */
+};
+
+
+int TestBase64(int argc, char* argv[])
+{
+ int i, testNb = 0;
+ int outLen;
+ BYTE *decoded;
+
+ testNb++;
+ fprintf(stderr, "%d:encode base64...", testNb);
+
+ for (i = 0; encodeTests[i].input; i++)
+ {
+ char *encoded = crypto_base64_encode((const BYTE *)encodeTests[i].input, encodeTests[i].len);
+
+ if (strcmp(encodeTests[i].output, encoded))
+ {
+ fprintf(stderr, "ko, error for string %d\n", i);
+ return -1;
+ }
+
+ free(encoded);
+ }
+ fprintf(stderr, "ok\n");
+
+ testNb++;
+ fprintf(stderr, "%d:decode base64...", testNb);
+ for (i = 0; encodeTests[i].input; i++)
+ {
+ crypto_base64_decode(encodeTests[i].output, strlen(encodeTests[i].output), &decoded, &outLen);
+
+ if (!decoded || (outLen != encodeTests[i].len) || memcmp(encodeTests[i].input, decoded, outLen))
+ {
+ fprintf(stderr, "ko, error for string %d\n", i);
+ return -1;
+ }
+
+ free(decoded);
+ }
+ fprintf(stderr, "ok\n");
+
+ testNb++;
+ fprintf(stderr, "%d:decode base64 errors...", testNb);
+ crypto_base64_decode("000", 3, &decoded, &outLen);
+ if (decoded)
+ {
+ fprintf(stderr, "ko, badly padded string\n");
+ return -1;
+ }
+
+ crypto_base64_decode("0=00", 4, &decoded, &outLen);
+ if (decoded)
+ {
+ fprintf(stderr, "ko, = in a wrong place\n");
+ return -1;
+ }
+
+ crypto_base64_decode("00=0", 4, &decoded, &outLen);
+ if (decoded)
+ {
+ fprintf(stderr, "ko, = in a wrong place\n");
+ return -1;
+ }
+ fprintf(stderr, "ok\n");
+
+
+ return 0;
+}