add CHD support.
[pcsx_rearmed.git] / deps / crypto / base64.c
1 /*********************************************************************
2 * Filename:   base64.c
3 * Author:     Brad Conte (brad AT bradconte.com)
4 * Copyright:
5 * Disclaimer: This code is presented "as is" without any guarantees.
6 * Details:    Implementation of the Base64 encoding algorithm.
7 *********************************************************************/
8
9 /*************************** HEADER FILES ***************************/
10 #include <stdlib.h>
11 #include "base64.h"
12
13 /****************************** MACROS ******************************/
14 #define NEWLINE_INVL 76
15
16 /**************************** VARIABLES *****************************/
17 // Note: To change the charset to a URL encoding, replace the '+' and '/' with '*' and '-'
18 static const BYTE charset[]={"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
19
20 /*********************** FUNCTION DEFINITIONS ***********************/
21 BYTE revchar(char ch)
22 {
23         if (ch >= 'A' && ch <= 'Z')
24                 ch -= 'A';
25         else if (ch >= 'a' && ch <='z')
26                 ch = ch - 'a' + 26;
27         else if (ch >= '0' && ch <='9')
28                 ch = ch - '0' + 52;
29         else if (ch == '+')
30                 ch = 62;
31         else if (ch == '/')
32                 ch = 63;
33
34         return(ch);
35 }
36
37 size_t base64_encode(const BYTE in[], BYTE out[], size_t len, int newline_flag)
38 {
39         size_t idx, idx2, blks, blk_ceiling, left_over, newline_count = 0;
40
41         blks = (len / 3);
42         left_over = len % 3;
43
44         if (out == NULL) {
45                 idx2 = blks * 4 ;
46                 if (left_over)
47                         idx2 += 4;
48                 if (newline_flag)
49                         idx2 += len / 57;   // (NEWLINE_INVL / 4) * 3 = 57. One newline per 57 input bytes.
50         }
51         else {
52                 // Since 3 input bytes = 4 output bytes, determine out how many even sets of
53                 // 3 bytes the input has.
54                 blk_ceiling = blks * 3;
55                 for (idx = 0, idx2 = 0; idx < blk_ceiling; idx += 3, idx2 += 4) {
56                         out[idx2]     = charset[in[idx] >> 2];
57                         out[idx2 + 1] = charset[((in[idx] & 0x03) << 4) | (in[idx + 1] >> 4)];
58                         out[idx2 + 2] = charset[((in[idx + 1] & 0x0f) << 2) | (in[idx + 2] >> 6)];
59                         out[idx2 + 3] = charset[in[idx + 2] & 0x3F];
60                         // The offical standard requires a newline every 76 characters.
61                         // (Eg, first newline is character 77 of the output.)
62                         if (((idx2 - newline_count + 4) % NEWLINE_INVL == 0) && newline_flag) {
63                                 out[idx2 + 4] = '\n';
64                                 idx2++;
65                                 newline_count++;
66                         }
67                 }
68
69                 if (left_over == 1) {
70                         out[idx2]     = charset[in[idx] >> 2];
71                         out[idx2 + 1] = charset[(in[idx] & 0x03) << 4];
72                         out[idx2 + 2] = '=';
73                         out[idx2 + 3] = '=';
74                         idx2 += 4;
75                 }
76                 else if (left_over == 2) {
77                         out[idx2]     = charset[in[idx] >> 2];
78                         out[idx2 + 1] = charset[((in[idx] & 0x03) << 4) | (in[idx + 1] >> 4)];
79                         out[idx2 + 2] = charset[(in[idx + 1] & 0x0F) << 2];
80                         out[idx2 + 3] = '=';
81                         idx2 += 4;
82                 }
83         }
84
85         return(idx2);
86 }
87
88 size_t base64_decode(const BYTE in[], BYTE out[], size_t len)
89 {
90         BYTE ch;
91         size_t idx, idx2, blks, blk_ceiling, left_over;
92
93         if (in[len - 1] == '=')
94                 len--;
95         if (in[len - 1] == '=')
96                 len--;
97
98         blks = len / 4;
99         left_over = len % 4;
100
101         if (out == NULL) {
102                 if (len >= 77 && in[NEWLINE_INVL] == '\n')   // Verify that newlines where used.
103                         len -= len / (NEWLINE_INVL + 1);
104                 blks = len / 4;
105                 left_over = len % 4;
106
107                 idx = blks * 3;
108                 if (left_over == 2)
109                         idx ++;
110                 else if (left_over == 3)
111                         idx += 2;
112         }
113         else {
114                 blk_ceiling = blks * 4;
115                 for (idx = 0, idx2 = 0; idx2 < blk_ceiling; idx += 3, idx2 += 4) {
116                         if (in[idx2] == '\n')
117                                 idx2++;
118                         out[idx]     = (revchar(in[idx2]) << 2) | ((revchar(in[idx2 + 1]) & 0x30) >> 4);
119                         out[idx + 1] = (revchar(in[idx2 + 1]) << 4) | (revchar(in[idx2 + 2]) >> 2);
120                         out[idx + 2] = (revchar(in[idx2 + 2]) << 6) | revchar(in[idx2 + 3]);
121                 }
122
123                 if (left_over == 2) {
124                         out[idx]     = (revchar(in[idx2]) << 2) | ((revchar(in[idx2 + 1]) & 0x30) >> 4);
125                         idx++;
126                 }
127                 else if (left_over == 3) {
128                         out[idx]     = (revchar(in[idx2]) << 2) | ((revchar(in[idx2 + 1]) & 0x30) >> 4);
129                         out[idx + 1] = (revchar(in[idx2 + 1]) << 4) | (revchar(in[idx2 + 2]) >> 2);
130                         idx += 2;
131                 }
132         }
133
134         return(idx);
135 }