Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/libfreerdp/crypto/base64.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Base64 Encoding & Decoding
4
 *
5
 * Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *   http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
20
#include <freerdp/config.h>
21
22
#include <winpr/crt.h>
23
24
#include <freerdp/crypto/crypto.h>
25
26
static const BYTE enc_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
27
static const BYTE enc_base64url[] =
28
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
29
30
static const signed char dec_base64url[] = {
31
  -1, /* 0        000 00  00000000  NUL &#00;   Null character */
32
  -1, /* 1        001 01  00000001  SOH &#01;   Start of Heading */
33
  -1, /* 2        002 02  00000010  STX &#02;   Start of Text */
34
  -1, /* 3        003 03  00000011  ETX &#03;   End of Text */
35
  -1, /* 4        004 04  00000100  EOT &#04;   End of Transmission */
36
  -1, /* 5        005 05  00000101  ENQ &#05;   Enquiry */
37
  -1, /* 6        006 06  00000110  ACK &#06;   Acknowledge */
38
  -1, /* 7        007 07  00000111  BEL &#07;   Bell, Alert */
39
  -1, /* 8        010 08  00001000  BS  &#08;   Backspace */
40
  -1, /* 9        011 09  00001001  HT  &#09;   Horizontal Tab */
41
  -1, /* 10        012  0A  00001010  LF  &#10;   Line Feed */
42
  -1, /* 11        013  0B  00001011  VT  &#11;   Vertical Tabulation */
43
  -1, /* 12        014  0C  00001100  FF  &#12;   Form Feed */
44
  -1, /* 13        015  0D  00001101  CR  &#13;   Carriage Return */
45
  -1, /* 14        016  0E  00001110  SO  &#14;   Shift Out */
46
  -1, /* 15        017  0F  00001111  SI  &#15;   Shift In */
47
  -1, /* 16        020  10  00010000  DLE &#16;   Data Link Escape */
48
  -1, /* 17        021  11  00010001  DC1 &#17;   Device Control One (XON) */
49
  -1, /* 18        022  12  00010010  DC2 &#18;   Device Control Two */
50
  -1, /* 19        023  13  00010011  DC3 &#19;   Device Control Three (XOFF) */
51
  -1, /* 20        024  14  00010100  DC4 &#20;   Device Control Four */
52
  -1, /* 21        025  15  00010101  NAK &#21;   Negative Acknowledge */
53
  -1, /* 22        026  16  00010110  SYN &#22;   Synchronous Idle */
54
  -1, /* 23        027  17  00010111  ETB &#23;   End of Transmission Block */
55
  -1, /* 24        030  18  00011000  CAN &#24;   Cancel */
56
  -1, /* 25        031  19  00011001  EM  &#25;   End of medium */
57
  -1, /* 26        032  1A  00011010  SUB &#26;   Substitute */
58
  -1, /* 27        033  1B  00011011  ESC &#27;   Escape */
59
  -1, /* 28        034  1C  00011100  FS  &#28;   File Separator */
60
  -1, /* 29        035  1D  00011101  GS  &#29;   Group Separator */
61
  -1, /* 30        036  1E  00011110  RS  &#30;   Record Separator */
62
  -1, /* 31        037  1F  00011111  US  &#31;   Unit Separator */
63
  -1, /* 32        040  20  00100000  SP  &#32;   Space */
64
  -1, /* 33        041  21  00100001  ! &#33; &excl;  Exclamation mark */
65
  -1, /* 34        042  22  00100010  " &#34; &quot;  Double quotes (or speech marks) */
66
  -1, /* 35        043  23  00100011  # &#35; &num; Number sign */
67
  -1, /* 36        044  24  00100100  $ &#36; &dollar;  Dollar */
68
  -1, /* 37        045  25  00100101  % &#37; &percnt;  Per cent sign */
69
  -1, /* 38        046  26  00100110  & &#38; &amp; Ampersand */
70
  -1, /* 39        047  27  00100111  ' &#39; &apos;  Single quote */
71
  -1, /* 40        050  28  00101000  ( &#40; &lparen;  Open parenthesis (or open
72
       * bracket)
73
       */
74
  -1, /* 41        051  29  00101001  ) &#41; &rparen;  Close parenthesis (or close
75
       * bracket)
76
       */
77
  -1, /* 42        052  2A  00101010  * &#42; &ast; Asterisk */
78
  -1, /* 43        053  2B  00101011  + &#43; &plus;  Plus */
79
  -1, /* 44        054  2C  00101100  , &#44; &comma; Comma */
80
  62, /* 45        055  2D  00101101  - &#45;   Hyphen-minus */
81
  -1, /* 46        056  2E  00101110  . &#46; &period;  Period, dot or full stop */
82
  -1, /* 47        057  2F  00101111  / &#47; &sol; Slash or divide */
83
  52, /* 48        060  30  00110000  0 &#48;   Zero */
84
  53, /* 49        061  31  00110001  1 &#49;   One */
85
  54, /* 50        062  32  00110010  2 &#50;   Two */
86
  55, /* 51        063  33  00110011  3 &#51;   Three */
87
  56, /* 52        064  34  00110100  4 &#52;   Four */
88
  57, /* 53        065  35  00110101  5 &#53;   Five */
89
  58, /* 54        066  36  00110110  6 &#54;   Six */
90
  59, /* 55        067  37  00110111  7 &#55;   Seven */
91
  60, /* 56        070  38  00111000  8 &#56;   Eight */
92
  61, /* 57        071  39  00111001  9 &#57;   Nine */
93
  -1, /* 58        072  3A  00111010  : &#58; &colon; Colon */
94
  -1, /* 59        073  3B  00111011  ; &#59; &semi;  Semicolon */
95
  -1, /* 60        074  3C  00111100  < &#60; &lt;  Less than (or open angled bracket)
96
       */
97
  -1, /* 61        075  3D  00111101  = &#61; &equals;  Equals */
98
  -1, /* 62        076  3E  00111110  > &#62; &gt;  Greater than (or close angled
99
       * bracket)
100
       */
101
  -1, /* 63        077  3F  00111111  ? &#63; &quest; Question mark */
102
  -1, /* 64        100  40  01000000  @ &#64; &commat;  At sign */
103
  0,  /* 65        101  41  01000001  A &#65;   Uppercase A */
104
  1,  /* 66        102  42  01000010  B &#66;   Uppercase B */
105
  2,  /* 67        103  43  01000011  C &#67;   Uppercase C */
106
  3,  /* 68        104  44  01000100  D &#68;   Uppercase D */
107
  4,  /* 69        105  45  01000101  E &#69;   Uppercase E */
108
  5,  /* 70        106  46  01000110  F &#70;   Uppercase F */
109
  6,  /* 71        107  47  01000111  G &#71;   Uppercase G */
110
  7,  /* 72        110  48  01001000  H &#72;   Uppercase H */
111
  8,  /* 73        111  49  01001001  I &#73;   Uppercase I */
112
  9,  /* 74        112  4A  01001010  J &#74;   Uppercase J */
113
  10, /* 75        113  4B  01001011  K &#75;   Uppercase K */
114
  11, /* 76        114  4C  01001100  L &#76;   Uppercase L */
115
  12, /* 77        115  4D  01001101  M &#77;   Uppercase M */
116
  13, /* 78        116  4E  01001110  N &#78;   Uppercase N */
117
  14, /* 79        117  4F  01001111  O &#79;   Uppercase O */
118
  15, /* 80        120  50  01010000  P &#80;   Uppercase P */
119
  16, /* 81        121  51  01010001  Q &#81;   Uppercase Q */
120
  17, /* 82        122  52  01010010  R &#82;   Uppercase R */
121
  18, /* 83        123  53  01010011  S &#83;   Uppercase S */
122
  19, /* 84        124  54  01010100  T &#84;   Uppercase T */
123
  20, /* 85        125  55  01010101  U &#85;   Uppercase U */
124
  21, /* 86        126  56  01010110  V &#86;   Uppercase V */
125
  22, /* 87        127  57  01010111  W &#87;   Uppercase W */
126
  23, /* 88        130  58  01011000  X &#88;   Uppercase X */
127
  24, /* 89        131  59  01011001  Y &#89;   Uppercase Y */
128
  25, /* 90        132  5A  01011010  Z &#90;   Uppercase Z */
129
  -1, /* 91        133  5B  01011011  [ &#91; &lsqb;  Opening bracket */
130
  -1, /* 92        134  5C  01011100  \ &#92; &bsol;  Backslash */
131
  -1, /* 93        135  5D  01011101  ] &#93; &rsqb;  Closing bracket */
132
  -1, /* 94        136  5E  01011110  ^ &#94; &Hat; Caret - circumflex */
133
  63, /* 95        137  5F  01011111  _ &#95; &lowbar;  Underscore */
134
  -1, /* 96        140  60  01100000  ` &#96; &grave; Grave accent */
135
  26, /* 97        141  61  01100001  a &#97;   Lowercase a */
136
  27, /* 98        142  62  01100010  b &#98;   Lowercase b */
137
  28, /* 99        143  63  01100011  c &#99;   Lowercase c */
138
  29, /* 100        144 64  01100100  d &#100;    Lowercase d */
139
  30, /* 101        145 65  01100101  e &#101;    Lowercase e */
140
  31, /* 102        146 66  01100110  f &#102;    Lowercase f */
141
  32, /* 103        147 67  01100111  g &#103;    Lowercase g */
142
  33, /* 104        150 68  01101000  h &#104;    Lowercase h */
143
  34, /* 105        151 69  01101001  i &#105;    Lowercase i */
144
  35, /* 106        152 6A  01101010  j &#106;    Lowercase j */
145
  36, /* 107        153 6B  01101011  k &#107;    Lowercase k */
146
  37, /* 108        154 6C  01101100  l &#108;    Lowercase l */
147
  38, /* 109        155 6D  01101101  m &#109;    Lowercase m */
148
  39, /* 110        156 6E  01101110  n &#110;    Lowercase n */
149
  40, /* 111        157 6F  01101111  o &#111;    Lowercase o */
150
  41, /* 112        160 70  01110000  p &#112;    Lowercase p */
151
  42, /* 113        161 71  01110001  q &#113;    Lowercase q */
152
  43, /* 114        162 72  01110010  r &#114;    Lowercase r */
153
  44, /* 115        163 73  01110011  s &#115;    Lowercase s */
154
  45, /* 116        164 74  01110100  t &#116;    Lowercase t */
155
  46, /* 117        165 75  01110101  u &#117;    Lowercase u */
156
  47, /* 118        166 76  01110110  v &#118;    Lowercase v */
157
  48, /* 119        167 77  01110111  w &#119;    Lowercase w */
158
  49, /* 120        170 78  01111000  x &#120;    Lowercase x */
159
  50, /* 121        171 79  01111001  y &#121;    Lowercase y */
160
  51, /* 122        172 7A  01111010  z &#122;    Lowercase z */
161
  -1, /* 123        173 7B  01111011  { &#123;  &lcub;  Opening brace */
162
  -1, /* 124        174 7C  01111100  | &#124;  &verbar;  Vertical bar */
163
  -1, /* 125        175 7D  01111101  } &#125;  &rcub;  Closing brace */
164
  -1, /* 126        176 7E  01111110  ~ &#126;  &tilde; Equivalency sign - tilde */
165
  -1, /* 127        177 7F  01111111  DEL &#127;    Delete */
166
};
167
static const signed char dec_base64[] = {
168
  -1, /* 0        000 00  00000000  NUL &#00;   Null character */
169
  -1, /* 1        001 01  00000001  SOH &#01;   Start of Heading */
170
  -1, /* 2        002 02  00000010  STX &#02;   Start of Text */
171
  -1, /* 3        003 03  00000011  ETX &#03;   End of Text */
172
  -1, /* 4        004 04  00000100  EOT &#04;   End of Transmission */
173
  -1, /* 5        005 05  00000101  ENQ &#05;   Enquiry */
174
  -1, /* 6        006 06  00000110  ACK &#06;   Acknowledge */
175
  -1, /* 7        007 07  00000111  BEL &#07;   Bell, Alert */
176
  -1, /* 8        010 08  00001000  BS  &#08;   Backspace */
177
  -1, /* 9        011 09  00001001  HT  &#09;   Horizontal Tab */
178
  -1, /* 10        012  0A  00001010  LF  &#10;   Line Feed */
179
  -1, /* 11        013  0B  00001011  VT  &#11;   Vertical Tabulation */
180
  -1, /* 12        014  0C  00001100  FF  &#12;   Form Feed */
181
  -1, /* 13        015  0D  00001101  CR  &#13;   Carriage Return */
182
  -1, /* 14        016  0E  00001110  SO  &#14;   Shift Out */
183
  -1, /* 15        017  0F  00001111  SI  &#15;   Shift In */
184
  -1, /* 16        020  10  00010000  DLE &#16;   Data Link Escape */
185
  -1, /* 17        021  11  00010001  DC1 &#17;   Device Control One (XON) */
186
  -1, /* 18        022  12  00010010  DC2 &#18;   Device Control Two */
187
  -1, /* 19        023  13  00010011  DC3 &#19;   Device Control Three (XOFF) */
188
  -1, /* 20        024  14  00010100  DC4 &#20;   Device Control Four */
189
  -1, /* 21        025  15  00010101  NAK &#21;   Negative Acknowledge */
190
  -1, /* 22        026  16  00010110  SYN &#22;   Synchronous Idle */
191
  -1, /* 23        027  17  00010111  ETB &#23;   End of Transmission Block */
192
  -1, /* 24        030  18  00011000  CAN &#24;   Cancel */
193
  -1, /* 25        031  19  00011001  EM  &#25;   End of medium */
194
  -1, /* 26        032  1A  00011010  SUB &#26;   Substitute */
195
  -1, /* 27        033  1B  00011011  ESC &#27;   Escape */
196
  -1, /* 28        034  1C  00011100  FS  &#28;   File Separator */
197
  -1, /* 29        035  1D  00011101  GS  &#29;   Group Separator */
198
  -1, /* 30        036  1E  00011110  RS  &#30;   Record Separator */
199
  -1, /* 31        037  1F  00011111  US  &#31;   Unit Separator */
200
  -1, /* 32        040  20  00100000  SP  &#32;   Space */
201
  -1, /* 33        041  21  00100001  ! &#33; &excl;  Exclamation mark */
202
  -1, /* 34        042  22  00100010  " &#34; &quot;  Double quotes (or speech marks) */
203
  -1, /* 35        043  23  00100011  # &#35; &num; Number sign */
204
  -1, /* 36        044  24  00100100  $ &#36; &dollar;  Dollar */
205
  -1, /* 37        045  25  00100101  % &#37; &percnt;  Per cent sign */
206
  -1, /* 38        046  26  00100110  & &#38; &amp; Ampersand */
207
  -1, /* 39        047  27  00100111  ' &#39; &apos;  Single quote */
208
  -1, /* 40        050  28  00101000  ( &#40; &lparen;  Open parenthesis (or open
209
       * bracket)
210
       */
211
  -1, /* 41        051  29  00101001  ) &#41; &rparen;  Close parenthesis (or close
212
       * bracket)
213
       */
214
  -1, /* 42        052  2A  00101010  * &#42; &ast; Asterisk */
215
  62, /* 43        053  2B  00101011  + &#43; &plus;  Plus */
216
  -1, /* 44        054  2C  00101100  , &#44; &comma; Comma */
217
  -1, /* 45        055  2D  00101101  - &#45;   Hyphen-minus */
218
  -1, /* 46        056  2E  00101110  . &#46; &period;  Period, dot or full stop */
219
  63, /* 47        057  2F  00101111  / &#47; &sol; Slash or divide */
220
  52, /* 48        060  30  00110000  0 &#48;   Zero */
221
  53, /* 49        061  31  00110001  1 &#49;   One */
222
  54, /* 50        062  32  00110010  2 &#50;   Two */
223
  55, /* 51        063  33  00110011  3 &#51;   Three */
224
  56, /* 52        064  34  00110100  4 &#52;   Four */
225
  57, /* 53        065  35  00110101  5 &#53;   Five */
226
  58, /* 54        066  36  00110110  6 &#54;   Six */
227
  59, /* 55        067  37  00110111  7 &#55;   Seven */
228
  60, /* 56        070  38  00111000  8 &#56;   Eight */
229
  61, /* 57        071  39  00111001  9 &#57;   Nine */
230
  -1, /* 58        072  3A  00111010  : &#58; &colon; Colon */
231
  -1, /* 59        073  3B  00111011  ; &#59; &semi;  Semicolon */
232
  -1, /* 60        074  3C  00111100  < &#60; &lt;  Less than (or open angled bracket)
233
       */
234
  -1, /* 61        075  3D  00111101  = &#61; &equals;  Equals */
235
  -1, /* 62        076  3E  00111110  > &#62; &gt;  Greater than (or close angled
236
       * bracket)
237
       */
238
  -1, /* 63        077  3F  00111111  ? &#63; &quest; Question mark */
239
  -1, /* 64        100  40  01000000  @ &#64; &commat;  At sign */
240
  0,  /* 65        101  41  01000001  A &#65;   Uppercase A */
241
  1,  /* 66        102  42  01000010  B &#66;   Uppercase B */
242
  2,  /* 67        103  43  01000011  C &#67;   Uppercase C */
243
  3,  /* 68        104  44  01000100  D &#68;   Uppercase D */
244
  4,  /* 69        105  45  01000101  E &#69;   Uppercase E */
245
  5,  /* 70        106  46  01000110  F &#70;   Uppercase F */
246
  6,  /* 71        107  47  01000111  G &#71;   Uppercase G */
247
  7,  /* 72        110  48  01001000  H &#72;   Uppercase H */
248
  8,  /* 73        111  49  01001001  I &#73;   Uppercase I */
249
  9,  /* 74        112  4A  01001010  J &#74;   Uppercase J */
250
  10, /* 75        113  4B  01001011  K &#75;   Uppercase K */
251
  11, /* 76        114  4C  01001100  L &#76;   Uppercase L */
252
  12, /* 77        115  4D  01001101  M &#77;   Uppercase M */
253
  13, /* 78        116  4E  01001110  N &#78;   Uppercase N */
254
  14, /* 79        117  4F  01001111  O &#79;   Uppercase O */
255
  15, /* 80        120  50  01010000  P &#80;   Uppercase P */
256
  16, /* 81        121  51  01010001  Q &#81;   Uppercase Q */
257
  17, /* 82        122  52  01010010  R &#82;   Uppercase R */
258
  18, /* 83        123  53  01010011  S &#83;   Uppercase S */
259
  19, /* 84        124  54  01010100  T &#84;   Uppercase T */
260
  20, /* 85        125  55  01010101  U &#85;   Uppercase U */
261
  21, /* 86        126  56  01010110  V &#86;   Uppercase V */
262
  22, /* 87        127  57  01010111  W &#87;   Uppercase W */
263
  23, /* 88        130  58  01011000  X &#88;   Uppercase X */
264
  24, /* 89        131  59  01011001  Y &#89;   Uppercase Y */
265
  25, /* 90        132  5A  01011010  Z &#90;   Uppercase Z */
266
  -1, /* 91        133  5B  01011011  [ &#91; &lsqb;  Opening bracket */
267
  -1, /* 92        134  5C  01011100  \ &#92; &bsol;  Backslash */
268
  -1, /* 93        135  5D  01011101  ] &#93; &rsqb;  Closing bracket */
269
  -1, /* 94        136  5E  01011110  ^ &#94; &Hat; Caret - circumflex */
270
  -1, /* 95        137  5F  01011111  _ &#95; &lowbar;  Underscore */
271
  -1, /* 96        140  60  01100000  ` &#96; &grave; Grave accent */
272
  26, /* 97        141  61  01100001  a &#97;   Lowercase a */
273
  27, /* 98        142  62  01100010  b &#98;   Lowercase b */
274
  28, /* 99        143  63  01100011  c &#99;   Lowercase c */
275
  29, /* 100        144 64  01100100  d &#100;    Lowercase d */
276
  30, /* 101        145 65  01100101  e &#101;    Lowercase e */
277
  31, /* 102        146 66  01100110  f &#102;    Lowercase f */
278
  32, /* 103        147 67  01100111  g &#103;    Lowercase g */
279
  33, /* 104        150 68  01101000  h &#104;    Lowercase h */
280
  34, /* 105        151 69  01101001  i &#105;    Lowercase i */
281
  35, /* 106        152 6A  01101010  j &#106;    Lowercase j */
282
  36, /* 107        153 6B  01101011  k &#107;    Lowercase k */
283
  37, /* 108        154 6C  01101100  l &#108;    Lowercase l */
284
  38, /* 109        155 6D  01101101  m &#109;    Lowercase m */
285
  39, /* 110        156 6E  01101110  n &#110;    Lowercase n */
286
  40, /* 111        157 6F  01101111  o &#111;    Lowercase o */
287
  41, /* 112        160 70  01110000  p &#112;    Lowercase p */
288
  42, /* 113        161 71  01110001  q &#113;    Lowercase q */
289
  43, /* 114        162 72  01110010  r &#114;    Lowercase r */
290
  44, /* 115        163 73  01110011  s &#115;    Lowercase s */
291
  45, /* 116        164 74  01110100  t &#116;    Lowercase t */
292
  46, /* 117        165 75  01110101  u &#117;    Lowercase u */
293
  47, /* 118        166 76  01110110  v &#118;    Lowercase v */
294
  48, /* 119        167 77  01110111  w &#119;    Lowercase w */
295
  49, /* 120        170 78  01111000  x &#120;    Lowercase x */
296
  50, /* 121        171 79  01111001  y &#121;    Lowercase y */
297
  51, /* 122        172 7A  01111010  z &#122;    Lowercase z */
298
  -1, /* 123        173 7B  01111011  { &#123;  &lcub;  Opening brace */
299
  -1, /* 124        174 7C  01111100  | &#124;  &verbar;  Vertical bar */
300
  -1, /* 125        175 7D  01111101  } &#125;  &rcub;  Closing brace */
301
  -1, /* 126        176 7E  01111110  ~ &#126;  &tilde; Equivalency sign - tilde */
302
  -1, /* 127        177 7F  01111111  DEL &#127;    Delete */
303
};
304
305
static INLINE char* base64_encode_ex(const BYTE* WINPR_RESTRICT alphabet,
306
                                     const BYTE* WINPR_RESTRICT data, size_t length, BOOL pad,
307
                                     BOOL crLf, size_t lineSize)
308
0
{
309
0
  int c = 0;
310
0
  size_t blocks = 0;
311
0
  size_t outLen = (length + 3) * 4 / 3;
312
0
  size_t extra = 0;
313
0
  if (crLf)
314
0
  {
315
0
    size_t nCrLf = (outLen + lineSize - 1) / lineSize;
316
0
    extra = nCrLf * 2;
317
0
  }
318
0
  size_t outCounter = 0;
319
320
0
  const BYTE* q = data;
321
0
  BYTE* p = malloc(outLen + extra + 1ull);
322
0
  if (!p)
323
0
    return NULL;
324
325
0
  char* ret = (char*)p;
326
327
  /* b1, b2, b3 are input bytes
328
   *
329
   * 0         1         2
330
   * 012345678901234567890123
331
   * |  b1  |  b2   |  b3   |
332
   *
333
   * [ c1 ]     [  c3 ]
334
   *      [  c2 ]     [  c4 ]
335
   *
336
   * c1, c2, c3, c4 are output chars in base64
337
   */
338
339
  /* first treat complete blocks */
340
0
  blocks = length - (length % 3);
341
0
  for (size_t i = 0; i < blocks; i += 3, q += 3)
342
0
  {
343
0
    c = (q[0] << 16) + (q[1] << 8) + q[2];
344
345
0
    *p++ = alphabet[(c & 0x00FC0000) >> 18];
346
0
    *p++ = alphabet[(c & 0x0003F000) >> 12];
347
0
    *p++ = alphabet[(c & 0x00000FC0) >> 6];
348
0
    *p++ = alphabet[c & 0x0000003F];
349
350
0
    outCounter += 4;
351
0
    if (crLf && (outCounter % lineSize == 0))
352
0
    {
353
0
      *p++ = '\r';
354
0
      *p++ = '\n';
355
0
    }
356
0
  }
357
358
  /* then remainder */
359
0
  switch (length % 3)
360
0
  {
361
0
    case 0:
362
0
      break;
363
0
    case 1:
364
0
      c = (q[0] << 16);
365
0
      *p++ = alphabet[(c & 0x00FC0000) >> 18];
366
0
      *p++ = alphabet[(c & 0x0003F000) >> 12];
367
0
      if (pad)
368
0
      {
369
0
        *p++ = '=';
370
0
        *p++ = '=';
371
0
      }
372
0
      break;
373
0
    case 2:
374
0
      c = (q[0] << 16) + (q[1] << 8);
375
0
      *p++ = alphabet[(c & 0x00FC0000) >> 18];
376
0
      *p++ = alphabet[(c & 0x0003F000) >> 12];
377
0
      *p++ = alphabet[(c & 0x00000FC0) >> 6];
378
0
      if (pad)
379
0
        *p++ = '=';
380
0
      break;
381
0
    default:
382
0
      break;
383
0
  }
384
385
0
  if (crLf && length % 3)
386
0
  {
387
0
    *p++ = '\r';
388
0
    *p++ = '\n';
389
0
  }
390
0
  *p = 0;
391
392
0
  return ret;
393
0
}
394
395
static INLINE char* base64_encode(const BYTE* WINPR_RESTRICT alphabet,
396
                                  const BYTE* WINPR_RESTRICT data, size_t length, BOOL pad)
397
0
{
398
0
  return base64_encode_ex(alphabet, data, length, pad, FALSE, 64);
399
0
}
400
401
static INLINE int base64_decode_char(const signed char* WINPR_RESTRICT alphabet, char c)
402
0
{
403
0
  if (c <= '\0')
404
0
    return -1;
405
406
0
  return alphabet[(size_t)c];
407
0
}
408
409
static INLINE void* base64_decode(const signed char* WINPR_RESTRICT alphabet,
410
                                  const char* WINPR_RESTRICT s, size_t length,
411
                                  size_t* WINPR_RESTRICT data_len, BOOL pad)
412
0
{
413
0
  int n[4] = { 0 };
414
0
  BYTE* data = NULL;
415
0
  const size_t remainder = length % 4;
416
417
0
  if ((pad && remainder > 0) || (remainder == 1))
418
0
    return NULL;
419
420
0
  if (!pad && remainder)
421
0
    length += 4 - remainder;
422
423
0
  BYTE* q = data = (BYTE*)malloc(length / 4 * 3 + 1);
424
0
  if (!q)
425
0
    return NULL;
426
427
  /* first treat complete blocks */
428
0
  const size_t nBlocks = (length / 4);
429
0
  size_t outputLen = 0;
430
431
0
  if (nBlocks < 1)
432
0
  {
433
0
    free(data);
434
0
    return NULL;
435
0
  }
436
437
0
  for (size_t i = 0; i < nBlocks - 1; i++, q += 3)
438
0
  {
439
0
    n[0] = base64_decode_char(alphabet, *s++);
440
0
    n[1] = base64_decode_char(alphabet, *s++);
441
0
    n[2] = base64_decode_char(alphabet, *s++);
442
0
    n[3] = base64_decode_char(alphabet, *s++);
443
444
0
    if ((n[0] == -1) || (n[1] == -1) || (n[2] == -1) || (n[3] == -1))
445
0
      goto out_free;
446
447
0
    q[0] = (BYTE)((n[0] << 2) + (n[1] >> 4));
448
0
    q[1] = (BYTE)(((n[1] & 15) << 4) + (n[2] >> 2));
449
0
    q[2] = (BYTE)(((n[2] & 3) << 6) + n[3]);
450
0
    outputLen += 3;
451
0
  }
452
453
  /* treat last block */
454
0
  n[0] = base64_decode_char(alphabet, *s++);
455
0
  n[1] = base64_decode_char(alphabet, *s++);
456
0
  if ((n[0] == -1) || (n[1] == -1))
457
0
    goto out_free;
458
459
0
  n[2] = remainder == 2 ? -1 : base64_decode_char(alphabet, *s++);
460
0
  n[3] = remainder >= 2 ? -1 : base64_decode_char(alphabet, *s++);
461
462
0
  q[0] = (BYTE)((n[0] << 2) + (n[1] >> 4));
463
0
  if (n[2] == -1)
464
0
  {
465
    /* XX== */
466
0
    outputLen += 1;
467
0
    if (n[3] != -1)
468
0
      goto out_free;
469
470
0
    q[1] = (BYTE)((n[1] & 15) << 4);
471
0
  }
472
0
  else if (n[3] == -1)
473
0
  {
474
    /* yyy= */
475
0
    outputLen += 2;
476
0
    q[1] = (BYTE)(((n[1] & 15) << 4) + (n[2] >> 2));
477
0
    q[2] = (BYTE)((n[2] & 3) << 6);
478
0
  }
479
0
  else
480
0
  {
481
    /* XXXX */
482
0
    outputLen += 3;
483
0
    q[0] = (BYTE)((n[0] << 2) + (n[1] >> 4));
484
0
    q[1] = (BYTE)(((n[1] & 15) << 4) + (n[2] >> 2));
485
0
    q[2] = (BYTE)(((n[2] & 3) << 6) + n[3]);
486
0
  }
487
488
0
  if (data_len)
489
0
    *data_len = outputLen;
490
0
  data[outputLen] = '\0';
491
492
0
  return data;
493
0
out_free:
494
0
  free(data);
495
0
  return NULL;
496
0
}
497
498
char* crypto_base64_encode_ex(const BYTE* WINPR_RESTRICT data, size_t length, BOOL withCrLf)
499
0
{
500
0
  return base64_encode_ex(enc_base64, data, length, TRUE, withCrLf, 64);
501
0
}
502
503
char* crypto_base64_encode(const BYTE* WINPR_RESTRICT data, size_t length)
504
0
{
505
0
  return base64_encode(enc_base64, data, length, TRUE);
506
0
}
507
508
void crypto_base64_decode(const char* WINPR_RESTRICT enc_data, size_t length,
509
                          BYTE** WINPR_RESTRICT dec_data, size_t* WINPR_RESTRICT res_length)
510
0
{
511
0
  *dec_data = base64_decode(dec_base64, enc_data, length, res_length, TRUE);
512
0
}
513
514
char* crypto_base64url_encode(const BYTE* WINPR_RESTRICT data, size_t length)
515
0
{
516
0
  return base64_encode(enc_base64url, data, length, FALSE);
517
0
}
518
519
void crypto_base64url_decode(const char* WINPR_RESTRICT enc_data, size_t length,
520
                             BYTE** WINPR_RESTRICT dec_data, size_t* WINPR_RESTRICT res_length)
521
0
{
522
0
  *dec_data = base64_decode(dec_base64url, enc_data, length, res_length, FALSE);
523
0
}