]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/ssl2Padding/ssl2Padding.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / ssl2Padding / ssl2Padding.cpp
1 /* Copyright (c) 2005-2006 Apple Computer, Inc.
2 *
3 * ssl2Padding.cpp - test CSSM_PADDING_APPLE_SSLv2.
4 */
5
6
7 /*
8 * This table illustrates the combinations of:
9 *
10 * -- SSLv2 (v2) and SSLv3/TLSv1 (v3+) enables (0/1) on the client and server side
11 * -- the resulting negotiated protocols (including those forced by a man-in-the-middle
12 * attacker, denoted by (m))
13 * -- the padding generated by the client (client pad)
14 * -- the padding style checked by the server (server pad)
15 * -- and the end results
16 *
17 * client server
18 * ------ ------
19 * v2 v3+ v2 v3+ negotiate client pad server pad result
20 * -- -- -- -- --------- ---------- ---------- ------
21 * 0 0 x x impossible
22 * x x 0 0 impossible
23 * 0 1 0 1 v3+ PKCS1 PKCS1 normal
24 * 0 1 0 1 v2 (m) Attack fails, client rejects server hello
25 * 0 1 1 0 fail incompatible
26 * 0 1 1 1 v3+ PKCS1 PKCS1 normal
27 * 0 1 1 1 v2 (m) Attack fails, client rejects server hello
28 * 1 0 0 1 fail incompatible
29 * 1 0 1 0 v2 PKCS1 PKCS1 normal, both sides are dumb SSL2
30 * 1 0 1 0 v3+ Attack fails, server rejects client hello
31 * 1 0 1 1 v2 PKCS1 SSLv2 normal, dumb client
32 * 1 0 1 1 v3+ (m) Attack fails, client rejects server hello
33 * 1 1 0 1 v3+ PKCS1 PKCS1 normal
34 * 1 1 0 1 v2 (m) Attack fails, server rejects SSL2 handshake
35 * 1 1 1 0 v2 SSLv2 PKCS1 normal, dumb server
36 * 1 1 1 0 v3+ (m) Attack fails, server rejects SSL3 handshakes
37 * 1 1 1 1 v3+ PKCS1 PKCS1 normal
38 * 1 1 1 1 v2 (m) SSLv2 SSLv2 Attack fails due to SSLv2 pad detect
39 *
40 * The client generates SSLv2 padding if it's capable of v3+ but is currently operating
41 * in v2 per negotiation.
42 *
43 * The server checks for SSLv2 padding if it's capable of v3+ but is currently operating
44 * in v2 per negotiation. If SSLv2 padding is seen, fail.
45 */
46
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <time.h>
51 #include <Security/cssm.h>
52 #include "cspwrap.h"
53 #include "common.h"
54 #include "cspdlTesting.h"
55
56 #define USAGE_NAME "noUsage"
57 #define USAGE_NAME_LEN (strlen(USAGE_NAME))
58 #define LOOPS_DEF 10
59
60 #define KEY_SIZE_DEF 1024
61 #define KEY_SIZE_SMALL 512
62
63 #define PTEXT_LEN 32 /* bytes */
64
65 static void usage(char **argv)
66 {
67 printf("usage: %s [options]\n", argv[0]);
68 printf(" Options:\n");
69 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
70 printf(" k=keySizeInBits; default=%d\n", KEY_SIZE_DEF);
71 printf(" D (CSP/DL; default = bare CSP)\n");
72 printf(" p (pause on each loop)\n");
73 printf(" u (quick; small keys)\n");
74 printf(" v(erbose)\n");
75 printf(" q(uiet)\n");
76 printf(" h(elp)\n");
77 exit(1);
78 }
79
80 /* special-purpose generate-context, encrypt, and decrypt routines just for this test */
81 static int genRsaCryptContext(
82 CSSM_CSP_HANDLE cspHand,
83 CSSM_KEY_PTR key,
84 CSSM_PADDING padding,
85 CSSM_BOOL quiet,
86 CSSM_CC_HANDLE &ccHand) // RETURNED
87 {
88 CSSM_RETURN crtn;
89 CSSM_ACCESS_CREDENTIALS creds;
90
91 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
92 crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
93 CSSM_ALGID_RSA,
94 &creds, // access
95 key,
96 padding,
97 &ccHand);
98 if(crtn) {
99 cssmPerror("CSSM_CSP_CreateAsymmetricContext", crtn);
100 return testError(quiet);
101 }
102 return 0;
103 }
104
105 static int doRsaEncrypt(
106 CSSM_CSP_HANDLE cspHand,
107 CSSM_KEY_PTR key,
108 CSSM_PADDING padding,
109 CSSM_BOOL quiet,
110 CSSM_DATA *ptext,
111 CSSM_DATA *ctext)
112 {
113 CSSM_CC_HANDLE ccHand;
114 int rtn;
115 CSSM_RETURN crtn;
116 CSSM_SIZE bytesMoved;
117 CSSM_DATA remData = {0, NULL};
118
119 rtn = genRsaCryptContext(cspHand, key, padding, quiet, ccHand);
120 if(rtn) {
121 return rtn;
122 }
123 crtn = CSSM_EncryptData(ccHand,
124 ptext,
125 1,
126 ctext,
127 1,
128 &bytesMoved,
129 &remData);
130 CSSM_DeleteContext(ccHand);
131 if(crtn == CSSM_OK) {
132 /*
133 * Deal with remData - its contents are included in bytesMoved.
134 */
135 if(remData.Length != 0) {
136 /* malloc and copy a new one */
137 uint8 *newCdata = (uint8 *)appMalloc(bytesMoved, NULL);
138 memmove(newCdata, ctext->Data, ctext->Length);
139 memmove(newCdata+ctext->Length, remData.Data, remData.Length);
140 CSSM_FREE(ctext->Data);
141 ctext->Data = newCdata;
142 }
143 ctext->Length = bytesMoved;
144 return 0;
145 }
146 else {
147 cssmPerror("CSSM_EncryptData", crtn);
148 return testError(quiet);
149 }
150 }
151
152 static int doRsaDecrypt(
153 CSSM_CSP_HANDLE cspHand,
154 CSSM_KEY_PTR key,
155 CSSM_PADDING padding,
156 CSSM_BOOL quiet,
157 CSSM_RETURN expectRtn,
158 CSSM_DATA *ctext,
159 CSSM_DATA *rptext)
160 {
161 CSSM_CC_HANDLE ccHand;
162 int rtn;
163 CSSM_RETURN crtn;
164 CSSM_SIZE bytesMoved;
165 CSSM_DATA remData = {0, NULL};
166
167 rtn = genRsaCryptContext(cspHand, key, padding, quiet, ccHand);
168 if(rtn) {
169 return rtn;
170 }
171 crtn = CSSM_DecryptData(ccHand,
172 ctext,
173 1,
174 rptext,
175 1,
176 &bytesMoved,
177 &remData);
178 CSSM_DeleteContext(ccHand);
179 if(crtn != expectRtn) {
180 printf(" CSSM_DecryptData: expect %s\n", cssmErrToStr(expectRtn));
181 printf(" CSSM_DecryptData: got %s\n", cssmErrToStr(crtn));
182 return testError(quiet);
183 }
184 if(crtn) {
185 /* no need to process further */
186 return 0;
187 }
188 if(crtn == CSSM_OK) {
189 /*
190 * Deal with remData - its contents are included in bytesMoved.
191 */
192 if(remData.Length != 0) {
193 /* malloc and copy a new one */
194 uint8 *newRpdata = (uint8 *)appMalloc(bytesMoved, NULL);
195 memmove(newRpdata, rptext->Data, rptext->Length);
196 memmove(newRpdata+rptext->Length, remData.Data, remData.Length);
197 CSSM_FREE(rptext->Data);
198 rptext->Data = newRpdata;
199 }
200 rptext->Length = bytesMoved;
201 return 0;
202 }
203 else {
204 cssmPerror("CSSM_DecryptData", crtn);
205 return testError(quiet);
206 }
207 }
208
209 /*
210 * encrypt with specified pad
211 * decrypt with specified pad, verify expected result (which may be failure)
212 */
213 static int doTest(
214 CSSM_CSP_HANDLE cspHand,
215 CSSM_KEY_PTR pubKey,
216 CSSM_KEY_PTR privKey,
217 CSSM_PADDING encrPad,
218 CSSM_PADDING decrPad,
219 CSSM_BOOL quiet,
220 CSSM_RETURN expectResult)
221 {
222 int rtn;
223 uint8 ptext[PTEXT_LEN];
224 CSSM_DATA ptextData = {PTEXT_LEN, ptext};
225 CSSM_DATA ctext = {0, NULL};
226 CSSM_DATA rptext = {0, NULL};
227
228 simpleGenData(&ptextData, PTEXT_LEN, PTEXT_LEN);
229 rtn = doRsaEncrypt(cspHand, pubKey, encrPad, quiet, &ptextData, &ctext);
230 if(rtn) {
231 goto errOut;
232 }
233 rtn = doRsaDecrypt(cspHand, privKey, decrPad, quiet, expectResult, &ctext, &rptext);
234 if(rtn) {
235 goto errOut;
236 }
237 if(expectResult == CSSM_OK) {
238 if(memcmp(rptext.Data, ptextData.Data, PTEXT_LEN)) {
239 printf("***Data miscomapare after decrypt\n");
240 rtn = testError(quiet);
241 }
242 }
243 errOut:
244 if(ctext.Data) {
245 CSSM_FREE(ctext.Data);
246 }
247 if(rptext.Data) {
248 CSSM_FREE(rptext.Data);
249 }
250 return rtn;
251 }
252
253 int main(int argc, char **argv)
254 {
255 int arg;
256 char *argp;
257 unsigned loop;
258 CSSM_CSP_HANDLE cspHand;
259 int rtn = 0;
260
261 /*
262 * User-spec'd params
263 */
264 unsigned loops = LOOPS_DEF;
265 CSSM_BOOL verbose = CSSM_FALSE;
266 CSSM_BOOL quiet = CSSM_FALSE;
267 uint32 keySizeInBits = KEY_SIZE_DEF;
268 CSSM_BOOL bareCsp = CSSM_TRUE;
269 CSSM_BOOL doPause = CSSM_FALSE;
270
271 for(arg=1; arg<argc; arg++) {
272 argp = argv[arg];
273 switch(argp[0]) {
274 case 'l':
275 loops = atoi(&argp[2]);
276 break;
277 case 'k':
278 keySizeInBits = atoi(&argv[arg][2]);
279 break;
280 case 'D':
281 bareCsp = CSSM_FALSE;
282 break;
283 case 'u':
284 keySizeInBits = KEY_SIZE_SMALL;
285 break;
286 case 'v':
287 verbose = CSSM_TRUE;
288 break;
289 case 'p':
290 doPause = CSSM_TRUE;
291 break;
292 case 'q':
293 quiet = CSSM_TRUE;
294 break;
295 case 'h':
296 default:
297 usage(argv);
298 }
299 }
300
301 testStartBanner("ssl2Padding", argc, argv);
302
303 cspHand = cspDlDbStartup(bareCsp, NULL);
304 if(cspHand == 0) {
305 exit(1);
306 }
307 CSSM_KEY pubKey;
308 CSSM_KEY privKey;
309
310 CSSM_RETURN crtn = cspGenKeyPair(cspHand, CSSM_ALGID_RSA,
311 USAGE_NAME, USAGE_NAME_LEN,
312 keySizeInBits,
313 &pubKey, CSSM_TRUE /* ref */, CSSM_KEYUSE_ANY, CSSM_KEYBLOB_RAW_FORMAT_NONE,
314 &privKey, CSSM_TRUE /* ref */, CSSM_KEYUSE_ANY, CSSM_KEYBLOB_RAW_FORMAT_NONE,
315 CSSM_FALSE);
316 if(crtn) {
317 printf("***Error generating key pair. Aborting.\n");
318 exit(1);
319 }
320 for(loop=1; ; loop++) {
321 if(doPause) {
322 fpurge(stdin);
323 printf("Top of loop; hit CR to proceed: ");
324 getchar();
325 }
326
327 /* encrypt by client, decrypt by server. */
328
329 /*
330 * SSLv3+ negotiated, normal case, or
331 * both sides support SSLv2 only
332 */
333 if(!quiet) {
334 printf("...loop %u\n", loop);
335 printf(" encrPad PKCS1 decrPad PKCS1\n");
336 }
337 rtn = doTest(cspHand, &pubKey, &privKey,
338 CSSM_PADDING_PKCS1, CSSM_PADDING_PKCS1,
339 quiet, CSSM_OK);
340 if(rtn) {
341 break;
342 }
343
344 /*
345 * Server supports SSLv2 and SSLv3+, client supports SSLv2 only
346 */
347 if(!quiet) {
348 printf(" encrPad PKCS1 decrPad SSLv2\n");
349 }
350 rtn = doTest(cspHand, &pubKey, &privKey,
351 CSSM_PADDING_PKCS1, CSSM_PADDING_APPLE_SSLv2,
352 quiet, CSSM_OK);
353 if(rtn) {
354 break;
355 }
356
357 /*
358 * Server supports SSLv2 only, client supports SSLv2 and SSLv3+
359 */
360 if(!quiet) {
361 printf(" encrPad SSLv2 decrPad PKCS1\n");
362 }
363 rtn = doTest(cspHand, &pubKey, &privKey,
364 CSSM_PADDING_APPLE_SSLv2, CSSM_PADDING_PKCS1,
365 quiet, CSSM_OK);
366 if(rtn) {
367 break;
368 }
369
370 /*
371 * Both sides support SSLv3+ but a man in the middle has forced the
372 * negotiated protocol down to SSLv2
373 */
374 if(!quiet) {
375 printf(" encrPad SSLv2 decrPad SSLv2, expect failure\n");
376 }
377 rtn = doTest(cspHand, &pubKey, &privKey,
378 CSSM_PADDING_APPLE_SSLv2, CSSM_PADDING_APPLE_SSLv2,
379 quiet, CSSMERR_CSP_APPLE_SSLv2_ROLLBACK);
380 if(rtn) {
381 break;
382 }
383
384 if(loops && (loop == loops)) {
385 break;
386 }
387 } /* for loop */
388
389 CSSM_ModuleDetach(cspHand);
390 if((rtn == 0) && !quiet) {
391 printf("%s test complete\n", argv[0]);
392 }
393 return rtn;
394 }