-
Notifications
You must be signed in to change notification settings - Fork 0
/
r_encode.c
195 lines (165 loc) · 5.25 KB
/
r_encode.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
R_ENCODE.C - RFC 1113 encoding and decoding routines
Based in a similar form to the PGP RFC 1113 coding routines.
*/
#include "rsaeuro.h"
/* RFC 1113 encoding:
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
*/
/*
PEM routines.
This converts a binary file into printable ASCII characters, in a
radix-64 form mostly compatible with the PEM RFC 1113 format.
This makes it easier to send encrypted files over a 7-bit channel.
*/
/* ENC is the basic 1 character encoding function to make a char printing */
#define ENC(c) ((int)bintoasc[((c) & 077)])
#define PAD '='
/* Index this array by a 6 bit value to get the character corresponding
to that value. */
static unsigned char bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz0123456789+/";
/* Index this array by a 7 bit value to get the 6-bit binary field
corresponding to that value. Any illegal characters return high bit set. */
static unsigned char asctobin[] =
{
0200,0200,0200,0200,0200,0200,0200,0200,
0200,0200,0200,0200,0200,0200,0200,0200,
0200,0200,0200,0200,0200,0200,0200,0200,
0200,0200,0200,0200,0200,0200,0200,0200,
0200,0200,0200,0200,0200,0200,0200,0200,
0200,0200,0200,0076,0200,0200,0200,0077,
0064,0065,0066,0067,0070,0071,0072,0073,
0074,0075,0200,0200,0200,0200,0200,0200,
0200,0000,0001,0002,0003,0004,0005,0006,
0007,0010,0011,0012,0013,0014,0015,0016,
0017,0020,0021,0022,0023,0024,0025,0026,
0027,0030,0031,0200,0200,0200,0200,0200,
0200,0032,0033,0034,0035,0036,0037,0040,
0041,0042,0043,0044,0045,0046,0047,0050,
0051,0052,0053,0054,0055,0056,0057,0060,
0061,0062,0063,0200,0200,0200,0200,0200
};
static void encode PROTO_LIST((unsigned char [4], unsigned char [3], int ));
/* This will always returns 0. It is an int function for future compatibility,
done to provide compatibility with RSAREF(tm). */
int R_EncodePEMBlock(encodedBlock, encodedBlockLen, block, blockLen)
unsigned char *encodedBlock; /* encoded block */
unsigned int *encodedBlockLen; /* length of encoded block */
unsigned char *block; /* block */
unsigned int blockLen; /* length of block */
{
unsigned int i, lastLen;
if(blockLen < 1) {
*encodedBlockLen = 0;
return (ID_OK);
}
*encodedBlockLen = 0;
/* Bug Fixed By SK 02/09/95 */
for (i = 0, lastLen = blockLen; i < blockLen; i += 3) {
encode(&encodedBlock[4*i/3], &block[i], (lastLen >= 3 ? 3 : lastLen));
lastLen -= 3;
*encodedBlockLen += 4;
}
return(ID_OK);
}
int R_DecodePEMBlock (outbuf, outlength, inbuf, inlength)
unsigned char *outbuf; /* block */
unsigned int *outlength; /* length of block */
unsigned char *inbuf; /* encoded block */
unsigned int inlength; /* length of encoded block */
{
unsigned char *bp;
int length;
unsigned int c1,c2,c3,c4;
register int j;
if(inlength % 4)
return (RE_ENCODING);
if(inlength < 1) {
*outlength = 0;
return (ID_OK);
}
length = 0;
bp = (unsigned char *)inbuf;
/* FOUR input characters go into each THREE output charcters */
while(inlength > 0) {
if(*bp&0x80 || (c1=asctobin[*bp])&0x80)
return(RE_ENCODING);
++bp;
if(*bp&0x80 || (c2=asctobin[*bp])&0x80)
return(RE_ENCODING);
if(*++bp == PAD){
c3 = c4 = 0;
length += 1;
if(*++bp != PAD)
return(RE_ENCODING);
}
else if(*bp&0x80 || (c3=asctobin[*bp])&0x80)
return(RE_ENCODING);
else
{
if(*++bp == PAD)
{
c4 = 0;
length += 2;
}
else if (*bp&0x80 || (c4=asctobin[*bp])&0x80)
return(RE_ENCODING);
else
length += 3;
}
++bp;
j = (c1 << 2) | (c2 >> 4);
*outbuf++=j;
j = (c2 << 4) | (c3 >> 2);
*outbuf++=j;
j = (c3 << 6) | c4;
*outbuf++=j;
inlength -= 4;
}
*outlength = length;
return(ID_OK); /* normal return */
}
/*
Output one group of up to 3 bytes, pointed at by p, to buffer at f.
If fewer than 3 are present, the 1 or two extras must be zeros.
*/
static void encode(f, p, count)
unsigned char *f; /* output buffer */
unsigned char *p; /* input buffer */
int count; /* count */
{
int c1, c2, c3, c4;
c1 = *p >> 2;
c2 = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
c3 = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
c4 = p[2] & 077;
*f++ = ENC(c1);
*f++ = ENC(c2);
if (count == 1)
{
*f++ = PAD;
*f++ = PAD;
}else{
*f++ = ENC(c3);
if(count == 2) *f++ = PAD;
else *f++ = ENC(c4);
}
}