526 lines
22 KiB
C
526 lines
22 KiB
C
/**
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
* Base64 Encoding & Decoding
|
|
*
|
|
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <freerdp/config.h>
|
|
|
|
#include <winpr/crt.h>
|
|
|
|
#include <freerdp/crypto/crypto.h>
|
|
|
|
static const BYTE enc_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
static const BYTE enc_base64url[] =
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
|
|
static const signed char dec_base64url[] = {
|
|
-1, /* 0 000 00 00000000 NUL � Null character */
|
|
-1, /* 1 001 01 00000001 SOH  Start of Heading */
|
|
-1, /* 2 002 02 00000010 STX  Start of Text */
|
|
-1, /* 3 003 03 00000011 ETX  End of Text */
|
|
-1, /* 4 004 04 00000100 EOT  End of Transmission */
|
|
-1, /* 5 005 05 00000101 ENQ  Enquiry */
|
|
-1, /* 6 006 06 00000110 ACK  Acknowledge */
|
|
-1, /* 7 007 07 00000111 BEL  Bell, Alert */
|
|
-1, /* 8 010 08 00001000 BS  Backspace */
|
|
-1, /* 9 011 09 00001001 HT 	 Horizontal Tab */
|
|
-1, /* 10 012 0A 00001010 LF Line Feed */
|
|
-1, /* 11 013 0B 00001011 VT  Vertical Tabulation */
|
|
-1, /* 12 014 0C 00001100 FF  Form Feed */
|
|
-1, /* 13 015 0D 00001101 CR Carriage Return */
|
|
-1, /* 14 016 0E 00001110 SO  Shift Out */
|
|
-1, /* 15 017 0F 00001111 SI  Shift In */
|
|
-1, /* 16 020 10 00010000 DLE  Data Link Escape */
|
|
-1, /* 17 021 11 00010001 DC1  Device Control One (XON) */
|
|
-1, /* 18 022 12 00010010 DC2  Device Control Two */
|
|
-1, /* 19 023 13 00010011 DC3  Device Control Three (XOFF) */
|
|
-1, /* 20 024 14 00010100 DC4  Device Control Four */
|
|
-1, /* 21 025 15 00010101 NAK  Negative Acknowledge */
|
|
-1, /* 22 026 16 00010110 SYN  Synchronous Idle */
|
|
-1, /* 23 027 17 00010111 ETB  End of Transmission Block */
|
|
-1, /* 24 030 18 00011000 CAN  Cancel */
|
|
-1, /* 25 031 19 00011001 EM  End of medium */
|
|
-1, /* 26 032 1A 00011010 SUB  Substitute */
|
|
-1, /* 27 033 1B 00011011 ESC  Escape */
|
|
-1, /* 28 034 1C 00011100 FS  File Separator */
|
|
-1, /* 29 035 1D 00011101 GS  Group Separator */
|
|
-1, /* 30 036 1E 00011110 RS  Record Separator */
|
|
-1, /* 31 037 1F 00011111 US  Unit Separator */
|
|
-1, /* 32 040 20 00100000 SP   Space */
|
|
-1, /* 33 041 21 00100001 ! ! ! Exclamation mark */
|
|
-1, /* 34 042 22 00100010 " " " Double quotes (or speech marks) */
|
|
-1, /* 35 043 23 00100011 # # # Number sign */
|
|
-1, /* 36 044 24 00100100 $ $ $ Dollar */
|
|
-1, /* 37 045 25 00100101 % % % Per cent sign */
|
|
-1, /* 38 046 26 00100110 & & & Ampersand */
|
|
-1, /* 39 047 27 00100111 ' ' ' Single quote */
|
|
-1, /* 40 050 28 00101000 ( ( &lparen; Open parenthesis (or open
|
|
* bracket)
|
|
*/
|
|
-1, /* 41 051 29 00101001 ) ) &rparen; Close parenthesis (or close
|
|
* bracket)
|
|
*/
|
|
-1, /* 42 052 2A 00101010 * * * Asterisk */
|
|
-1, /* 43 053 2B 00101011 + + + Plus */
|
|
-1, /* 44 054 2C 00101100 , , , Comma */
|
|
62, /* 45 055 2D 00101101 - - Hyphen-minus */
|
|
-1, /* 46 056 2E 00101110 . . . Period, dot or full stop */
|
|
-1, /* 47 057 2F 00101111 / / / Slash or divide */
|
|
52, /* 48 060 30 00110000 0 0 Zero */
|
|
53, /* 49 061 31 00110001 1 1 One */
|
|
54, /* 50 062 32 00110010 2 2 Two */
|
|
55, /* 51 063 33 00110011 3 3 Three */
|
|
56, /* 52 064 34 00110100 4 4 Four */
|
|
57, /* 53 065 35 00110101 5 5 Five */
|
|
58, /* 54 066 36 00110110 6 6 Six */
|
|
59, /* 55 067 37 00110111 7 7 Seven */
|
|
60, /* 56 070 38 00111000 8 8 Eight */
|
|
61, /* 57 071 39 00111001 9 9 Nine */
|
|
-1, /* 58 072 3A 00111010 : : : Colon */
|
|
-1, /* 59 073 3B 00111011 ; ; ; Semicolon */
|
|
-1, /* 60 074 3C 00111100 < < < Less than (or open angled bracket)
|
|
*/
|
|
-1, /* 61 075 3D 00111101 = = = Equals */
|
|
-1, /* 62 076 3E 00111110 > > > Greater than (or close angled
|
|
* bracket)
|
|
*/
|
|
-1, /* 63 077 3F 00111111 ? ? ? Question mark */
|
|
-1, /* 64 100 40 01000000 @ @ @ At sign */
|
|
0, /* 65 101 41 01000001 A A Uppercase A */
|
|
1, /* 66 102 42 01000010 B B Uppercase B */
|
|
2, /* 67 103 43 01000011 C C Uppercase C */
|
|
3, /* 68 104 44 01000100 D D Uppercase D */
|
|
4, /* 69 105 45 01000101 E E Uppercase E */
|
|
5, /* 70 106 46 01000110 F F Uppercase F */
|
|
6, /* 71 107 47 01000111 G G Uppercase G */
|
|
7, /* 72 110 48 01001000 H H Uppercase H */
|
|
8, /* 73 111 49 01001001 I I Uppercase I */
|
|
9, /* 74 112 4A 01001010 J J Uppercase J */
|
|
10, /* 75 113 4B 01001011 K K Uppercase K */
|
|
11, /* 76 114 4C 01001100 L L Uppercase L */
|
|
12, /* 77 115 4D 01001101 M M Uppercase M */
|
|
13, /* 78 116 4E 01001110 N N Uppercase N */
|
|
14, /* 79 117 4F 01001111 O O Uppercase O */
|
|
15, /* 80 120 50 01010000 P P Uppercase P */
|
|
16, /* 81 121 51 01010001 Q Q Uppercase Q */
|
|
17, /* 82 122 52 01010010 R R Uppercase R */
|
|
18, /* 83 123 53 01010011 S S Uppercase S */
|
|
19, /* 84 124 54 01010100 T T Uppercase T */
|
|
20, /* 85 125 55 01010101 U U Uppercase U */
|
|
21, /* 86 126 56 01010110 V V Uppercase V */
|
|
22, /* 87 127 57 01010111 W W Uppercase W */
|
|
23, /* 88 130 58 01011000 X X Uppercase X */
|
|
24, /* 89 131 59 01011001 Y Y Uppercase Y */
|
|
25, /* 90 132 5A 01011010 Z Z Uppercase Z */
|
|
-1, /* 91 133 5B 01011011 [ [ [ Opening bracket */
|
|
-1, /* 92 134 5C 01011100 \ \ \ Backslash */
|
|
-1, /* 93 135 5D 01011101 ] ] ] Closing bracket */
|
|
-1, /* 94 136 5E 01011110 ^ ^ ^ Caret - circumflex */
|
|
63, /* 95 137 5F 01011111 _ _ _ Underscore */
|
|
-1, /* 96 140 60 01100000 ` ` ` Grave accent */
|
|
26, /* 97 141 61 01100001 a a Lowercase a */
|
|
27, /* 98 142 62 01100010 b b Lowercase b */
|
|
28, /* 99 143 63 01100011 c c Lowercase c */
|
|
29, /* 100 144 64 01100100 d d Lowercase d */
|
|
30, /* 101 145 65 01100101 e e Lowercase e */
|
|
31, /* 102 146 66 01100110 f f Lowercase f */
|
|
32, /* 103 147 67 01100111 g g Lowercase g */
|
|
33, /* 104 150 68 01101000 h h Lowercase h */
|
|
34, /* 105 151 69 01101001 i i Lowercase i */
|
|
35, /* 106 152 6A 01101010 j j Lowercase j */
|
|
36, /* 107 153 6B 01101011 k k Lowercase k */
|
|
37, /* 108 154 6C 01101100 l l Lowercase l */
|
|
38, /* 109 155 6D 01101101 m m Lowercase m */
|
|
39, /* 110 156 6E 01101110 n n Lowercase n */
|
|
40, /* 111 157 6F 01101111 o o Lowercase o */
|
|
41, /* 112 160 70 01110000 p p Lowercase p */
|
|
42, /* 113 161 71 01110001 q q Lowercase q */
|
|
43, /* 114 162 72 01110010 r r Lowercase r */
|
|
44, /* 115 163 73 01110011 s s Lowercase s */
|
|
45, /* 116 164 74 01110100 t t Lowercase t */
|
|
46, /* 117 165 75 01110101 u u Lowercase u */
|
|
47, /* 118 166 76 01110110 v v Lowercase v */
|
|
48, /* 119 167 77 01110111 w w Lowercase w */
|
|
49, /* 120 170 78 01111000 x x Lowercase x */
|
|
50, /* 121 171 79 01111001 y y Lowercase y */
|
|
51, /* 122 172 7A 01111010 z z Lowercase z */
|
|
-1, /* 123 173 7B 01111011 { { { Opening brace */
|
|
-1, /* 124 174 7C 01111100 | | | Vertical bar */
|
|
-1, /* 125 175 7D 01111101 } } } Closing brace */
|
|
-1, /* 126 176 7E 01111110 ~ ~ ˜ Equivalency sign - tilde */
|
|
-1, /* 127 177 7F 01111111 DEL  Delete */
|
|
};
|
|
static const signed char dec_base64[] = {
|
|
-1, /* 0 000 00 00000000 NUL � Null character */
|
|
-1, /* 1 001 01 00000001 SOH  Start of Heading */
|
|
-1, /* 2 002 02 00000010 STX  Start of Text */
|
|
-1, /* 3 003 03 00000011 ETX  End of Text */
|
|
-1, /* 4 004 04 00000100 EOT  End of Transmission */
|
|
-1, /* 5 005 05 00000101 ENQ  Enquiry */
|
|
-1, /* 6 006 06 00000110 ACK  Acknowledge */
|
|
-1, /* 7 007 07 00000111 BEL  Bell, Alert */
|
|
-1, /* 8 010 08 00001000 BS  Backspace */
|
|
-1, /* 9 011 09 00001001 HT 	 Horizontal Tab */
|
|
-1, /* 10 012 0A 00001010 LF Line Feed */
|
|
-1, /* 11 013 0B 00001011 VT  Vertical Tabulation */
|
|
-1, /* 12 014 0C 00001100 FF  Form Feed */
|
|
-1, /* 13 015 0D 00001101 CR Carriage Return */
|
|
-1, /* 14 016 0E 00001110 SO  Shift Out */
|
|
-1, /* 15 017 0F 00001111 SI  Shift In */
|
|
-1, /* 16 020 10 00010000 DLE  Data Link Escape */
|
|
-1, /* 17 021 11 00010001 DC1  Device Control One (XON) */
|
|
-1, /* 18 022 12 00010010 DC2  Device Control Two */
|
|
-1, /* 19 023 13 00010011 DC3  Device Control Three (XOFF) */
|
|
-1, /* 20 024 14 00010100 DC4  Device Control Four */
|
|
-1, /* 21 025 15 00010101 NAK  Negative Acknowledge */
|
|
-1, /* 22 026 16 00010110 SYN  Synchronous Idle */
|
|
-1, /* 23 027 17 00010111 ETB  End of Transmission Block */
|
|
-1, /* 24 030 18 00011000 CAN  Cancel */
|
|
-1, /* 25 031 19 00011001 EM  End of medium */
|
|
-1, /* 26 032 1A 00011010 SUB  Substitute */
|
|
-1, /* 27 033 1B 00011011 ESC  Escape */
|
|
-1, /* 28 034 1C 00011100 FS  File Separator */
|
|
-1, /* 29 035 1D 00011101 GS  Group Separator */
|
|
-1, /* 30 036 1E 00011110 RS  Record Separator */
|
|
-1, /* 31 037 1F 00011111 US  Unit Separator */
|
|
-1, /* 32 040 20 00100000 SP   Space */
|
|
-1, /* 33 041 21 00100001 ! ! ! Exclamation mark */
|
|
-1, /* 34 042 22 00100010 " " " Double quotes (or speech marks) */
|
|
-1, /* 35 043 23 00100011 # # # Number sign */
|
|
-1, /* 36 044 24 00100100 $ $ $ Dollar */
|
|
-1, /* 37 045 25 00100101 % % % Per cent sign */
|
|
-1, /* 38 046 26 00100110 & & & Ampersand */
|
|
-1, /* 39 047 27 00100111 ' ' ' Single quote */
|
|
-1, /* 40 050 28 00101000 ( ( &lparen; Open parenthesis (or open
|
|
* bracket)
|
|
*/
|
|
-1, /* 41 051 29 00101001 ) ) &rparen; Close parenthesis (or close
|
|
* bracket)
|
|
*/
|
|
-1, /* 42 052 2A 00101010 * * * Asterisk */
|
|
62, /* 43 053 2B 00101011 + + + Plus */
|
|
-1, /* 44 054 2C 00101100 , , , Comma */
|
|
-1, /* 45 055 2D 00101101 - - Hyphen-minus */
|
|
-1, /* 46 056 2E 00101110 . . . Period, dot or full stop */
|
|
63, /* 47 057 2F 00101111 / / / Slash or divide */
|
|
52, /* 48 060 30 00110000 0 0 Zero */
|
|
53, /* 49 061 31 00110001 1 1 One */
|
|
54, /* 50 062 32 00110010 2 2 Two */
|
|
55, /* 51 063 33 00110011 3 3 Three */
|
|
56, /* 52 064 34 00110100 4 4 Four */
|
|
57, /* 53 065 35 00110101 5 5 Five */
|
|
58, /* 54 066 36 00110110 6 6 Six */
|
|
59, /* 55 067 37 00110111 7 7 Seven */
|
|
60, /* 56 070 38 00111000 8 8 Eight */
|
|
61, /* 57 071 39 00111001 9 9 Nine */
|
|
-1, /* 58 072 3A 00111010 : : : Colon */
|
|
-1, /* 59 073 3B 00111011 ; ; ; Semicolon */
|
|
-1, /* 60 074 3C 00111100 < < < Less than (or open angled bracket)
|
|
*/
|
|
-1, /* 61 075 3D 00111101 = = = Equals */
|
|
-1, /* 62 076 3E 00111110 > > > Greater than (or close angled
|
|
* bracket)
|
|
*/
|
|
-1, /* 63 077 3F 00111111 ? ? ? Question mark */
|
|
-1, /* 64 100 40 01000000 @ @ @ At sign */
|
|
0, /* 65 101 41 01000001 A A Uppercase A */
|
|
1, /* 66 102 42 01000010 B B Uppercase B */
|
|
2, /* 67 103 43 01000011 C C Uppercase C */
|
|
3, /* 68 104 44 01000100 D D Uppercase D */
|
|
4, /* 69 105 45 01000101 E E Uppercase E */
|
|
5, /* 70 106 46 01000110 F F Uppercase F */
|
|
6, /* 71 107 47 01000111 G G Uppercase G */
|
|
7, /* 72 110 48 01001000 H H Uppercase H */
|
|
8, /* 73 111 49 01001001 I I Uppercase I */
|
|
9, /* 74 112 4A 01001010 J J Uppercase J */
|
|
10, /* 75 113 4B 01001011 K K Uppercase K */
|
|
11, /* 76 114 4C 01001100 L L Uppercase L */
|
|
12, /* 77 115 4D 01001101 M M Uppercase M */
|
|
13, /* 78 116 4E 01001110 N N Uppercase N */
|
|
14, /* 79 117 4F 01001111 O O Uppercase O */
|
|
15, /* 80 120 50 01010000 P P Uppercase P */
|
|
16, /* 81 121 51 01010001 Q Q Uppercase Q */
|
|
17, /* 82 122 52 01010010 R R Uppercase R */
|
|
18, /* 83 123 53 01010011 S S Uppercase S */
|
|
19, /* 84 124 54 01010100 T T Uppercase T */
|
|
20, /* 85 125 55 01010101 U U Uppercase U */
|
|
21, /* 86 126 56 01010110 V V Uppercase V */
|
|
22, /* 87 127 57 01010111 W W Uppercase W */
|
|
23, /* 88 130 58 01011000 X X Uppercase X */
|
|
24, /* 89 131 59 01011001 Y Y Uppercase Y */
|
|
25, /* 90 132 5A 01011010 Z Z Uppercase Z */
|
|
-1, /* 91 133 5B 01011011 [ [ [ Opening bracket */
|
|
-1, /* 92 134 5C 01011100 \ \ \ Backslash */
|
|
-1, /* 93 135 5D 01011101 ] ] ] Closing bracket */
|
|
-1, /* 94 136 5E 01011110 ^ ^ ^ Caret - circumflex */
|
|
-1, /* 95 137 5F 01011111 _ _ _ Underscore */
|
|
-1, /* 96 140 60 01100000 ` ` ` Grave accent */
|
|
26, /* 97 141 61 01100001 a a Lowercase a */
|
|
27, /* 98 142 62 01100010 b b Lowercase b */
|
|
28, /* 99 143 63 01100011 c c Lowercase c */
|
|
29, /* 100 144 64 01100100 d d Lowercase d */
|
|
30, /* 101 145 65 01100101 e e Lowercase e */
|
|
31, /* 102 146 66 01100110 f f Lowercase f */
|
|
32, /* 103 147 67 01100111 g g Lowercase g */
|
|
33, /* 104 150 68 01101000 h h Lowercase h */
|
|
34, /* 105 151 69 01101001 i i Lowercase i */
|
|
35, /* 106 152 6A 01101010 j j Lowercase j */
|
|
36, /* 107 153 6B 01101011 k k Lowercase k */
|
|
37, /* 108 154 6C 01101100 l l Lowercase l */
|
|
38, /* 109 155 6D 01101101 m m Lowercase m */
|
|
39, /* 110 156 6E 01101110 n n Lowercase n */
|
|
40, /* 111 157 6F 01101111 o o Lowercase o */
|
|
41, /* 112 160 70 01110000 p p Lowercase p */
|
|
42, /* 113 161 71 01110001 q q Lowercase q */
|
|
43, /* 114 162 72 01110010 r r Lowercase r */
|
|
44, /* 115 163 73 01110011 s s Lowercase s */
|
|
45, /* 116 164 74 01110100 t t Lowercase t */
|
|
46, /* 117 165 75 01110101 u u Lowercase u */
|
|
47, /* 118 166 76 01110110 v v Lowercase v */
|
|
48, /* 119 167 77 01110111 w w Lowercase w */
|
|
49, /* 120 170 78 01111000 x x Lowercase x */
|
|
50, /* 121 171 79 01111001 y y Lowercase y */
|
|
51, /* 122 172 7A 01111010 z z Lowercase z */
|
|
-1, /* 123 173 7B 01111011 { { { Opening brace */
|
|
-1, /* 124 174 7C 01111100 | | | Vertical bar */
|
|
-1, /* 125 175 7D 01111101 } } } Closing brace */
|
|
-1, /* 126 176 7E 01111110 ~ ~ ˜ Equivalency sign - tilde */
|
|
-1, /* 127 177 7F 01111111 DEL  Delete */
|
|
};
|
|
|
|
static INLINE char* base64_encode_ex(const BYTE* WINPR_RESTRICT alphabet,
|
|
const BYTE* WINPR_RESTRICT data, size_t length, BOOL pad,
|
|
BOOL crLf, size_t lineSize)
|
|
{
|
|
int c = 0;
|
|
const BYTE* q = NULL;
|
|
char* p = NULL;
|
|
char* ret = NULL;
|
|
int blocks = 0;
|
|
size_t outLen = (length + 3) * 4 / 3;
|
|
size_t extra = 0;
|
|
if (crLf)
|
|
{
|
|
size_t nCrLf = (outLen + lineSize - 1) / lineSize;
|
|
extra = nCrLf * 2;
|
|
}
|
|
size_t outCounter = 0;
|
|
|
|
q = data;
|
|
p = ret = (char*)malloc(outLen + extra + 1ull);
|
|
if (!p)
|
|
return NULL;
|
|
|
|
/* 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 (int i = 0; i < blocks; i += 3, q += 3)
|
|
{
|
|
c = (q[0] << 16) + (q[1] << 8) + q[2];
|
|
|
|
*p++ = alphabet[(c & 0x00FC0000) >> 18];
|
|
*p++ = alphabet[(c & 0x0003F000) >> 12];
|
|
*p++ = alphabet[(c & 0x00000FC0) >> 6];
|
|
*p++ = alphabet[c & 0x0000003F];
|
|
|
|
outCounter += 4;
|
|
if (crLf && (outCounter % lineSize == 0))
|
|
{
|
|
*p++ = '\r';
|
|
*p++ = '\n';
|
|
}
|
|
}
|
|
|
|
/* then remainder */
|
|
switch (length % 3)
|
|
{
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
c = (q[0] << 16);
|
|
*p++ = alphabet[(c & 0x00FC0000) >> 18];
|
|
*p++ = alphabet[(c & 0x0003F000) >> 12];
|
|
if (pad)
|
|
{
|
|
*p++ = '=';
|
|
*p++ = '=';
|
|
}
|
|
break;
|
|
case 2:
|
|
c = (q[0] << 16) + (q[1] << 8);
|
|
*p++ = alphabet[(c & 0x00FC0000) >> 18];
|
|
*p++ = alphabet[(c & 0x0003F000) >> 12];
|
|
*p++ = alphabet[(c & 0x00000FC0) >> 6];
|
|
if (pad)
|
|
*p++ = '=';
|
|
break;
|
|
}
|
|
|
|
if (crLf && length % 3)
|
|
{
|
|
*p++ = '\r';
|
|
*p++ = '\n';
|
|
}
|
|
*p = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static INLINE char* base64_encode(const BYTE* WINPR_RESTRICT alphabet,
|
|
const BYTE* WINPR_RESTRICT data, size_t length, BOOL pad)
|
|
{
|
|
return base64_encode_ex(alphabet, data, length, pad, FALSE, 64);
|
|
}
|
|
|
|
static INLINE int base64_decode_char(const signed char* WINPR_RESTRICT alphabet, char c)
|
|
{
|
|
if (c <= '\0')
|
|
return -1;
|
|
|
|
return alphabet[(size_t)c];
|
|
}
|
|
|
|
static INLINE void* base64_decode(const signed char* WINPR_RESTRICT alphabet,
|
|
const char* WINPR_RESTRICT s, size_t length,
|
|
size_t* WINPR_RESTRICT data_len, BOOL pad)
|
|
{
|
|
int n[4];
|
|
BYTE* q = NULL;
|
|
BYTE* data = NULL;
|
|
size_t nBlocks = 0;
|
|
size_t outputLen = 0;
|
|
int remainder = length % 4;
|
|
|
|
if ((pad && remainder > 0) || (remainder == 1))
|
|
return NULL;
|
|
|
|
if (!pad && remainder)
|
|
length += 4 - remainder;
|
|
|
|
q = data = (BYTE*)malloc(length / 4 * 3 + 1);
|
|
if (!q)
|
|
return NULL;
|
|
|
|
/* first treat complete blocks */
|
|
nBlocks = (length / 4);
|
|
outputLen = 0;
|
|
|
|
if (nBlocks < 1)
|
|
{
|
|
free(data);
|
|
return NULL;
|
|
}
|
|
|
|
for (size_t i = 0; i < nBlocks - 1; i++, q += 3)
|
|
{
|
|
n[0] = base64_decode_char(alphabet, *s++);
|
|
n[1] = base64_decode_char(alphabet, *s++);
|
|
n[2] = base64_decode_char(alphabet, *s++);
|
|
n[3] = base64_decode_char(alphabet, *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;
|
|
}
|
|
|
|
/* treat last block */
|
|
n[0] = base64_decode_char(alphabet, *s++);
|
|
n[1] = base64_decode_char(alphabet, *s++);
|
|
if ((n[0] == -1) || (n[1] == -1))
|
|
goto out_free;
|
|
|
|
n[2] = remainder == 2 ? -1 : base64_decode_char(alphabet, *s++);
|
|
n[3] = remainder >= 2 ? -1 : base64_decode_char(alphabet, *s++);
|
|
|
|
q[0] = (n[0] << 2) + (n[1] >> 4);
|
|
if (n[2] == -1)
|
|
{
|
|
/* XX== */
|
|
outputLen += 1;
|
|
if (n[3] != -1)
|
|
goto out_free;
|
|
|
|
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];
|
|
}
|
|
|
|
if (data_len)
|
|
*data_len = outputLen;
|
|
data[outputLen] = '\0';
|
|
|
|
return data;
|
|
out_free:
|
|
free(data);
|
|
return NULL;
|
|
}
|
|
|
|
char* crypto_base64_encode_ex(const BYTE* WINPR_RESTRICT data, size_t length, BOOL withCrLf)
|
|
{
|
|
return base64_encode_ex(enc_base64, data, length, TRUE, withCrLf, 64);
|
|
}
|
|
|
|
char* crypto_base64_encode(const BYTE* WINPR_RESTRICT data, size_t length)
|
|
{
|
|
return base64_encode(enc_base64, data, length, TRUE);
|
|
}
|
|
|
|
void crypto_base64_decode(const char* WINPR_RESTRICT enc_data, size_t length,
|
|
BYTE** WINPR_RESTRICT dec_data, size_t* WINPR_RESTRICT res_length)
|
|
{
|
|
*dec_data = base64_decode(dec_base64, enc_data, length, res_length, TRUE);
|
|
}
|
|
|
|
char* crypto_base64url_encode(const BYTE* WINPR_RESTRICT data, size_t length)
|
|
{
|
|
return base64_encode(enc_base64url, data, length, FALSE);
|
|
}
|
|
|
|
void crypto_base64url_decode(const char* WINPR_RESTRICT enc_data, size_t length,
|
|
BYTE** WINPR_RESTRICT dec_data, size_t* WINPR_RESTRICT res_length)
|
|
{
|
|
*dec_data = base64_decode(dec_base64url, enc_data, length, res_length, FALSE);
|
|
}
|