]>
Commit | Line | Data |
---|---|---|
bd940221 | 1 | /* R_ENCODE.C - RFC 1113 encoding and decoding routines |
2 | */ | |
3 | ||
4 | /* Copyright (C) RSA Laboratories, a division of RSA Data Security, | |
5 | Inc., created 1991. All rights reserved. | |
6 | */ | |
7 | ||
8 | #include "global.h" | |
9 | #include "rsaref.h" | |
10 | ||
11 | /* RFC 1113 encoding: | |
12 | ||
13 | Value Encoding Value Encoding Value Encoding Value Encoding | |
14 | 0 A 17 R 34 i 51 z | |
15 | 1 B 18 S 35 j 52 0 | |
16 | 2 C 19 T 36 k 53 1 | |
17 | 3 D 20 U 37 l 54 2 | |
18 | 4 E 21 V 38 m 55 3 | |
19 | 5 F 22 W 39 n 56 4 | |
20 | 6 G 23 X 40 o 57 5 | |
21 | 7 H 24 Y 41 p 58 6 | |
22 | 8 I 25 Z 42 q 59 7 | |
23 | 9 J 26 a 43 r 60 8 | |
24 | 10 K 27 b 44 s 61 9 | |
25 | 11 L 28 c 45 t 62 + | |
26 | 12 M 29 d 46 u 63 / | |
27 | 13 N 30 e 47 v | |
28 | 14 O 31 f 48 w (pad) = | |
29 | 15 P 32 g 49 x | |
30 | 16 Q 33 h 50 y | |
31 | */ | |
32 | #define ENCODING(i) \ | |
33 | (unsigned char)(((i) < 26) ? ((i) + 0x41) : \ | |
34 | (((i) < 52) ? ((i) - 26 + 0x61) : \ | |
35 | (((i) < 62) ? ((i) - 52 + 0x30) : \ | |
36 | (((i) == 62) ? 0x2b : 0x2f)))) | |
37 | #define ENCODING_PAD 0x3d | |
38 | ||
39 | #define IS_ENCODING(c) \ | |
40 | ((((c) >= 0x41) && ((c) <= 0x5a)) || \ | |
41 | (((c) >= 0x61) && ((c) <= 0x7a)) || \ | |
42 | (((c) >= 0x30) && ((c) <= 0x39)) || \ | |
43 | ((c) == 0x2b) || \ | |
44 | ((c) == 0x2f)) | |
45 | ||
46 | /* assumes IS_ENCODING (c) == 1 */ | |
47 | #define DECODING(c) \ | |
48 | (((c) == 0x2b) ? 62 : \ | |
49 | (((c) == 0x2f) ? 63 : \ | |
50 | (((c) <= 0x39) ? ((c) - 0x30 + 52) : \ | |
51 | (((c) <= 0x5a) ? ((c) - 0x41) : ((c) - 0x61 + 26))))) | |
52 | ||
53 | static void EncodeQuantum PROTO_LIST ((unsigned char [4], unsigned char [3])); | |
54 | static int DecodeQuantum PROTO_LIST ((unsigned char [3], unsigned char [4])); | |
55 | static void EncodeLastQuantum | |
56 | PROTO_LIST ((unsigned char [4], unsigned char *, unsigned int)); | |
57 | static int DecodeLastQuantum | |
58 | PROTO_LIST ((unsigned char *, unsigned int *, unsigned char [4])); | |
59 | ||
60 | /* This always returns 0. It is an int function for future compatibility. | |
61 | */ | |
62 | int R_EncodePEMBlock (encodedBlock, encodedBlockLen, block, blockLen) | |
63 | unsigned char *encodedBlock; /* encoded block */ | |
64 | unsigned int *encodedBlockLen; /* length of encoded block */ | |
65 | unsigned char *block; /* block */ | |
66 | unsigned int blockLen; /* length of block */ | |
67 | { | |
68 | unsigned int i, lastLen; | |
69 | ||
70 | if (blockLen < 1) { | |
71 | *encodedBlockLen = 0; | |
72 | return (0); | |
73 | } | |
74 | ||
75 | for (i = 0; i < (blockLen-1)/3; i++) | |
76 | EncodeQuantum (&encodedBlock[4*i], &block[3*i]); | |
77 | ||
78 | lastLen = blockLen - 3*i; | |
79 | EncodeLastQuantum (&encodedBlock[4*i], &block[3*i], lastLen); | |
80 | *encodedBlockLen = 4*i + 4; | |
81 | ||
82 | return (0); | |
83 | } | |
84 | ||
85 | int R_DecodePEMBlock (block, blockLen, encodedBlock, encodedBlockLen) | |
86 | unsigned char *block; /* block */ | |
87 | unsigned int *blockLen; /* length of block */ | |
88 | unsigned char *encodedBlock; /* encoded block */ | |
89 | unsigned int encodedBlockLen; /* length of encoded block */ | |
90 | { | |
91 | int status; | |
92 | unsigned int i, lastLen; | |
93 | ||
94 | if (encodedBlockLen % 4) | |
95 | return (RE_ENCODING); | |
96 | ||
97 | if (encodedBlockLen < 1) { | |
98 | *blockLen = 0; | |
99 | return (0); | |
100 | } | |
101 | ||
102 | for (i = 0; i < (encodedBlockLen-1)/4; i++) | |
103 | if (status = DecodeQuantum (&block[3*i], &encodedBlock[4*i])) | |
104 | return (status); | |
105 | ||
106 | if (status = DecodeLastQuantum (&block[3*i], &lastLen, &encodedBlock[4*i])) | |
107 | return (status); | |
108 | ||
109 | *blockLen = 3*i + lastLen; | |
110 | return (0); | |
111 | } | |
112 | ||
113 | static void EncodeQuantum (encodedQuantum, quantum) | |
114 | unsigned char encodedQuantum[4]; | |
115 | unsigned char quantum[3]; | |
116 | { | |
117 | UINT4 temp; | |
118 | unsigned int a, b, c, d; | |
119 | ||
120 | temp = ((UINT4)quantum[0]) << 16; | |
121 | temp |= ((UINT4)quantum[1]) << 8; | |
122 | temp |= (UINT4)quantum[2]; | |
123 | ||
124 | a = (unsigned int)((temp >> 18) & 0x3f); | |
125 | b = (unsigned int)((temp >> 12) & 0x3f); | |
126 | c = (unsigned int)((temp >> 6) & 0x3f); | |
127 | d = (unsigned int)(temp & 0x3f); | |
128 | ||
129 | encodedQuantum[0] = ENCODING (a); | |
130 | encodedQuantum[1] = ENCODING (b); | |
131 | encodedQuantum[2] = ENCODING (c); | |
132 | encodedQuantum[3] = ENCODING (d); | |
133 | ||
134 | /* Zeroize potentially sensitive information. | |
135 | */ | |
136 | temp = 0; | |
137 | a = b = c = d = 0; | |
138 | } | |
139 | ||
140 | static int DecodeQuantum (quantum, encodedQuantum) | |
141 | unsigned char quantum[3]; | |
142 | unsigned char encodedQuantum[4]; | |
143 | { | |
144 | UINT4 temp; | |
145 | unsigned int a, b, c, d; | |
146 | ||
147 | if (! IS_ENCODING (encodedQuantum[0]) || | |
148 | ! IS_ENCODING (encodedQuantum[1]) || | |
149 | ! IS_ENCODING (encodedQuantum[2]) || | |
150 | ! IS_ENCODING (encodedQuantum[3])) | |
151 | return (RE_ENCODING); | |
152 | ||
153 | a = DECODING (encodedQuantum[0]); | |
154 | b = DECODING (encodedQuantum[1]); | |
155 | c = DECODING (encodedQuantum[2]); | |
156 | d = DECODING (encodedQuantum[3]); | |
157 | ||
158 | temp = ((UINT4)a) << 18; | |
159 | temp |= ((UINT4)b) << 12; | |
160 | temp |= ((UINT4)c) << 6; | |
161 | temp |= (UINT4)d; | |
162 | ||
163 | quantum[0] = (unsigned char)(temp >> 16); | |
164 | quantum[1] = (unsigned char)(temp >> 8); | |
165 | quantum[2] = (unsigned char)temp; | |
166 | ||
167 | /* Zeroize potentially sensitive information. | |
168 | */ | |
169 | temp = 0; | |
170 | a = b = c = d = 0; | |
171 | ||
172 | return (0); | |
173 | } | |
174 | ||
175 | static void EncodeLastQuantum (encodedQuantum, quantum, quantumLen) | |
176 | unsigned char encodedQuantum[4]; | |
177 | unsigned char *quantum; | |
178 | unsigned int quantumLen; /* 1, 2 or 3 */ | |
179 | { | |
180 | UINT4 temp; | |
181 | unsigned int a, b, c, d; | |
182 | ||
183 | temp = ((UINT4)quantum[0]) << 16; | |
184 | if (quantumLen >= 2) | |
185 | temp |= ((UINT4)quantum[1]) << 8; | |
186 | if (quantumLen == 3) | |
187 | temp |= ((UINT4)quantum[2]); | |
188 | ||
189 | a = (unsigned int)((temp >> 18) & 0x3f); | |
190 | b = (unsigned int)((temp >> 12) & 0x3f); | |
191 | if (quantumLen >= 2) | |
192 | c = (unsigned int)((temp >> 6) & 0x3f); | |
193 | if (quantumLen == 3) | |
194 | d = (unsigned int)(temp & 0x3f); | |
195 | ||
196 | encodedQuantum[0] = ENCODING (a); | |
197 | encodedQuantum[1] = ENCODING (b); | |
198 | if (quantumLen >= 2) | |
199 | encodedQuantum[2] = ENCODING (c); | |
200 | else | |
201 | encodedQuantum[2] = ENCODING_PAD; | |
202 | if (quantumLen == 3) | |
203 | encodedQuantum[3] = ENCODING (d); | |
204 | else | |
205 | encodedQuantum[3] = ENCODING_PAD; | |
206 | ||
207 | /* Zeroize potentially sensitive information. | |
208 | */ | |
209 | temp = 0; | |
210 | a = b = c = d = 0; | |
211 | } | |
212 | ||
213 | static int DecodeLastQuantum (quantum, quantumLen, encodedQuantum) | |
214 | unsigned char *quantum; | |
215 | unsigned int *quantumLen; /* 1, 2 or 3 */ | |
216 | unsigned char encodedQuantum[4]; | |
217 | { | |
218 | UINT4 temp; | |
219 | unsigned int a, b, c, d; | |
220 | ||
221 | if (! IS_ENCODING (encodedQuantum[0]) || | |
222 | ! IS_ENCODING (encodedQuantum[1]) || | |
223 | (! IS_ENCODING (encodedQuantum[2]) && | |
224 | (encodedQuantum[2] != ENCODING_PAD)) || | |
225 | (! IS_ENCODING (encodedQuantum[3]) && | |
226 | (encodedQuantum[3] != ENCODING_PAD))) | |
227 | return (RE_ENCODING); | |
228 | ||
229 | if (encodedQuantum[2] == ENCODING_PAD) | |
230 | *quantumLen = 1; | |
231 | else if (encodedQuantum[3] == ENCODING_PAD) | |
232 | *quantumLen = 2; | |
233 | else | |
234 | *quantumLen = 3; | |
235 | ||
236 | a = DECODING (encodedQuantum[0]); | |
237 | b = DECODING (encodedQuantum[1]); | |
238 | if (*quantumLen >= 2) | |
239 | c = DECODING (encodedQuantum[2]); | |
240 | if (*quantumLen == 3) | |
241 | d = DECODING (encodedQuantum[3]); | |
242 | ||
243 | temp = ((UINT4)a) << 18; | |
244 | temp |= ((UINT4)b) << 12; | |
245 | if (*quantumLen >= 2) | |
246 | temp |= ((UINT4)c) << 6; | |
247 | if (*quantumLen == 3) | |
248 | temp |= ((UINT4)d); | |
249 | ||
250 | quantum[0] = (unsigned char)(temp >> 16); | |
251 | if (*quantumLen >= 2) | |
252 | quantum[1] = (unsigned char)(temp >> 8); | |
253 | if (*quantumLen == 3) | |
254 | quantum[2] = (unsigned char)temp; | |
255 | ||
256 | /* Zeroize potentially sensitive information. | |
257 | */ | |
258 | temp = 0; | |
259 | a = b = c = d = 0; | |
260 | ||
261 | return (0); | |
262 | } |