+++ /dev/null
-/* Copyright (c) 2005-2006 Apple Computer, Inc.
- *
- * ssl2Padding.cpp - test CSSM_PADDING_APPLE_SSLv2.
- */
-
-
- /*
- * This table illustrates the combinations of:
- *
- * -- SSLv2 (v2) and SSLv3/TLSv1 (v3+) enables (0/1) on the client and server side
- * -- the resulting negotiated protocols (including those forced by a man-in-the-middle
- * attacker, denoted by (m))
- * -- the padding generated by the client (client pad)
- * -- the padding style checked by the server (server pad)
- * -- and the end results
- *
- * client server
- * ------ ------
- * v2 v3+ v2 v3+ negotiate client pad server pad result
- * -- -- -- -- --------- ---------- ---------- ------
- * 0 0 x x impossible
- * x x 0 0 impossible
- * 0 1 0 1 v3+ PKCS1 PKCS1 normal
- * 0 1 0 1 v2 (m) Attack fails, client rejects server hello
- * 0 1 1 0 fail incompatible
- * 0 1 1 1 v3+ PKCS1 PKCS1 normal
- * 0 1 1 1 v2 (m) Attack fails, client rejects server hello
- * 1 0 0 1 fail incompatible
- * 1 0 1 0 v2 PKCS1 PKCS1 normal, both sides are dumb SSL2
- * 1 0 1 0 v3+ Attack fails, server rejects client hello
- * 1 0 1 1 v2 PKCS1 SSLv2 normal, dumb client
- * 1 0 1 1 v3+ (m) Attack fails, client rejects server hello
- * 1 1 0 1 v3+ PKCS1 PKCS1 normal
- * 1 1 0 1 v2 (m) Attack fails, server rejects SSL2 handshake
- * 1 1 1 0 v2 SSLv2 PKCS1 normal, dumb server
- * 1 1 1 0 v3+ (m) Attack fails, server rejects SSL3 handshakes
- * 1 1 1 1 v3+ PKCS1 PKCS1 normal
- * 1 1 1 1 v2 (m) SSLv2 SSLv2 Attack fails due to SSLv2 pad detect
- *
- * The client generates SSLv2 padding if it's capable of v3+ but is currently operating
- * in v2 per negotiation.
- *
- * The server checks for SSLv2 padding if it's capable of v3+ but is currently operating
- * in v2 per negotiation. If SSLv2 padding is seen, fail.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <Security/cssm.h>
-#include "cspwrap.h"
-#include "common.h"
-#include "cspdlTesting.h"
-
-#define USAGE_NAME "noUsage"
-#define USAGE_NAME_LEN (strlen(USAGE_NAME))
-#define LOOPS_DEF 10
-
-#define KEY_SIZE_DEF 1024
-#define KEY_SIZE_SMALL 512
-
-#define PTEXT_LEN 32 /* bytes */
-
-static void usage(char **argv)
-{
- printf("usage: %s [options]\n", argv[0]);
- printf(" Options:\n");
- printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
- printf(" k=keySizeInBits; default=%d\n", KEY_SIZE_DEF);
- printf(" D (CSP/DL; default = bare CSP)\n");
- printf(" p (pause on each loop)\n");
- printf(" u (quick; small keys)\n");
- printf(" v(erbose)\n");
- printf(" q(uiet)\n");
- printf(" h(elp)\n");
- exit(1);
-}
-
-/* special-purpose generate-context, encrypt, and decrypt routines just for this test */
-static int genRsaCryptContext(
- CSSM_CSP_HANDLE cspHand,
- CSSM_KEY_PTR key,
- CSSM_PADDING padding,
- CSSM_BOOL quiet,
- CSSM_CC_HANDLE &ccHand) // RETURNED
-{
- CSSM_RETURN crtn;
- CSSM_ACCESS_CREDENTIALS creds;
-
- memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
- crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
- CSSM_ALGID_RSA,
- &creds, // access
- key,
- padding,
- &ccHand);
- if(crtn) {
- cssmPerror("CSSM_CSP_CreateAsymmetricContext", crtn);
- return testError(quiet);
- }
- return 0;
-}
-
-static int doRsaEncrypt(
- CSSM_CSP_HANDLE cspHand,
- CSSM_KEY_PTR key,
- CSSM_PADDING padding,
- CSSM_BOOL quiet,
- CSSM_DATA *ptext,
- CSSM_DATA *ctext)
-{
- CSSM_CC_HANDLE ccHand;
- int rtn;
- CSSM_RETURN crtn;
- CSSM_SIZE bytesMoved;
- CSSM_DATA remData = {0, NULL};
-
- rtn = genRsaCryptContext(cspHand, key, padding, quiet, ccHand);
- if(rtn) {
- return rtn;
- }
- crtn = CSSM_EncryptData(ccHand,
- ptext,
- 1,
- ctext,
- 1,
- &bytesMoved,
- &remData);
- CSSM_DeleteContext(ccHand);
- if(crtn == CSSM_OK) {
- /*
- * Deal with remData - its contents are included in bytesMoved.
- */
- if(remData.Length != 0) {
- /* malloc and copy a new one */
- uint8 *newCdata = (uint8 *)appMalloc(bytesMoved, NULL);
- memmove(newCdata, ctext->Data, ctext->Length);
- memmove(newCdata+ctext->Length, remData.Data, remData.Length);
- CSSM_FREE(ctext->Data);
- ctext->Data = newCdata;
- }
- ctext->Length = bytesMoved;
- return 0;
- }
- else {
- cssmPerror("CSSM_EncryptData", crtn);
- return testError(quiet);
- }
-}
-
-static int doRsaDecrypt(
- CSSM_CSP_HANDLE cspHand,
- CSSM_KEY_PTR key,
- CSSM_PADDING padding,
- CSSM_BOOL quiet,
- CSSM_RETURN expectRtn,
- CSSM_DATA *ctext,
- CSSM_DATA *rptext)
-{
- CSSM_CC_HANDLE ccHand;
- int rtn;
- CSSM_RETURN crtn;
- CSSM_SIZE bytesMoved;
- CSSM_DATA remData = {0, NULL};
-
- rtn = genRsaCryptContext(cspHand, key, padding, quiet, ccHand);
- if(rtn) {
- return rtn;
- }
- crtn = CSSM_DecryptData(ccHand,
- ctext,
- 1,
- rptext,
- 1,
- &bytesMoved,
- &remData);
- CSSM_DeleteContext(ccHand);
- if(crtn != expectRtn) {
- printf(" CSSM_DecryptData: expect %s\n", cssmErrToStr(expectRtn));
- printf(" CSSM_DecryptData: got %s\n", cssmErrToStr(crtn));
- return testError(quiet);
- }
- if(crtn) {
- /* no need to process further */
- return 0;
- }
- if(crtn == CSSM_OK) {
- /*
- * Deal with remData - its contents are included in bytesMoved.
- */
- if(remData.Length != 0) {
- /* malloc and copy a new one */
- uint8 *newRpdata = (uint8 *)appMalloc(bytesMoved, NULL);
- memmove(newRpdata, rptext->Data, rptext->Length);
- memmove(newRpdata+rptext->Length, remData.Data, remData.Length);
- CSSM_FREE(rptext->Data);
- rptext->Data = newRpdata;
- }
- rptext->Length = bytesMoved;
- return 0;
- }
- else {
- cssmPerror("CSSM_DecryptData", crtn);
- return testError(quiet);
- }
-}
-
-/*
- * encrypt with specified pad
- * decrypt with specified pad, verify expected result (which may be failure)
- */
-static int doTest(
- CSSM_CSP_HANDLE cspHand,
- CSSM_KEY_PTR pubKey,
- CSSM_KEY_PTR privKey,
- CSSM_PADDING encrPad,
- CSSM_PADDING decrPad,
- CSSM_BOOL quiet,
- CSSM_RETURN expectResult)
-{
- int rtn;
- uint8 ptext[PTEXT_LEN];
- CSSM_DATA ptextData = {PTEXT_LEN, ptext};
- CSSM_DATA ctext = {0, NULL};
- CSSM_DATA rptext = {0, NULL};
-
- simpleGenData(&ptextData, PTEXT_LEN, PTEXT_LEN);
- rtn = doRsaEncrypt(cspHand, pubKey, encrPad, quiet, &ptextData, &ctext);
- if(rtn) {
- goto errOut;
- }
- rtn = doRsaDecrypt(cspHand, privKey, decrPad, quiet, expectResult, &ctext, &rptext);
- if(rtn) {
- goto errOut;
- }
- if(expectResult == CSSM_OK) {
- if(memcmp(rptext.Data, ptextData.Data, PTEXT_LEN)) {
- printf("***Data miscomapare after decrypt\n");
- rtn = testError(quiet);
- }
- }
-errOut:
- if(ctext.Data) {
- CSSM_FREE(ctext.Data);
- }
- if(rptext.Data) {
- CSSM_FREE(rptext.Data);
- }
- return rtn;
-}
-
-int main(int argc, char **argv)
-{
- int arg;
- char *argp;
- unsigned loop;
- CSSM_CSP_HANDLE cspHand;
- int rtn = 0;
-
- /*
- * User-spec'd params
- */
- unsigned loops = LOOPS_DEF;
- CSSM_BOOL verbose = CSSM_FALSE;
- CSSM_BOOL quiet = CSSM_FALSE;
- uint32 keySizeInBits = KEY_SIZE_DEF;
- CSSM_BOOL bareCsp = CSSM_TRUE;
- CSSM_BOOL doPause = CSSM_FALSE;
-
- for(arg=1; arg<argc; arg++) {
- argp = argv[arg];
- switch(argp[0]) {
- case 'l':
- loops = atoi(&argp[2]);
- break;
- case 'k':
- keySizeInBits = atoi(&argv[arg][2]);
- break;
- case 'D':
- bareCsp = CSSM_FALSE;
- break;
- case 'u':
- keySizeInBits = KEY_SIZE_SMALL;
- break;
- case 'v':
- verbose = CSSM_TRUE;
- break;
- case 'p':
- doPause = CSSM_TRUE;
- break;
- case 'q':
- quiet = CSSM_TRUE;
- break;
- case 'h':
- default:
- usage(argv);
- }
- }
-
- testStartBanner("ssl2Padding", argc, argv);
-
- cspHand = cspDlDbStartup(bareCsp, NULL);
- if(cspHand == 0) {
- exit(1);
- }
- CSSM_KEY pubKey;
- CSSM_KEY privKey;
-
- CSSM_RETURN crtn = cspGenKeyPair(cspHand, CSSM_ALGID_RSA,
- USAGE_NAME, USAGE_NAME_LEN,
- keySizeInBits,
- &pubKey, CSSM_TRUE /* ref */, CSSM_KEYUSE_ANY, CSSM_KEYBLOB_RAW_FORMAT_NONE,
- &privKey, CSSM_TRUE /* ref */, CSSM_KEYUSE_ANY, CSSM_KEYBLOB_RAW_FORMAT_NONE,
- CSSM_FALSE);
- if(crtn) {
- printf("***Error generating key pair. Aborting.\n");
- exit(1);
- }
- for(loop=1; ; loop++) {
- if(doPause) {
- fpurge(stdin);
- printf("Top of loop; hit CR to proceed: ");
- getchar();
- }
-
- /* encrypt by client, decrypt by server. */
-
- /*
- * SSLv3+ negotiated, normal case, or
- * both sides support SSLv2 only
- */
- if(!quiet) {
- printf("...loop %u\n", loop);
- printf(" encrPad PKCS1 decrPad PKCS1\n");
- }
- rtn = doTest(cspHand, &pubKey, &privKey,
- CSSM_PADDING_PKCS1, CSSM_PADDING_PKCS1,
- quiet, CSSM_OK);
- if(rtn) {
- break;
- }
-
- /*
- * Server supports SSLv2 and SSLv3+, client supports SSLv2 only
- */
- if(!quiet) {
- printf(" encrPad PKCS1 decrPad SSLv2\n");
- }
- rtn = doTest(cspHand, &pubKey, &privKey,
- CSSM_PADDING_PKCS1, CSSM_PADDING_APPLE_SSLv2,
- quiet, CSSM_OK);
- if(rtn) {
- break;
- }
-
- /*
- * Server supports SSLv2 only, client supports SSLv2 and SSLv3+
- */
- if(!quiet) {
- printf(" encrPad SSLv2 decrPad PKCS1\n");
- }
- rtn = doTest(cspHand, &pubKey, &privKey,
- CSSM_PADDING_APPLE_SSLv2, CSSM_PADDING_PKCS1,
- quiet, CSSM_OK);
- if(rtn) {
- break;
- }
-
- /*
- * Both sides support SSLv3+ but a man in the middle has forced the
- * negotiated protocol down to SSLv2
- */
- if(!quiet) {
- printf(" encrPad SSLv2 decrPad SSLv2, expect failure\n");
- }
- rtn = doTest(cspHand, &pubKey, &privKey,
- CSSM_PADDING_APPLE_SSLv2, CSSM_PADDING_APPLE_SSLv2,
- quiet, CSSMERR_CSP_APPLE_SSLv2_ROLLBACK);
- if(rtn) {
- break;
- }
-
- if(loops && (loop == loops)) {
- break;
- }
- } /* for loop */
-
- CSSM_ModuleDetach(cspHand);
- if((rtn == 0) && !quiet) {
- printf("%s test complete\n", argv[0]);
- }
- return rtn;
-}