#include <utilLib/common.h>
#include <utilLib/cspwrap.h>
#include <clAppUtils/clutils.h>
#include <clAppUtils/certVerify.h>
#include <clAppUtils/BlobList.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Security/cssm.h>
#include <Security/x509defs.h>
#include <Security/oidsattr.h>
#include <Security/oidscert.h>
#include <Security/oidsalg.h>
#include <Security/certextensions.h>
#include <Security/cssmapple.h>
#include <security_cdsa_utils/cuPrintCert.h>
#include <string.h>
#define SUBJ_KEY_LABEL "subjectKey"
#define ROOT_KEY_LABEL "rootKey"
#define SIG_ALG_DEFAULT CSSM_ALGID_SHA1WithRSA
#define SIG_OID_DEFAULT CSSMOID_SHA1WithRSA
#define KEY_ALG_DEFAULT CSSM_ALGID_RSA
#define KEY_SIZE_DEFAULT 512
static void usage(char **argv)
{
printf("Usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" p(rint leaf certs)\n");
printf(" P(ause for MallocDebug)\n");
printf(" q(uiet)\n");
printf(" v(erbose)\n");
exit(1);
}
CSSM_APPLE_TP_NAME_OID rootRdn[] =
{
{ "Apple Computer", &CSSMOID_OrganizationName },
{ "The Big Cheese", &CSSMOID_Title }
};
#define NUM_ROOT_NAMES (sizeof(rootRdn) / sizeof(CSSM_APPLE_TP_NAME_OID))
typedef struct {
const char *testDesc;
CertVerifyPolicy policy;
const char *subjNameEmail; const char *subjAltNameEmail; CSSM_BOOL subjAltNameCritical;
const char *subjNameCommon;
const char *vfyEmailAddrs;
CE_KeyUsage certKeyUse;
CSSM_BOOL keyUseCritical;
CE_KeyUsage vfyKeyUse;
const CSSM_OID *ekuOid;
const char *expectErrStr;
const char *certErrorStr;
const char *orgUnit;
const char *orgName;
} SP_TestCase;
#define GOOD_EMAIL "Alice@Apple.com"
#define BAD_EMAIL "bob@apple.com"
#define CASE_EMAIL_GOOD "Alice@APPLE.com"
#define CASE_EMAIL_BAD "ALice@Apple.com"
#define COMMON_NAME "Alice"
#define ICHAT_ORG "Apple Computer, Inc."
#define ICHAT_ORG_CASE "APPLE Computer, Inc."
#define ICHAT_ORG_BAD "Apple Computer, Inc"
#define ICHAT_NAME "Alice"
#define ICHAT_DOMAIN "mac.com"
#define ICHAT_HANDLE "Alice@mac.com"
#define ICHAT_HANDLE_CASE1 "ALice@mac.com"
#define ICHAT_HANDLE_CASE2 "Alice@mAc.com"
#define ICHAT_NAME_CASE "ALice"
#define ICHAT_DOMAIN_CASE "maC.com"
#define ICHAT_NAME_BAD "Alice_"
#define ICHAT_DOMAIN_BAD "mac.co"
#define ICHAT_HANDLE_BAD1 "Alice@mac.co"
#define ICHAT_HANDLE_BAD2 "Alicg@mac.com"
#define ICHAT_HANDLE_BAD3 "Alicemac.com"
#define ICHAT_HANDLE_BAD4 "Alice@mac@com"
#define KEYUSE_NONE 0
SP_TestCase testCases[] =
{
{
"iChat custom",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_SIGNING,
NULL, NULL,
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION,
NULL, NULL,
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_ExtendedKeyUsageAny,
NULL, NULL,
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom, alt case in name",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME_CASE, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION,
NULL, NULL,
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom, alt case in domain",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_SIGNING,
NULL, NULL,
ICHAT_DOMAIN_CASE, ICHAT_ORG
},
{
"iChat custom, alt case in org, expect fail",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION,
"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
ICHAT_DOMAIN, ICHAT_ORG_CASE
},
{
"iChat custom, bad name",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME_BAD, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_SIGNING,
"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom, bad name",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME_BAD, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION,
"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom, bad domain",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_ExtendedKeyUsageAny,
"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
ICHAT_DOMAIN_BAD, ICHAT_ORG
},
{
"iChat custom, bad org",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION,
"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
ICHAT_DOMAIN, ICHAT_ORG_BAD
},
{
"iChat custom, bad handle (short)",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE_BAD1,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION,
"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom, bad handle (bad name component)",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE_BAD2,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION,
"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom, bad handle (no @)",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE_BAD3,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION,
"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom, bad handle (two @s)",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE_BAD4,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_APPLE_EKU_ICHAT_ENCRYPTION,
"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom, no EKU",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
"CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE",
"0:CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE",
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom, bad EKU",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_TimeStamping,
"CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE",
"0:CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE",
ICHAT_DOMAIN, ICHAT_ORG
},
{
"Email addrs in subjAltName, S/MIME",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL, NULL, NULL
},
{
"Email addrs in subjAltName, iChat",
CVP_iChat,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
NULL, NULL
},
{
"Email addrs in subject name, S/MIME",
CVP_SMIME,
GOOD_EMAIL, NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
NULL, NULL
},
{
"Email addrs in subject name, iChat",
CVP_iChat,
GOOD_EMAIL, NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
NULL, NULL
},
{
"No Email addrs, S/MIME",
CVP_SMIME,
NULL, NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
NULL, NULL
},
{
"No Email addrs, iChat",
CVP_iChat,
NULL, NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
"CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS"
},
{
"Wrong email addrs in SubjectName, S/MIME",
CVP_SMIME,
BAD_EMAIL, NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
"CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND",
"0:CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND"
},
{
"Wrong email addrs in SubjectName, iChat",
CVP_iChat,
BAD_EMAIL, NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
"CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND",
"0:CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND"
},
{
"Wrong email addrs in SubjectAltName, S/MIME",
CVP_SMIME,
NULL, BAD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
"CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND",
"0:CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND"
},
{
"Wrong email addrs in SubjectAltName, iChat",
CVP_iChat,
NULL, BAD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
"CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND",
"0:CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND"
},
{
"Wrong addrs in subj name, correct in subjAltName, S/MIME",
CVP_SMIME,
BAD_EMAIL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
NULL, NULL
},
{
"Wrong addrs in subj name, correct in subjAltName, iChat",
CVP_iChat,
BAD_EMAIL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
NULL, NULL
},
{
"Wrong addrs in subjAltname, correct in subjName, S/MIME",
CVP_SMIME,
GOOD_EMAIL, BAD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
NULL, NULL
},
{
"Wrong addrs in subjAltname, correct in subjName, iChat",
CVP_iChat,
GOOD_EMAIL, BAD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
NULL, NULL
},
{
"Empty subj name, correct subjAltName, no search",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_TRUE,
NULL, NULL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
NULL, NULL
},
{
"Empty subj name, correct subjAltName, good search",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_TRUE,
NULL, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
NULL, NULL
},
{
"Empty subj name, correct subjAltName, not critical, no search",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
NULL, NULL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
"CSSMERR_TP_VERIFY_ACTION_FAILED",
"0:CSSMERR_APPLETP_SMIME_SUBJ_ALT_NAME_NOT_CRIT"
},
{
"Empty subj name, correct subjAltName, not critical, good search",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
NULL, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
"CSSMERR_TP_VERIFY_ACTION_FAILED",
"0:CSSMERR_APPLETP_SMIME_SUBJ_ALT_NAME_NOT_CRIT"
},
{
"Empty subj name, empty subjAltName, no search",
CVP_SMIME,
NULL, NULL, CSSM_FALSE,
NULL, NULL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
"CSSMERR_TP_VERIFY_ACTION_FAILED",
"0:CSSMERR_APPLETP_SMIME_NO_EMAIL_ADDRS"
},
{
"Different case domain in subjAltName, S/MIME",
CVP_SMIME,
NULL, CASE_EMAIL_GOOD, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL, NULL, NULL
},
{
"Different case domain in subjAltName, iChat",
CVP_iChat,
NULL, CASE_EMAIL_GOOD, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
NULL, NULL
},
{
"Different case domain in subjectName, S/MIME",
CVP_SMIME,
CASE_EMAIL_GOOD, NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
NULL, NULL
},
{
"Different case domain in subjectName, iChat",
CVP_iChat,
CASE_EMAIL_GOOD, NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
NULL, NULL
},
{
"Different case local-part in subjAltName, SMIME",
CVP_SMIME,
NULL, CASE_EMAIL_BAD, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
"CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND",
"0:CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND"
},
{
"Different case local-part in subjAltName, iChat",
CVP_iChat,
NULL, CASE_EMAIL_BAD, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
NULL, NULL
},
{
"Different case local-part in SubjectName, S/MIME",
CVP_SMIME,
CASE_EMAIL_BAD, NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
NULL, NULL
},
{
"Different case local-part in SubjectName, iChat",
CVP_iChat,
CASE_EMAIL_BAD, NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
NULL, NULL
},
{
"local-part missing @ in SubjectName",
CVP_SMIME,
"alice_apple.com", NULL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
NULL,
"CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND",
"0:CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND"
},
{
"Key Usage good 1",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_DigitalSignature, CSSM_TRUE, CE_KU_DigitalSignature,
NULL,
NULL, NULL
},
{
"Key Usage good 2",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_DigitalSignature | CE_KU_NonRepudiation, CSSM_TRUE,
CE_KU_DigitalSignature,
NULL,
NULL, NULL
},
{
"KeyUsage in cert but not verified",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_DigitalSignature | CE_KU_NonRepudiation, CSSM_TRUE,
KEYUSE_NONE, NULL,
NULL, NULL
},
{
"Key Usage bad 1",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_DigitalSignature, CSSM_TRUE, CE_KU_NonRepudiation,
NULL,
"CSSMERR_TP_VERIFY_ACTION_FAILED",
"0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE"
},
{
"Key Usage bad 2",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_DigitalSignature | CE_KU_NonRepudiation, CSSM_TRUE,
CE_KU_CRLSign,
NULL,
"CSSMERR_TP_VERIFY_ACTION_FAILED",
"0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE"
},
#if 0
{
"Key Usage not critical",
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_DigitalSignature, CSSM_FALSE, CE_KU_DigitalSignature,
NULL,
"CSSMERR_TP_VERIFY_ACTION_FAILED",
"0:CSSMERR_APPLETP_SMIME_KEYUSAGE_NOT_CRITICAL"
},
#endif
{
"Key Usage KeyAgreement good 1",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_KeyAgreement | CE_KU_EncipherOnly, CSSM_TRUE,
CE_KU_KeyAgreement | CE_KU_EncipherOnly,
NULL,
NULL, NULL
},
{
"Key Usage KeyAgreement good 2",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_KeyAgreement | CE_KU_DecipherOnly, CSSM_TRUE,
CE_KU_KeyAgreement | CE_KU_DecipherOnly,
NULL,
NULL, NULL
},
{
"Key Usage KeyAgreement no {En,De}CipherOnly",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_KeyAgreement | CE_KU_DecipherOnly, CSSM_TRUE,
CE_KU_KeyAgreement,
NULL,
"CSSMERR_TP_VERIFY_ACTION_FAILED",
"0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE"
},
{
"Key Usage KeyAgreement bad EncipherOnly",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_KeyAgreement | CE_KU_DecipherOnly, CSSM_TRUE,
CE_KU_KeyAgreement | CE_KU_EncipherOnly,
NULL,
"CSSMERR_TP_VERIFY_ACTION_FAILED",
"0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE"
},
{
"Key Usage KeyAgreement bad DecipherOnly",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
CE_KU_KeyAgreement | CE_KU_EncipherOnly, CSSM_TRUE,
CE_KU_KeyAgreement | CE_KU_DecipherOnly,
NULL,
"CSSMERR_TP_VERIFY_ACTION_FAILED",
"0:CSSMERR_APPLETP_SMIME_BAD_KEY_USE"
},
{
"Extended Key Usage EmailProtection, S/MIME",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
NULL, NULL
},
{
"Extended Key Usage EmailProtection, iChat",
CVP_iChat,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_EmailProtection,
NULL, NULL
},
{
"Extended Key Usage ExtendedKeyUsageAny, S/MIME",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_ExtendedKeyUsageAny,
NULL, NULL
},
{
"Extended Key Usage ExtendedKeyUsageAny, iChat",
CVP_iChat,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_ExtendedKeyUsageAny,
NULL, NULL
},
{
"Extended Key Usage TimeStamping (bad), S/MIME",
CVP_SMIME,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_TimeStamping,
"CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE",
"0:CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE"
},
{
"Extended Key Usage TimeStamping (bad), iChat",
CVP_iChat,
NULL, GOOD_EMAIL, CSSM_FALSE,
COMMON_NAME, GOOD_EMAIL,
KEYUSE_NONE, CSSM_FALSE, KEYUSE_NONE,
&CSSMOID_TimeStamping,
"CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE",
"0:CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE"
},
{
"iChat custom, missing ICHAT_SIGNING EKU",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
CE_KU_DigitalSignature, CSSM_TRUE, CE_KU_DigitalSignature,
NULL, "CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE",
"0:CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE",
ICHAT_DOMAIN, ICHAT_ORG
},
{
"iChat custom, missing ICHAT_ENCRYPTION EKU",
CVP_iChat,
NULL, NULL, CSSM_FALSE, ICHAT_NAME, ICHAT_HANDLE,
CE_KU_DataEncipherment, CSSM_TRUE, CE_KU_DataEncipherment,
NULL, "CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE",
"0:CSSMERR_APPLETP_SMIME_BAD_EXT_KEY_USE",
ICHAT_DOMAIN, ICHAT_ORG
},
};
#define NUM_TEST_CASES (sizeof(testCases) / sizeof(SP_TestCase))
static CSSM_RETURN genCerts(
CSSM_CL_HANDLE clHand,
CSSM_CSP_HANDLE cspHand,
CSSM_TP_HANDLE tpHand,
CSSM_KEY_PTR rootPrivKey,
CSSM_KEY_PTR rootPubKey,
CSSM_KEY_PTR subjPubKey,
const char *subjNameEmail, const char *subjAltNameEmail, const char *subjNameCommon,
CSSM_BOOL subjAltNameCritical,
const char *subjOrgUnit,
const char *subjOrgName,
CE_KeyUsage certKeyUse,
CSSM_BOOL keyUseCritical,
const CSSM_OID *ekuOid,
CSSM_DATA &rootCert, CSSM_DATA &subjCert)
{
CSSM_DATA refId;
CSSM_RETURN crtn;
CSSM_APPLE_TP_CERT_REQUEST certReq;
CSSM_TP_REQUEST_SET reqSet;
sint32 estTime;
CSSM_BOOL confirmRequired;
CSSM_TP_RESULT_SET_PTR resultSet;
CSSM_ENCODED_CERT *encCert;
CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext;
CSSM_FIELD policyId;
CE_GeneralNames genNames;
CE_GeneralName genName;
CE_ExtendedKeyUsage extendedKeyUse;
CE_DataAndType rootExts[2];
CE_DataAndType leafExts[3];
unsigned numLeafExts = 0;
rootExts[0].type = DT_KeyUsage;
rootExts[0].critical = CSSM_TRUE;
rootExts[0].extension.keyUsage =
CE_KU_DigitalSignature | CE_KU_KeyCertSign;
rootExts[1].type = DT_BasicConstraints;
rootExts[1].critical = CSSM_TRUE;
rootExts[1].extension.basicConstraints.cA = CSSM_TRUE;
rootExts[1].extension.basicConstraints.pathLenConstraintPresent =
CSSM_TRUE;
rootExts[1].extension.basicConstraints.pathLenConstraint = 2;
if(certKeyUse) {
leafExts[0].type = DT_KeyUsage;
leafExts[0].critical = keyUseCritical;
leafExts[0].extension.keyUsage = certKeyUse;
numLeafExts++;
}
if(subjAltNameEmail) {
leafExts[numLeafExts].type = DT_SubjectAltName;
leafExts[numLeafExts].critical = subjAltNameCritical;
genName.berEncoded = CSSM_FALSE;
genName.name.Data = (uint8 *)subjAltNameEmail;
genName.nameType = GNT_RFC822Name;
genName.name.Length = strlen(subjAltNameEmail);
genNames.numNames = 1;
genNames.generalName = &genName;
leafExts[numLeafExts].extension.subjectAltName = genNames;
numLeafExts++;
}
if(ekuOid) {
leafExts[numLeafExts].type = DT_ExtendedKeyUsage;
leafExts[numLeafExts].critical = CSSM_FALSE; extendedKeyUse.numPurposes = 1;
extendedKeyUse.purposes = (CSSM_OID_PTR)ekuOid;
leafExts[numLeafExts].extension.extendedKeyUsage = extendedKeyUse;
numLeafExts++;
}
CSSM_APPLE_TP_NAME_OID subjRdn[4];
unsigned numSubjNames = 0;
if(subjNameEmail) {
subjRdn[0].string = subjNameEmail;
subjRdn[0].oid = &CSSMOID_EmailAddress;
numSubjNames++;
}
if(subjNameCommon) {
subjRdn[numSubjNames].string = subjNameCommon;
subjRdn[numSubjNames].oid = &CSSMOID_CommonName;
numSubjNames++;
}
if(subjOrgUnit) {
subjRdn[numSubjNames].string = subjOrgUnit;
subjRdn[numSubjNames].oid = &CSSMOID_OrganizationalUnitName;
numSubjNames++;
}
if(subjOrgName) {
subjRdn[numSubjNames].string = subjOrgName;
subjRdn[numSubjNames].oid = &CSSMOID_OrganizationName;
numSubjNames++;
}
memset(&certReq, 0, sizeof(CSSM_APPLE_TP_CERT_REQUEST));
certReq.cspHand = cspHand;
certReq.clHand = clHand;
certReq.serialNumber = 0x12345678;
certReq.numSubjectNames = NUM_ROOT_NAMES;
certReq.subjectNames = rootRdn;
certReq.numIssuerNames = 0;
certReq.issuerNames = NULL;
certReq.certPublicKey = rootPubKey;
certReq.issuerPrivateKey = rootPrivKey;
certReq.signatureAlg = SIG_ALG_DEFAULT;
certReq.signatureOid = SIG_OID_DEFAULT;
certReq.notBefore = 0; certReq.notAfter = 10000; certReq.numExtensions = 2;
certReq.extensions = rootExts;
reqSet.NumberOfRequests = 1;
reqSet.Requests = &certReq;
memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
memset(&policyId, 0, sizeof(CSSM_FIELD));
policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN;
CallerAuthContext.Policy.NumberOfPolicyIds = 1;
CallerAuthContext.Policy.PolicyIds = &policyId;
crtn = CSSM_TP_SubmitCredRequest(tpHand,
NULL, CSSM_TP_AUTHORITY_REQUEST_CERTISSUE,
&reqSet,
&CallerAuthContext,
&estTime,
&refId);
if(crtn) {
printError("CSSM_TP_SubmitCredRequest", crtn);
return crtn;
}
crtn = CSSM_TP_RetrieveCredResult(tpHand,
&refId,
NULL, &estTime,
&confirmRequired,
&resultSet);
if(crtn) {
printError("CSSM_TP_RetrieveCredResult", crtn);
return crtn;
}
if(resultSet == NULL) {
printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n");
return crtn;
}
encCert = (CSSM_ENCODED_CERT *)resultSet->Results;
rootCert = encCert->CertBlob;
CSSM_FREE(encCert);
CSSM_FREE(resultSet);
certReq.serialNumber = 0x8765;
certReq.numSubjectNames = numSubjNames;
certReq.subjectNames = subjRdn;
certReq.numIssuerNames = NUM_ROOT_NAMES;
certReq.issuerNames = rootRdn;
certReq.certPublicKey = subjPubKey;
certReq.issuerPrivateKey = rootPrivKey;
certReq.numExtensions = numLeafExts;
certReq.extensions = leafExts;
crtn = CSSM_TP_SubmitCredRequest(tpHand,
NULL, CSSM_TP_AUTHORITY_REQUEST_CERTISSUE,
&reqSet,
&CallerAuthContext,
&estTime,
&refId);
if(crtn) {
printError("CSSM_TP_SubmitCredRequest (2)", crtn);
return crtn;
}
crtn = CSSM_TP_RetrieveCredResult(tpHand,
&refId,
NULL, &estTime,
&confirmRequired,
&resultSet); if(crtn) {
printError("CSSM_TP_RetrieveCredResult (2)", crtn);
return crtn;
}
if(resultSet == NULL) {
printf("***CSSM_TP_RetrieveCredResult (2) returned NULL "
"result set.\n");
return crtn;
}
encCert = (CSSM_ENCODED_CERT *)resultSet->Results;
subjCert = encCert->CertBlob;
CSSM_FREE(encCert);
CSSM_FREE(resultSet);
return CSSM_OK;
}
static void copyToBlob(
const CSSM_DATA &src,
CSSM_DATA &blob)
{
blob.Data = (uint8 *)malloc(src.Length);
blob.Length = src.Length;
memmove(blob.Data, src.Data, src.Length);
}
int main(int argc, char **argv)
{
CSSM_CL_HANDLE clHand; CSSM_CSP_HANDLE cspHand; CSSM_TP_HANDLE tpHand; CSSM_DATA rootCert;
CSSM_DATA subjCert;
CSSM_KEY subjPubKey; CSSM_KEY subjPrivKey; CSSM_KEY rootPubKey; CSSM_KEY rootPrivKey; CSSM_RETURN crtn = CSSM_OK;
int vfyRtn = 0;
int arg;
SP_TestCase *testCase;
unsigned testNum;
CSSM_BOOL printLeafCerts = CSSM_FALSE;
CSSM_BOOL quiet = CSSM_FALSE;
CSSM_BOOL verbose = CSSM_FALSE;
CSSM_BOOL doPause = CSSM_FALSE;
for(arg=1; arg<argc; arg++) {
char *argp = argv[arg];
switch(argp[0]) {
case 'p':
printLeafCerts = CSSM_TRUE;
break;
case 'P':
doPause = CSSM_TRUE;
break;
case 'q':
quiet = CSSM_TRUE;
break;
case 'v':
verbose = CSSM_TRUE;
break;
default:
usage(argv);
}
}
testStartBanner("smimePolicy", argc, argv);
clHand = clStartup();
if(clHand == 0) {
return 0;
}
tpHand = tpStartup();
if(tpHand == 0) {
return 0;
}
cspHand = cspStartup();
if(cspHand == 0) {
return 0;
}
crtn = cspGenKeyPair(cspHand,
KEY_ALG_DEFAULT,
SUBJ_KEY_LABEL,
strlen(SUBJ_KEY_LABEL),
KEY_SIZE_DEFAULT,
&subjPubKey,
CSSM_FALSE, CSSM_KEYUSE_VERIFY,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
&subjPrivKey,
CSSM_TRUE, CSSM_KEYUSE_SIGN,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
CSSM_FALSE);
if(crtn) {
return crtn;
}
crtn = cspGenKeyPair(cspHand,
KEY_ALG_DEFAULT,
ROOT_KEY_LABEL,
strlen(ROOT_KEY_LABEL),
KEY_SIZE_DEFAULT,
&rootPubKey,
CSSM_FALSE, CSSM_KEYUSE_VERIFY,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
&rootPrivKey,
CSSM_TRUE, CSSM_KEYUSE_SIGN,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
CSSM_FALSE);
if(crtn) {
goto abort;
}
for(testNum=0; testNum<NUM_TEST_CASES; testNum++) {
testCase = &testCases[testNum];
if(!quiet) {
printf("%s\n", testCase->testDesc);
}
crtn = genCerts(clHand, cspHand, tpHand,
&rootPrivKey, &rootPubKey, &subjPubKey,
testCase->subjNameEmail, testCase->subjAltNameEmail,
testCase->subjNameCommon, testCase->subjAltNameCritical,
testCase->orgUnit, testCase->orgName,
testCase->certKeyUse, testCase->keyUseCritical, testCase->ekuOid,
rootCert, subjCert);
if(printLeafCerts) {
printCert(subjCert.Data, subjCert.Length, CSSM_FALSE);
}
BlobList leaf;
BlobList root;
CSSM_DATA blob;
copyToBlob(subjCert, blob);
CSSM_FREE(subjCert.Data);
leaf.addBlob(blob);
copyToBlob(rootCert, blob);
CSSM_FREE(rootCert.Data);
root.addBlob(blob);
if(crtn) {
if(testError(quiet)) {
break;
}
}
vfyRtn = certVerifySimple(tpHand, clHand, cspHand,
leaf, root,
CSSM_FALSE, CSSM_FALSE, CSSM_FALSE, testCase->policy,
NULL, CSSM_FALSE, testCase->vfyEmailAddrs,
testCase->vfyKeyUse,
testCase->expectErrStr,
testCase->certErrorStr ? 1 : 0,
testCase->certErrorStr ? (const char **)&testCase->certErrorStr :
NULL,
0, NULL, CSSM_FALSE, quiet,
verbose);
if(vfyRtn) {
if(testError(quiet)) {
break;
}
}
if(doPause) {
fpurge(stdin);
printf("Pausing for mallocDebug. CR to continue: ");
getchar();
}
}
cspFreeKey(cspHand, &rootPubKey);
cspFreeKey(cspHand, &rootPrivKey);
cspFreeKey(cspHand, &subjPubKey);
cspFreeKey(cspHand, &subjPrivKey);
abort:
if(cspHand != 0) {
CSSM_ModuleDetach(cspHand);
}
if(clHand != 0) {
CSSM_ModuleDetach(clHand);
}
if(tpHand != 0) {
CSSM_ModuleDetach(tpHand);
}
if(!vfyRtn && !crtn && !quiet) {
printf("...test passed\n");
}
return 0;
}