1 /* Copyright (c) 2005-2006 Apple Computer, Inc.
3 * ssl2Padding.cpp - test CSSM_PADDING_APPLE_SSLv2.
8 * This table illustrates the combinations of:
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
19 * v2 v3+ v2 v3+ negotiate client pad server pad result
20 * -- -- -- -- --------- ---------- ---------- ------
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
40 * The client generates SSLv2 padding if it's capable of v3+ but is currently operating
41 * in v2 per negotiation.
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.
51 #include <Security/cssm.h>
54 #include "cspdlTesting.h"
56 #define USAGE_NAME "noUsage"
57 #define USAGE_NAME_LEN (strlen(USAGE_NAME))
60 #define KEY_SIZE_DEF 1024
61 #define KEY_SIZE_SMALL 512
63 #define PTEXT_LEN 32 /* bytes */
65 static void usage(char **argv
)
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");
80 /* special-purpose generate-context, encrypt, and decrypt routines just for this test */
81 static int genRsaCryptContext(
82 CSSM_CSP_HANDLE cspHand
,
86 CSSM_CC_HANDLE
&ccHand
) // RETURNED
89 CSSM_ACCESS_CREDENTIALS creds
;
91 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
92 crtn
= CSSM_CSP_CreateAsymmetricContext(cspHand
,
99 cssmPerror("CSSM_CSP_CreateAsymmetricContext", crtn
);
100 return testError(quiet
);
105 static int doRsaEncrypt(
106 CSSM_CSP_HANDLE cspHand
,
108 CSSM_PADDING padding
,
113 CSSM_CC_HANDLE ccHand
;
116 CSSM_SIZE bytesMoved
;
117 CSSM_DATA remData
= {0, NULL
};
119 rtn
= genRsaCryptContext(cspHand
, key
, padding
, quiet
, ccHand
);
123 crtn
= CSSM_EncryptData(ccHand
,
130 CSSM_DeleteContext(ccHand
);
131 if(crtn
== CSSM_OK
) {
133 * Deal with remData - its contents are included in bytesMoved.
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
;
143 ctext
->Length
= bytesMoved
;
147 cssmPerror("CSSM_EncryptData", crtn
);
148 return testError(quiet
);
152 static int doRsaDecrypt(
153 CSSM_CSP_HANDLE cspHand
,
155 CSSM_PADDING padding
,
157 CSSM_RETURN expectRtn
,
161 CSSM_CC_HANDLE ccHand
;
164 CSSM_SIZE bytesMoved
;
165 CSSM_DATA remData
= {0, NULL
};
167 rtn
= genRsaCryptContext(cspHand
, key
, padding
, quiet
, ccHand
);
171 crtn
= CSSM_DecryptData(ccHand
,
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
);
185 /* no need to process further */
188 if(crtn
== CSSM_OK
) {
190 * Deal with remData - its contents are included in bytesMoved.
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
;
200 rptext
->Length
= bytesMoved
;
204 cssmPerror("CSSM_DecryptData", crtn
);
205 return testError(quiet
);
210 * encrypt with specified pad
211 * decrypt with specified pad, verify expected result (which may be failure)
214 CSSM_CSP_HANDLE cspHand
,
216 CSSM_KEY_PTR privKey
,
217 CSSM_PADDING encrPad
,
218 CSSM_PADDING decrPad
,
220 CSSM_RETURN expectResult
)
223 uint8 ptext
[PTEXT_LEN
];
224 CSSM_DATA ptextData
= {PTEXT_LEN
, ptext
};
225 CSSM_DATA ctext
= {0, NULL
};
226 CSSM_DATA rptext
= {0, NULL
};
228 simpleGenData(&ptextData
, PTEXT_LEN
, PTEXT_LEN
);
229 rtn
= doRsaEncrypt(cspHand
, pubKey
, encrPad
, quiet
, &ptextData
, &ctext
);
233 rtn
= doRsaDecrypt(cspHand
, privKey
, decrPad
, quiet
, expectResult
, &ctext
, &rptext
);
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
);
245 CSSM_FREE(ctext
.Data
);
248 CSSM_FREE(rptext
.Data
);
253 int main(int argc
, char **argv
)
258 CSSM_CSP_HANDLE cspHand
;
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
;
271 for(arg
=1; arg
<argc
; arg
++) {
275 loops
= atoi(&argp
[2]);
278 keySizeInBits
= atoi(&argv
[arg
][2]);
281 bareCsp
= CSSM_FALSE
;
284 keySizeInBits
= KEY_SIZE_SMALL
;
301 testStartBanner("ssl2Padding", argc
, argv
);
303 cspHand
= cspDlDbStartup(bareCsp
, NULL
);
310 CSSM_RETURN crtn
= cspGenKeyPair(cspHand
, CSSM_ALGID_RSA
,
311 USAGE_NAME
, USAGE_NAME_LEN
,
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
,
317 printf("***Error generating key pair. Aborting.\n");
320 for(loop
=1; ; loop
++) {
323 printf("Top of loop; hit CR to proceed: ");
327 /* encrypt by client, decrypt by server. */
330 * SSLv3+ negotiated, normal case, or
331 * both sides support SSLv2 only
334 printf("...loop %u\n", loop
);
335 printf(" encrPad PKCS1 decrPad PKCS1\n");
337 rtn
= doTest(cspHand
, &pubKey
, &privKey
,
338 CSSM_PADDING_PKCS1
, CSSM_PADDING_PKCS1
,
345 * Server supports SSLv2 and SSLv3+, client supports SSLv2 only
348 printf(" encrPad PKCS1 decrPad SSLv2\n");
350 rtn
= doTest(cspHand
, &pubKey
, &privKey
,
351 CSSM_PADDING_PKCS1
, CSSM_PADDING_APPLE_SSLv2
,
358 * Server supports SSLv2 only, client supports SSLv2 and SSLv3+
361 printf(" encrPad SSLv2 decrPad PKCS1\n");
363 rtn
= doTest(cspHand
, &pubKey
, &privKey
,
364 CSSM_PADDING_APPLE_SSLv2
, CSSM_PADDING_PKCS1
,
371 * Both sides support SSLv3+ but a man in the middle has forced the
372 * negotiated protocol down to SSLv2
375 printf(" encrPad SSLv2 decrPad SSLv2, expect failure\n");
377 rtn
= doTest(cspHand
, &pubKey
, &privKey
,
378 CSSM_PADDING_APPLE_SSLv2
, CSSM_PADDING_APPLE_SSLv2
,
379 quiet
, CSSMERR_CSP_APPLE_SSLv2_ROLLBACK
);
384 if(loops
&& (loop
== loops
)) {
389 CSSM_ModuleDetach(cspHand
);
390 if((rtn
== 0) && !quiet
) {
391 printf("%s test complete\n", argv
[0]);