diff options
Diffstat (limited to 'uirdesktop/ssl_calls.c')
| -rwxr-xr-x | uirdesktop/ssl_calls.c | 1645 |
1 files changed, 0 insertions, 1645 deletions
diff --git a/uirdesktop/ssl_calls.c b/uirdesktop/ssl_calls.c deleted file mode 100755 index a7439259..00000000 --- a/uirdesktop/ssl_calls.c +++ /dev/null @@ -1,1645 +0,0 @@ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2004-2005 - - ssl calls - -*/ - -#include "rdesktop.h" - -#define APP_CC - -/*****************************************************************************/ -static void * g_malloc(int size, int zero) -{ - void * p; - - p = xmalloc(size); - if (zero) - { - memset(p, 0, size); - } - return p; -} - -/*****************************************************************************/ -static void g_free(void * in) -{ - xfree(in); -} - -/*****************************************************************************/ -/*****************************************************************************/ -/* rc4 stuff */ -/* An implementation of the ARC4 algorithm - * - * Copyright (C) 2001-2003 Christophe Devine - */ -struct rc4_state -{ - int x; - int y; - int m[256]; -}; - -/*****************************************************************************/ -void* APP_CC -ssl_rc4_info_create(void) -{ - return g_malloc(sizeof(struct rc4_state), 1);; -} - -/*****************************************************************************/ -void APP_CC -ssl_rc4_info_delete(void* rc4_info) -{ - g_free(rc4_info); -} - -/*****************************************************************************/ -void APP_CC -ssl_rc4_set_key(void* rc4_info, char* key, int len) -{ - int i; - int j; - int k; - int a; - int* m; - struct rc4_state* s; - - s = (struct rc4_state*)rc4_info; - s->x = 0; - s->y = 0; - m = s->m; - for (i = 0; i < 256; i++) - { - m[i] = i; - } - j = 0; - k = 0; - for (i = 0; i < 256; i++) - { - a = m[i]; - j = (unsigned char)(j + a + key[k]); - m[i] = m[j]; - m[j] = a; - k++; - if (k >= len) - { - k = 0; - } - } -} - -/*****************************************************************************/ -void APP_CC -ssl_rc4_crypt(void* rc4_info, char* in_data, char* out_data, int len) -{ - int i; - int x; - int y; - int a; - int b; - int* m; - struct rc4_state* s; - - s = (struct rc4_state*)rc4_info; - x = s->x; - y = s->y; - m = s->m; - for (i = 0; i < len; i++) - { - x = (unsigned char)(x + 1); - a = m[x]; - y = (unsigned char)(y + a); - b = m[y]; - m[x] = b; - m[y] = a; - out_data[i] = in_data[i] ^ (m[(unsigned char)(a + b)]); - } - s->x = x; - s->y = y; -} - -/*****************************************************************************/ -/*****************************************************************************/ -/* sha1 stuff */ -/* FIPS-180-1 compliant SHA-1 implementation - * - * Copyright (C) 2001-2003 Christophe Devine - */ -struct sha1_context -{ - int total[2]; - int state[5]; - char buffer[64]; -}; - -/*****************************************************************************/ -void* APP_CC -ssl_sha1_info_create(void) -{ - return g_malloc(sizeof(struct sha1_context), 1); -} - -/*****************************************************************************/ -void APP_CC -ssl_sha1_info_delete(void* sha1_info) -{ - g_free(sha1_info); -} - -/*****************************************************************************/ -void APP_CC -ssl_sha1_clear(void* sha1_info) -{ - struct sha1_context* ctx; - - ctx = (struct sha1_context*)sha1_info; - memset(ctx, 0, sizeof(struct sha1_context)); - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; -} - -#undef GET_UINT32 -#define GET_UINT32(n, b, i) \ -{ \ - (n) = ((b)[(i) + 0] << 24) | \ - ((b)[(i) + 1] << 16) | \ - ((b)[(i) + 2] << 8) | \ - ((b)[(i) + 3] << 0); \ -} - -#undef PUT_UINT32 -#define PUT_UINT32(n, b, i) \ -{ \ - (b)[(i) + 0] = ((n) >> 24); \ - (b)[(i) + 1] = ((n) >> 16); \ - (b)[(i) + 2] = ((n) >> 8); \ - (b)[(i) + 3] = ((n) >> 0); \ -} - -/*****************************************************************************/ -static void APP_CC -sha1_process(struct sha1_context* ctx, char* in_data) -{ - int temp; - int W[16]; - int A; - int B; - int C; - int D; - int E; - unsigned char* data; - - data = (unsigned char*)in_data; - - GET_UINT32(W[0], data, 0); - GET_UINT32(W[1], data, 4); - GET_UINT32(W[2], data, 8); - GET_UINT32(W[3], data, 12); - GET_UINT32(W[4], data, 16); - GET_UINT32(W[5], data, 20); - GET_UINT32(W[6], data, 24); - GET_UINT32(W[7], data, 28); - GET_UINT32(W[8], data, 32); - GET_UINT32(W[9], data, 36); - GET_UINT32(W[10], data, 40); - GET_UINT32(W[11], data, 44); - GET_UINT32(W[12], data, 48); - GET_UINT32(W[13], data, 52); - GET_UINT32(W[14], data, 56); - GET_UINT32(W[15], data, 60); - -#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define R(t) \ -( \ - temp = W[(t - 3) & 0x0F] ^ \ - W[(t - 8) & 0x0F] ^ \ - W[(t - 14) & 0x0F] ^ \ - W[(t - 0) & 0x0F], \ - (W[t & 0x0F] = S(temp, 1)) \ -) - -#undef P -#define P(a, b, c, d, e, x) \ -{ \ - e += S(a, 5) + F(b, c, d) + K + x; \ - b = S(b, 30); \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - -#define F(x, y, z) (z ^ (x & (y ^ z))) -#define K 0x5A827999 - - P(A, B, C, D, E, W[0]); - P(E, A, B, C, D, W[1]); - P(D, E, A, B, C, W[2]); - P(C, D, E, A, B, W[3]); - P(B, C, D, E, A, W[4]); - P(A, B, C, D, E, W[5]); - P(E, A, B, C, D, W[6]); - P(D, E, A, B, C, W[7]); - P(C, D, E, A, B, W[8]); - P(B, C, D, E, A, W[9]); - P(A, B, C, D, E, W[10]); - P(E, A, B, C, D, W[11]); - P(D, E, A, B, C, W[12]); - P(C, D, E, A, B, W[13]); - P(B, C, D, E, A, W[14]); - P(A, B, C, D, E, W[15]); - P(E, A, B, C, D, R(16)); - P(D, E, A, B, C, R(17)); - P(C, D, E, A, B, R(18)); - P(B, C, D, E, A, R(19)); - -#undef K -#undef F - -#define F(x, y, z) (x ^ y ^ z) -#define K 0x6ED9EBA1 - - P(A, B, C, D, E, R(20)); - P(E, A, B, C, D, R(21)); - P(D, E, A, B, C, R(22)); - P(C, D, E, A, B, R(23)); - P(B, C, D, E, A, R(24)); - P(A, B, C, D, E, R(25)); - P(E, A, B, C, D, R(26)); - P(D, E, A, B, C, R(27)); - P(C, D, E, A, B, R(28)); - P(B, C, D, E, A, R(29)); - P(A, B, C, D, E, R(30)); - P(E, A, B, C, D, R(31)); - P(D, E, A, B, C, R(32)); - P(C, D, E, A, B, R(33)); - P(B, C, D, E, A, R(34)); - P(A, B, C, D, E, R(35)); - P(E, A, B, C, D, R(36)); - P(D, E, A, B, C, R(37)); - P(C, D, E, A, B, R(38)); - P(B, C, D, E, A, R(39)); - -#undef K -#undef F - -#define F(x, y, z) ((x & y) | (z & (x | y))) -#define K 0x8F1BBCDC - - P(A, B, C, D, E, R(40)); - P(E, A, B, C, D, R(41)); - P(D, E, A, B, C, R(42)); - P(C, D, E, A, B, R(43)); - P(B, C, D, E, A, R(44)); - P(A, B, C, D, E, R(45)); - P(E, A, B, C, D, R(46)); - P(D, E, A, B, C, R(47)); - P(C, D, E, A, B, R(48)); - P(B, C, D, E, A, R(49)); - P(A, B, C, D, E, R(50)); - P(E, A, B, C, D, R(51)); - P(D, E, A, B, C, R(52)); - P(C, D, E, A, B, R(53)); - P(B, C, D, E, A, R(54)); - P(A, B, C, D, E, R(55)); - P(E, A, B, C, D, R(56)); - P(D, E, A, B, C, R(57)); - P(C, D, E, A, B, R(58)); - P(B, C, D, E, A, R(59)); - -#undef K -#undef F - -#define F(x, y, z) (x ^ y ^ z) -#define K 0xCA62C1D6 - - P(A, B, C, D, E, R(60)); - P(E, A, B, C, D, R(61)); - P(D, E, A, B, C, R(62)); - P(C, D, E, A, B, R(63)); - P(B, C, D, E, A, R(64)); - P(A, B, C, D, E, R(65)); - P(E, A, B, C, D, R(66)); - P(D, E, A, B, C, R(67)); - P(C, D, E, A, B, R(68)); - P(B, C, D, E, A, R(69)); - P(A, B, C, D, E, R(70)); - P(E, A, B, C, D, R(71)); - P(D, E, A, B, C, R(72)); - P(C, D, E, A, B, R(73)); - P(B, C, D, E, A, R(74)); - P(A, B, C, D, E, R(75)); - P(E, A, B, C, D, R(76)); - P(D, E, A, B, C, R(77)); - P(C, D, E, A, B, R(78)); - P(B, C, D, E, A, R(79)); - -#undef K -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; -} - -/*****************************************************************************/ -void APP_CC -ssl_sha1_transform(void* sha1_info, char* data, int len) -{ - int left; - int fill; - struct sha1_context* ctx; - - ctx = (struct sha1_context*)sha1_info; - if (len == 0) - { - return; - } - left = ctx->total[0] & 0x3F; - fill = 64 - left; - ctx->total[0] += len; - ctx->total[0] &= 0xFFFFFFFF; - if (ctx->total[0] < len) - { - ctx->total[1]++; - } - if (left && (len >= fill)) - { - memcpy(ctx->buffer + left, data, fill); - sha1_process(ctx, ctx->buffer); - len -= fill; - data += fill; - left = 0; - } - while (len >= 64) - { - sha1_process(ctx, data); - len -= 64; - data += 64; - } - if (len != 0) - { - memcpy(ctx->buffer + left, data, len); - } -} - -static unsigned char sha1_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/*****************************************************************************/ -void APP_CC -ssl_sha1_complete(void* sha1_info, char* data) -{ - int last; - int padn; - int high; - int low; - char msglen[8]; - struct sha1_context* ctx; - - ctx = (struct sha1_context*)sha1_info; - high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); - low = (ctx->total[0] << 3); - PUT_UINT32(high, msglen, 0); - PUT_UINT32(low, msglen, 4); - last = ctx->total[0] & 0x3F; - padn = (last < 56) ? (56 - last) : (120 - last); - ssl_sha1_transform(ctx, sha1_padding, padn); - ssl_sha1_transform(ctx, msglen, 8); - PUT_UINT32(ctx->state[0], data, 0); - PUT_UINT32(ctx->state[1], data, 4); - PUT_UINT32(ctx->state[2], data, 8); - PUT_UINT32(ctx->state[3], data, 12); - PUT_UINT32(ctx->state[4], data, 16); -} - -/*****************************************************************************/ -/*****************************************************************************/ -/* md5 stuff */ -/* RFC 1321 compliant MD5 implementation - * - * Copyright (C) 2001-2003 Christophe Devine - */ - -struct md5_context -{ - int total[2]; - int state[4]; - char buffer[64]; -}; - -/*****************************************************************************/ -void* APP_CC -ssl_md5_info_create(void) -{ - return g_malloc(sizeof(struct md5_context), 1); -} - -/*****************************************************************************/ -void APP_CC -ssl_md5_info_delete(void* md5_info) -{ - g_free(md5_info); -} - -/*****************************************************************************/ -void APP_CC -ssl_md5_clear(void* md5_info) -{ - struct md5_context* ctx; - - ctx = (struct md5_context*)md5_info; - memset(ctx, 0, sizeof(struct md5_context)); - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -#undef GET_UINT32 -#define GET_UINT32(n, b, i) \ -{ \ - (n) = ((b)[(i) + 0] << 0) | \ - ((b)[(i) + 1] << 8) | \ - ((b)[(i) + 2] << 16) | \ - ((b)[(i) + 3] << 24); \ -} - -#undef PUT_UINT32 -#define PUT_UINT32(n, b, i) \ -{ \ - (b)[(i) + 0] = ((n) >> 0); \ - (b)[(i) + 1] = ((n) >> 8); \ - (b)[(i) + 2] = ((n) >> 16); \ - (b)[(i) + 3] = ((n) >> 24); \ -} - -/*****************************************************************************/ -static void -md5_process(struct md5_context* ctx, char* in_data) -{ - int X[16]; - int A; - int B; - int C; - int D; - unsigned char* data; - - data = (unsigned char*)in_data; - GET_UINT32(X[0], data, 0); - GET_UINT32(X[1], data, 4); - GET_UINT32(X[2], data, 8); - GET_UINT32(X[3], data, 12); - GET_UINT32(X[4], data, 16); - GET_UINT32(X[5], data, 20); - GET_UINT32(X[6], data, 24); - GET_UINT32(X[7], data, 28); - GET_UINT32(X[8], data, 32); - GET_UINT32(X[9], data, 36); - GET_UINT32(X[10], data, 40); - GET_UINT32(X[11], data, 44); - GET_UINT32(X[12], data, 48); - GET_UINT32(X[13], data, 52); - GET_UINT32(X[14], data, 56); - GET_UINT32(X[15], data, 60); - -#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#undef P -#define P(a, b, c, d, k, s, t) \ -{ \ - a += F(b, c, d) + X[k] + t; \ - a = S(a, s) + b; \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x, y, z) (z ^ (x & (y ^ z))) - - P(A, B, C, D, 0, 7, 0xD76AA478); - P(D, A, B, C, 1, 12, 0xE8C7B756); - P(C, D, A, B, 2, 17, 0x242070DB); - P(B, C, D, A, 3, 22, 0xC1BDCEEE); - P(A, B, C, D, 4, 7, 0xF57C0FAF); - P(D, A, B, C, 5, 12, 0x4787C62A); - P(C, D, A, B, 6, 17, 0xA8304613); - P(B, C, D, A, 7, 22, 0xFD469501); - P(A, B, C, D, 8, 7, 0x698098D8); - P(D, A, B, C, 9, 12, 0x8B44F7AF); - P(C, D, A, B, 10, 17, 0xFFFF5BB1); - P(B, C, D, A, 11, 22, 0x895CD7BE); - P(A, B, C, D, 12, 7, 0x6B901122); - P(D, A, B, C, 13, 12, 0xFD987193); - P(C, D, A, B, 14, 17, 0xA679438E); - P(B, C, D, A, 15, 22, 0x49B40821); - -#undef F - -#define F(x, y, z) (y ^ (z & (x ^ y))) - - P(A, B, C, D, 1, 5, 0xF61E2562); - P(D, A, B, C, 6, 9, 0xC040B340); - P(C, D, A, B, 11, 14, 0x265E5A51); - P(B, C, D, A, 0, 20, 0xE9B6C7AA); - P(A, B, C, D, 5, 5, 0xD62F105D); - P(D, A, B, C, 10, 9, 0x02441453); - P(C, D, A, B, 15, 14, 0xD8A1E681); - P(B, C, D, A, 4, 20, 0xE7D3FBC8); - P(A, B, C, D, 9, 5, 0x21E1CDE6); - P(D, A, B, C, 14, 9, 0xC33707D6); - P(C, D, A, B, 3, 14, 0xF4D50D87); - P(B, C, D, A, 8, 20, 0x455A14ED); - P(A, B, C, D, 13, 5, 0xA9E3E905); - P(D, A, B, C, 2, 9, 0xFCEFA3F8); - P(C, D, A, B, 7, 14, 0x676F02D9); - P(B, C, D, A, 12, 20, 0x8D2A4C8A); - -#undef F - -#define F(x, y, z) (x ^ y ^ z) - - P(A, B, C, D, 5, 4, 0xFFFA3942); - P(D, A, B, C, 8, 11, 0x8771F681); - P(C, D, A, B, 11, 16, 0x6D9D6122); - P(B, C, D, A, 14, 23, 0xFDE5380C); - P(A, B, C, D, 1, 4, 0xA4BEEA44); - P(D, A, B, C, 4, 11, 0x4BDECFA9); - P(C, D, A, B, 7, 16, 0xF6BB4B60); - P(B, C, D, A, 10, 23, 0xBEBFBC70); - P(A, B, C, D, 13, 4, 0x289B7EC6); - P(D, A, B, C, 0, 11, 0xEAA127FA); - P(C, D, A, B, 3, 16, 0xD4EF3085); - P(B, C, D, A, 6, 23, 0x04881D05); - P(A, B, C, D, 9, 4, 0xD9D4D039); - P(D, A, B, C, 12, 11, 0xE6DB99E5); - P(C, D, A, B, 15, 16, 0x1FA27CF8); - P(B, C, D, A, 2, 23, 0xC4AC5665); - -#undef F - -#define F(x, y, z) (y ^ (x | ~z)) - - P(A, B, C, D, 0, 6, 0xF4292244); - P(D, A, B, C, 7, 10, 0x432AFF97); - P(C, D, A, B, 14, 15, 0xAB9423A7); - P(B, C, D, A, 5, 21, 0xFC93A039); - P(A, B, C, D, 12, 6, 0x655B59C3); - P(D, A, B, C, 3, 10, 0x8F0CCC92); - P(C, D, A, B, 10, 15, 0xFFEFF47D); - P(B, C, D, A, 1, 21, 0x85845DD1); - P(A, B, C, D, 8, 6, 0x6FA87E4F); - P(D, A, B, C, 15, 10, 0xFE2CE6E0); - P(C, D, A, B, 6, 15, 0xA3014314); - P(B, C, D, A, 13, 21, 0x4E0811A1); - P(A, B, C, D, 4, 6, 0xF7537E82); - P(D, A, B, C, 11, 10, 0xBD3AF235); - P(C, D, A, B, 2, 15, 0x2AD7D2BB); - P(B, C, D, A, 9, 21, 0xEB86D391); - -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} - -/*****************************************************************************/ -void APP_CC -ssl_md5_transform(void* md5_info, char* data, int len) -{ - int left; - int fill; - struct md5_context* ctx; - - ctx = (struct md5_context*)md5_info; - if (len == 0) - { - return; - } - left = ctx->total[0] & 0x3F; - fill = 64 - left; - ctx->total[0] += len; - ctx->total[0] &= 0xFFFFFFFF; - if (ctx->total[0] < len) - { - ctx->total[1]++; - } - if (left && (len >= fill)) - { - memcpy(ctx->buffer + left, data, fill); - md5_process(ctx, ctx->buffer); - len -= fill; - data += fill; - left = 0; - } - while (len >= 64) - { - md5_process(ctx, data); - len -= 64; - data += 64; - } - if (len != 0) - { - memcpy(ctx->buffer + left, data, len); - } -} - -static unsigned char md5_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/*****************************************************************************/ -void APP_CC -ssl_md5_complete(void* md5_info, char* data) -{ - int last; - int padn; - int high; - int low; - char msglen[8]; - struct md5_context* ctx; - - ctx = (struct md5_context*)md5_info; - high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); - low = (ctx->total[0] << 3); - PUT_UINT32(low, msglen, 0); - PUT_UINT32(high, msglen, 4); - last = ctx->total[0] & 0x3F; - padn = (last < 56) ? (56 - last) : (120 - last); - ssl_md5_transform(ctx, md5_padding, padn); - ssl_md5_transform(ctx, msglen, 8); - PUT_UINT32(ctx->state[0], data, 0); - PUT_UINT32(ctx->state[1], data, 4); - PUT_UINT32(ctx->state[2], data, 8); - PUT_UINT32(ctx->state[3], data, 12); -} - -/*****************************************************************************/ -/*****************************************************************************/ -/* big number stuff */ -/******************* SHORT COPYRIGHT NOTICE************************* -This source code is part of the BigDigits multiple-precision -arithmetic library Version 1.0 originally written by David Ireland, -copyright (c) 2001 D.I. Management Services Pty Limited, all rights -reserved. It is provided "as is" with no warranties. You may use -this software under the terms of the full copyright notice -"bigdigitsCopyright.txt" that should have been included with -this library. To obtain a copy send an email to -<code@di-mgt.com.au> or visit <www.di-mgt.com.au/crypto.html>. -This notice must be retained in any copy. -****************** END OF COPYRIGHT NOTICE*************************/ -/************************* COPYRIGHT NOTICE************************* -This source code is part of the BigDigits multiple-precision -arithmetic library Version 1.0 originally written by David Ireland, -copyright (c) 2001 D.I. Management Services Pty Limited, all rights -reserved. You are permitted to use compiled versions of this code as -part of your own executable files and to distribute unlimited copies -of such executable files for any purposes including commercial ones -provided you keep the copyright notices intact in the source code -and that you ensure that the following characters remain in any -object or executable files you distribute: - -"Contains multiple-precision arithmetic code originally written -by David Ireland, copyright (c) 2001 by D.I. Management Services -Pty Limited <www.di-mgt.com.au>, and is used with permission." - -David Ireland and DI Management Services Pty Limited make no -representations concerning either the merchantability of this -software or the suitability of this software for any particular -purpose. It is provided "as is" without express or implied warranty -of any kind. - -Please forward any comments and bug reports to <code@di-mgt.com.au>. -The latest version of the source code can be downloaded from -www.di-mgt.com.au/crypto.html. -****************** END OF COPYRIGHT NOTICE*************************/ - -typedef unsigned int DIGIT_T; -#define HIBITMASK 0x80000000 -#define MAX_DIG_LEN 51 -#define MAX_DIGIT 0xffffffff -#define BITS_PER_DIGIT 32 -#define MAX_HALF_DIGIT 0xffff -#define B_J (MAX_HALF_DIGIT + 1) -#define LOHALF(x) ((DIGIT_T)((x) & 0xffff)) -#define HIHALF(x) ((DIGIT_T)((x) >> 16 & 0xffff)) -#define TOHIGH(x) ((DIGIT_T)((x) << 16)) - -#define mpNEXTBITMASK(mask, n) \ -{ \ - if (mask == 1) \ - { \ - mask = HIBITMASK; \ - n--; \ - } \ - else \ - { \ - mask >>= 1; \ - } \ -} - -/*****************************************************************************/ -static DIGIT_T APP_CC -mpAdd(DIGIT_T* w, DIGIT_T* u, DIGIT_T* v, unsigned int ndigits) -{ - /* Calculates w = u + v - where w, u, v are multiprecision integers of ndigits each - Returns carry if overflow. Carry = 0 or 1. - - Ref: Knuth Vol 2 Ch 4.3.1 p 266 Algorithm A. */ - DIGIT_T k; - unsigned int j; - - /* Step A1. Initialise */ - k = 0; - for (j = 0; j < ndigits; j++) - { - /* Step A2. Add digits w_j = (u_j + v_j + k) - Set k = 1 if carry (overflow) occurs */ - w[j] = u[j] + k; - if (w[j] < k) - { - k = 1; - } - else - { - k = 0; - } - w[j] += v[j]; - if (w[j] < v[j]) - { - k++; - } - } /* Step A3. Loop on j */ - return k; /* w_n = k */ -} - -/*****************************************************************************/ -static void APP_CC -mpSetDigit(DIGIT_T* a, DIGIT_T d, unsigned int ndigits) -{ /* Sets a = d where d is a single digit */ - unsigned int i; - - for (i = 1; i < ndigits; i++) - { - a[i] = 0; - } - a[0] = d; -} - -/*****************************************************************************/ -static int APP_CC -mpCompare(DIGIT_T* a, DIGIT_T* b, unsigned int ndigits) -{ - /* Returns sign of (a - b) */ - if (ndigits == 0) - { - return 0; - } - while (ndigits--) - { - if (a[ndigits] > b[ndigits]) - { - return 1; /* GT */ - } - if (a[ndigits] < b[ndigits]) - { - return -1; /* LT */ - } - } - return 0; /* EQ */ -} - -/*****************************************************************************/ -static void APP_CC -mpSetZero(DIGIT_T* a, unsigned int ndigits) -{ /* Sets a = 0 */ - unsigned int i; - - for (i = 0; i < ndigits; i++) - { - a[i] = 0; - } -} - -/*****************************************************************************/ -static void APP_CC -mpSetEqual(DIGIT_T* a, DIGIT_T* b, unsigned int ndigits) -{ /* Sets a = b */ - unsigned int i; - - for (i = 0; i < ndigits; i++) - { - a[i] = b[i]; - } -} - -/*****************************************************************************/ -static unsigned int APP_CC -mpSizeof(DIGIT_T* a, unsigned int ndigits) -{ /* Returns size of significant digits in a */ - while (ndigits--) - { - if (a[ndigits] != 0) - { - return (++ndigits); - } - } - return 0; -} - -/*****************************************************************************/ -static DIGIT_T APP_CC -mpShiftLeft(DIGIT_T* a, DIGIT_T* b, unsigned int x, unsigned int ndigits) -{ /* Computes a = b << x */ - unsigned int i; - unsigned int y; - DIGIT_T mask; - DIGIT_T carry; - DIGIT_T nextcarry; - - /* Check input - NB unspecified result */ - if (x >= BITS_PER_DIGIT) - { - return 0; - } - /* Construct mask */ - mask = HIBITMASK; - for (i = 1; i < x; i++) - { - mask = (mask >> 1) | mask; - } - if (x == 0) - { - mask = 0x0; - } - y = BITS_PER_DIGIT - x; - carry = 0; - for (i = 0; i < ndigits; i++) - { - nextcarry = (b[i] & mask) >> y; - a[i] = b[i] << x | carry; - carry = nextcarry; - } - return carry; -} - -/*****************************************************************************/ -static DIGIT_T APP_CC -mpShiftRight(DIGIT_T* a, DIGIT_T* b, unsigned int x, unsigned int ndigits) -{ /* Computes a = b >> x */ - unsigned int i; - unsigned int y; - DIGIT_T mask; - DIGIT_T carry; - DIGIT_T nextcarry; - - /* Check input - NB unspecified result */ - if (x >= BITS_PER_DIGIT) - { - return 0; - } - /* Construct mask */ - mask = 0x1; - for (i = 1; i < x; i++) - { - mask = (mask << 1) | mask; - } - if (x == 0) - { - mask = 0x0; - } - y = BITS_PER_DIGIT - x; - carry = 0; - i = ndigits; - while (i--) - { - nextcarry = (b[i] & mask) << y; - a[i] = b[i] >> x | carry; - carry = nextcarry; - } - return carry; -} - -/*****************************************************************************/ -static void APP_CC -spMultSub(DIGIT_T* uu, DIGIT_T qhat, DIGIT_T v1, DIGIT_T v0) -{ - /* Compute uu = uu - q(v1v0) - where uu = u3u2u1u0, u3 = 0 - and u_n, v_n are all half-digits - even though v1, v2 are passed as full digits. */ - DIGIT_T p0; - DIGIT_T p1; - DIGIT_T t; - - p0 = qhat * v0; - p1 = qhat * v1; - t = p0 + TOHIGH(LOHALF(p1)); - uu[0] -= t; - if (uu[0] > MAX_DIGIT - t) - { - uu[1]--; /* Borrow */ - } - uu[1] -= HIHALF(p1); -} - -/*****************************************************************************/ -static int APP_CC -spMultiply(DIGIT_T* p, DIGIT_T x, DIGIT_T y) -{ /* Computes p = x * y */ - /* Ref: Arbitrary Precision Computation - http://numbers.computation.free.fr/Constants/constants.html - - high p1 p0 low - +--------+--------+--------+--------+ - | x1*y1 | x0*y0 | - +--------+--------+--------+--------+ - +-+--------+--------+ - |1| (x0*y1 + x1*y1) | - +-+--------+--------+ - ^carry from adding (x0*y1+x1*y1) together - +-+ - |1|< carry from adding LOHALF t - +-+ to high half of p0 */ - DIGIT_T x0; - DIGIT_T y0; - DIGIT_T x1; - DIGIT_T y1; - DIGIT_T t; - DIGIT_T u; - DIGIT_T carry; - - /* Split each x,y into two halves - x = x0 + B * x1 - y = y0 + B * y1 - where B = 2^16, half the digit size - Product is - xy = x0y0 + B(x0y1 + x1y0) + B^2(x1y1) */ - - x0 = LOHALF(x); - x1 = HIHALF(x); - y0 = LOHALF(y); - y1 = HIHALF(y); - - /* Calc low part - no carry */ - p[0] = x0 * y0; - - /* Calc middle part */ - t = x0 * y1; - u = x1 * y0; - t += u; - if (t < u) - { - carry = 1; - } - else - { - carry = 0; - } - /* This carry will go to high half of p[1] - + high half of t into low half of p[1] */ - carry = TOHIGH(carry) + HIHALF(t); - - /* Add low half of t to high half of p[0] */ - t = TOHIGH(t); - p[0] += t; - if (p[0] < t) - { - carry++; - } - - p[1] = x1 * y1; - p[1] += carry; - - return 0; -} - -/*****************************************************************************/ -static DIGIT_T APP_CC -spDivide(DIGIT_T* q, DIGIT_T* r, DIGIT_T* u, DIGIT_T v) -{ /* Computes quotient q = u / v, remainder r = u mod v - where u is a double digit - and q, v, r are single precision digits. - Returns high digit of quotient (max value is 1) - Assumes normalised such that v1 >= b/2 - where b is size of HALF_DIGIT - i.e. the most significant bit of v should be one - - In terms of half-digits in Knuth notation: - (q2q1q0) = (u4u3u2u1u0) / (v1v0) - (r1r0) = (u4u3u2u1u0) mod (v1v0) - for m = 2, n = 2 where u4 = 0 - q2 is either 0 or 1. - We set q = (q1q0) and return q2 as "overflow' */ - DIGIT_T qhat; - DIGIT_T rhat; - DIGIT_T t; - DIGIT_T v0; - DIGIT_T v1; - DIGIT_T u0; - DIGIT_T u1; - DIGIT_T u2; - DIGIT_T u3; - DIGIT_T uu[2]; - DIGIT_T q2; - - /* Check for normalisation */ - if (!(v & HIBITMASK)) - { - *q = *r = 0; - return MAX_DIGIT; - } - - /* Split up into half-digits */ - v0 = LOHALF(v); - v1 = HIHALF(v); - u0 = LOHALF(u[0]); - u1 = HIHALF(u[0]); - u2 = LOHALF(u[1]); - u3 = HIHALF(u[1]); - - /* Do three rounds of Knuth Algorithm D Vol 2 p272 */ - - /* ROUND 1. Set j = 2 and calculate q2 */ - /* Estimate qhat = (u4u3)/v1 = 0 or 1 - then set (u4u3u2) -= qhat(v1v0) - where u4 = 0. */ - qhat = u3 / v1; - if (qhat > 0) - { - rhat = u3 - qhat * v1; - t = TOHIGH(rhat) | u2; - if (qhat * v0 > t) - { - qhat--; - } - } - uu[1] = 0; /* (u4) */ - uu[0] = u[1]; /* (u3u2) */ - if (qhat > 0) - { - /* (u4u3u2) -= qhat(v1v0) where u4 = 0 */ - spMultSub(uu, qhat, v1, v0); - if (HIHALF(uu[1]) != 0) - { /* Add back */ - qhat--; - uu[0] += v; - uu[1] = 0; - } - } - q2 = qhat; - /* ROUND 2. Set j = 1 and calculate q1 */ - /* Estimate qhat = (u3u2) / v1 - then set (u3u2u1) -= qhat(v1v0) */ - t = uu[0]; - qhat = t / v1; - rhat = t - qhat * v1; - /* Test on v0 */ - t = TOHIGH(rhat) | u1; - if ((qhat == B_J) || (qhat * v0 > t)) - { - qhat--; - rhat += v1; - t = TOHIGH(rhat) | u1; - if ((rhat < B_J) && (qhat * v0 > t)) - { - qhat--; - } - } - /* Multiply and subtract - (u3u2u1)' = (u3u2u1) - qhat(v1v0) */ - uu[1] = HIHALF(uu[0]); /* (0u3) */ - uu[0] = TOHIGH(LOHALF(uu[0])) | u1; /* (u2u1) */ - spMultSub(uu, qhat, v1, v0); - if (HIHALF(uu[1]) != 0) - { /* Add back */ - qhat--; - uu[0] += v; - uu[1] = 0; - } - /* q1 = qhat */ - *q = TOHIGH(qhat); - /* ROUND 3. Set j = 0 and calculate q0 */ - /* Estimate qhat = (u2u1) / v1 - then set (u2u1u0) -= qhat(v1v0) */ - t = uu[0]; - qhat = t / v1; - rhat = t - qhat * v1; - /* Test on v0 */ - t = TOHIGH(rhat) | u0; - if ((qhat == B_J) || (qhat * v0 > t)) - { - qhat--; - rhat += v1; - t = TOHIGH(rhat) | u0; - if ((rhat < B_J) && (qhat * v0 > t)) - { - qhat--; - } - } - /* Multiply and subtract - (u2u1u0)" = (u2u1u0)' - qhat(v1v0) */ - uu[1] = HIHALF(uu[0]); /* (0u2) */ - uu[0] = TOHIGH(LOHALF(uu[0])) | u0; /* (u1u0) */ - spMultSub(uu, qhat, v1, v0); - if (HIHALF(uu[1]) != 0) - { /* Add back */ - qhat--; - uu[0] += v; - uu[1] = 0; - } - /* q0 = qhat */ - *q |= LOHALF(qhat); - /* Remainder is in (u1u0) i.e. uu[0] */ - *r = uu[0]; - return q2; -} - -/*****************************************************************************/ -static int APP_CC -QhatTooBig(DIGIT_T qhat, DIGIT_T rhat, DIGIT_T vn2, DIGIT_T ujn2) -{ /* Returns true if Qhat is too big - i.e. if (Qhat * Vn-2) > (b.Rhat + Uj+n-2) */ - DIGIT_T t[2]; - - spMultiply(t, qhat, vn2); - if (t[1] < rhat) - { - return 0; - } - else if (t[1] > rhat) - { - return 1; - } - else if (t[0] > ujn2) - { - return 1; - } - return 0; -} - -/*****************************************************************************/ -static DIGIT_T APP_CC -mpShortDiv(DIGIT_T* q, DIGIT_T* u, DIGIT_T v, unsigned int ndigits) -{ - /* Calculates quotient q = u div v - Returns remainder r = u mod v - where q, u are multiprecision integers of ndigits each - and d, v are single precision digits. - - Makes no assumptions about normalisation. - - Ref: Knuth Vol 2 Ch 4.3.1 Exercise 16 p625 */ - unsigned int j; - unsigned int shift; - DIGIT_T t[2]; - DIGIT_T r; - DIGIT_T bitmask; - DIGIT_T overflow; - DIGIT_T* uu; - - if (ndigits == 0) - { - return 0; - } - if (v == 0) - { - return 0; /* Divide by zero error */ - } - /* Normalise first */ - /* Requires high bit of V - to be set, so find most signif. bit then shift left, - i.e. d = 2^shift, u' = u * d, v' = v * d. */ - bitmask = HIBITMASK; - for (shift = 0; shift < BITS_PER_DIGIT; shift++) - { - if (v & bitmask) - { - break; - } - bitmask >>= 1; - } - v <<= shift; - overflow = mpShiftLeft(q, u, shift, ndigits); - uu = q; - /* Step S1 - modified for extra digit. */ - r = overflow; /* New digit Un */ - j = ndigits; - while (j--) - { - /* Step S2. */ - t[1] = r; - t[0] = uu[j]; - overflow = spDivide(&q[j], &r, t, v); - } - /* Unnormalise */ - r >>= shift; - return r; -} - -/*****************************************************************************/ -static DIGIT_T APP_CC -mpMultSub(DIGIT_T wn, DIGIT_T* w, DIGIT_T* v, DIGIT_T q, unsigned int n) -{ /* Compute w = w - qv - where w = (WnW[n-1]...W[0]) - return modified Wn. */ - DIGIT_T k; - DIGIT_T t[2]; - unsigned int i; - - if (q == 0) /* No change */ - { - return wn; - } - k = 0; - for (i = 0; i < n; i++) - { - spMultiply(t, q, v[i]); - w[i] -= k; - if (w[i] > MAX_DIGIT - k) - { - k = 1; - } - else - { - k = 0; - } - w[i] -= t[0]; - if (w[i] > MAX_DIGIT - t[0]) - { - k++; - } - k += t[1]; - } - /* Cope with Wn not stored in array w[0..n-1] */ - wn -= k; - return wn; -} - -/*****************************************************************************/ -static int APP_CC -mpDivide(DIGIT_T* q, DIGIT_T* r, DIGIT_T* u, unsigned int udigits, - DIGIT_T* v, unsigned int vdigits) -{ /* Computes quotient q = u / v and remainder r = u mod v - where q, r, u are multiple precision digits - all of udigits and the divisor v is vdigits. - - Ref: Knuth Vol 2 Ch 4.3.1 p 272 Algorithm D. - - Do without extra storage space, i.e. use r[] for - normalised u[], unnormalise v[] at end, and cope with - extra digit Uj+n added to u after normalisation. - - WARNING: this trashes q and r first, so cannot do - u = u / v or v = u mod v. */ - unsigned int shift; - int n; - int m; - int j; - int qhatOK; - int cmp; - DIGIT_T bitmask; - DIGIT_T overflow; - DIGIT_T qhat; - DIGIT_T rhat; - DIGIT_T t[2]; - DIGIT_T* uu; - DIGIT_T* ww; - - /* Clear q and r */ - mpSetZero(q, udigits); - mpSetZero(r, udigits); - /* Work out exact sizes of u and v */ - n = (int)mpSizeof(v, vdigits); - m = (int)mpSizeof(u, udigits); - m -= n; - /* Catch special cases */ - if (n == 0) - { - return -1; /* Error: divide by zero */ - } - if (n == 1) - { /* Use short division instead */ - r[0] = mpShortDiv(q, u, v[0], udigits); - return 0; - } - if (m < 0) - { /* v > u, so just set q = 0 and r = u */ - mpSetEqual(r, u, udigits); - return 0; - } - if (m == 0) - { /* u and v are the same length */ - cmp = mpCompare(u, v, (unsigned int)n); - if (cmp < 0) - { /* v > u, as above */ - mpSetEqual(r, u, udigits); - return 0; - } - else if (cmp == 0) - { /* v == u, so set q = 1 and r = 0 */ - mpSetDigit(q, 1, udigits); - return 0; - } - } - /* In Knuth notation, we have: - Given - u = (Um+n-1 ... U1U0) - v = (Vn-1 ... V1V0) - Compute - q = u/v = (QmQm-1 ... Q0) - r = u mod v = (Rn-1 ... R1R0) */ - /* Step D1. Normalise */ - /* Requires high bit of Vn-1 - to be set, so find most signif. bit then shift left, - i.e. d = 2^shift, u' = u * d, v' = v * d. */ - bitmask = HIBITMASK; - for (shift = 0; shift < BITS_PER_DIGIT; shift++) - { - if (v[n - 1] & bitmask) - { - break; - } - bitmask >>= 1; - } - /* Normalise v in situ - NB only shift non-zero digits */ - overflow = mpShiftLeft(v, v, shift, n); - /* Copy normalised dividend u*d into r */ - overflow = mpShiftLeft(r, u, shift, n + m); - uu = r; /* Use ptr to keep notation constant */ - t[0] = overflow; /* New digit Um+n */ - /* Step D2. Initialise j. Set j = m */ - for (j = m; j >= 0; j--) - { - /* Step D3. Calculate Qhat = (b.Uj+n + Uj+n-1)/Vn-1 */ - qhatOK = 0; - t[1] = t[0]; /* This is Uj+n */ - t[0] = uu[j+n-1]; - overflow = spDivide(&qhat, &rhat, t, v[n - 1]); - /* Test Qhat */ - if (overflow) - { /* Qhat = b */ - qhat = MAX_DIGIT; - rhat = uu[j + n - 1]; - rhat += v[n - 1]; - if (rhat < v[n - 1]) /* Overflow */ - { - qhatOK = 1; - } - } - if (!qhatOK && QhatTooBig(qhat, rhat, v[n - 2], uu[j + n - 2])) - { /* Qhat.Vn-2 > b.Rhat + Uj+n-2 */ - qhat--; - rhat += v[n - 1]; - if (!(rhat < v[n - 1])) - { - if (QhatTooBig(qhat, rhat, v[n - 2], uu[j + n - 2])) - { - qhat--; - } - } - } - /* Step D4. Multiply and subtract */ - ww = &uu[j]; - overflow = mpMultSub(t[1], ww, v, qhat, (unsigned int)n); - /* Step D5. Test remainder. Set Qj = Qhat */ - q[j] = qhat; - if (overflow) - { /* Step D6. Add back if D4 was negative */ - q[j]--; - overflow = mpAdd(ww, ww, v, (unsigned int)n); - } - t[0] = uu[j + n - 1]; /* Uj+n on next round */ - } /* Step D7. Loop on j */ - /* Clear high digits in uu */ - for (j = n; j < m+n; j++) - { - uu[j] = 0; - } - /* Step D8. Unnormalise. */ - mpShiftRight(r, r, shift, n); - mpShiftRight(v, v, shift, n); - return 0; -} - -/*****************************************************************************/ -static int APP_CC -mpModulo(DIGIT_T* r, DIGIT_T* u, unsigned int udigits, - DIGIT_T* v, unsigned int vdigits) -{ - /* Calculates r = u mod v - where r, v are multiprecision integers of length vdigits - and u is a multiprecision integer of length udigits. - r may overlap v. - - Note that r here is only vdigits long, - whereas in mpDivide it is udigits long. - - Use remainder from mpDivide function. */ - /* Double-length temp variable for divide fn */ - DIGIT_T qq[MAX_DIG_LEN * 2]; - /* Use a double-length temp for r to allow overlap of r and v */ - DIGIT_T rr[MAX_DIG_LEN * 2]; - - /* rr[2n] = u[2n] mod v[n] */ - mpDivide(qq, rr, u, udigits, v, vdigits); - mpSetEqual(r, rr, vdigits); - mpSetZero(rr, udigits); - mpSetZero(qq, udigits); - return 0; -} - -/*****************************************************************************/ -static int APP_CC -mpMultiply(DIGIT_T* w, DIGIT_T* u, DIGIT_T* v, unsigned int ndigits) -{ - /* Computes product w = u * v - where u, v are multiprecision integers of ndigits each - and w is a multiprecision integer of 2*ndigits - Ref: Knuth Vol 2 Ch 4.3.1 p 268 Algorithm M. */ - DIGIT_T k; - DIGIT_T t[2]; - unsigned int i; - unsigned int j; - unsigned int m; - unsigned int n; - - n = ndigits; - m = n; - /* Step M1. Initialise */ - for (i = 0; i < 2 * m; i++) - { - w[i] = 0; - } - for (j = 0; j < n; j++) - { - /* Step M2. Zero multiplier? */ - if (v[j] == 0) - { - w[j + m] = 0; - } - else - { - /* Step M3. Initialise i */ - k = 0; - for (i = 0; i < m; i++) - { - /* Step M4. Multiply and add */ - /* t = u_i * v_j + w_(i+j) + k */ - spMultiply(t, u[i], v[j]); - t[0] += k; - if (t[0] < k) - { - t[1]++; - } - t[0] += w[i + j]; - if (t[0] < w[i+j]) - { - t[1]++; - } - w[i + j] = t[0]; - k = t[1]; - } - /* Step M5. Loop on i, set w_(j+m) = k */ - w[j + m] = k; - } - } /* Step M6. Loop on j */ - return 0; -} - -/*****************************************************************************/ -static int APP_CC -mpModMult(DIGIT_T* a, DIGIT_T* x, DIGIT_T* y, - DIGIT_T* m, unsigned int ndigits) -{ /* Computes a = (x * y) mod m */ - /* Double-length temp variable */ - DIGIT_T p[MAX_DIG_LEN * 2]; - - /* Calc p[2n] = x * y */ - mpMultiply(p, x, y, ndigits); - /* Then modulo */ - mpModulo(a, p, ndigits * 2, m, ndigits); - mpSetZero(p, ndigits * 2); - return 0; -} - -/*****************************************************************************/ -int APP_CC -ssl_mod_exp(char* out, int out_len, char* in, int in_len, - char* mod, int mod_len, char* exp, int exp_len) -{ - /* Computes y = x ^ e mod m */ - /* Binary left-to-right method */ - DIGIT_T mask; - DIGIT_T* e; - DIGIT_T* x; - DIGIT_T* y; - DIGIT_T* m; - unsigned int n; - int max_size; - char* l_out; - char* l_in; - char* l_mod; - char* l_exp; - - if (in_len > out_len || in_len == 0 || - out_len == 0 || mod_len == 0 || exp_len == 0) - { - return 0; - } - max_size = out_len; - if (in_len > max_size) - { - max_size = in_len; - } - if (mod_len > max_size) - { - max_size = mod_len; - } - if (exp_len > max_size) - { - max_size = exp_len; - } - l_out = (char*)g_malloc(max_size, 1); - l_in = (char*)g_malloc(max_size, 1); - l_mod = (char*)g_malloc(max_size, 1); - l_exp = (char*)g_malloc(max_size, 1); - memcpy(l_in, in, in_len); - memcpy(l_mod, mod, mod_len); - memcpy(l_exp, exp, exp_len); - max_size = out_len; - e = (DIGIT_T*)l_exp; - x = (DIGIT_T*)l_in; - y = (DIGIT_T*)l_out; - m = (DIGIT_T*)l_mod; - /* Find second-most significant bit in e */ - n = mpSizeof(e, max_size / 4); - for (mask = HIBITMASK; mask > 0; mask >>= 1) - { - if (e[n - 1] & mask) - { - break; - } - } - mpNEXTBITMASK(mask, n); - /* Set y = x */ - mpSetEqual(y, x, max_size / 4); - /* For bit j = k - 2 downto 0 step -1 */ - while (n) - { - mpModMult(y, y, y, m, max_size / 4); /* Square */ - if (e[n - 1] & mask) - { - mpModMult(y, y, x, m, max_size / 4); /* Multiply */ - } - /* Move to next bit */ - mpNEXTBITMASK(mask, n); - } - memcpy(out, l_out, out_len); - g_free(l_out); - g_free(l_in); - g_free(l_mod); - g_free(l_exp); - return out_len; -} - |
