You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5959 lines
194 KiB
5959 lines
194 KiB
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1996
|
|
//
|
|
// File: tstore2.cpp
|
|
//
|
|
// Contents: Cert Store API Tests: Create and Add a chain of certificates
|
|
// and CRLs to the store.
|
|
//
|
|
// See Usage() for a list of test options.
|
|
//
|
|
//
|
|
// Functions: main
|
|
//
|
|
// History: 07-Mar-96 philh created
|
|
// 31-May-96 helles Removed check for a particular error code,
|
|
// NTE_PROV_TYPE_NOT_DEF, since this can get
|
|
// overwritten due to known problem with
|
|
// the msvcr40d.dll on Win95.
|
|
// 07-Jun-96 HelleS Added printing the command line
|
|
// 20-Aug-96 jeffspel name changes
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#define CMS_PKCS7 1
|
|
|
|
#include <windows.h>
|
|
#include <assert.h>
|
|
#include "wincrypt.h"
|
|
#include "setcert.h"
|
|
#include "signcde.h"
|
|
#include "softpub.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
#include <time.h>
|
|
#include <stddef.h>
|
|
|
|
//#define TEST_PROV_DSS PROV_DSS
|
|
#define TEST_PROV_DSS PROV_DSS_DH
|
|
|
|
// # of bytes for a hash. Such as, SHA1 (20) or MD5 (16)
|
|
#define MAX_HASH_LEN 20
|
|
|
|
#if 1
|
|
// client authentication doesn't know about sha1
|
|
#define SIGNATURE_ALG_OBJID szOID_RSA_MD5RSA
|
|
#else
|
|
#define SIGNATURE_ALG_OBJID szOID_OIWSEC_sha1RSASign
|
|
#endif
|
|
|
|
#define DSS_SIGNATURE_ALG_OBJID szOID_X957_SHA1DSA
|
|
|
|
#define ENH_1024_CONTAINER_NAME_A "Regression 1024"
|
|
#define ENH_1024_CONTAINER_NAME_W L"Regression 1024"
|
|
#define ENH_2048_CONTAINER_NAME_A "Regression 2048"
|
|
#define ENH_2048_CONTAINER_NAME_W L"Regression 2048"
|
|
#define DSS_512_CONTAINER_NAME_A "Regression 512"
|
|
#define DSS_512_CONTAINER_NAME_W L"Regression 512"
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Parameters, data used to encode the messages.
|
|
//--------------------------------------------------------------------------
|
|
static DWORD dwCertEncodingType = X509_ASN_ENCODING;
|
|
static DWORD dwMsgEncodingType = PKCS_7_ASN_ENCODING;
|
|
static DWORD dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
|
|
static SYSTEMTIME TestTime;
|
|
static LPSTR pszContainer = NULL;
|
|
static LPWSTR pwszContainer = NULL;
|
|
static HCRYPTPROV hRSACryptProv = 0;
|
|
static HCRYPTPROV hEnh1024CryptProv = 0;
|
|
static HCRYPTPROV hEnh2048CryptProv = 0;
|
|
static HCRYPTPROV hDSSCryptProv = 0;
|
|
static HCRYPTPROV hDSS512CryptProv = 0;
|
|
static BOOL fGenerate = FALSE;
|
|
static BOOL fExportable = FALSE;
|
|
static BOOL fUserProtected = FALSE;
|
|
static BOOL fProviders = FALSE;
|
|
static BOOL fMachine = FALSE;
|
|
static BOOL fInheritParameters = FALSE;
|
|
|
|
#define TIME_INVALID_PARA_FLAG 0x00000001
|
|
#define REVOKED_PARA_FLAG 0x00000002
|
|
#define PROV_PARA_FLAG 0x00000004
|
|
#define XCHG_PARA_FLAG 0x00000008
|
|
#define CA_PARA_FLAG 0x00000010
|
|
#define NO_NAME_PARA_FLAG 0x00000020
|
|
#define ALT_DIR_NAME_PARA_FLAG 0x00000040
|
|
#define SET_PARA_FLAG 0x00000080
|
|
#define ALL_EXT_PARA_FLAG 0x00000100
|
|
#define SPC_EXT_PARA_FLAG 0x00000200
|
|
#define SPC_COM_PARA_FLAG 0x00000400
|
|
#define SPC_AGENCY_PARA_FLAG 0x00000800
|
|
#define SPC_AGENCY_INFO_PARA_FLAG 0x00001000
|
|
// "Valid" certs to give to other companies to test interoperability
|
|
#define VALID_PARA_FLAG 0x00002000
|
|
#define DELTA_CRL_PARA_FLAG 0x00004000
|
|
#define AUX1_PARA_FLAG 0x00010000
|
|
#define AUX2_PARA_FLAG 0x00020000
|
|
// For duplicate, use previous cert's serial number
|
|
#define DUPLICATE_PARA_FLAG 0x00040000
|
|
#define NO_EXT_PARA_FLAG 0x00080000
|
|
#define DUPLICATE_CRL_PARA_FLAG 0x00100000
|
|
#define NO_CRL_EXT_PARA_FLAG 0x00200000
|
|
#define GENERALIZED_TIME_PARA_FLAG 0x00400000
|
|
#define NETSCAPE_PARA_FLAG 0x00800000
|
|
|
|
#define CTL1_PARA_FLAG 0x01000000
|
|
#define CTL2_PARA_FLAG 0x02000000
|
|
#define USE1_PARA_FLAG 0x04000000
|
|
#define USE2_PARA_FLAG 0x08000000
|
|
#define HTTP_PARA_FLAG 0x10000000
|
|
|
|
#define DSS_PARA_FLAG 0x80000000
|
|
#define DSS_512_PARA_FLAG 0x40000000
|
|
#define ENH_1024_PARA_FLAG 0x40000000
|
|
#define ENH_2048_PARA_FLAG 0x20000000
|
|
|
|
|
|
#define szSignManifold "Signer Manifold"
|
|
#define szXchgManifold "Recipient Manifold"
|
|
|
|
typedef struct _CERT_PARA {
|
|
LPSTR pszName;
|
|
DWORD dwIssuer;
|
|
DWORD dwFlags;
|
|
LPSTR pszManifold;
|
|
} CERT_PARA;
|
|
|
|
#define BASE_OR_DELTA_CA_ISSUER 1
|
|
#define UPDATE_CTL_SIGNER 1
|
|
|
|
#define POLICY_ROOT 0
|
|
#define POLICY_CA 1
|
|
|
|
#define CERT_CNT 76
|
|
static CERT_PARA CertPara[CERT_CNT] = {
|
|
"root", 0, CA_PARA_FLAG, // 0
|
|
NULL,
|
|
"CA", 0, CA_PARA_FLAG |
|
|
DUPLICATE_CRL_PARA_FLAG, // 1
|
|
NULL,
|
|
"TestRoot", 2, CA_PARA_FLAG |
|
|
ENH_2048_PARA_FLAG |
|
|
VALID_PARA_FLAG, // 2
|
|
NULL,
|
|
"TestSigner", 2, PROV_PARA_FLAG | VALID_PARA_FLAG |
|
|
USE1_PARA_FLAG, // 3
|
|
szSignManifold,
|
|
"TestRecipient",2, PROV_PARA_FLAG | XCHG_PARA_FLAG |
|
|
VALID_PARA_FLAG | USE1_PARA_FLAG, // 4
|
|
szXchgManifold,
|
|
"me", 1, PROV_PARA_FLAG |
|
|
ENH_1024_PARA_FLAG |
|
|
USE2_PARA_FLAG, // 5
|
|
NULL,
|
|
"me", 1, PROV_PARA_FLAG |
|
|
ENH_1024_PARA_FLAG |
|
|
XCHG_PARA_FLAG, // 6
|
|
NULL,
|
|
"setrevoked", 1, REVOKED_PARA_FLAG | PROV_PARA_FLAG |
|
|
SET_PARA_FLAG |
|
|
ENH_2048_PARA_FLAG, // 7
|
|
NULL,
|
|
"setrevoked", 1, REVOKED_PARA_FLAG | XCHG_PARA_FLAG |
|
|
SET_PARA_FLAG |
|
|
PROV_PARA_FLAG | ENH_2048_PARA_FLAG,// 8
|
|
NULL,
|
|
"time invalid", 1, TIME_INVALID_PARA_FLAG, // 9
|
|
NULL,
|
|
"setkeith", 1, SET_PARA_FLAG, // 10
|
|
NULL,
|
|
"setkeith", 1, XCHG_PARA_FLAG | USE2_PARA_FLAG | // 11
|
|
SET_PARA_FLAG,
|
|
NULL,
|
|
"kevin", 1, 0, // 12
|
|
NULL,
|
|
"kevin", 1, XCHG_PARA_FLAG | USE2_PARA_FLAG, // 13
|
|
NULL,
|
|
"all ext", 1, ALL_EXT_PARA_FLAG | AUX1_PARA_FLAG |
|
|
SET_PARA_FLAG |
|
|
ALT_DIR_NAME_PARA_FLAG |
|
|
AUX2_PARA_FLAG |
|
|
USE1_PARA_FLAG | USE2_PARA_FLAG, // 14
|
|
NULL,
|
|
"MSPub", 17, SPC_EXT_PARA_FLAG | SPC_COM_PARA_FLAG |
|
|
PROV_PARA_FLAG | USE1_PARA_FLAG, // 15
|
|
NULL,
|
|
"PhilPub", 17, SPC_EXT_PARA_FLAG | PROV_PARA_FLAG |
|
|
USE2_PARA_FLAG, // 16
|
|
NULL,
|
|
"MSAgency", 1, SPC_EXT_PARA_FLAG | SPC_AGENCY_PARA_FLAG |
|
|
PROV_PARA_FLAG | CA_PARA_FLAG, // 17
|
|
NULL,
|
|
"AgencyInfo", 1, SPC_AGENCY_INFO_PARA_FLAG, // 18
|
|
NULL,
|
|
"duplicate1", 1, AUX1_PARA_FLAG | NO_EXT_PARA_FLAG |
|
|
USE1_PARA_FLAG, // 19
|
|
NULL,
|
|
"duplicate2", 1, AUX2_PARA_FLAG | NO_EXT_PARA_FLAG |
|
|
DUPLICATE_PARA_FLAG |
|
|
USE2_PARA_FLAG, // 20
|
|
NULL,
|
|
"GeneralRoot", 21, CA_PARA_FLAG |
|
|
GENERALIZED_TIME_PARA_FLAG |
|
|
PROV_PARA_FLAG |
|
|
DSS_PARA_FLAG, // 21
|
|
NULL,
|
|
"GeneralTime", 21, GENERALIZED_TIME_PARA_FLAG |
|
|
PROV_PARA_FLAG |
|
|
DSS_512_PARA_FLAG |
|
|
DSS_PARA_FLAG, // 22
|
|
NULL,
|
|
"Generalrevoked", 21, REVOKED_PARA_FLAG | DSS_PARA_FLAG, // 23
|
|
NULL,
|
|
"NoCRLExtCA", 0, CA_PARA_FLAG | NO_CRL_EXT_PARA_FLAG, // 24
|
|
NULL,
|
|
"NoCRLExtrevoked", 24, REVOKED_PARA_FLAG, // 25
|
|
NULL,
|
|
"NetscapeCA", 0, NETSCAPE_PARA_FLAG | CA_PARA_FLAG |
|
|
DSS_PARA_FLAG |
|
|
REVOKED_PARA_FLAG, // 26
|
|
NULL,
|
|
"Netscape", 26, NETSCAPE_PARA_FLAG | REVOKED_PARA_FLAG, // 27
|
|
NULL,
|
|
"Ctl0", 1, CTL1_PARA_FLAG | NO_EXT_PARA_FLAG, // 28
|
|
NULL,
|
|
"Ctl1", 2, CTL1_PARA_FLAG, // 29
|
|
NULL,
|
|
"Ctl1Invalid", 2, CTL1_PARA_FLAG | TIME_INVALID_PARA_FLAG |
|
|
DUPLICATE_PARA_FLAG, // 30
|
|
NULL,
|
|
"Ctl2", 1, CTL2_PARA_FLAG, // 31
|
|
NULL,
|
|
"Ctl2Invalid", 1, CTL2_PARA_FLAG | TIME_INVALID_PARA_FLAG |
|
|
DUPLICATE_PARA_FLAG, // 32
|
|
NULL,
|
|
"Http2", 1, CTL2_PARA_FLAG | HTTP_PARA_FLAG |
|
|
NO_EXT_PARA_FLAG, // 33
|
|
NULL,
|
|
"Http2Invalid", 1, CTL2_PARA_FLAG | TIME_INVALID_PARA_FLAG |
|
|
DUPLICATE_PARA_FLAG | HTTP_PARA_FLAG |
|
|
NO_EXT_PARA_FLAG, // 34
|
|
NULL,
|
|
"NoNameIssuer1", 0, CA_PARA_FLAG | ALT_DIR_NAME_PARA_FLAG, // 35
|
|
NULL,
|
|
"NoNameSubject1", 35, NO_NAME_PARA_FLAG, // 36
|
|
NULL,
|
|
"NoNameIssuer2", 0, CA_PARA_FLAG | ALT_DIR_NAME_PARA_FLAG, // 37
|
|
NULL,
|
|
"NoNameSubject2", 37, NO_NAME_PARA_FLAG |
|
|
ALT_DIR_NAME_PARA_FLAG, // 38
|
|
NULL,
|
|
"Hellman", 21, XCHG_PARA_FLAG | NO_EXT_PARA_FLAG |
|
|
PROV_PARA_FLAG |
|
|
DSS_PARA_FLAG, // 39
|
|
NULL,
|
|
"TestSigner2", 2, PROV_PARA_FLAG | VALID_PARA_FLAG |
|
|
USE1_PARA_FLAG, // 40
|
|
szSignManifold,
|
|
"TestRecipient2", 2, PROV_PARA_FLAG | XCHG_PARA_FLAG |
|
|
VALID_PARA_FLAG | USE1_PARA_FLAG, // 41
|
|
szXchgManifold,
|
|
"TestSigner3", 2, PROV_PARA_FLAG | VALID_PARA_FLAG |
|
|
USE1_PARA_FLAG, // 42
|
|
szSignManifold,
|
|
"UTF8", 2, VALID_PARA_FLAG | NO_EXT_PARA_FLAG, // 43
|
|
NULL,
|
|
"DssRoot", 44, CA_PARA_FLAG | VALID_PARA_FLAG |
|
|
NO_EXT_PARA_FLAG |
|
|
DSS_PARA_FLAG, // 44
|
|
NULL,
|
|
"DssCA", 44, CA_PARA_FLAG | VALID_PARA_FLAG |
|
|
NO_EXT_PARA_FLAG |
|
|
DSS_PARA_FLAG, // 45
|
|
NULL,
|
|
"DssEnd", 45, VALID_PARA_FLAG | NO_EXT_PARA_FLAG |
|
|
PROV_PARA_FLAG |
|
|
DSS_PARA_FLAG, // 46
|
|
NULL,
|
|
"ZeroNotAfter", 2, VALID_PARA_FLAG |
|
|
PROV_PARA_FLAG, // 47
|
|
NULL,
|
|
"V1", 48, CA_PARA_FLAG | VALID_PARA_FLAG |
|
|
NO_EXT_PARA_FLAG |
|
|
NO_CRL_EXT_PARA_FLAG, // 48
|
|
NULL,
|
|
"V2", 48, VALID_PARA_FLAG | NO_EXT_PARA_FLAG, // 49
|
|
NULL,
|
|
"DeltaEndValid", 1, DELTA_CRL_PARA_FLAG, // 50
|
|
NULL,
|
|
"DeltaNoValid", 1, DELTA_CRL_PARA_FLAG | NO_EXT_PARA_FLAG, // 51
|
|
NULL,
|
|
"DeltaEndRevoked", 1, DELTA_CRL_PARA_FLAG | // 52
|
|
REVOKED_PARA_FLAG,
|
|
NULL,
|
|
"DeltaCAValid", 1, DELTA_CRL_PARA_FLAG | // 53
|
|
CA_PARA_FLAG,
|
|
NULL,
|
|
"DeltaCARevoked", 1, DELTA_CRL_PARA_FLAG | // 54
|
|
CA_PARA_FLAG |
|
|
REVOKED_PARA_FLAG,
|
|
NULL,
|
|
"NoCDPValid", 1, DELTA_CRL_PARA_FLAG, // 55
|
|
NULL,
|
|
"NoCDPRevoked", 1, DELTA_CRL_PARA_FLAG | // 56
|
|
REVOKED_PARA_FLAG,
|
|
NULL,
|
|
"UnsupportedCDP", 1, DELTA_CRL_PARA_FLAG | // 57
|
|
REVOKED_PARA_FLAG,
|
|
NULL,
|
|
"NotPermitted", 1, ALT_DIR_NAME_PARA_FLAG, // 58
|
|
NULL,
|
|
"Excluded", 1, ALT_DIR_NAME_PARA_FLAG, // 59
|
|
NULL,
|
|
|
|
"TestAIARoot", 60, CA_PARA_FLAG | NO_EXT_PARA_FLAG | // 60
|
|
NO_CRL_EXT_PARA_FLAG,
|
|
NULL,
|
|
"TestAIARevokeRoot", 61, CA_PARA_FLAG | NO_EXT_PARA_FLAG | // 61
|
|
NO_CRL_EXT_PARA_FLAG,
|
|
NULL,
|
|
"TestAIACA", 60, CA_PARA_FLAG | NO_EXT_PARA_FLAG | // 62
|
|
NO_CRL_EXT_PARA_FLAG,
|
|
NULL,
|
|
"TestAIACA", 61, CA_PARA_FLAG | NO_EXT_PARA_FLAG |
|
|
NO_CRL_EXT_PARA_FLAG |
|
|
REVOKED_PARA_FLAG, // 63
|
|
NULL,
|
|
"TestAIAEnd", 63, NO_EXT_PARA_FLAG, // 64
|
|
NULL,
|
|
"MissingNCCA", 0, CA_PARA_FLAG, // 65
|
|
NULL,
|
|
"MissingNCEnd", 65, 0, // 66
|
|
NULL,
|
|
"TestAIAExpireRoot", 67, CA_PARA_FLAG | NO_EXT_PARA_FLAG | // 67
|
|
NO_CRL_EXT_PARA_FLAG,
|
|
NULL,
|
|
"TestAIACA", 67, CA_PARA_FLAG | NO_EXT_PARA_FLAG |
|
|
NO_CRL_EXT_PARA_FLAG |
|
|
TIME_INVALID_PARA_FLAG, // 68
|
|
NULL,
|
|
|
|
"InvalidKeyUsageCA", 2, CA_PARA_FLAG | VALID_PARA_FLAG, // 69
|
|
NULL,
|
|
"InvalidKeyUsageEnd", 69, NO_EXT_PARA_FLAG, // 70
|
|
NULL,
|
|
|
|
"RolloverRoot", 71, CA_PARA_FLAG | VALID_PARA_FLAG | NO_EXT_PARA_FLAG |
|
|
DSS_PARA_FLAG, // 71
|
|
NULL,
|
|
"RolloverCA", 71, CA_PARA_FLAG | VALID_PARA_FLAG | NO_EXT_PARA_FLAG |
|
|
DSS_PARA_FLAG, // 72
|
|
NULL,
|
|
"RolloverEnd", 72, VALID_PARA_FLAG |
|
|
DSS_PARA_FLAG, // 73
|
|
NULL,
|
|
|
|
"RolloverRoot", 2, CA_PARA_FLAG | VALID_PARA_FLAG | NO_EXT_PARA_FLAG|
|
|
ENH_1024_PARA_FLAG,
|
|
NULL, // 74
|
|
"RolloverRoot", 74, CA_PARA_FLAG | VALID_PARA_FLAG | NO_EXT_PARA_FLAG |
|
|
DSS_PARA_FLAG, // 75
|
|
NULL,
|
|
};
|
|
|
|
#define ROLLOVER_CROSS_CERT 74
|
|
|
|
|
|
#define EXPIRED_CRL_FLAG 0x00000001
|
|
#define REMOVE_FROM_CRL_FLAG 0x00000002
|
|
#define HOLD_CRL_FLAG 0x00000004
|
|
#define FRESHEST_CRL_FLAG 0x00000010
|
|
#define NO_FRESHEST_CDP_CRL_FLAG 0x00000020
|
|
#define NO_IDP_CRL_FLAG 0x00000100
|
|
#define ONLY_USERS_CRL_FLAG 0x00000200
|
|
#define ONLY_CAS_CRL_FLAG 0x00000400
|
|
#define UNSUPPORTED_IDP_OPTIONS_CRL_FLAG 0x00000800
|
|
#define UNSUPPORTED_CRITICAL_EXT_CRL_FLAG 0x00001000
|
|
#define NO_ENTRIES_CRL_FLAG 0x00002000
|
|
|
|
typedef struct _BASE_DELTA_CRL_PARA {
|
|
int iBase;
|
|
DWORD dwFlags;
|
|
} BASE_DELTA_CRL_PARA;
|
|
|
|
static BASE_DELTA_CRL_PARA BaseDeltaCrlPara[] = {
|
|
// Users Only: Base and Delta
|
|
1, ONLY_USERS_CRL_FLAG,
|
|
1, ONLY_USERS_CRL_FLAG | FRESHEST_CRL_FLAG,
|
|
|
|
// CAs Only: Base and Delta
|
|
2, ONLY_CAS_CRL_FLAG,
|
|
2, ONLY_CAS_CRL_FLAG | FRESHEST_CRL_FLAG,
|
|
|
|
// Base has entries, Delta has no entries
|
|
3, HOLD_CRL_FLAG,
|
|
3, NO_ENTRIES_CRL_FLAG | FRESHEST_CRL_FLAG,
|
|
|
|
// Base has no entries, Delta has entries
|
|
4, NO_ENTRIES_CRL_FLAG,
|
|
4, FRESHEST_CRL_FLAG,
|
|
|
|
// Base has entries, Delta has remove entries
|
|
5, HOLD_CRL_FLAG,
|
|
5, REMOVE_FROM_CRL_FLAG | FRESHEST_CRL_FLAG,
|
|
|
|
// Valid base, delta has unsupported IDP options
|
|
6, HOLD_CRL_FLAG,
|
|
6, FRESHEST_CRL_FLAG | UNSUPPORTED_IDP_OPTIONS_CRL_FLAG,
|
|
|
|
// Expired base, valid delta
|
|
7, EXPIRED_CRL_FLAG,
|
|
7, FRESHEST_CRL_FLAG,
|
|
|
|
// Valid base, expired delta
|
|
8, 0,
|
|
8, EXPIRED_CRL_FLAG | FRESHEST_CRL_FLAG,
|
|
|
|
|
|
// Expired base, without a freshest CDP extension
|
|
9, EXPIRED_CRL_FLAG | NO_FRESHEST_CDP_CRL_FLAG,
|
|
9, FRESHEST_CRL_FLAG,
|
|
|
|
// Base without IDP and no freshest, delta CRL
|
|
10, NO_IDP_CRL_FLAG | NO_FRESHEST_CDP_CRL_FLAG,
|
|
|
|
// Base and Delta CRL with unsupported critical ext
|
|
11, UNSUPPORTED_CRITICAL_EXT_CRL_FLAG,
|
|
11, UNSUPPORTED_CRITICAL_EXT_CRL_FLAG | FRESHEST_CRL_FLAG,
|
|
|
|
// Valid base with number > above delta indicator
|
|
100, 0,
|
|
};
|
|
#define BASE_DELTA_CRL_CNT \
|
|
(sizeof(BaseDeltaCrlPara)/sizeof(BaseDeltaCrlPara[0]))
|
|
|
|
typedef struct _UPDATE_CTL_PARA {
|
|
BOOL fTimeInvalid;
|
|
LPSTR pszUsageObjId;
|
|
LPSTR pszListIdentifier;
|
|
LPWSTR pwszUrl;
|
|
} UPDATE_CTL_PARA;
|
|
|
|
static UPDATE_CTL_PARA UpdateCtlPara[] = {
|
|
FALSE, "1.3.2000.1", "UpdateCtl1", L"file://testupdate1.ctl",
|
|
TRUE, "1.3.2000.1", "UpdateCtl1", L"file://testupdate1.ctl",
|
|
FALSE, "1.3.2000.2", "UpdateCtl2", L"file://testupdate2.ctl",
|
|
TRUE, "1.3.2000.2", "UpdateCtl2", L"file://testupdate2.ctl",
|
|
};
|
|
#define UPDATE_CTL_CNT (sizeof(UpdateCtlPara)/sizeof(UpdateCtlPara[0]))
|
|
|
|
|
|
#define STRING_OTHER_NAME_OID "1.2.3.4.2600.1"
|
|
#define OCTET_OTHER_NAME_OID "1.2.3.4.2600.2"
|
|
|
|
#define RDN_CNT 4
|
|
#define ATTR_CNT 4
|
|
|
|
#define ATTR_0_OBJID szOID_COMMON_NAME
|
|
#define ATTR_1_OBJID "1.2.1"
|
|
#define ATTR_2_OBJID "1.2.2"
|
|
#define UTF8_NAME L"*** UTF8 ***"
|
|
|
|
// Attr[0] - CertPara[].pszName
|
|
// Attr[1] - "xchg" | "sign"
|
|
// Attr[2] - "default" | pszContainer
|
|
|
|
static LPSTR rgpszUsageIdentifier[] = {
|
|
"1.2.3.0", // 0
|
|
"1.2.3.1", // 1
|
|
"1.2.3.2", // 2
|
|
"1.2.3.2.1" // 3
|
|
};
|
|
|
|
static CTL_USAGE rgCtlUsage[] = {
|
|
1, &rgpszUsageIdentifier[0], // 0
|
|
1, &rgpszUsageIdentifier[1], // 1
|
|
2, &rgpszUsageIdentifier[2], // 2
|
|
3, &rgpszUsageIdentifier[1] // 3
|
|
};
|
|
|
|
static PCCERT_CONTEXT rgpCertContext[CERT_CNT];
|
|
|
|
void MySystemTimeToFileTime(
|
|
SYSTEMTIME *pSystemTime,
|
|
FILETIME *pFileTime
|
|
)
|
|
{
|
|
SYSTEMTIME TmpTime;
|
|
|
|
if (!SystemTimeToFileTime(pSystemTime, pFileTime)) {
|
|
TmpTime = *pSystemTime;
|
|
|
|
// Following is a fix for Feb 29, 2000 when advancing the year forward or backward.
|
|
TmpTime.wDay = 1;
|
|
SystemTimeToFileTime(&TmpTime, pFileTime);
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Error output routines
|
|
//--------------------------------------------------------------------------
|
|
static void PrintError(LPCSTR pszMsg)
|
|
{
|
|
printf("%s\n", pszMsg);
|
|
}
|
|
static void PrintLastError(LPCSTR pszMsg)
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
printf("%s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Test allocation and free routines
|
|
//--------------------------------------------------------------------------
|
|
static
|
|
LPVOID
|
|
WINAPI
|
|
TestAlloc(
|
|
IN size_t cbBytes
|
|
)
|
|
{
|
|
LPVOID pv;
|
|
pv = malloc(cbBytes);
|
|
if (pv == NULL) {
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
PrintLastError("TestAlloc");
|
|
}
|
|
return pv;
|
|
}
|
|
|
|
|
|
static
|
|
VOID
|
|
WINAPI
|
|
TestFree(
|
|
IN LPVOID pv
|
|
)
|
|
{
|
|
if (pv)
|
|
free(pv);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Allocate and convert a multi-byte string to a wide string
|
|
//--------------------------------------------------------------------------
|
|
static LPWSTR AllocAndSzToWsz(LPCSTR psz)
|
|
{
|
|
size_t cb;
|
|
LPWSTR pwsz = NULL;
|
|
|
|
if (-1 == (cb = mbstowcs( NULL, psz, strlen(psz))))
|
|
goto bad_param;
|
|
cb += 1; // terminating NULL
|
|
if (NULL == (pwsz = (LPWSTR)TestAlloc( cb * sizeof(WCHAR)))) {
|
|
PrintLastError("AllocAndSzToWsz");
|
|
goto failed;
|
|
}
|
|
if (-1 == mbstowcs( pwsz, psz, cb))
|
|
goto bad_param;
|
|
goto common_return;
|
|
|
|
bad_param:
|
|
PrintError("Bad AllocAndSzToWsz");
|
|
failed:
|
|
if (pwsz) {
|
|
TestFree(pwsz);
|
|
pwsz = NULL;
|
|
}
|
|
common_return:
|
|
return pwsz;
|
|
}
|
|
|
|
static HCRYPTPROV GetCryptProv(
|
|
DWORD dwProvType,
|
|
LPCSTR pszProvider = NULL,
|
|
LPCSTR pszInContainer = pszContainer,
|
|
DWORD dwBitLen = 0
|
|
)
|
|
{
|
|
HCRYPTPROV hProv = 0;
|
|
BOOL fResult;
|
|
DWORD dwFlags;
|
|
|
|
if (fMachine)
|
|
dwFlags = CRYPT_MACHINE_KEYSET;
|
|
else
|
|
dwFlags = 0;
|
|
|
|
fResult = CryptAcquireContext(
|
|
&hProv,
|
|
pszInContainer,
|
|
pszProvider,
|
|
dwProvType,
|
|
dwFlags
|
|
);
|
|
|
|
if (fResult) {
|
|
if (fGenerate) {
|
|
// Delete the existing keys
|
|
CryptReleaseContext(hProv, 0);
|
|
printf("Deleting existing private keys\n");
|
|
|
|
// Note: for CRYPT_DELETEKEYSET, the returned hProv is undefined
|
|
// and must not be released.
|
|
fResult = CryptAcquireContext(
|
|
&hProv,
|
|
pszInContainer,
|
|
pszProvider,
|
|
dwProvType,
|
|
dwFlags | CRYPT_DELETEKEYSET
|
|
);
|
|
if (!fResult) {
|
|
PrintLastError("CryptAcquireContext(CRYPT_DELETEKEYSET)");
|
|
return 0;
|
|
}
|
|
hProv = 0;
|
|
}
|
|
}
|
|
|
|
if (0 == hProv) {
|
|
printf("Creating new private keys\n");
|
|
fResult = CryptAcquireContext(
|
|
&hProv,
|
|
pszInContainer,
|
|
pszProvider,
|
|
dwProvType,
|
|
dwFlags | CRYPT_NEWKEYSET
|
|
);
|
|
if (!fResult || hProv == 0) {
|
|
PrintLastError("CryptAcquireContext(CRYPT_NEWKEYSET)");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
HCRYPTKEY hKey = 0;
|
|
dwFlags = dwBitLen << 16;
|
|
if (fExportable)
|
|
dwFlags |= CRYPT_EXPORTABLE;
|
|
if (fUserProtected)
|
|
dwFlags |= CRYPT_USER_PROTECTED;
|
|
|
|
if (CryptGetUserKey(
|
|
hProv,
|
|
AT_SIGNATURE,
|
|
&hKey
|
|
)) {
|
|
printf("Using existing SIGNATURE private key\n");
|
|
CryptDestroyKey(hKey);
|
|
hKey = 0;
|
|
} else {
|
|
printf("Generating SIGNATURE private key\n");
|
|
fResult = CryptGenKey(
|
|
hProv,
|
|
AT_SIGNATURE,
|
|
dwFlags,
|
|
&hKey
|
|
);
|
|
if (!fResult || hKey == 0)
|
|
PrintLastError("CryptGenKey(AT_SIGNATURE)");
|
|
else
|
|
CryptDestroyKey(hKey);
|
|
}
|
|
|
|
if (PROV_DSS == dwProvType)
|
|
return hProv;
|
|
|
|
if (CryptGetUserKey(
|
|
hProv,
|
|
AT_KEYEXCHANGE,
|
|
&hKey
|
|
)) {
|
|
printf("Using existing EXCHANGE private key\n");
|
|
CryptDestroyKey(hKey);
|
|
hKey = 0;
|
|
} else {
|
|
printf("Generating EXCHANGE private key\n");
|
|
hKey = 0;
|
|
fResult = CryptGenKey(
|
|
hProv,
|
|
AT_KEYEXCHANGE,
|
|
dwFlags,
|
|
&hKey
|
|
);
|
|
if (!fResult || hKey == 0)
|
|
PrintLastError("CryptGenKey(AT_KEYEXCHANGE)");
|
|
else
|
|
CryptDestroyKey(hKey);
|
|
}
|
|
|
|
return hProv;
|
|
}
|
|
|
|
static HCERTSTORE OpenStore(LPCSTR pszStoreFilename)
|
|
{
|
|
HCERTSTORE hStore;
|
|
HANDLE hFile = 0;
|
|
|
|
if( INVALID_HANDLE_VALUE == (hFile = CreateFile(pszStoreFilename,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL, OPEN_EXISTING, 0, NULL))) {
|
|
hStore = CertOpenStore(
|
|
CERT_STORE_PROV_MEMORY,
|
|
dwCertEncodingType,
|
|
0, // hCryptProv
|
|
0, // dwFlags
|
|
NULL // pvPara
|
|
);
|
|
} else {
|
|
hStore = CertOpenStore(
|
|
CERT_STORE_PROV_FILE,
|
|
dwCertEncodingType,
|
|
0, // hCryptProv
|
|
0, // dwFlags
|
|
hFile
|
|
);
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
if (hStore == NULL)
|
|
PrintLastError("CertOpenStore");
|
|
|
|
return hStore;
|
|
}
|
|
|
|
static void SaveStore(HCERTSTORE hStore, LPCSTR pszSaveFilename)
|
|
{
|
|
HANDLE hFile;
|
|
hFile = CreateFile(pszSaveFilename,
|
|
GENERIC_WRITE,
|
|
0, // fdwShareMode
|
|
NULL, // lpsa
|
|
CREATE_ALWAYS,
|
|
0, // fdwAttrsAndFlags
|
|
0); // TemplateFile
|
|
if (INVALID_HANDLE_VALUE == hFile) {
|
|
printf( "can't open %s\n", pszSaveFilename);
|
|
PrintLastError("CloseStore::CreateFile");
|
|
} else {
|
|
if (!CertSaveStore(
|
|
hStore,
|
|
0, // dwEncodingType,
|
|
CERT_STORE_SAVE_AS_STORE,
|
|
CERT_STORE_SAVE_TO_FILE,
|
|
(void *) hFile,
|
|
0 // dwFlags
|
|
))
|
|
PrintLastError("CertSaveStore");
|
|
CloseHandle(hFile);
|
|
}
|
|
}
|
|
|
|
static CRYPT_ENCODE_PARA TestEncodePara = {
|
|
offsetof(CRYPT_ENCODE_PARA, pfnFree) + sizeof(TestEncodePara.pfnFree),
|
|
TestAlloc,
|
|
TestFree
|
|
};
|
|
|
|
static BOOL AllocAndEncodeObject(
|
|
IN LPCSTR lpszStructType,
|
|
IN const void *pvStructInfo,
|
|
OUT BYTE **ppbEncoded,
|
|
OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
|
|
fResult = CryptEncodeObjectEx(
|
|
dwCertEncodingType,
|
|
lpszStructType,
|
|
pvStructInfo,
|
|
CRYPT_ENCODE_ALLOC_FLAG,
|
|
&TestEncodePara,
|
|
(void *) ppbEncoded,
|
|
pcbEncoded
|
|
);
|
|
|
|
if (!fResult) {
|
|
if ((DWORD_PTR) lpszStructType <= 0xFFFF)
|
|
printf("CryptEncodeObject(StructType: %d)",
|
|
(DWORD)(DWORD_PTR) lpszStructType);
|
|
else
|
|
printf("CryptEncodeObject(StructType: %s)",
|
|
lpszStructType);
|
|
PrintLastError("");
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateEnhancedKeyUsage(
|
|
IN DWORD dwFlags,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
PCTL_USAGE pCtlUsage;
|
|
|
|
dwFlags &= USE1_PARA_FLAG | USE2_PARA_FLAG;
|
|
|
|
switch (dwFlags) {
|
|
case 0:
|
|
pCtlUsage = &rgCtlUsage[0];
|
|
break;
|
|
case USE1_PARA_FLAG:
|
|
pCtlUsage = &rgCtlUsage[1];
|
|
break;
|
|
case USE2_PARA_FLAG:
|
|
pCtlUsage = &rgCtlUsage[2];
|
|
break;
|
|
case USE1_PARA_FLAG | USE2_PARA_FLAG:
|
|
default:
|
|
pCtlUsage = &rgCtlUsage[3];
|
|
break;
|
|
}
|
|
|
|
return AllocAndEncodeObject(
|
|
X509_ENHANCED_KEY_USAGE,
|
|
(const void *) pCtlUsage,
|
|
ppbEncoded,
|
|
pcbEncoded
|
|
);
|
|
}
|
|
|
|
|
|
static BOOL CreateNextUpdateLocation(
|
|
DWORD dwCert,
|
|
BOOL fProp,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded,
|
|
IN OPTIONAL LPWSTR pwszUrl = NULL
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
CERT_ALT_NAME_INFO AltNameInfo;
|
|
CERT_ALT_NAME_ENTRY rgAltNameEntry[5];
|
|
|
|
rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
rgAltNameEntry[0].pwszRfc822Name = L"RFC822";
|
|
rgAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[1].pwszURL = L"file://file1.ctl";
|
|
rgAltNameEntry[2].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[2].pwszURL = L"http://timestamp/ctltest/http1.ctl";
|
|
|
|
rgAltNameEntry[3].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[3].pwszURL = L"file://file2.ctl";
|
|
rgAltNameEntry[4].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[4].pwszURL = L"http://timestamp/ctltest/http2.ctl";
|
|
|
|
if (dwCert == UPDATE_CTL_SIGNER) {
|
|
rgAltNameEntry[1].pwszURL = L"file://nonexistant1.ctl";
|
|
rgAltNameEntry[2].pwszURL = L"file://nonexistant2.ctl";
|
|
if (pwszUrl)
|
|
rgAltNameEntry[3].pwszURL = pwszUrl;
|
|
else
|
|
rgAltNameEntry[3].pwszURL = L"file://testupdate1.ctl";
|
|
rgAltNameEntry[4].pwszURL = L"file://nonexistant3.ctl";
|
|
AltNameInfo.cAltEntry = 5;
|
|
AltNameInfo.rgAltEntry = &rgAltNameEntry[0];
|
|
} else if (fProp) {
|
|
if (CertPara[dwCert].dwFlags & HTTP_PARA_FLAG)
|
|
AltNameInfo.cAltEntry = 2;
|
|
else
|
|
AltNameInfo.cAltEntry = 1;
|
|
AltNameInfo.rgAltEntry = &rgAltNameEntry[3];
|
|
} else {
|
|
if (CertPara[dwCert].dwFlags & HTTP_PARA_FLAG)
|
|
AltNameInfo.cAltEntry = 5;
|
|
else
|
|
AltNameInfo.cAltEntry = 2;
|
|
AltNameInfo.rgAltEntry = &rgAltNameEntry[0];
|
|
}
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_ALTERNATE_NAME,
|
|
&AltNameInfo,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL AddCert(
|
|
HCERTSTORE hStore,
|
|
DWORD dwCert,
|
|
BYTE *pbEncoded,
|
|
DWORD cbEncoded)
|
|
{
|
|
BOOL fResult;
|
|
PCCERT_CONTEXT pCert = NULL;
|
|
|
|
fResult = CertAddEncodedCertificateToStore(hStore, dwCertEncodingType,
|
|
pbEncoded, cbEncoded, CERT_STORE_ADD_NEW, NULL);
|
|
if (!fResult) {
|
|
if (GetLastError() == CRYPT_E_EXISTS) {
|
|
printf("Cert already exists in store. Adding duplicate\n");
|
|
fResult = CertAddEncodedCertificateToStore(hStore,
|
|
dwCertEncodingType, pbEncoded, cbEncoded,
|
|
CERT_STORE_ADD_ALWAYS, &pCert);
|
|
}
|
|
if (!fResult)
|
|
PrintLastError("CertAddEncodedCertificateToStore");
|
|
} else {
|
|
fResult = CertAddEncodedCertificateToStore(hStore,
|
|
dwCertEncodingType, pbEncoded, cbEncoded,
|
|
CERT_STORE_ADD_USE_EXISTING, &pCert);
|
|
if (!fResult)
|
|
PrintLastError("CertAddEncodedCertificateToStore");
|
|
}
|
|
if (pCert) {
|
|
if (CertPara[dwCert].dwFlags & PROV_PARA_FLAG) {
|
|
CRYPT_KEY_PROV_INFO KeyProvInfo;
|
|
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo));
|
|
if ((CertPara[dwCert].dwFlags & DSS_PARA_FLAG) &&
|
|
(CertPara[dwCert].dwFlags & DSS_512_PARA_FLAG))
|
|
KeyProvInfo.pwszContainerName = DSS_512_CONTAINER_NAME_W;
|
|
else if (CertPara[dwCert].dwFlags & ENH_1024_PARA_FLAG)
|
|
KeyProvInfo.pwszContainerName = ENH_1024_CONTAINER_NAME_W;
|
|
else if (CertPara[dwCert].dwFlags & ENH_2048_PARA_FLAG)
|
|
KeyProvInfo.pwszContainerName = ENH_2048_CONTAINER_NAME_W;
|
|
else if (pwszContainer)
|
|
KeyProvInfo.pwszContainerName = pwszContainer;
|
|
if (CertPara[dwCert].dwFlags & DSS_PARA_FLAG)
|
|
KeyProvInfo.dwProvType = TEST_PROV_DSS;
|
|
else
|
|
KeyProvInfo.dwProvType = PROV_RSA_FULL;
|
|
if (CertPara[dwCert].dwFlags & XCHG_PARA_FLAG) {
|
|
KeyProvInfo.dwFlags = CERT_SET_KEY_PROV_HANDLE_PROP_ID;
|
|
KeyProvInfo.dwKeySpec = AT_KEYEXCHANGE;
|
|
} else
|
|
KeyProvInfo.dwKeySpec = AT_SIGNATURE;
|
|
if (fMachine)
|
|
KeyProvInfo.dwFlags |= CRYPT_MACHINE_KEYSET;
|
|
|
|
fResult = CertSetCertificateContextProperty(
|
|
pCert,
|
|
CERT_KEY_PROV_INFO_PROP_ID,
|
|
0, // dwFlags
|
|
&KeyProvInfo
|
|
);
|
|
if (!fResult)
|
|
PrintLastError("CertSetCertificateContextProperty");
|
|
}
|
|
|
|
if (((CertPara[dwCert].dwFlags & (USE1_PARA_FLAG | USE2_PARA_FLAG)) &&
|
|
(CertPara[dwCert].dwFlags &
|
|
(NO_EXT_PARA_FLAG | VALID_PARA_FLAG)))
|
|
||
|
|
(CertPara[dwCert].dwFlags & (USE1_PARA_FLAG | USE2_PARA_FLAG)) ==
|
|
(USE1_PARA_FLAG | USE2_PARA_FLAG)) {
|
|
|
|
CRYPT_DATA_BLOB Data;
|
|
DWORD dwFlags = CertPara[dwCert].dwFlags;
|
|
if (0 == (CertPara[dwCert].dwFlags &
|
|
(NO_EXT_PARA_FLAG | VALID_PARA_FLAG)))
|
|
dwFlags = 0;
|
|
if (CreateEnhancedKeyUsage(
|
|
dwFlags,
|
|
&Data.pbData,
|
|
&Data.cbData)) {
|
|
if (!CertSetCertificateContextProperty(
|
|
pCert,
|
|
CERT_CTL_USAGE_PROP_ID,
|
|
0, // dwFlags
|
|
&Data
|
|
))
|
|
PrintLastError(
|
|
"CertSetCertificateContextProperty(CTL_USAGE)");
|
|
TestFree(Data.pbData);
|
|
}
|
|
}
|
|
|
|
if (CertPara[dwCert].dwFlags & AUX1_PARA_FLAG) {
|
|
DWORD i;
|
|
CRYPT_DATA_BLOB Data[4];
|
|
BYTE rgbAux0[] = {0x11, 0x0};
|
|
BYTE rgbAux1[] = {0x11, 0x1};
|
|
BYTE rgbAux2[] = {0x11, 0x2, 0x2};
|
|
BYTE rgbAux3[] = {0x11, 0x3, 0x3, 0x3};
|
|
|
|
Data[0].pbData = NULL;
|
|
Data[0].cbData = 0;
|
|
Data[1].pbData = rgbAux1;
|
|
Data[1].cbData = sizeof(rgbAux1);
|
|
Data[2].pbData = rgbAux2;
|
|
Data[2].cbData = sizeof(rgbAux2);
|
|
Data[3].pbData = rgbAux3;
|
|
Data[3].cbData = sizeof(rgbAux3);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (!CertSetCertificateContextProperty(
|
|
pCert,
|
|
CERT_FIRST_USER_PROP_ID + i,
|
|
0, // dwFlags
|
|
&Data[i]
|
|
)) {
|
|
fResult = FALSE;
|
|
PrintLastError("CertSetCertificateContextProperty");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (CertPara[dwCert].dwFlags & AUX2_PARA_FLAG) {
|
|
DWORD i;
|
|
CRYPT_DATA_BLOB Data[3];
|
|
BYTE rgbAux0[] = {0x22, 0x2, 0x2};
|
|
BYTE rgbAux1[] = {0x22, 0x3, 0x3, 0x3};
|
|
BYTE rgbAux2[] = {0x22, 0x4, 0x4, 0x4, 0x4, 0x12, 0x34};
|
|
|
|
Data[0].pbData = rgbAux0;
|
|
Data[0].cbData = sizeof(rgbAux0);
|
|
Data[1].pbData = rgbAux1;
|
|
Data[1].cbData = sizeof(rgbAux1);
|
|
Data[2].pbData = rgbAux2;
|
|
Data[2].cbData = sizeof(rgbAux2);
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
if (!CertSetCertificateContextProperty(
|
|
pCert,
|
|
CERT_FIRST_USER_PROP_ID + 2 + i,
|
|
0, // dwFlags
|
|
&Data[i]
|
|
)) {
|
|
fResult = FALSE;
|
|
PrintLastError("CertSetCertificateContextProperty");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (CertPara[dwCert].dwFlags & AUX1_PARA_FLAG) {
|
|
// Delete CERT_FIRST_USER_PROP_ID + 1
|
|
if (!CertSetCertificateContextProperty(
|
|
pCert,
|
|
CERT_FIRST_USER_PROP_ID + 1,
|
|
0, // dwFlags
|
|
NULL
|
|
)) {
|
|
fResult = FALSE;
|
|
PrintLastError("CertSetCertificateContextProperty");
|
|
}
|
|
}
|
|
}
|
|
CertFreeCertificateContext(pCert);
|
|
}
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL AddCrl(
|
|
HCERTSTORE hStore,
|
|
DWORD dwCert,
|
|
DWORD dwAuxFlags,
|
|
BYTE *pbEncoded,
|
|
DWORD cbEncoded,
|
|
BOOL fDuplicate = FALSE
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
PCCRL_CONTEXT pCrl = NULL;
|
|
|
|
fResult = CertAddEncodedCRLToStore(hStore, dwCertEncodingType,
|
|
pbEncoded, cbEncoded, CERT_STORE_ADD_NEW, NULL);
|
|
if (!fResult) {
|
|
if (GetLastError() == CRYPT_E_EXISTS) {
|
|
if (fDuplicate ||
|
|
0 == strcmp("TestAIACA", CertPara[dwCert].pszName)) {
|
|
printf("CRL already exists in store. Adding duplicate\n");
|
|
fResult = CertAddEncodedCRLToStore(hStore,
|
|
dwCertEncodingType, pbEncoded, cbEncoded,
|
|
CERT_STORE_ADD_ALWAYS, &pCrl);
|
|
}
|
|
}
|
|
if (!fResult)
|
|
PrintLastError("CertAddEncodedCRLToStore");
|
|
} else {
|
|
if (fDuplicate)
|
|
printf("AddCrl failed => ADD_NEW duplicate succeeded\n");
|
|
|
|
fResult = CertAddEncodedCRLToStore(hStore,
|
|
dwCertEncodingType, pbEncoded, cbEncoded,
|
|
CERT_STORE_ADD_USE_EXISTING, &pCrl);
|
|
if (!fResult)
|
|
PrintLastError("CertAddEncodedCRLToStore");
|
|
}
|
|
if (pCrl) {
|
|
if (dwAuxFlags & AUX1_PARA_FLAG) {
|
|
DWORD i;
|
|
CRYPT_DATA_BLOB Data[4];
|
|
BYTE rgbAux0[] = {0x11, 0x0};
|
|
BYTE rgbAux1[] = {0x11, 0x1};
|
|
BYTE rgbAux2[] = {0x11, 0x2, 0x2};
|
|
BYTE rgbAux3[] = {0x11, 0x3, 0x3, 0x3};
|
|
|
|
Data[0].pbData = NULL;
|
|
Data[0].cbData = 0;
|
|
Data[1].pbData = rgbAux1;
|
|
Data[1].cbData = sizeof(rgbAux1);
|
|
Data[2].pbData = rgbAux2;
|
|
Data[2].cbData = sizeof(rgbAux2);
|
|
Data[3].pbData = rgbAux3;
|
|
Data[3].cbData = sizeof(rgbAux3);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (!CertSetCRLContextProperty(
|
|
pCrl,
|
|
CERT_FIRST_USER_PROP_ID + i,
|
|
0, // dwFlags
|
|
&Data[i]
|
|
)) {
|
|
fResult = FALSE;
|
|
PrintLastError("CertSetCRLContextProperty");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwAuxFlags & AUX2_PARA_FLAG) {
|
|
DWORD i;
|
|
CRYPT_DATA_BLOB Data[3];
|
|
BYTE rgbAux0[] = {0x22, 0x2, 0x2};
|
|
BYTE rgbAux1[] = {0x22, 0x3, 0x3, 0x3};
|
|
BYTE rgbAux2[] = {0x22, 0x4, 0x4, 0x4, 0x4, 0x12, 0x34};
|
|
|
|
Data[0].pbData = rgbAux0;
|
|
Data[0].cbData = sizeof(rgbAux0);
|
|
Data[1].pbData = rgbAux1;
|
|
Data[1].cbData = sizeof(rgbAux1);
|
|
Data[2].pbData = rgbAux2;
|
|
Data[2].cbData = sizeof(rgbAux2);
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
if (!CertSetCRLContextProperty(
|
|
pCrl,
|
|
CERT_FIRST_USER_PROP_ID + 2 + i,
|
|
0, // dwFlags
|
|
&Data[i]
|
|
)) {
|
|
fResult = FALSE;
|
|
PrintLastError("CertSetCRLContextProperty");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
CertFreeCRLContext(pCrl);
|
|
}
|
|
return fResult;
|
|
}
|
|
|
|
|
|
static BOOL AddCtl(
|
|
HCERTSTORE hStore,
|
|
DWORD dwCert,
|
|
BYTE *pbEncoded,
|
|
DWORD cbEncoded)
|
|
{
|
|
BOOL fResult;
|
|
PCCTL_CONTEXT pCtl = NULL;
|
|
|
|
fResult = CertAddEncodedCTLToStore(hStore, dwMsgAndCertEncodingType,
|
|
pbEncoded, cbEncoded, CERT_STORE_ADD_NEW, NULL);
|
|
if (!fResult) {
|
|
if (GetLastError() == CRYPT_E_EXISTS) {
|
|
printf("CTL already exists in store. Adding duplicate\n");
|
|
fResult = CertAddEncodedCTLToStore(hStore,
|
|
dwMsgAndCertEncodingType, pbEncoded, cbEncoded,
|
|
CERT_STORE_ADD_ALWAYS, &pCtl);
|
|
}
|
|
if (!fResult)
|
|
PrintLastError("CertAddEncodedCTLToStore");
|
|
} else {
|
|
fResult = CertAddEncodedCTLToStore(hStore,
|
|
dwMsgAndCertEncodingType, pbEncoded, cbEncoded,
|
|
CERT_STORE_ADD_USE_EXISTING, &pCtl);
|
|
if (!fResult)
|
|
PrintLastError("CertAddEncodedCTLToStore");
|
|
}
|
|
if (pCtl) {
|
|
if (0 == (CertPara[dwCert].dwFlags & NO_EXT_PARA_FLAG)) {
|
|
CRYPT_DATA_BLOB Data;
|
|
|
|
if (CreateNextUpdateLocation(
|
|
dwCert,
|
|
TRUE, // fProp
|
|
&Data.pbData,
|
|
&Data.cbData)) {
|
|
if (!CertSetCTLContextProperty(
|
|
pCtl,
|
|
CERT_NEXT_UPDATE_LOCATION_PROP_ID,
|
|
0, // dwFlags
|
|
&Data
|
|
))
|
|
PrintLastError(
|
|
"CertSetCertificateContextProperty(NEXT_UPDATE)");
|
|
TestFree(Data.pbData);
|
|
}
|
|
}
|
|
CertFreeCTLContext(pCtl);
|
|
}
|
|
return fResult;
|
|
}
|
|
|
|
#define AKI2_KEYID 0
|
|
#define AKI2_NONE 1
|
|
#define AKI2_FULL 2
|
|
#define AKI2_BAD_KEYID 3
|
|
#define AKI2_BAD_ISSUER 4
|
|
#define AKI2_BAD_SERIAL_NUMBER 5
|
|
|
|
#define AKI2_CNT 6
|
|
|
|
// On 02-May-01 updated to not look at the IssuerAndSerialNumber in the CRL's
|
|
// AKI
|
|
#define AKI2_BAD_CNT 1
|
|
|
|
|
|
|
|
static BOOL EncodeCert(DWORD dwCert, BYTE **ppbEncoded, DWORD *pcbEncoded);
|
|
static BOOL EncodeCrl(
|
|
DWORD dwCert,
|
|
BYTE **ppbEncoded,
|
|
DWORD *pcbEncoded,
|
|
DWORD dwAki = AKI2_KEYID
|
|
);
|
|
static BOOL EncodeBaseOrDeltaCrl(
|
|
DWORD dwIssuer,
|
|
int iBase,
|
|
DWORD dwFlags,
|
|
BYTE **ppbEncoded,
|
|
DWORD *pcbEncoded
|
|
);
|
|
static BOOL EncodeCtl(DWORD dwCert, DWORD dwEncodeFlags, BYTE **ppbEncoded,
|
|
DWORD *pcbEncoded);
|
|
|
|
static BOOL EncodeUpdateCtl(
|
|
BOOL fTimeInvalid,
|
|
LPSTR pszUsageObjId,
|
|
LPSTR pszListIdentifier,
|
|
LPWSTR pwszUrl,
|
|
BYTE **ppbEncoded,
|
|
DWORD *pcbEncoded
|
|
);
|
|
|
|
|
|
|
|
static void Usage(void)
|
|
{
|
|
printf("Usage: tstore2 [options] <StoreFilename>\n");
|
|
printf("Options are:\n");
|
|
printf(" -h - This message\n");
|
|
printf(" -c<name> - Crypto key container name\n");
|
|
printf(" -g - Generate new keys\n");
|
|
printf(" -E - Exportable private keys\n");
|
|
printf(" -U - User protected private keys\n");
|
|
printf(" -M - Store in local Machine, not current User\n");
|
|
printf(" -P - Use enhanced and DSS providers\n");
|
|
printf(" -I - Inherit DSS public key parameters\n");
|
|
printf(" -K - Keep extra Crls\n");
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
int _cdecl main(int argc, char * argv[])
|
|
{
|
|
LPSTR pszStoreFilename = NULL;
|
|
HANDLE hStore = 0;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
DWORD i;
|
|
BOOL fKeepCrls = FALSE;
|
|
|
|
while (--argc>0)
|
|
{
|
|
if (**++argv == '-')
|
|
{
|
|
switch(argv[0][1])
|
|
{
|
|
case 'c':
|
|
pszContainer = argv[0]+2;
|
|
pwszContainer = AllocAndSzToWsz(pszContainer);
|
|
if (*pszContainer == '\0') {
|
|
printf("Need to specify crypto key container name\n");
|
|
Usage();
|
|
return -1;
|
|
}
|
|
break;
|
|
case 'g':
|
|
fGenerate = TRUE;
|
|
break;
|
|
case 'E':
|
|
fExportable = TRUE;
|
|
break;
|
|
case 'U':
|
|
fUserProtected = TRUE;
|
|
break;
|
|
case 'M':
|
|
fMachine = TRUE;
|
|
break;
|
|
case 'P':
|
|
fProviders = TRUE;
|
|
break;
|
|
case 'I':
|
|
fInheritParameters = TRUE;
|
|
break;
|
|
case 'K':
|
|
fKeepCrls = TRUE;
|
|
break;
|
|
case 'h':
|
|
default:
|
|
Usage();
|
|
return -1;
|
|
}
|
|
} else
|
|
pszStoreFilename = argv[0];
|
|
}
|
|
|
|
|
|
if (pszStoreFilename == NULL) {
|
|
printf("missing store filename\n");
|
|
Usage();
|
|
return -1;
|
|
}
|
|
|
|
printf("command line: %s\n", GetCommandLine());
|
|
|
|
// Get time used time stamping and serial numbers
|
|
GetSystemTime(&TestTime);
|
|
TestTime.wMilliseconds = 0;
|
|
|
|
printf("Getting RSA provider\n");
|
|
hRSACryptProv = GetCryptProv(PROV_RSA_FULL, MS_DEF_PROV_A);
|
|
if (hRSACryptProv == 0)
|
|
return -1;
|
|
|
|
printf("Getting DSS provider\n");
|
|
hDSSCryptProv = GetCryptProv(TEST_PROV_DSS);
|
|
|
|
if (fProviders) {
|
|
printf("Getting Enhanced RSA provider (1024 bit)\n");
|
|
hEnh1024CryptProv = GetCryptProv(PROV_RSA_FULL, MS_ENHANCED_PROV_A,
|
|
ENH_1024_CONTAINER_NAME_A, 1024);
|
|
if (hEnh1024CryptProv == 0)
|
|
return -1;
|
|
|
|
printf("Getting Enhanced RSA provider (2048 bit)\n");
|
|
hEnh2048CryptProv = GetCryptProv(PROV_RSA_FULL, MS_ENHANCED_PROV_A,
|
|
ENH_2048_CONTAINER_NAME_A, 2048);
|
|
if (hEnh2048CryptProv == 0)
|
|
return -1;
|
|
|
|
printf("Getting DSS provider (512 bit)\n");
|
|
hDSS512CryptProv = GetCryptProv(TEST_PROV_DSS, NULL,
|
|
DSS_512_CONTAINER_NAME_A, 512);
|
|
} else {
|
|
// Disable all enhanced provider flags
|
|
for (i = 0; i < CERT_CNT; i++)
|
|
CertPara[i].dwFlags &= ~(DSS_512_PARA_FLAG |
|
|
ENH_1024_PARA_FLAG | ENH_2048_PARA_FLAG);
|
|
}
|
|
|
|
// Attempt to open the store
|
|
hStore = OpenStore(pszStoreFilename);
|
|
if (hStore == NULL)
|
|
goto ErrorReturn;
|
|
|
|
// Encode certs and CRLs and add to the store.
|
|
for (i = 0; i < CERT_CNT; i++) {
|
|
if (EncodeCert(i, &pbEncoded, &cbEncoded)) {
|
|
rgpCertContext[i] = CertCreateCertificateContext(
|
|
dwCertEncodingType, pbEncoded, cbEncoded);
|
|
AddCert(hStore, i, pbEncoded, cbEncoded);
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
|
|
if (CertPara[i].dwFlags & CA_PARA_FLAG) {
|
|
if (0 == strncmp(CertPara[i].pszName, "Rollover", 8)) {
|
|
// No CRL for rollover certs
|
|
;
|
|
} else if (CertPara[i].dwFlags & DUPLICATE_CRL_PARA_FLAG) {
|
|
DWORD dwAki;
|
|
for (dwAki = 0; dwAki < AKI2_CNT; dwAki++) {
|
|
if (EncodeCrl(i, &pbEncoded, &cbEncoded, dwAki)) {
|
|
if (AKI2_BAD_SERIAL_NUMBER == dwAki)
|
|
// Modify the signature
|
|
pbEncoded[cbEncoded -1] ^= 0xFF;
|
|
|
|
AddCrl(hStore, i, AUX1_PARA_FLAG, pbEncoded, cbEncoded);
|
|
AddCrl(hStore, i, AUX2_PARA_FLAG, pbEncoded, cbEncoded,
|
|
TRUE);
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
if (EncodeCrl(i, &pbEncoded, &cbEncoded)) {
|
|
AddCrl(hStore, i, 0, pbEncoded, cbEncoded);
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test CertFindCRLInStore(CRL_FIND_ISSUED_BY)
|
|
for (i = 0; i < CERT_CNT; i++) {
|
|
if ((CA_PARA_FLAG | DUPLICATE_CRL_PARA_FLAG) ==
|
|
((CA_PARA_FLAG | DUPLICATE_CRL_PARA_FLAG) &
|
|
CertPara[i].dwFlags)) {
|
|
PCCERT_CONTEXT pIssuer = rgpCertContext[i];
|
|
DWORD dwCnt;
|
|
PCCRL_CONTEXT pCrl;
|
|
|
|
printf("CertFindCRLInStore(CRL_FIND_ISSUED_BY) [%d]\n", i);
|
|
|
|
dwCnt = 0;
|
|
pCrl = NULL;
|
|
while (pCrl = CertFindCRLInStore(
|
|
hStore,
|
|
dwCertEncodingType,
|
|
0, // dwFindFlags
|
|
CRL_FIND_ISSUED_BY,
|
|
(const void *) pIssuer,
|
|
pCrl
|
|
))
|
|
dwCnt++;
|
|
if ((AKI2_CNT * 2) != dwCnt)
|
|
printf("CRL_FIND_ISSUED_BY failed count => expected: %d actual: %d\n",
|
|
AKI2_CNT * 2, dwCnt);
|
|
|
|
dwCnt = 0;
|
|
pCrl = NULL;
|
|
while (pCrl = CertFindCRLInStore(
|
|
hStore,
|
|
dwCertEncodingType,
|
|
CRL_FIND_ISSUED_BY_AKI_FLAG,
|
|
CRL_FIND_ISSUED_BY,
|
|
(const void *) pIssuer,
|
|
pCrl
|
|
))
|
|
dwCnt++;
|
|
if (((AKI2_CNT - AKI2_BAD_CNT) * 2) != dwCnt)
|
|
printf("CRL_FIND_ISSUED_BY(AKI_FLAG) failed count => expected: %d actual: %d\n",
|
|
(AKI2_CNT - AKI2_BAD_CNT) * 2, dwCnt);
|
|
|
|
dwCnt = 0;
|
|
pCrl = NULL;
|
|
while (pCrl = CertFindCRLInStore(
|
|
hStore,
|
|
dwCertEncodingType,
|
|
CRL_FIND_ISSUED_BY_SIGNATURE_FLAG,
|
|
CRL_FIND_ISSUED_BY,
|
|
(const void *) pIssuer,
|
|
pCrl
|
|
))
|
|
dwCnt++;
|
|
if (((AKI2_CNT - 1) * 2) != dwCnt)
|
|
printf("CRL_FIND_ISSUED_BY(SIGNATURE_FLAG) failed count => expected: %d actual: %d\n",
|
|
(AKI2_CNT - 1) * 2, dwCnt);
|
|
|
|
if (!fKeepCrls) {
|
|
// Delete all but the last pair of duplicates
|
|
|
|
dwCnt = 0;
|
|
pCrl = NULL;
|
|
while (pCrl = CertFindCRLInStore(
|
|
hStore,
|
|
dwCertEncodingType,
|
|
0, // dwFindFlags
|
|
CRL_FIND_ISSUED_BY,
|
|
(const void *) pIssuer,
|
|
pCrl
|
|
)) {
|
|
PCCRL_CONTEXT pDeleteCrl = CertDuplicateCRLContext(pCrl);
|
|
CertDeleteCRLFromStore(pDeleteCrl);
|
|
if (((AKI2_CNT - 1) * 2) == ++dwCnt) {
|
|
CertFreeCRLContext(pCrl);
|
|
break;
|
|
}
|
|
}
|
|
|
|
dwCnt = 0;
|
|
pCrl = NULL;
|
|
while (pCrl = CertFindCRLInStore(
|
|
hStore,
|
|
dwCertEncodingType,
|
|
CRL_FIND_ISSUED_BY_AKI_FLAG |
|
|
CRL_FIND_ISSUED_BY_SIGNATURE_FLAG,
|
|
CRL_FIND_ISSUED_BY,
|
|
(const void *) pIssuer,
|
|
pCrl
|
|
))
|
|
dwCnt++;
|
|
if (2 != dwCnt)
|
|
printf("CRL_FIND_ISSUED_BY(After delete) failed count => expected: %d actual: %d\n",
|
|
2, dwCnt);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Encode CTLs and add to the store.
|
|
for (i = 0; i < CERT_CNT; i++) {
|
|
if (CertPara[i].dwFlags & (CTL1_PARA_FLAG | CTL2_PARA_FLAG)) {
|
|
if (EncodeCtl(i, 0, &pbEncoded, &cbEncoded)) {
|
|
AddCtl(hStore, i, pbEncoded, cbEncoded);
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
if (EncodeCtl(
|
|
i,
|
|
#ifdef CMS_PKCS7
|
|
CMSG_CMS_ENCAPSULATED_CTL_FLAG |
|
|
#endif // CMS_PKCS7
|
|
CMSG_ENCODE_SORTED_CTL_FLAG |
|
|
((CertPara[i].dwFlags & CTL1_PARA_FLAG) ? 0 :
|
|
CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG),
|
|
&pbEncoded,
|
|
&cbEncoded)) {
|
|
AddCtl(hStore, i, pbEncoded, cbEncoded);
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < BASE_DELTA_CRL_CNT; i++) {
|
|
if (EncodeBaseOrDeltaCrl(
|
|
BASE_OR_DELTA_CA_ISSUER,
|
|
BaseDeltaCrlPara[i].iBase,
|
|
BaseDeltaCrlPara[i].dwFlags,
|
|
&pbEncoded,
|
|
&cbEncoded)) {
|
|
BOOL fResult;
|
|
|
|
fResult = CertAddEncodedCRLToStore(hStore,
|
|
dwCertEncodingType, pbEncoded, cbEncoded,
|
|
CERT_STORE_ADD_ALWAYS, NULL);
|
|
if (!fResult)
|
|
PrintLastError("CertAddEncodedCRLToStore");
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < UPDATE_CTL_CNT; i++) {
|
|
if (EncodeUpdateCtl(
|
|
UpdateCtlPara[i].fTimeInvalid,
|
|
UpdateCtlPara[i].pszUsageObjId,
|
|
UpdateCtlPara[i].pszListIdentifier,
|
|
UpdateCtlPara[i].pwszUrl,
|
|
&pbEncoded,
|
|
&cbEncoded)) {
|
|
BOOL fResult;
|
|
|
|
fResult = CertAddEncodedCTLToStore(hStore,
|
|
dwMsgAndCertEncodingType, pbEncoded, cbEncoded,
|
|
CERT_STORE_ADD_ALWAYS, NULL);
|
|
if (!fResult)
|
|
PrintLastError("CertAddEncodedCTLToStore");
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < CERT_CNT; i++)
|
|
CertFreeCertificateContext(rgpCertContext[i]);
|
|
|
|
|
|
SaveStore(hStore, pszStoreFilename);
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded)
|
|
TestFree(pbEncoded);
|
|
|
|
if (hStore) {
|
|
if (!CertCloseStore(hStore, 0))
|
|
PrintLastError("CertCloseStore");
|
|
}
|
|
|
|
if (hRSACryptProv)
|
|
CryptReleaseContext(hRSACryptProv, 0);
|
|
if (hEnh1024CryptProv)
|
|
CryptReleaseContext(hEnh1024CryptProv, 0);
|
|
if (hEnh2048CryptProv)
|
|
CryptReleaseContext(hEnh2048CryptProv, 0);
|
|
if (hDSSCryptProv)
|
|
CryptReleaseContext(hDSSCryptProv, 0);
|
|
if (hDSS512CryptProv)
|
|
CryptReleaseContext(hDSS512CryptProv, 0);
|
|
|
|
if (pwszContainer)
|
|
TestFree(pwszContainer);
|
|
|
|
printf("Done.\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static BOOL AllocAndSignToBeSigned(
|
|
DWORD dwIssuer,
|
|
BYTE *pbToBeSigned,
|
|
DWORD cbToBeSigned,
|
|
PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
|
|
BYTE **ppbSignature,
|
|
DWORD *pcbSignature)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbSignature = NULL;
|
|
DWORD cbSignature;
|
|
HCRYPTPROV hProv;
|
|
|
|
if (CertPara[dwIssuer].dwFlags & DSS_PARA_FLAG) {
|
|
if (CertPara[dwIssuer].dwFlags & DSS_512_PARA_FLAG)
|
|
hProv = hDSS512CryptProv;
|
|
else
|
|
hProv = hDSSCryptProv;
|
|
} else if (CertPara[dwIssuer].dwFlags & ENH_1024_PARA_FLAG)
|
|
hProv = hEnh1024CryptProv;
|
|
else if (CertPara[dwIssuer].dwFlags & ENH_2048_PARA_FLAG)
|
|
hProv = hEnh2048CryptProv;
|
|
else
|
|
hProv = hRSACryptProv;
|
|
|
|
cbSignature = 0;
|
|
CryptSignCertificate(
|
|
hProv,
|
|
AT_SIGNATURE,
|
|
dwCertEncodingType,
|
|
pbToBeSigned,
|
|
cbToBeSigned,
|
|
pSignatureAlgorithm,
|
|
NULL, // pvHashAuxInfo
|
|
NULL, // pbSignature
|
|
&cbSignature
|
|
);
|
|
if (cbSignature == 0) {
|
|
PrintLastError("AllocAndSignToBeSigned::CryptSignCertificate(cb == 0)");
|
|
goto ErrorReturn;
|
|
}
|
|
pbSignature = (BYTE *) TestAlloc(cbSignature);
|
|
if (pbSignature == NULL) goto ErrorReturn;
|
|
if (!CryptSignCertificate(
|
|
hProv,
|
|
AT_SIGNATURE,
|
|
dwCertEncodingType,
|
|
pbToBeSigned,
|
|
cbToBeSigned,
|
|
pSignatureAlgorithm,
|
|
NULL, // pvHashAuxInfo
|
|
pbSignature,
|
|
&cbSignature
|
|
)) {
|
|
PrintLastError("AllocAndSignToBeSigned::CryptSignCertificate");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
fResult = FALSE;
|
|
if (pbSignature) {
|
|
TestFree(pbSignature);
|
|
pbSignature = NULL;
|
|
}
|
|
cbSignature = 0;
|
|
CommonReturn:
|
|
*ppbSignature = pbSignature;
|
|
*pcbSignature = cbSignature;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL EncodeSignedContent(
|
|
DWORD dwIssuer,
|
|
BYTE *pbToBeSigned,
|
|
DWORD cbToBeSigned,
|
|
BYTE **ppbEncoded,
|
|
DWORD *pcbEncoded)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
BYTE *pbSignature = NULL;
|
|
DWORD cbSignature;
|
|
CERT_SIGNED_CONTENT_INFO CertEncoding;
|
|
|
|
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm = {
|
|
SIGNATURE_ALG_OBJID, 0, 0
|
|
};
|
|
|
|
if (CertPara[dwIssuer].dwFlags & DSS_PARA_FLAG)
|
|
SignatureAlgorithm.pszObjId = DSS_SIGNATURE_ALG_OBJID;
|
|
|
|
if (!AllocAndSignToBeSigned(dwIssuer, pbToBeSigned, cbToBeSigned,
|
|
&SignatureAlgorithm, &pbSignature, &cbSignature))
|
|
goto ErrorReturn;
|
|
|
|
memset(&CertEncoding, 0, sizeof(CertEncoding));
|
|
CertEncoding.ToBeSigned.pbData = pbToBeSigned;
|
|
CertEncoding.ToBeSigned.cbData = cbToBeSigned;
|
|
CertEncoding.SignatureAlgorithm = SignatureAlgorithm;
|
|
CertEncoding.Signature.pbData = pbSignature;
|
|
CertEncoding.Signature.cbData = cbSignature;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_CERT,
|
|
&CertEncoding,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if (pbSignature)
|
|
TestFree(pbSignature);
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
|
|
static BOOL GetPublicKey(
|
|
DWORD dwCert,
|
|
PCERT_PUBLIC_KEY_INFO *ppPubKeyInfo)
|
|
{
|
|
BOOL fResult;
|
|
PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
|
|
DWORD cbPubKeyInfo;
|
|
DWORD dwKeySpec;
|
|
HCRYPTPROV hProv;
|
|
|
|
if (CertPara[dwCert].dwFlags & XCHG_PARA_FLAG)
|
|
dwKeySpec = AT_KEYEXCHANGE;
|
|
else
|
|
dwKeySpec = AT_SIGNATURE;
|
|
|
|
if (CertPara[dwCert].dwFlags & DSS_PARA_FLAG) {
|
|
if (CertPara[dwCert].dwFlags & DSS_512_PARA_FLAG)
|
|
hProv = hDSS512CryptProv;
|
|
else
|
|
hProv = hDSSCryptProv;
|
|
} else if (CertPara[dwCert].dwFlags & ENH_1024_PARA_FLAG)
|
|
hProv = hEnh1024CryptProv;
|
|
else if (CertPara[dwCert].dwFlags & ENH_2048_PARA_FLAG)
|
|
hProv = hEnh2048CryptProv;
|
|
else
|
|
hProv = hRSACryptProv;
|
|
|
|
cbPubKeyInfo = 0;
|
|
CryptExportPublicKeyInfo(
|
|
hProv,
|
|
dwKeySpec,
|
|
dwCertEncodingType,
|
|
NULL, // pPubKeyInfo
|
|
&cbPubKeyInfo
|
|
);
|
|
if (cbPubKeyInfo == 0) {
|
|
PrintLastError("GetPublicKey::CryptExportPublicKeyInfo(cb == 0)");
|
|
goto ErrorReturn;
|
|
}
|
|
pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) TestAlloc(cbPubKeyInfo);
|
|
if (pPubKeyInfo == NULL) goto ErrorReturn;
|
|
if (!CryptExportPublicKeyInfo(
|
|
hProv,
|
|
dwKeySpec,
|
|
dwCertEncodingType,
|
|
pPubKeyInfo,
|
|
&cbPubKeyInfo
|
|
)) {
|
|
PrintLastError("GetPublicKey::CryptExportPublicKeyInfo");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (fInheritParameters) {
|
|
DWORD dwIssuer = CertPara[dwCert].dwIssuer;
|
|
|
|
if (dwCert != dwIssuer &&
|
|
0 == (CertPara[dwCert].dwFlags & XCHG_PARA_FLAG) &&
|
|
0 == (CertPara[dwCert].dwFlags & DSS_512_PARA_FLAG) &&
|
|
0 != (CertPara[dwCert].dwFlags & DSS_PARA_FLAG) &&
|
|
0 == (CertPara[dwIssuer].dwFlags & DSS_512_PARA_FLAG) &&
|
|
0 != (CertPara[dwIssuer].dwFlags & DSS_PARA_FLAG)) {
|
|
pPubKeyInfo->Algorithm.Parameters.cbData = 0;
|
|
pPubKeyInfo->Algorithm.Parameters.pbData = NULL;
|
|
}
|
|
}
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
fResult = FALSE;
|
|
if (pPubKeyInfo) {
|
|
TestFree(pPubKeyInfo);
|
|
pPubKeyInfo = NULL;
|
|
}
|
|
CommonReturn:
|
|
*ppPubKeyInfo = pPubKeyInfo;
|
|
return fResult;
|
|
}
|
|
|
|
#define SHA1_HASH_LEN 20
|
|
static BOOL Sha1HashPublicKey(
|
|
DWORD dwCert,
|
|
BYTE rgbHash[SHA1_HASH_LEN]
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
|
|
DWORD cbHash;
|
|
|
|
// Get Certificates's PUBLIC KEY. SHA1 hash the encoded public key.
|
|
if (!GetPublicKey(dwCert, &pPubKeyInfo)) goto ErrorReturn;
|
|
|
|
#if 1
|
|
cbHash = SHA1_HASH_LEN;
|
|
if (!CryptHashPublicKeyInfo(
|
|
0, // hCryptProv
|
|
CALG_SHA1,
|
|
0,
|
|
dwCertEncodingType,
|
|
pPubKeyInfo,
|
|
rgbHash,
|
|
&cbHash)) {
|
|
PrintLastError("Sha1HashPublicKey::CryptHashPublicKeyInfo");
|
|
goto ErrorReturn;
|
|
}
|
|
#else
|
|
cbHash = SHA1_HASH_LEN;
|
|
if (!CryptHashCertificate(
|
|
0, // hCryptProv
|
|
CALG_SHA1,
|
|
0, // dwFlags
|
|
pPubKeyInfo->PublicKey.pbData,
|
|
pPubKeyInfo->PublicKey.cbData,
|
|
rgbHash,
|
|
&cbHash)) {
|
|
PrintLastError("Sha1HashPublicKey::CryptHashCertificate");
|
|
goto ErrorReturn;
|
|
}
|
|
#endif
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
fResult = FALSE;
|
|
memset(rgbHash, 0, SHA1_HASH_LEN);
|
|
CommonReturn:
|
|
if (pPubKeyInfo)
|
|
TestFree(pPubKeyInfo);
|
|
return fResult;
|
|
}
|
|
|
|
static void CreateNameInfo(
|
|
DWORD dwCert,
|
|
PCERT_NAME_INFO pInfo,
|
|
PCERT_RDN pRDN,
|
|
CERT_RDN_ATTR rgAttr[]
|
|
)
|
|
{
|
|
LPSTR pszKey;
|
|
LPSTR pszUser;
|
|
DWORD i;
|
|
|
|
|
|
assert(RDN_CNT == ATTR_CNT);
|
|
for (i = 0; i < RDN_CNT; i++) {
|
|
pRDN[i].cRDNAttr = 1;
|
|
pRDN[i].rgRDNAttr = &rgAttr[i];
|
|
}
|
|
|
|
if (CertPara[dwCert].dwFlags & NO_NAME_PARA_FLAG) {
|
|
pInfo->cRDN = 0;
|
|
pInfo->rgRDN = NULL;
|
|
} else if (CertPara[dwCert].dwFlags & VALID_PARA_FLAG) {
|
|
pInfo->cRDN = 1;
|
|
pInfo->rgRDN = pRDN;
|
|
} else if (CertPara[dwCert].dwFlags & CA_PARA_FLAG) {
|
|
pInfo->cRDN = RDN_CNT - 1;
|
|
pInfo->rgRDN = pRDN;
|
|
} else {
|
|
pInfo->cRDN = RDN_CNT;
|
|
pInfo->rgRDN = pRDN;
|
|
}
|
|
|
|
rgAttr[0].pszObjId = ATTR_0_OBJID;
|
|
if (0 == strcmp("UTF8", CertPara[dwCert].pszName)) {
|
|
rgAttr[0].dwValueType = CERT_RDN_UTF8_STRING;
|
|
rgAttr[0].Value.pbData = (BYTE *) UTF8_NAME;
|
|
rgAttr[0].Value.cbData = wcslen(UTF8_NAME) * sizeof(WCHAR);
|
|
} else {
|
|
rgAttr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
rgAttr[0].Value.pbData = (BYTE *) CertPara[dwCert].pszName;
|
|
rgAttr[0].Value.cbData = strlen(CertPara[dwCert].pszName);
|
|
}
|
|
|
|
rgAttr[1].pszObjId = ATTR_1_OBJID;
|
|
rgAttr[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
if (CertPara[dwCert].dwFlags & XCHG_PARA_FLAG)
|
|
pszKey = "xchg";
|
|
else
|
|
pszKey = "sign";
|
|
rgAttr[1].Value.pbData = (BYTE *) pszKey;
|
|
rgAttr[1].Value.cbData = strlen(pszKey);
|
|
|
|
rgAttr[2].pszObjId = ATTR_2_OBJID;
|
|
rgAttr[2].dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
if (pszContainer)
|
|
pszUser = pszContainer;
|
|
else
|
|
pszUser = "default";
|
|
rgAttr[2].Value.pbData = (BYTE *) pszUser;
|
|
rgAttr[2].Value.cbData = strlen(pszUser);
|
|
|
|
rgAttr[3].pszObjId = szOID_RSA_emailAddr;
|
|
rgAttr[3].dwValueType = CERT_RDN_IA5_STRING;
|
|
rgAttr[3].Value.pbData = (BYTE *) " [email protected] ";
|
|
rgAttr[3].Value.cbData = strlen(" [email protected] ");
|
|
|
|
assert(ATTR_CNT == 3+1);
|
|
}
|
|
|
|
static BOOL CreateAuthorityKeyId(
|
|
DWORD dwIssuer,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
BYTE *pbNameEncoded = NULL;
|
|
DWORD cbNameEncoded;
|
|
CERT_AUTHORITY_KEY_ID_INFO KeyIdInfo;
|
|
|
|
CERT_RDN rgRDN[RDN_CNT];
|
|
CERT_RDN_ATTR rgAttr[ATTR_CNT];
|
|
CERT_NAME_INFO Name;
|
|
FILETIME SerialNumber;
|
|
|
|
memset(&KeyIdInfo, 0, sizeof(KeyIdInfo));
|
|
|
|
// Issuer's KeyId
|
|
KeyIdInfo.KeyId.pbData = (BYTE *) &dwIssuer;
|
|
KeyIdInfo.KeyId.cbData = sizeof(dwIssuer);
|
|
|
|
// Issuer's Issuer
|
|
CreateNameInfo(CertPara[dwIssuer].dwIssuer,
|
|
&Name, rgRDN, rgAttr);
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&Name,
|
|
&pbNameEncoded,
|
|
&cbNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
KeyIdInfo.CertIssuer.pbData = pbNameEncoded;
|
|
KeyIdInfo.CertIssuer.cbData = cbNameEncoded;
|
|
|
|
// Issuer's SerialNumber
|
|
{
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
SystemTime.wMilliseconds += (WORD) dwIssuer;
|
|
MySystemTimeToFileTime(&SystemTime, &SerialNumber);
|
|
}
|
|
KeyIdInfo.CertSerialNumber.pbData = (BYTE *) &SerialNumber;
|
|
KeyIdInfo.CertSerialNumber.cbData = sizeof(SerialNumber);
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_AUTHORITY_KEY_ID,
|
|
&KeyIdInfo,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if (pbNameEncoded)
|
|
TestFree(pbNameEncoded);
|
|
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateAuthorityKeyId2(
|
|
DWORD dwCert,
|
|
DWORD dwIssuer,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded,
|
|
IN DWORD dwAki = AKI2_KEYID
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
BYTE *pbNameEncoded = NULL;
|
|
DWORD cbNameEncoded;
|
|
CERT_AUTHORITY_KEY_ID2_INFO KeyId2Info;
|
|
CERT_ALT_NAME_ENTRY AltNameEntry;
|
|
|
|
BYTE rgbPubKeyHash[SHA1_HASH_LEN];
|
|
|
|
CERT_RDN rgRDN[RDN_CNT];
|
|
CERT_RDN_ATTR rgAttr[ATTR_CNT];
|
|
CERT_NAME_INFO Name;
|
|
FILETIME SerialNumber;
|
|
|
|
memset(&KeyId2Info, 0, sizeof(KeyId2Info));
|
|
|
|
// Issuer's KeyId
|
|
if (AKI2_BAD_KEYID == dwAki)
|
|
memset(rgbPubKeyHash, 0xba, sizeof(rgbPubKeyHash));
|
|
else
|
|
Sha1HashPublicKey(dwIssuer, rgbPubKeyHash);
|
|
KeyId2Info.KeyId.pbData = rgbPubKeyHash;
|
|
KeyId2Info.KeyId.cbData = sizeof(rgbPubKeyHash);
|
|
|
|
if (AKI2_FULL == dwAki ||
|
|
AKI2_BAD_ISSUER == dwAki ||
|
|
AKI2_BAD_SERIAL_NUMBER == dwAki ||
|
|
(CertPara[dwCert].dwFlags & ALL_EXT_PARA_FLAG)) {
|
|
|
|
if (AKI2_BAD_ISSUER == dwAki) {
|
|
Name.cRDN = 1;
|
|
Name.rgRDN = rgRDN;
|
|
rgRDN[0].cRDNAttr = 1;
|
|
rgRDN[0].rgRDNAttr = rgAttr;
|
|
|
|
rgAttr[0].pszObjId = szOID_COMMON_NAME;
|
|
rgAttr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
rgAttr[0].Value.pbData = (BYTE *) "AKI2BadIssuer";
|
|
rgAttr[0].Value.cbData = strlen("AKI2BadIssuer");
|
|
} else
|
|
// Issuer's Issuer
|
|
CreateNameInfo(CertPara[dwIssuer].dwIssuer,
|
|
&Name, rgRDN, rgAttr);
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&Name,
|
|
&pbNameEncoded,
|
|
&cbNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
AltNameEntry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
AltNameEntry.DirectoryName.pbData = pbNameEncoded;
|
|
AltNameEntry.DirectoryName.cbData = cbNameEncoded;
|
|
KeyId2Info.AuthorityCertIssuer.cAltEntry = 1;
|
|
KeyId2Info.AuthorityCertIssuer.rgAltEntry = &AltNameEntry;
|
|
|
|
// Issuer's SerialNumber
|
|
{
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
if (AKI2_BAD_SERIAL_NUMBER == dwAki)
|
|
SystemTime.wMilliseconds += CERT_CNT;
|
|
else
|
|
SystemTime.wMilliseconds += (WORD) dwIssuer;
|
|
MySystemTimeToFileTime(&SystemTime, &SerialNumber);
|
|
}
|
|
KeyId2Info.AuthorityCertSerialNumber.pbData = (BYTE *) &SerialNumber;
|
|
KeyId2Info.AuthorityCertSerialNumber.cbData = sizeof(SerialNumber);
|
|
}
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_AUTHORITY_KEY_ID2,
|
|
&KeyId2Info,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if (pbNameEncoded)
|
|
TestFree(pbNameEncoded);
|
|
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateAuthorityInfoAccess(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
DWORD dwIssuer = CertPara[dwCert].dwIssuer;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
BYTE *pbNameEncoded = NULL;
|
|
DWORD cbNameEncoded;
|
|
CERT_AUTHORITY_INFO_ACCESS AuthorityInfoAccess;
|
|
|
|
#define ACCESS_DESCR_COUNT 12
|
|
CERT_ACCESS_DESCRIPTION rgAccess[ACCESS_DESCR_COUNT];
|
|
|
|
CERT_RDN rgRDN[RDN_CNT];
|
|
CERT_RDN_ATTR rgAttr[ATTR_CNT];
|
|
CERT_NAME_INFO Name;
|
|
|
|
// Issuer's Issuer
|
|
CreateNameInfo(CertPara[dwIssuer].dwIssuer, &Name, rgRDN, rgAttr);
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&Name,
|
|
&pbNameEncoded,
|
|
&cbNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
rgAccess[0].pszAccessMethod = szOID_PKIX_OCSP;
|
|
rgAccess[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[0].AccessLocation.pwszURL = L"URL to the stars";
|
|
rgAccess[1].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[1].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
rgAccess[1].AccessLocation.DirectoryName.pbData = pbNameEncoded;
|
|
rgAccess[1].AccessLocation.DirectoryName.cbData = cbNameEncoded;
|
|
rgAccess[2].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[2].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
rgAccess[2].AccessLocation.pwszRfc822Name = L"[email protected]";
|
|
rgAccess[3].pszAccessMethod = szOID_PKIX_OCSP;
|
|
rgAccess[3].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[3].AccessLocation.pwszURL = L"URL to the POLICY";
|
|
rgAccess[4].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[4].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[4].AccessLocation.pwszURL = L"http://URLToTheIssuerCertificate";
|
|
rgAccess[5].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[5].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[5].AccessLocation.pwszURL = L"ldap://ntdev.microsoft.com/c=us??sub";
|
|
rgAccess[6].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[6].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[6].AccessLocation.pwszURL = L"file://FileToTheIssuerCertificate";
|
|
rgAccess[7].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[7].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[7].AccessLocation.pwszURL = L"file://FileToTheIssuerCertificate";
|
|
rgAccess[8].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[8].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[8].AccessLocation.pwszURL = L"file://FileToTheIssuerCertificate";
|
|
rgAccess[9].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[9].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[9].AccessLocation.pwszURL = L"file://FileToTheIssuerCertificate";
|
|
rgAccess[10].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[10].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[10].AccessLocation.pwszURL = L"http://crl.verisign.com/class1.crl";
|
|
rgAccess[11].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[11].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[11].AccessLocation.pwszURL = L"http://crl.microsoft.com/pki/crl/products/CodeSignPCA.crl";
|
|
|
|
memset(&AuthorityInfoAccess, 0, sizeof(AuthorityInfoAccess));
|
|
if (0 == strcmp("TestAIAEnd", CertPara[dwCert].pszName)) {
|
|
rgAccess[0].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[0].AccessLocation.pwszURL = L"file://TestAIACA.p7b";
|
|
AuthorityInfoAccess.cAccDescr = 1;
|
|
AuthorityInfoAccess.rgAccDescr = rgAccess;
|
|
} else if (0 == strcmp("RolloverCA", CertPara[dwCert].pszName)) {
|
|
rgAccess[0].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[0].AccessLocation.pwszURL = L"file://RolloverAIARoot.p7b";
|
|
AuthorityInfoAccess.cAccDescr = 1;
|
|
AuthorityInfoAccess.rgAccDescr = rgAccess;
|
|
} else if (0 == strcmp("kevin", CertPara[dwCert].pszName)) {
|
|
rgAccess[0].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
|
|
rgAccess[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAccess[0].AccessLocation.pwszURL = L"http://vbl03ca.ntdev.microsoft.com/CertEnroll/vbl03ca.ntdev.microsoft.com_Microsoft%20Windows%20VBL03CA.crt";
|
|
AuthorityInfoAccess.cAccDescr = 1;
|
|
AuthorityInfoAccess.rgAccDescr = rgAccess;
|
|
} else if (CertPara[dwCert].dwFlags & ALL_EXT_PARA_FLAG) {
|
|
AuthorityInfoAccess.cAccDescr = 11;
|
|
AuthorityInfoAccess.rgAccDescr = &rgAccess[1];
|
|
} else {
|
|
AuthorityInfoAccess.cAccDescr = 1;
|
|
AuthorityInfoAccess.rgAccDescr = rgAccess;
|
|
}
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_AUTHORITY_INFO_ACCESS,
|
|
&AuthorityInfoAccess,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if (pbNameEncoded)
|
|
TestFree(pbNameEncoded);
|
|
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BYTE CrlIPAddress[] = {1,2,3,4};
|
|
#define CRL_DNS_NAME L"CRL.DNS.NAME.COM"
|
|
#define CRL_EMAIL_NAME L"[email protected]"
|
|
#define CRL_URL_NAME1 L"file://crltest1.p7b"
|
|
#define CRL_URL_NAME2 L"file://crltest2.p7b"
|
|
#define CRL_REGISTERED_ID "1.2.3.4.5.6"
|
|
|
|
static BYTE rgbCrlOtherName[] = {0x02, 0x02, 0x11, 0x22};
|
|
static CERT_OTHER_NAME CrlOtherName = {
|
|
"1.2.33.44.55.66", sizeof(rgbCrlOtherName), rgbCrlOtherName };
|
|
|
|
#define CRL_DIST_POINTS_DELTA_FLAG 0x1
|
|
#define CRL_DIST_POINTS_UNSUPPORTED_FLAG 0x2
|
|
|
|
static BOOL CreateCrlDistPoints(
|
|
DWORD dwIssuer,
|
|
BOOL dwFlags,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
CRL_DIST_POINTS_INFO CrlDistPointsInfo;
|
|
|
|
BYTE bReasonFlags;
|
|
CERT_ALT_NAME_ENTRY rgAltNameEntry[9];
|
|
CERT_ALT_NAME_ENTRY rgIssuerAltNameEntry[1];
|
|
CRL_DIST_POINT rgDistPoint[5];
|
|
|
|
CERT_RDN rgRDN[RDN_CNT];
|
|
CERT_RDN_ATTR rgAttr[ATTR_CNT];
|
|
CERT_NAME_INFO Name;
|
|
BYTE *pbIssuerNameEncoded = NULL;
|
|
DWORD cbIssuerNameEncoded;
|
|
|
|
if (dwFlags & CRL_DIST_POINTS_DELTA_FLAG) {
|
|
// ISSUER
|
|
CreateNameInfo(dwIssuer, &Name, rgRDN, rgAttr);
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&Name,
|
|
&pbIssuerNameEncoded,
|
|
&cbIssuerNameEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
|
|
rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
|
|
rgAltNameEntry[0].pwszDNSName = CRL_DNS_NAME;
|
|
rgAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
rgAltNameEntry[1].pwszRfc822Name = CRL_EMAIL_NAME;
|
|
rgAltNameEntry[2].dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
|
|
rgAltNameEntry[2].IPAddress.pbData = CrlIPAddress;
|
|
rgAltNameEntry[2].IPAddress.cbData = sizeof(CrlIPAddress);
|
|
rgAltNameEntry[3].dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
|
|
rgAltNameEntry[3].pszRegisteredID = CRL_REGISTERED_ID;
|
|
rgAltNameEntry[4].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[4].pwszURL = CRL_URL_NAME2;
|
|
rgAltNameEntry[5].dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgAltNameEntry[5].pOtherName = &CrlOtherName;
|
|
rgAltNameEntry[6].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[6].pwszURL = CRL_URL_NAME1;
|
|
rgAltNameEntry[7].dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
rgAltNameEntry[7].DirectoryName.pbData = pbIssuerNameEncoded;
|
|
rgAltNameEntry[7].DirectoryName.cbData = cbIssuerNameEncoded;
|
|
rgAltNameEntry[8].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[8].pwszURL = L"file://BadUnsupportedChoice.crl";
|
|
|
|
|
|
rgIssuerAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgIssuerAltNameEntry[0].pwszURL = L"CRL Issuer URL";
|
|
|
|
memset(rgDistPoint, 0, sizeof(rgDistPoint));
|
|
|
|
// [0] has unsupported ReasonFlags
|
|
rgDistPoint[0].DistPointName.dwDistPointNameChoice =
|
|
CRL_DIST_POINT_FULL_NAME;
|
|
rgDistPoint[0].DistPointName.FullName.cAltEntry = 1;
|
|
rgDistPoint[0].DistPointName.FullName.rgAltEntry = &rgAltNameEntry[8];
|
|
rgDistPoint[0].ReasonFlags.cbData = 1;
|
|
rgDistPoint[0].ReasonFlags.pbData = &bReasonFlags;
|
|
rgDistPoint[0].ReasonFlags.cUnusedBits = 1;
|
|
bReasonFlags = CRL_REASON_KEY_COMPROMISE_FLAG |
|
|
CRL_REASON_CA_COMPROMISE_FLAG;
|
|
// [1] has unsupported CRLIssuer
|
|
rgDistPoint[1].DistPointName.dwDistPointNameChoice =
|
|
CRL_DIST_POINT_FULL_NAME;
|
|
rgDistPoint[1].DistPointName.FullName.cAltEntry = 1;
|
|
rgDistPoint[1].DistPointName.FullName.rgAltEntry = &rgAltNameEntry[8];
|
|
rgDistPoint[1].CRLIssuer.cAltEntry = 1;
|
|
rgDistPoint[1].CRLIssuer.rgAltEntry = rgIssuerAltNameEntry;
|
|
// [2] is empty
|
|
rgDistPoint[3].DistPointName.dwDistPointNameChoice =
|
|
CRL_DIST_POINT_FULL_NAME;
|
|
rgDistPoint[3].DistPointName.FullName.cAltEntry = 5;
|
|
rgDistPoint[3].DistPointName.FullName.rgAltEntry = &rgAltNameEntry[0];
|
|
rgDistPoint[4].DistPointName.dwDistPointNameChoice =
|
|
CRL_DIST_POINT_FULL_NAME;
|
|
rgDistPoint[4].DistPointName.FullName.cAltEntry = 3;
|
|
rgDistPoint[4].DistPointName.FullName.rgAltEntry = &rgAltNameEntry[5];
|
|
|
|
memset(&CrlDistPointsInfo, 0, sizeof(CrlDistPointsInfo));
|
|
CrlDistPointsInfo.rgDistPoint = &rgDistPoint[0];
|
|
if (dwFlags & CRL_DIST_POINTS_UNSUPPORTED_FLAG)
|
|
CrlDistPointsInfo.cDistPoint = 1;
|
|
else
|
|
CrlDistPointsInfo.cDistPoint = 5;
|
|
} else {
|
|
rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[0].pwszURL = L"file://test1.crl";
|
|
|
|
memset(rgDistPoint, 0, sizeof(rgDistPoint));
|
|
rgDistPoint[0].DistPointName.dwDistPointNameChoice =
|
|
CRL_DIST_POINT_FULL_NAME;
|
|
rgDistPoint[0].DistPointName.FullName.cAltEntry = 1;
|
|
rgDistPoint[0].DistPointName.FullName.rgAltEntry = &rgAltNameEntry[0];
|
|
|
|
memset(&CrlDistPointsInfo, 0, sizeof(CrlDistPointsInfo));
|
|
CrlDistPointsInfo.rgDistPoint = &rgDistPoint[0];
|
|
CrlDistPointsInfo.cDistPoint = 1;
|
|
}
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_CRL_DIST_POINTS,
|
|
&CrlDistPointsInfo,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if(pbIssuerNameEncoded)
|
|
TestFree(pbIssuerNameEncoded);
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
|
|
static BOOL CreateCertIssuingDistPoint(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
CRL_ISSUING_DIST_POINT Info;
|
|
|
|
BYTE bOnlySomeReasonFlags;
|
|
CERT_ALT_NAME_ENTRY rgAltNameEntry[2];
|
|
|
|
rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[0].pwszURL = L"file://test1.crl";
|
|
rgAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[1].pwszURL = L"file://test1.crl";
|
|
|
|
memset(&Info, 0, sizeof(Info));
|
|
Info.DistPointName.dwDistPointNameChoice =
|
|
CRL_DIST_POINT_FULL_NAME;
|
|
Info.DistPointName.FullName.cAltEntry = 2;
|
|
Info.DistPointName.FullName.rgAltEntry = &rgAltNameEntry[0];
|
|
|
|
Info.OnlySomeReasonFlags.cbData = 1;
|
|
Info.OnlySomeReasonFlags.pbData = &bOnlySomeReasonFlags;
|
|
Info.OnlySomeReasonFlags.cUnusedBits = 1;
|
|
bOnlySomeReasonFlags = CRL_REASON_KEY_COMPROMISE_FLAG |
|
|
CRL_REASON_CA_COMPROMISE_FLAG;
|
|
|
|
Info.fIndirectCRL = TRUE;
|
|
Info.fOnlyContainsUserCerts = TRUE;
|
|
Info.fOnlyContainsCACerts = TRUE;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_ISSUING_DIST_POINT,
|
|
&Info,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateCrlIssuingDistPoint(
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
CRL_ISSUING_DIST_POINT Info;
|
|
|
|
CERT_ALT_NAME_ENTRY rgAltNameEntry[1];
|
|
|
|
rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[0].pwszURL = L"file://test1.crl";
|
|
|
|
memset(&Info, 0, sizeof(Info));
|
|
Info.DistPointName.dwDistPointNameChoice =
|
|
CRL_DIST_POINT_FULL_NAME;
|
|
Info.DistPointName.FullName.cAltEntry = 1;
|
|
Info.DistPointName.FullName.rgAltEntry = &rgAltNameEntry[0];
|
|
|
|
if (!AllocAndEncodeObject(
|
|
szOID_ISSUING_DIST_POINT,
|
|
&Info,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateNameConstraints(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
PCERT_NAME_CONSTRAINTS_INFO pInfo;
|
|
|
|
CERT_NAME_CONSTRAINTS_INFO RootInfo;
|
|
CERT_GENERAL_SUBTREE rgRootPermitted[15];
|
|
CERT_GENERAL_SUBTREE rgRootExcluded[15];
|
|
|
|
CERT_NAME_CONSTRAINTS_INFO CaInfo;
|
|
CERT_GENERAL_SUBTREE rgCaPermitted[15];
|
|
|
|
CERT_NAME_CONSTRAINTS_INFO MissingInfo;
|
|
CERT_GENERAL_SUBTREE rgMissingPermitted[15];
|
|
CERT_GENERAL_SUBTREE rgMissingExcluded[15];
|
|
|
|
BYTE rgbMissing[3] = {2, 1, 1}; // INTEGER
|
|
CERT_OTHER_NAME MissingOtherName =
|
|
{"1.2.3.4.5.6", sizeof(rgbMissing), rgbMissing};
|
|
|
|
BYTE rgbEmpty[2] = {5, 0}; // NULL
|
|
CERT_OTHER_NAME AnyOctetOtherName =
|
|
{OCTET_OTHER_NAME_OID, sizeof(rgbEmpty), rgbEmpty};
|
|
CERT_OTHER_NAME AnyStringOtherName =
|
|
{STRING_OTHER_NAME_OID, sizeof(rgbEmpty), rgbEmpty};
|
|
|
|
CERT_NAME_VALUE NameValue;
|
|
CERT_OTHER_NAME PermittedUPNOtherName;
|
|
BYTE *pbPermittedUPNNameEncoded = NULL;
|
|
DWORD cbPermittedUPNNameEncoded;
|
|
|
|
CERT_OTHER_NAME ExcludedUPNOtherName;
|
|
BYTE *pbExcludedUPNNameEncoded = NULL;
|
|
DWORD cbExcludedUPNNameEncoded;
|
|
|
|
CERT_OTHER_NAME AnyUPNOtherName;
|
|
BYTE *pbAnyUPNNameEncoded = NULL;
|
|
DWORD cbAnyUPNNameEncoded;
|
|
|
|
CERT_OTHER_NAME PermittedStringOtherName;
|
|
BYTE *pbPermittedStringOtherNameEncoded = NULL;
|
|
DWORD cbPermittedStringOtherNameEncoded;
|
|
|
|
CERT_OTHER_NAME ExcludedStringOtherName;
|
|
BYTE *pbExcludedStringOtherNameEncoded = NULL;
|
|
DWORD cbExcludedStringOtherNameEncoded;
|
|
|
|
BYTE rgbDefaultIPAddress[] = {1,1,0,0, 255,255,0,0};
|
|
BYTE rgbAllExtIPAddress[] = {
|
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0xF0};
|
|
BYTE rgbExcludedIPAddress[] = {2,2,2,2, 255,254,254,254};
|
|
|
|
CERT_RDN rgRDN[3];
|
|
CERT_RDN_ATTR rgAttr[3];
|
|
CERT_NAME_INFO NameInfo;
|
|
BYTE *pbPermittedNameEncoded = NULL;
|
|
DWORD cbPermittedNameEncoded;
|
|
BYTE *pbExcludedNameEncoded = NULL;
|
|
DWORD cbExcludedNameEncoded;
|
|
BYTE *pbAnyOUNameEncoded = NULL;
|
|
DWORD cbAnyOUNameEncoded;
|
|
BYTE *pbAnyNameEncoded = NULL;
|
|
DWORD cbAnyNameEncoded;
|
|
LPSTR pszSign = "\n sign \r";
|
|
|
|
DWORD i;
|
|
|
|
NameValue.dwValueType = CERT_RDN_BMP_STRING;
|
|
NameValue.Value.pbData = (BYTE *) L" @UPN.COM ";
|
|
NameValue.Value.cbData = 0;
|
|
if (!AllocAndEncodeObject(
|
|
X509_UNICODE_ANY_STRING,
|
|
&NameValue,
|
|
&pbPermittedUPNNameEncoded,
|
|
&cbPermittedUPNNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
PermittedUPNOtherName.pszObjId = szOID_NT_PRINCIPAL_NAME;
|
|
PermittedUPNOtherName.Value.pbData = pbPermittedUPNNameEncoded;
|
|
PermittedUPNOtherName.Value.cbData = cbPermittedUPNNameEncoded;
|
|
|
|
NameValue.dwValueType = CERT_RDN_UNIVERSAL_STRING;
|
|
NameValue.Value.pbData = (BYTE *) L" [email protected] ";
|
|
NameValue.Value.cbData = 0;
|
|
if (!AllocAndEncodeObject(
|
|
X509_UNICODE_ANY_STRING,
|
|
&NameValue,
|
|
&pbExcludedUPNNameEncoded,
|
|
&cbExcludedUPNNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
ExcludedUPNOtherName.pszObjId = szOID_NT_PRINCIPAL_NAME;
|
|
ExcludedUPNOtherName.Value.pbData = pbExcludedUPNNameEncoded;
|
|
ExcludedUPNOtherName.Value.cbData = cbExcludedUPNNameEncoded;
|
|
|
|
NameValue.dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
NameValue.Value.pbData = (BYTE *) L"";
|
|
NameValue.Value.cbData = 0;
|
|
if (!AllocAndEncodeObject(
|
|
X509_UNICODE_ANY_STRING,
|
|
&NameValue,
|
|
&pbAnyUPNNameEncoded,
|
|
&cbAnyUPNNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
AnyUPNOtherName.pszObjId = szOID_NT_PRINCIPAL_NAME;
|
|
AnyUPNOtherName.Value.pbData = pbAnyUPNNameEncoded;
|
|
AnyUPNOtherName.Value.cbData = cbAnyUPNNameEncoded;
|
|
|
|
NameValue.dwValueType = CERT_RDN_VISIBLE_STRING;
|
|
NameValue.Value.pbData = (BYTE *) L" String@OtherName ";
|
|
NameValue.Value.cbData = 0;
|
|
if (!AllocAndEncodeObject(
|
|
X509_UNICODE_ANY_STRING,
|
|
&NameValue,
|
|
&pbPermittedStringOtherNameEncoded,
|
|
&cbPermittedStringOtherNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
PermittedStringOtherName.pszObjId = STRING_OTHER_NAME_OID;
|
|
PermittedStringOtherName.Value.pbData = pbPermittedStringOtherNameEncoded;
|
|
PermittedStringOtherName.Value.cbData = cbPermittedStringOtherNameEncoded;
|
|
|
|
NameValue.dwValueType = CERT_RDN_GRAPHIC_STRING;
|
|
NameValue.Value.pbData = (BYTE *) L" excludedString@OtherName ";
|
|
NameValue.Value.cbData = 0;
|
|
if (!AllocAndEncodeObject(
|
|
X509_UNICODE_ANY_STRING,
|
|
&NameValue,
|
|
&pbExcludedStringOtherNameEncoded,
|
|
&cbExcludedStringOtherNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
ExcludedStringOtherName.pszObjId = STRING_OTHER_NAME_OID;
|
|
ExcludedStringOtherName.Value.pbData = pbExcludedStringOtherNameEncoded;
|
|
ExcludedStringOtherName.Value.cbData = cbExcludedStringOtherNameEncoded;
|
|
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
rgRDN[i].cRDNAttr = 1;
|
|
rgRDN[i].rgRDNAttr = &rgAttr[i];
|
|
}
|
|
|
|
// Any
|
|
rgAttr[0].pszObjId = ATTR_0_OBJID;
|
|
rgAttr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
rgAttr[0].Value.pbData = NULL;
|
|
rgAttr[0].Value.cbData = 0;
|
|
|
|
rgAttr[1].pszObjId = ATTR_1_OBJID;
|
|
rgAttr[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
rgAttr[1].Value.pbData = (BYTE *) pszSign;
|
|
rgAttr[1].Value.cbData = strlen(pszSign);
|
|
|
|
rgAttr[2].pszObjId = ATTR_2_OBJID;
|
|
rgAttr[2].dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
rgAttr[2].Value.pbData = (BYTE *) "default";
|
|
rgAttr[2].Value.cbData = strlen("default");
|
|
|
|
NameInfo.cRDN = 3;
|
|
NameInfo.rgRDN = rgRDN;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&NameInfo,
|
|
&pbPermittedNameEncoded,
|
|
&cbPermittedNameEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
rgAttr[0].pszObjId = ATTR_0_OBJID;
|
|
rgAttr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
rgAttr[0].Value.pbData = (BYTE *) "excluded";
|
|
rgAttr[0].Value.cbData = strlen("excluded");
|
|
NameInfo.cRDN = 1;
|
|
NameInfo.rgRDN = rgRDN;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&NameInfo,
|
|
&pbExcludedNameEncoded,
|
|
&cbExcludedNameEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
rgAttr[0].pszObjId = szOID_ORGANIZATIONAL_UNIT_NAME;
|
|
rgAttr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
rgAttr[0].Value.pbData = NULL;
|
|
rgAttr[0].Value.cbData = 0;
|
|
NameInfo.cRDN = 1;
|
|
NameInfo.rgRDN = rgRDN;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&NameInfo,
|
|
&pbAnyOUNameEncoded,
|
|
&cbAnyOUNameEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
NameInfo.cRDN = 0;
|
|
NameInfo.rgRDN = rgRDN;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&NameInfo,
|
|
&pbAnyNameEncoded,
|
|
&cbAnyNameEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
memset(&rgRootPermitted, 0, sizeof(rgRootPermitted));
|
|
rgRootPermitted[0].Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
|
|
rgRootPermitted[0].Base.pwszDNSName = L"dns Name ";
|
|
rgRootPermitted[1].Base.dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
rgRootPermitted[1].Base.pwszRfc822Name = L" eMail.COM";
|
|
rgRootPermitted[2].Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
|
|
rgRootPermitted[2].Base.pwszDNSName = L" kevin ";
|
|
rgRootPermitted[3].Base.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgRootPermitted[3].Base.pwszURL = L".url.com";
|
|
rgRootPermitted[4].Base.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgRootPermitted[4].Base.pOtherName = &PermittedUPNOtherName;
|
|
|
|
rgRootPermitted[5].Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
|
|
rgRootPermitted[5].Base.IPAddress.pbData = rgbDefaultIPAddress;
|
|
rgRootPermitted[5].Base.IPAddress.cbData = sizeof(rgbDefaultIPAddress);
|
|
rgRootPermitted[6].Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
|
|
rgRootPermitted[6].Base.IPAddress.pbData = rgbAllExtIPAddress;
|
|
rgRootPermitted[6].Base.IPAddress.cbData = sizeof(rgbAllExtIPAddress);
|
|
|
|
rgRootPermitted[7].Base.dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
rgRootPermitted[7].Base.pwszRfc822Name = L" [email protected] ";
|
|
|
|
rgRootPermitted[8].Base.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
rgRootPermitted[8].Base.DirectoryName.pbData = pbPermittedNameEncoded;
|
|
rgRootPermitted[8].Base.DirectoryName.cbData = cbPermittedNameEncoded;
|
|
rgRootPermitted[9].Base.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
rgRootPermitted[9].Base.DirectoryName.pbData = pbAnyOUNameEncoded;
|
|
rgRootPermitted[9].Base.DirectoryName.cbData = cbAnyOUNameEncoded;
|
|
|
|
rgRootPermitted[10].Base.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgRootPermitted[10].Base.pOtherName = &PermittedStringOtherName;
|
|
rgRootPermitted[11].Base.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgRootPermitted[11].Base.pOtherName = &AnyOctetOtherName;
|
|
|
|
rgRootPermitted[12].Base.dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
rgRootPermitted[12].Base.pwszRfc822Name = L"[email protected]";
|
|
|
|
|
|
memset(&rgRootExcluded, 0, sizeof(rgRootExcluded));
|
|
rgRootExcluded[0].Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
|
|
rgRootExcluded[0].Base.pwszDNSName = L"www.ExcLuDed.dns.com ";
|
|
rgRootExcluded[1].Base.dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
rgRootExcluded[1].Base.pwszRfc822Name = L"[email protected]";
|
|
rgRootExcluded[2].Base.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgRootExcluded[2].Base.pwszURL = L"excluded.url.com";
|
|
rgRootExcluded[3].Base.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgRootExcluded[3].Base.pOtherName = &ExcludedUPNOtherName;
|
|
|
|
rgRootExcluded[4].Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
|
|
rgRootExcluded[4].Base.IPAddress.pbData = rgbExcludedIPAddress;
|
|
rgRootExcluded[4].Base.IPAddress.cbData = sizeof(rgbExcludedIPAddress);
|
|
|
|
rgRootExcluded[5].Base.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
rgRootExcluded[5].Base.DirectoryName.pbData = pbExcludedNameEncoded;
|
|
rgRootExcluded[5].Base.DirectoryName.cbData = cbExcludedNameEncoded;
|
|
|
|
rgRootExcluded[6].Base.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgRootExcluded[6].Base.pOtherName = &ExcludedStringOtherName;
|
|
|
|
|
|
memset(&RootInfo, 0, sizeof(RootInfo));
|
|
RootInfo.cPermittedSubtree = 13;
|
|
RootInfo.rgPermittedSubtree = rgRootPermitted;
|
|
RootInfo.cExcludedSubtree = 7;
|
|
RootInfo.rgExcludedSubtree = rgRootExcluded;
|
|
|
|
|
|
memset(&rgCaPermitted, 0, sizeof(rgCaPermitted));
|
|
rgCaPermitted[0].Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
|
|
rgCaPermitted[0].Base.pwszDNSName = L"";
|
|
rgCaPermitted[1].Base.dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
rgCaPermitted[1].Base.pwszRfc822Name = L"";
|
|
rgCaPermitted[2].Base.dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgCaPermitted[2].Base.pwszURL = L"";
|
|
rgCaPermitted[3].Base.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgCaPermitted[3].Base.pOtherName = &AnyUPNOtherName;
|
|
rgCaPermitted[4].Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
|
|
rgCaPermitted[4].Base.IPAddress.pbData = NULL;
|
|
rgCaPermitted[4].Base.IPAddress.cbData = 0;
|
|
rgCaPermitted[5].Base.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
rgCaPermitted[5].Base.DirectoryName.pbData = pbAnyNameEncoded;
|
|
rgCaPermitted[5].Base.DirectoryName.cbData = cbAnyNameEncoded;
|
|
|
|
rgCaPermitted[6].Base.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgCaPermitted[6].Base.pOtherName = &AnyOctetOtherName;
|
|
rgCaPermitted[7].Base.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgCaPermitted[7].Base.pOtherName = &AnyStringOtherName;
|
|
|
|
|
|
memset(&CaInfo, 0, sizeof(CaInfo));
|
|
CaInfo.cPermittedSubtree = 8;
|
|
CaInfo.rgPermittedSubtree = rgCaPermitted;
|
|
CaInfo.cExcludedSubtree = 0;
|
|
CaInfo.rgExcludedSubtree = NULL;
|
|
|
|
memset(&rgMissingPermitted, 0, sizeof(rgMissingPermitted));
|
|
rgMissingPermitted[0].Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
|
|
rgMissingPermitted[0].Base.pwszDNSName = L"a super dns Name ";
|
|
rgMissingPermitted[0].dwMinimum = 1;
|
|
rgMissingPermitted[1].Base.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgMissingPermitted[1].Base.pOtherName = &MissingOtherName;
|
|
|
|
memset(&rgMissingExcluded, 0, sizeof(rgMissingExcluded));
|
|
rgMissingExcluded[0].Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
|
|
rgMissingExcluded[0].Base.pwszDNSName = L"www.ReallyExcLuDed.dns.com ";
|
|
rgMissingExcluded[1].Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
|
|
rgMissingExcluded[1].Base.pwszDNSName = L"www.ExcLuDed.dns.com ";
|
|
rgMissingExcluded[1].fMaximum = TRUE;
|
|
rgMissingExcluded[1].dwMaximum = 2;
|
|
rgMissingExcluded[2].Base.dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgMissingExcluded[2].Base.pOtherName = &MissingOtherName;
|
|
|
|
memset(&MissingInfo, 0, sizeof(MissingInfo));
|
|
MissingInfo.cPermittedSubtree = 2;
|
|
MissingInfo.rgPermittedSubtree = rgMissingPermitted;
|
|
MissingInfo.cExcludedSubtree = 3;
|
|
MissingInfo.rgExcludedSubtree = rgMissingExcluded;
|
|
|
|
if (dwCert == POLICY_ROOT)
|
|
pInfo = &RootInfo;
|
|
else if (dwCert == POLICY_CA)
|
|
pInfo = &CaInfo;
|
|
else if (0 == strcmp(CertPara[dwCert].pszName, "MissingNCCA"))
|
|
pInfo = &MissingInfo;
|
|
else
|
|
goto ErrorReturn;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME_CONSTRAINTS,
|
|
pInfo,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
TestFree(pbPermittedUPNNameEncoded);
|
|
TestFree(pbExcludedUPNNameEncoded);
|
|
TestFree(pbAnyUPNNameEncoded);
|
|
TestFree(pbPermittedNameEncoded);
|
|
TestFree(pbExcludedNameEncoded);
|
|
TestFree(pbPermittedStringOtherNameEncoded);
|
|
TestFree(pbExcludedStringOtherNameEncoded);
|
|
TestFree(pbAnyOUNameEncoded);
|
|
TestFree(pbAnyNameEncoded);
|
|
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreatePolicyMappings(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
PCERT_POLICY_MAPPINGS_INFO pInfo;
|
|
|
|
CERT_POLICY_MAPPING rgRootPolicyMapping[] = {
|
|
"1.1.22", "1.2.22.1",
|
|
"1.1.22", "1.2.22.2", // multiple subjects may map to same issuer
|
|
"1.1.4444", "1.2.4444",
|
|
"1.1.4444", "1.1.4444", // multiple subjects for same issuer
|
|
"1.1.22.333", "1.2.22.1", // duplicate subject
|
|
"1.1.22", "1.2.22.3",
|
|
"1.1.333", "1.2.333.1",
|
|
"1.1.333", "1.2.333.2",
|
|
"1.1.333", "1.2.333.3",
|
|
"1.1.22", "1.2.22.3", // multiple subjects for same issuer
|
|
"1.1.22", "1.2.22.3", // duplicate subject
|
|
"1.1.22", "1.2.22.4", // multiple subjects for same issuer
|
|
};
|
|
CERT_POLICY_MAPPINGS_INFO RootInfo = {
|
|
sizeof(rgRootPolicyMapping) / sizeof(rgRootPolicyMapping[0]),
|
|
rgRootPolicyMapping
|
|
};
|
|
|
|
CERT_POLICY_MAPPING rgCaPolicyMapping[] = {
|
|
"1.1.1", "1.3.1.1",
|
|
"1.1.1", "1.3.1.2",
|
|
"1.2.22.2", "1.3.22.2.1", // -> 1.1.22
|
|
"1.2.22.2", "1.3.22.2.2", // -> 1.1.22
|
|
};
|
|
CERT_POLICY_MAPPINGS_INFO CaInfo = {
|
|
sizeof(rgCaPolicyMapping) / sizeof(rgCaPolicyMapping[0]),
|
|
rgCaPolicyMapping
|
|
};
|
|
|
|
if (dwCert == POLICY_ROOT)
|
|
pInfo = &RootInfo;
|
|
else if (dwCert == POLICY_CA)
|
|
pInfo = &CaInfo;
|
|
else
|
|
goto ErrorReturn;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_POLICY_MAPPINGS,
|
|
pInfo,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
|
|
static BOOL CreatePolicyConstraints(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
PCERT_POLICY_CONSTRAINTS_INFO pInfo;
|
|
|
|
CERT_POLICY_CONSTRAINTS_INFO RootInfo = {
|
|
TRUE, // fRequireExplicitPolicy
|
|
1, // dwRequireExplicitPolicySkipCerts
|
|
TRUE, // fInhibitPolicyMapping
|
|
1 // dwInhibitPolicyMappingSkipCerts
|
|
};
|
|
|
|
CERT_POLICY_CONSTRAINTS_INFO CaInfo = {
|
|
TRUE, // fRequireExplicitPolicy
|
|
0, // dwRequireExplicitPolicySkipCerts
|
|
TRUE, // fInhibitPolicyMapping
|
|
0 // dwInhibitPolicyMappingSkipCerts
|
|
};
|
|
|
|
if (dwCert == POLICY_ROOT)
|
|
pInfo = &RootInfo;
|
|
else if (dwCert == POLICY_CA)
|
|
pInfo = &CaInfo;
|
|
else if (dwCert == ROLLOVER_CROSS_CERT) {
|
|
CaInfo.dwRequireExplicitPolicySkipCerts = 2;
|
|
pInfo = &CaInfo;
|
|
} else
|
|
goto ErrorReturn;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_POLICY_CONSTRAINTS,
|
|
pInfo,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateCrossCertDistPoints(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
CROSS_CERT_DIST_POINTS_INFO Info;
|
|
CERT_ALT_NAME_INFO rgDistPoint[2];
|
|
CERT_ALT_NAME_ENTRY rgAltNameEntry[3];
|
|
|
|
rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[0].pwszURL = L"file://vsgood.cer";
|
|
rgAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[1].pwszURL = L"file://nt.store";
|
|
rgAltNameEntry[2].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[2].pwszURL = L"file://win95.store";
|
|
|
|
rgDistPoint[0].cAltEntry = 1;
|
|
rgDistPoint[0].rgAltEntry = &rgAltNameEntry[0];
|
|
rgDistPoint[1].cAltEntry = 2;
|
|
rgDistPoint[1].rgAltEntry = &rgAltNameEntry[1];
|
|
|
|
memset(&Info, 0, sizeof(Info));
|
|
Info.dwSyncDeltaTime = 60 * 60 * 8;
|
|
Info.cDistPoint = 2;
|
|
Info.rgDistPoint = rgDistPoint;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_CROSS_CERT_DIST_POINTS,
|
|
&Info,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateKeyId(
|
|
DWORD dwIssuer,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BYTE rgbPubKeyHash[SHA1_HASH_LEN];
|
|
CRYPT_DATA_BLOB KeyIdentifier;
|
|
|
|
Sha1HashPublicKey(dwIssuer, rgbPubKeyHash);
|
|
|
|
KeyIdentifier.pbData = rgbPubKeyHash;
|
|
KeyIdentifier.cbData = sizeof(rgbPubKeyHash);
|
|
|
|
return AllocAndEncodeObject(
|
|
X509_OCTET_STRING,
|
|
&KeyIdentifier,
|
|
ppbEncoded,
|
|
pcbEncoded
|
|
);
|
|
}
|
|
|
|
static BOOL CreateKeyAttributes(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
CERT_KEY_ATTRIBUTES_INFO KeyAttrInfo;
|
|
CERT_PRIVATE_KEY_VALIDITY KeyValidity;
|
|
|
|
BYTE bIntendedKeyUsage;
|
|
|
|
memset(&KeyAttrInfo, 0, sizeof(KeyAttrInfo));
|
|
|
|
if (CertPara[dwCert].dwFlags & CA_PARA_FLAG) {
|
|
// Issuer's KeyId
|
|
KeyAttrInfo.KeyId.pbData = (BYTE *) &dwCert;
|
|
KeyAttrInfo.KeyId.cbData = sizeof(dwCert);
|
|
}
|
|
|
|
if (CertPara[dwCert].dwFlags & XCHG_PARA_FLAG)
|
|
bIntendedKeyUsage = CERT_KEY_ENCIPHERMENT_KEY_USAGE |
|
|
CERT_DATA_ENCIPHERMENT_KEY_USAGE | CERT_KEY_AGREEMENT_KEY_USAGE;
|
|
else
|
|
bIntendedKeyUsage =
|
|
CERT_DIGITAL_SIGNATURE_KEY_USAGE | CERT_NON_REPUDIATION_KEY_USAGE;
|
|
if (CertPara[dwCert].dwFlags & CA_PARA_FLAG)
|
|
bIntendedKeyUsage |= CERT_KEY_CERT_SIGN_KEY_USAGE;
|
|
|
|
KeyAttrInfo.IntendedKeyUsage.pbData = &bIntendedKeyUsage;
|
|
KeyAttrInfo.IntendedKeyUsage.cbData = 1;
|
|
KeyAttrInfo.IntendedKeyUsage.cUnusedBits = 1;
|
|
|
|
{
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
|
|
SystemTime.wMilliseconds = 123;
|
|
MySystemTimeToFileTime(&SystemTime, &KeyValidity.NotBefore);
|
|
SystemTime.wYear += 2;
|
|
SystemTime.wMilliseconds = 456;
|
|
|
|
MySystemTimeToFileTime(&SystemTime, &KeyValidity.NotAfter);
|
|
}
|
|
KeyAttrInfo.pPrivateKeyUsagePeriod = &KeyValidity;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_KEY_ATTRIBUTES,
|
|
&KeyAttrInfo,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateKeyUsageRestriction(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
CERT_KEY_USAGE_RESTRICTION_INFO KeyUsageInfo;
|
|
BYTE bRestrictedKeyUsage;
|
|
|
|
LPSTR rgpszCertPolicyElementId[4] = {
|
|
"1.2.333.1",
|
|
"1.2.333.22",
|
|
"1.2.333.333",
|
|
"1.2.333.4444"
|
|
};
|
|
CERT_POLICY_ID rgCertPolicyId[3] = {
|
|
0, NULL,
|
|
1, rgpszCertPolicyElementId,
|
|
4, rgpszCertPolicyElementId
|
|
};
|
|
|
|
LPSTR rgpszSpcCertPolicyElementId[2] = {
|
|
SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID,
|
|
SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID
|
|
};
|
|
CERT_POLICY_ID rgSpcCertPolicyId[2] = {
|
|
1, &rgpszSpcCertPolicyElementId[0],
|
|
1, &rgpszSpcCertPolicyElementId[1]
|
|
};
|
|
|
|
memset(&KeyUsageInfo, 0, sizeof(KeyUsageInfo));
|
|
|
|
if (CertPara[dwCert].dwFlags & XCHG_PARA_FLAG)
|
|
bRestrictedKeyUsage = CERT_KEY_ENCIPHERMENT_KEY_USAGE |
|
|
CERT_DATA_ENCIPHERMENT_KEY_USAGE | CERT_KEY_AGREEMENT_KEY_USAGE;
|
|
else
|
|
bRestrictedKeyUsage =
|
|
CERT_DIGITAL_SIGNATURE_KEY_USAGE | CERT_NON_REPUDIATION_KEY_USAGE;
|
|
if (CertPara[dwCert].dwFlags & CA_PARA_FLAG)
|
|
bRestrictedKeyUsage |= CERT_KEY_CERT_SIGN_KEY_USAGE;
|
|
|
|
KeyUsageInfo.RestrictedKeyUsage.pbData = &bRestrictedKeyUsage;
|
|
KeyUsageInfo.RestrictedKeyUsage.cbData = 1;
|
|
KeyUsageInfo.RestrictedKeyUsage.cUnusedBits = 1;
|
|
|
|
if (CertPara[dwCert].dwFlags & SPC_AGENCY_PARA_FLAG) {
|
|
KeyUsageInfo.cCertPolicyId = 2;
|
|
KeyUsageInfo.rgCertPolicyId = rgSpcCertPolicyId;
|
|
} else if (CertPara[dwCert].dwFlags & SPC_COM_PARA_FLAG) {
|
|
KeyUsageInfo.cCertPolicyId = 1;
|
|
KeyUsageInfo.rgCertPolicyId = &rgSpcCertPolicyId[1];
|
|
} else if (CertPara[dwCert].dwFlags & SPC_EXT_PARA_FLAG) {
|
|
KeyUsageInfo.cCertPolicyId = 1;
|
|
KeyUsageInfo.rgCertPolicyId = &rgSpcCertPolicyId[0];
|
|
} else if (CertPara[dwCert].dwFlags & ALL_EXT_PARA_FLAG) {
|
|
KeyUsageInfo.cCertPolicyId = 3;
|
|
KeyUsageInfo.rgCertPolicyId = rgCertPolicyId;
|
|
}
|
|
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_KEY_USAGE_RESTRICTION,
|
|
&KeyUsageInfo,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateBasicConstraints(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
BYTE *pbSubtreesEncoded = NULL;
|
|
DWORD cbSubtreesEncoded;
|
|
CERT_NAME_BLOB rgSubtreesConstraint[2];
|
|
|
|
CERT_BASIC_CONSTRAINTS_INFO BasicConstraintsInfo;
|
|
BYTE bSubjectType;
|
|
|
|
memset(&BasicConstraintsInfo, 0, sizeof(BasicConstraintsInfo));
|
|
|
|
if (CertPara[dwCert].dwFlags & CA_PARA_FLAG) {
|
|
bSubjectType = CERT_CA_SUBJECT_FLAG;
|
|
BasicConstraintsInfo.fPathLenConstraint = TRUE;
|
|
BasicConstraintsInfo.dwPathLenConstraint = dwCert + 1;
|
|
} else
|
|
bSubjectType = CERT_END_ENTITY_SUBJECT_FLAG;
|
|
BasicConstraintsInfo.SubjectType.pbData = &bSubjectType;
|
|
BasicConstraintsInfo.SubjectType.cbData = 1;
|
|
BasicConstraintsInfo.SubjectType.cUnusedBits = 6;
|
|
|
|
if (CertPara[dwCert].dwFlags & ALL_EXT_PARA_FLAG) {
|
|
CERT_RDN rgRDN[RDN_CNT];
|
|
CERT_RDN_ATTR rgAttr[ATTR_CNT];
|
|
CERT_NAME_INFO Name;
|
|
|
|
CreateNameInfo(dwCert, &Name, rgRDN, rgAttr);
|
|
cbSubtreesEncoded = 0;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&Name,
|
|
&pbSubtreesEncoded,
|
|
&cbSubtreesEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
BasicConstraintsInfo.cSubtreesConstraint = 2;
|
|
BasicConstraintsInfo.rgSubtreesConstraint = rgSubtreesConstraint;
|
|
rgSubtreesConstraint[0].pbData = pbSubtreesEncoded;
|
|
rgSubtreesConstraint[0].cbData = cbSubtreesEncoded;
|
|
rgSubtreesConstraint[1].pbData = pbSubtreesEncoded;
|
|
rgSubtreesConstraint[1].cbData = cbSubtreesEncoded;
|
|
}
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_BASIC_CONSTRAINTS,
|
|
&BasicConstraintsInfo,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if (pbSubtreesEncoded)
|
|
TestFree(pbSubtreesEncoded);
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateKeyUsage(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
CRYPT_BIT_BLOB KeyUsageInfo;
|
|
BYTE bKeyUsage;
|
|
|
|
memset(&KeyUsageInfo, 0, sizeof(KeyUsageInfo));
|
|
|
|
if (CertPara[dwCert].dwFlags & XCHG_PARA_FLAG)
|
|
bKeyUsage = CERT_KEY_ENCIPHERMENT_KEY_USAGE |
|
|
CERT_DATA_ENCIPHERMENT_KEY_USAGE | CERT_KEY_AGREEMENT_KEY_USAGE;
|
|
else
|
|
bKeyUsage =
|
|
CERT_DIGITAL_SIGNATURE_KEY_USAGE | CERT_NON_REPUDIATION_KEY_USAGE;
|
|
if (0 == strcmp(CertPara[dwCert].pszName, "InvalidKeyUsageCA"))
|
|
// No cert signing usage for this cert
|
|
;
|
|
else if (CertPara[dwCert].dwFlags & CA_PARA_FLAG)
|
|
bKeyUsage |= CERT_KEY_CERT_SIGN_KEY_USAGE;
|
|
|
|
KeyUsageInfo.pbData = &bKeyUsage;
|
|
KeyUsageInfo.cbData = 1;
|
|
KeyUsageInfo.cUnusedBits = 1;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_KEY_USAGE,
|
|
&KeyUsageInfo,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateBasicConstraints2(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
|
|
CERT_BASIC_CONSTRAINTS2_INFO BasicConstraints2Info;
|
|
|
|
memset(&BasicConstraints2Info, 0, sizeof(BasicConstraints2Info));
|
|
|
|
if (dwCert == POLICY_ROOT || dwCert == ROLLOVER_CROSS_CERT) {
|
|
BasicConstraints2Info.fCA = TRUE;
|
|
BasicConstraints2Info.fPathLenConstraint = TRUE;
|
|
BasicConstraints2Info.dwPathLenConstraint = 1;
|
|
} else if (dwCert == POLICY_CA) {
|
|
BasicConstraints2Info.fCA = TRUE;
|
|
BasicConstraints2Info.fPathLenConstraint = TRUE;
|
|
BasicConstraints2Info.dwPathLenConstraint = 0;
|
|
} else if (CertPara[dwCert].dwFlags & CA_PARA_FLAG) {
|
|
BasicConstraints2Info.fCA = TRUE;
|
|
BasicConstraints2Info.fPathLenConstraint = TRUE;
|
|
if (0 == strcmp(CertPara[dwCert].pszName, "TestRoot"))
|
|
BasicConstraints2Info.dwPathLenConstraint = 2;
|
|
else
|
|
BasicConstraints2Info.dwPathLenConstraint = dwCert + 1;
|
|
} else
|
|
BasicConstraints2Info.fCA = FALSE;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_BASIC_CONSTRAINTS2,
|
|
&BasicConstraints2Info,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreatePolicies(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BYTE rgbQualifier2[] = {5, 0}; // NULL
|
|
BYTE rgbQualifier4[] = {4, 8, 1,2,3,4,5,6,7,8}; // Octet String
|
|
|
|
CERT_POLICY_QUALIFIER_INFO rgQualifierInfo[4] = {
|
|
"1.2.1", 0, NULL,
|
|
"1.2.2", sizeof(rgbQualifier2), rgbQualifier2,
|
|
"1.2.3", 0, NULL,
|
|
"1.2.4", sizeof(rgbQualifier4), rgbQualifier4
|
|
};
|
|
|
|
// Root has the following policies:
|
|
// 1.1.1
|
|
// 1.1.55555
|
|
// 1.1.22
|
|
// 1.1.333
|
|
// 1.1.4444
|
|
CERT_POLICY_INFO rgRootPolicyInfo[] = {
|
|
"1.1.1", 0, NULL,
|
|
"1.1.55555", 0, NULL,
|
|
"1.1.22", 2, rgQualifierInfo,
|
|
"1.1.333", 2, &rgQualifierInfo[2],
|
|
"1.1.333", 0, NULL, // duplicate, should be removed
|
|
"1.1.4444", 1, rgQualifierInfo,
|
|
"1.1.4444", 0, NULL, // duplicate
|
|
"1.1.1", 0, NULL, // duplicate
|
|
"1.1.1", 0, NULL, // duplicate
|
|
};
|
|
|
|
// After mapping, the CA has the following policies:
|
|
// 1.1.1
|
|
// 1.1.22
|
|
// 1.1.333
|
|
// 1.1.4444
|
|
CERT_POLICY_INFO rgCaPolicyInfo[] = {
|
|
"1.2.22.1", 0, NULL, // 1.1.22
|
|
"1.2.22.2", 0, NULL, // 1.1.22
|
|
"1.2.22.3", 0, NULL, // 1.1.22
|
|
"1.2.333.1", 0, NULL, // 1.1.333
|
|
"1.2.333.2", 0, NULL, // 1.1.333
|
|
"1.2.4444", 0, NULL, // 1.1.4444
|
|
"1.1.4444", 0, NULL, // 1.1.4444
|
|
"1.1.1", 0, NULL, // 1.1.1
|
|
"1.2.333.3", 0, NULL, // 1.1.333
|
|
"1.2.55555", 0, NULL, // no mapping
|
|
};
|
|
|
|
// After mapping, the cert has the following policies:
|
|
// 1.1.1
|
|
// 1.1.22
|
|
CERT_POLICY_INFO rgPolicyInfo[] = {
|
|
"1.1.55555", 0, NULL, // no mapping via ca
|
|
"1.3.22.2.1", 0, NULL, // 1.2.22.2 -> 1.1.22
|
|
"1.3.1.1", 0, NULL, // 1.1.1
|
|
"1.2.55555", 0, NULL, // no mapping via root
|
|
};
|
|
|
|
// After mapping, the cert has the following policies:
|
|
// 1.1.1
|
|
// 1.1.22
|
|
// 1.1.4444
|
|
CERT_POLICY_INFO rgAllExtPolicyInfo[] = {
|
|
"1.3.1.2", 0, NULL, // 1.1.1
|
|
"1.3.22.2.2", 0, NULL, // 1.2.22.2 -> 1.1.22
|
|
"1.1.55555", 0, NULL, // no mapping via ca
|
|
"1.2.55555", 0, NULL, // not mapping via root
|
|
"1.1.4444", 0, NULL, // 1.1.4444
|
|
};
|
|
|
|
CERT_POLICY_INFO rgSpcPolicyInfo[2] = {
|
|
SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID, 0, NULL,
|
|
SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID, 0, NULL
|
|
};
|
|
|
|
CERT_POLICY_INFO rgDssCAPolicyInfo[] = {
|
|
szOID_ANY_CERT_POLICY, 0, NULL,
|
|
};
|
|
|
|
CERT_POLICY_INFO rgDssEndPolicyInfo[] = {
|
|
"1.1.4444", 0, NULL,
|
|
"1.1.55555", 0, NULL,
|
|
};
|
|
|
|
CERT_POLICIES_INFO PoliciesInfo;
|
|
memset(&PoliciesInfo, 0, sizeof(PoliciesInfo));
|
|
|
|
if (0 == strcmp(CertPara[dwCert].pszName, "DssCA")) {
|
|
PoliciesInfo.cPolicyInfo = sizeof(rgDssCAPolicyInfo) /
|
|
sizeof(rgDssCAPolicyInfo[0]);
|
|
PoliciesInfo.rgPolicyInfo = rgDssCAPolicyInfo;
|
|
} else if (0 == strcmp(CertPara[dwCert].pszName, "DssEnd")) {
|
|
PoliciesInfo.cPolicyInfo = sizeof(rgDssEndPolicyInfo) /
|
|
sizeof(rgDssEndPolicyInfo[0]);
|
|
PoliciesInfo.rgPolicyInfo = rgDssEndPolicyInfo;
|
|
} else if (POLICY_ROOT == dwCert) {
|
|
PoliciesInfo.cPolicyInfo = sizeof(rgRootPolicyInfo) /
|
|
sizeof(rgRootPolicyInfo[0]);
|
|
PoliciesInfo.rgPolicyInfo = rgRootPolicyInfo;
|
|
} else if (POLICY_CA == dwCert) {
|
|
PoliciesInfo.cPolicyInfo = sizeof(rgCaPolicyInfo) /
|
|
sizeof(rgCaPolicyInfo[0]);
|
|
PoliciesInfo.rgPolicyInfo = rgCaPolicyInfo;
|
|
} else if (CertPara[dwCert].dwFlags & SPC_AGENCY_PARA_FLAG) {
|
|
PoliciesInfo.cPolicyInfo = 2;
|
|
PoliciesInfo.rgPolicyInfo = rgSpcPolicyInfo;
|
|
} else if (CertPara[dwCert].dwFlags & SPC_COM_PARA_FLAG) {
|
|
PoliciesInfo.cPolicyInfo = 1;
|
|
PoliciesInfo.rgPolicyInfo = &rgSpcPolicyInfo[1];
|
|
} else if (CertPara[dwCert].dwFlags & SPC_EXT_PARA_FLAG) {
|
|
PoliciesInfo.cPolicyInfo = 1;
|
|
PoliciesInfo.rgPolicyInfo = &rgSpcPolicyInfo[0];
|
|
} else if (CertPara[dwCert].dwFlags & ALL_EXT_PARA_FLAG) {
|
|
PoliciesInfo.cPolicyInfo = sizeof(rgAllExtPolicyInfo) /
|
|
sizeof(rgAllExtPolicyInfo[0]);
|
|
PoliciesInfo.rgPolicyInfo = rgAllExtPolicyInfo;
|
|
} else {
|
|
PoliciesInfo.cPolicyInfo = sizeof(rgPolicyInfo) /
|
|
sizeof(rgPolicyInfo[0]);
|
|
PoliciesInfo.rgPolicyInfo = rgPolicyInfo;
|
|
}
|
|
|
|
return AllocAndEncodeObject(
|
|
X509_CERT_POLICIES,
|
|
&PoliciesInfo,
|
|
ppbEncoded,
|
|
pcbEncoded);
|
|
}
|
|
|
|
static BOOL CreateSMIMECapabilities(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BYTE rgb128BitLen[] = {2, 2, 0, 128}; // Integer
|
|
BYTE rgb40BitLen[] = {2, 1, 40}; // Integer
|
|
|
|
CRYPT_SMIME_CAPABILITY rgCapability[4] = {
|
|
szOID_RSA_DES_EDE3_CBC, 0, NULL,
|
|
szOID_RSA_RC2CBC, sizeof(rgb128BitLen), rgb128BitLen,
|
|
szOID_RSA_RC2CBC, sizeof(rgb40BitLen), rgb40BitLen,
|
|
szOID_RSA_preferSignedData, 0, NULL
|
|
};
|
|
|
|
CRYPT_SMIME_CAPABILITIES Capabilities = {
|
|
sizeof(rgCapability)/sizeof(rgCapability[0]), rgCapability
|
|
};
|
|
|
|
return AllocAndEncodeObject(
|
|
PKCS_SMIME_CAPABILITIES,
|
|
&Capabilities,
|
|
ppbEncoded,
|
|
pcbEncoded);
|
|
}
|
|
|
|
|
|
static BOOL CreateAltName(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
CERT_ALT_NAME_INFO AltNameInfo;
|
|
#define ALT_NAME_ENTRY_CNT 15
|
|
CERT_ALT_NAME_ENTRY rgAltNameEntry[ALT_NAME_ENTRY_CNT];
|
|
DWORD i;
|
|
|
|
BYTE *pbNameEncoded = NULL;
|
|
DWORD cbNameEncoded;
|
|
|
|
CERT_OTHER_NAME UPNOtherName;
|
|
BYTE *pbUPNNameEncoded = NULL;
|
|
DWORD cbUPNNameEncoded;
|
|
|
|
CERT_OTHER_NAME StringOtherName;
|
|
BYTE *pbStringOtherNameEncoded = NULL;
|
|
DWORD cbStringOtherNameEncoded;
|
|
DWORD dwStringOtherNameValueType = CERT_RDN_UTF8_STRING;
|
|
|
|
LPWSTR pwszEmail = NULL;
|
|
LPWSTR pwszUrl = NULL;
|
|
LPWSTR pwszUPN = NULL;
|
|
LPWSTR pwszStringOtherName = NULL;
|
|
LPWSTR pwszDns = NULL;
|
|
|
|
BYTE rgbOctetOtherName[] = {0x04, 0x02, 0x11, 0x22};
|
|
CERT_OTHER_NAME OctetOtherName;
|
|
PCERT_OTHER_NAME pOctetOtherName = NULL;
|
|
|
|
LPSTR pszRegisteredID = NULL;
|
|
|
|
BYTE rgbDefaultIPAddress[] = {1,1,0,0};
|
|
BYTE rgbAllExtIPAddress[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17};
|
|
BYTE rgbExcludedIPAddress[] = {2,2,3,3};
|
|
BYTE rgbNotPermittedIPAddress[] = {3,3,3,3};
|
|
BYTE *pbIPAddress = NULL;
|
|
DWORD cbIPAddress = 0;
|
|
|
|
if (CertPara[dwCert].dwFlags &
|
|
(NO_NAME_PARA_FLAG | ALT_DIR_NAME_PARA_FLAG)) {
|
|
pwszEmail = L"[email protected]";
|
|
}
|
|
|
|
if (CertPara[dwCert].dwFlags & ALL_EXT_PARA_FLAG) {
|
|
pwszEmail = L" [email protected] ";
|
|
pwszUrl = L" http://www.AllExt.url.com:388/more url stuff";
|
|
pwszDns = L"DNS name";
|
|
pwszUPN = L"[email protected]";
|
|
pwszStringOtherName = L"AllExtString@OtherName";
|
|
dwStringOtherNameValueType = CERT_RDN_TELETEX_STRING;
|
|
pbIPAddress = rgbAllExtIPAddress;
|
|
cbIPAddress = sizeof(rgbAllExtIPAddress);
|
|
} else if (0 == strcmp(CertPara[dwCert].pszName, "Excluded")) {
|
|
pwszEmail = L" [email protected] ";
|
|
pwszUrl = L" http://Excluded.url.com/more url stuff";
|
|
pwszDns = L"www.excluded.dns.com";
|
|
pwszUPN = L"[email protected]";
|
|
pwszStringOtherName = L"ExcludedString@OtherName";
|
|
dwStringOtherNameValueType = CERT_RDN_IA5_STRING;
|
|
pbIPAddress = rgbExcludedIPAddress;
|
|
cbIPAddress = sizeof(rgbExcludedIPAddress);
|
|
} else if (0 == strcmp(CertPara[dwCert].pszName, "NotPermitted")) {
|
|
pwszEmail = L"[email protected]";
|
|
pwszUrl = L"http://www.url.not/more url stuff";
|
|
pwszDns = L"www.excluded.dns.not";
|
|
pwszUPN = L"[email protected]";
|
|
pwszStringOtherName = L"String@OtherNameNot";
|
|
dwStringOtherNameValueType = CERT_RDN_GENERAL_STRING;
|
|
pbIPAddress = rgbNotPermittedIPAddress;
|
|
cbIPAddress = sizeof(rgbNotPermittedIPAddress);
|
|
|
|
OctetOtherName.pszObjId = OCTET_OTHER_NAME_OID;
|
|
OctetOtherName.Value.pbData = rgbOctetOtherName;
|
|
OctetOtherName.Value.cbData = sizeof(rgbOctetOtherName);
|
|
pOctetOtherName = &OctetOtherName;
|
|
|
|
pszRegisteredID = "1.2.3.4.5.6.7";
|
|
} else {
|
|
pwszUPN = L" [email protected] ";
|
|
pwszStringOtherName = L" DefaultString@OtherName ";
|
|
dwStringOtherNameValueType = CERT_RDN_UTF8_STRING;
|
|
pbIPAddress = rgbDefaultIPAddress;
|
|
cbIPAddress = sizeof(rgbDefaultIPAddress);
|
|
}
|
|
|
|
if (0 == strcmp(CertPara[dwCert].pszName, "MissingNCEnd")) {
|
|
OctetOtherName.pszObjId = OCTET_OTHER_NAME_OID;
|
|
OctetOtherName.Value.pbData = rgbOctetOtherName;
|
|
OctetOtherName.Value.cbData = sizeof(rgbOctetOtherName);
|
|
pOctetOtherName = &OctetOtherName;
|
|
}
|
|
|
|
|
|
i = 0;
|
|
if (pwszEmail) {
|
|
rgAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
rgAltNameEntry[0].pwszRfc822Name = pwszEmail;
|
|
i++;
|
|
}
|
|
|
|
if (pwszUPN) {
|
|
CERT_NAME_VALUE UPNNameValue;
|
|
|
|
UPNNameValue.dwValueType = CERT_RDN_UTF8_STRING;
|
|
UPNNameValue.Value.pbData = (BYTE *) pwszUPN;
|
|
UPNNameValue.Value.cbData = 0;
|
|
if (!AllocAndEncodeObject(
|
|
X509_UNICODE_ANY_STRING,
|
|
&UPNNameValue,
|
|
&pbUPNNameEncoded,
|
|
&cbUPNNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
UPNOtherName.pszObjId = szOID_NT_PRINCIPAL_NAME;
|
|
UPNOtherName.Value.pbData = pbUPNNameEncoded;
|
|
UPNOtherName.Value.cbData = cbUPNNameEncoded;
|
|
|
|
rgAltNameEntry[i].dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgAltNameEntry[i].pOtherName = &UPNOtherName;
|
|
i++;
|
|
}
|
|
|
|
if (pwszStringOtherName) {
|
|
CERT_NAME_VALUE OtherNameValue;
|
|
|
|
OtherNameValue.dwValueType = dwStringOtherNameValueType;
|
|
OtherNameValue.Value.pbData = (BYTE *) pwszStringOtherName;
|
|
OtherNameValue.Value.cbData = 0;
|
|
if (!AllocAndEncodeObject(
|
|
X509_UNICODE_ANY_STRING,
|
|
&OtherNameValue,
|
|
&pbStringOtherNameEncoded,
|
|
&cbStringOtherNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
StringOtherName.pszObjId = STRING_OTHER_NAME_OID;
|
|
StringOtherName.Value.pbData = pbStringOtherNameEncoded;
|
|
StringOtherName.Value.cbData = cbStringOtherNameEncoded;
|
|
|
|
rgAltNameEntry[i].dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgAltNameEntry[i].pOtherName = &StringOtherName;
|
|
i++;
|
|
}
|
|
|
|
if (pwszUrl) {
|
|
rgAltNameEntry[i].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgAltNameEntry[i].pwszURL = pwszUrl;
|
|
i++;
|
|
}
|
|
|
|
if (pwszDns) {
|
|
rgAltNameEntry[i].dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
|
|
rgAltNameEntry[i].pwszDNSName = pwszDns;
|
|
i++;
|
|
}
|
|
|
|
if (pszRegisteredID) {
|
|
rgAltNameEntry[i].dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
|
|
rgAltNameEntry[i].pszRegisteredID = pszRegisteredID;
|
|
i++;
|
|
}
|
|
|
|
if (pbIPAddress && cbIPAddress) {
|
|
rgAltNameEntry[i].dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
|
|
rgAltNameEntry[i].IPAddress.pbData = pbIPAddress;
|
|
rgAltNameEntry[i].IPAddress.cbData = cbIPAddress;
|
|
i++;
|
|
}
|
|
|
|
if (pOctetOtherName) {
|
|
rgAltNameEntry[i].dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgAltNameEntry[i].pOtherName = pOctetOtherName;
|
|
i++;
|
|
}
|
|
|
|
|
|
if (CertPara[dwCert].dwFlags & ALT_DIR_NAME_PARA_FLAG) {
|
|
CERT_NAME_INFO NameInfo;
|
|
CERT_RDN rgRDN[1];
|
|
CERT_RDN_ATTR rgAttr[1];
|
|
|
|
NameInfo.cRDN = 1;
|
|
NameInfo.rgRDN = rgRDN;
|
|
|
|
rgRDN[0].cRDNAttr = 1;
|
|
rgRDN[0].rgRDNAttr = rgAttr;
|
|
|
|
rgAttr[0].pszObjId = szOID_ORGANIZATIONAL_UNIT_NAME;
|
|
rgAttr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
rgAttr[0].Value.pbData = (BYTE *) CertPara[dwCert].pszName;
|
|
rgAttr[0].Value.cbData = strlen(CertPara[dwCert].pszName);
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&NameInfo,
|
|
&pbNameEncoded,
|
|
&cbNameEncoded))
|
|
goto ErrorReturn;
|
|
|
|
rgAltNameEntry[i].dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
rgAltNameEntry[i].DirectoryName.pbData = pbNameEncoded;
|
|
rgAltNameEntry[i].DirectoryName.cbData = cbNameEncoded;
|
|
i++;
|
|
}
|
|
|
|
AltNameInfo.cAltEntry = i;
|
|
AltNameInfo.rgAltEntry = rgAltNameEntry;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_ALTERNATE_NAME,
|
|
&AltNameInfo,
|
|
&pbEncoded,
|
|
&cbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
TestFree(pbNameEncoded);
|
|
TestFree(pbUPNNameEncoded);
|
|
TestFree(pbStringOtherNameEncoded);
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateSETAccountAlias(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
|
|
BOOL bInfo;
|
|
|
|
if (CertPara[dwCert].dwFlags & ALL_EXT_PARA_FLAG)
|
|
bInfo = TRUE;
|
|
else
|
|
bInfo = FALSE;
|
|
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_SET_ACCOUNT_ALIAS,
|
|
&bInfo,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateSETHashedRootKey(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
|
|
BYTE i;
|
|
BYTE rgbInfo[SET_HASHED_ROOT_LEN];
|
|
|
|
for (i = 0; i < SET_HASHED_ROOT_LEN; i++)
|
|
rgbInfo[i] = i;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_SET_HASHED_ROOT_KEY,
|
|
rgbInfo,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateSETCertificateType(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
|
|
CRYPT_BIT_BLOB Info;
|
|
BYTE rgbType[2] = {0,0};
|
|
|
|
if (dwCert < 8)
|
|
rgbType[0] = 1 << (dwCert % 8);
|
|
else
|
|
rgbType[1] = 0x40 << (dwCert % 2);
|
|
Info.pbData = rgbType;
|
|
Info.cbData = 2;
|
|
Info.cUnusedBits = 6;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_SET_CERTIFICATE_TYPE,
|
|
&Info,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateSETMerchantData(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
|
|
SET_MERCHANT_DATA_INFO Info;
|
|
|
|
memset(&Info, 0, sizeof(Info));
|
|
if (CertPara[dwCert].dwFlags & ALL_EXT_PARA_FLAG) {
|
|
Info.pszMerID = "ID";
|
|
Info.pszMerAcquirerBIN = "0123456";
|
|
Info.pszMerTermID = "TermID";
|
|
Info.pszMerName = "Name";
|
|
Info.pszMerCity = "City";
|
|
Info.pszMerStateProvince = "StateProvince";
|
|
Info.pszMerPostalCode = "PostalCode";
|
|
Info.pszMerCountry = "Country/Region";
|
|
Info.pszMerPhone = "Phone";
|
|
Info.fMerPhoneRelease = TRUE;
|
|
Info.fMerAuthFlag = TRUE;
|
|
} else {
|
|
Info.pszMerID = "";
|
|
Info.pszMerAcquirerBIN = "";
|
|
Info.pszMerTermID = "";
|
|
Info.pszMerName = "";
|
|
Info.pszMerCity = "";
|
|
Info.pszMerStateProvince = "";
|
|
Info.pszMerPostalCode = "";
|
|
Info.pszMerCountry = "";
|
|
Info.pszMerPhone = "";
|
|
Info.fMerPhoneRelease = FALSE;
|
|
Info.fMerAuthFlag = FALSE;
|
|
}
|
|
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_SET_MERCHANT_DATA,
|
|
&Info,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateSpcSpAgency(
|
|
DWORD dwCert,
|
|
DWORD dwLevel,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
|
|
SPC_LINK UrlLink;
|
|
SPC_LINK MonikerLink;
|
|
#define MONIKER_DATA "Moniker Serialized Data"
|
|
SPC_LINK FileLink;
|
|
SPC_IMAGE Image;
|
|
SPC_SP_AGENCY_INFO AgencyInfo;
|
|
|
|
#define BIT_MAP "Bit Map"
|
|
#define META_FILE "Metafile"
|
|
#define ENHANCED_META_FILE "Enhanced Metafile"
|
|
#define GIF_FILE "Gif File"
|
|
|
|
int i;
|
|
|
|
UrlLink.dwLinkChoice = SPC_URL_LINK_CHOICE;
|
|
UrlLink.pwszUrl = L"http://microsoft.com";
|
|
|
|
MonikerLink.dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
|
|
for (i = 0; i < sizeof(MonikerLink.Moniker.ClassId); i++)
|
|
MonikerLink.Moniker.ClassId[i] = (BYTE) (i + 1);
|
|
MonikerLink.Moniker.SerializedData.cbData = strlen(MONIKER_DATA);
|
|
MonikerLink.Moniker.SerializedData.pbData = (BYTE *) MONIKER_DATA;
|
|
|
|
FileLink.dwLinkChoice = SPC_FILE_LINK_CHOICE;
|
|
FileLink.pwszFile = L"Unicode File Link";
|
|
|
|
memset(&Image, 0, sizeof(Image));
|
|
memset(&AgencyInfo, 0, sizeof(AgencyInfo));
|
|
|
|
AgencyInfo.pLogoImage = &Image;
|
|
|
|
if (dwLevel >= 1) {
|
|
AgencyInfo.pPolicyInformation = &UrlLink;
|
|
AgencyInfo.pwszPolicyDisplayText = L"MICROSOFT PRODUCTS POLICY";
|
|
AgencyInfo.pLogoImage = NULL;
|
|
}
|
|
|
|
if (dwLevel >= 2) {
|
|
AgencyInfo.pPolicyInformation = &UrlLink;
|
|
AgencyInfo.pwszPolicyDisplayText = L"Unicode String";
|
|
Image.Bitmap.cbData = strlen(BIT_MAP);
|
|
Image.Bitmap.pbData = (BYTE *) BIT_MAP;
|
|
}
|
|
|
|
if (dwLevel >= 3) {
|
|
AgencyInfo.pwszPolicyDisplayText = L"Policy Display Unicode String";
|
|
AgencyInfo.pLogoLink = &MonikerLink;
|
|
Image.pImageLink = &FileLink;
|
|
Image.Metafile.cbData = strlen(META_FILE);
|
|
Image.Metafile.pbData = (BYTE *) META_FILE;
|
|
Image.EnhancedMetafile.cbData = strlen(ENHANCED_META_FILE);
|
|
Image.EnhancedMetafile.pbData = (BYTE *) ENHANCED_META_FILE;
|
|
Image.GifFile.cbData = strlen(GIF_FILE);
|
|
Image.GifFile.pbData = (BYTE *) GIF_FILE;
|
|
}
|
|
|
|
if (!AllocAndEncodeObject(
|
|
SPC_SP_AGENCY_INFO_STRUCT,
|
|
&AgencyInfo,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateSpcCommonName(
|
|
DWORD dwCert,
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbEncoded = NULL;
|
|
DWORD cbEncoded;
|
|
|
|
#define SPC_AGENCY_NAME L"Microsoft Code Signing Agency"
|
|
#define SPC_COM_NAME "Microsoft Software Products"
|
|
|
|
CERT_NAME_VALUE NameValue;
|
|
|
|
if (CertPara[dwCert].dwFlags & SPC_AGENCY_PARA_FLAG) {
|
|
NameValue.dwValueType = CERT_RDN_UNICODE_STRING;
|
|
NameValue.Value.pbData = (BYTE *) SPC_AGENCY_NAME;
|
|
NameValue.Value.cbData = wcslen(SPC_AGENCY_NAME) * sizeof(WCHAR);
|
|
} else if (CertPara[dwCert].dwFlags & SPC_COM_PARA_FLAG) {
|
|
NameValue.dwValueType = CERT_RDN_IA5_STRING;
|
|
NameValue.Value.pbData = (BYTE *) SPC_COM_NAME;
|
|
NameValue.Value.cbData = strlen(SPC_COM_NAME);
|
|
} else {
|
|
NameValue.dwValueType = CERT_RDN_PRINTABLE_STRING;
|
|
NameValue.Value.pbData = (BYTE *) CertPara[dwCert].pszName;
|
|
NameValue.Value.cbData = strlen(CertPara[dwCert].pszName);
|
|
}
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME_VALUE,
|
|
&NameValue,
|
|
&pbEncoded,
|
|
&cbEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbEncoded) {
|
|
TestFree(pbEncoded);
|
|
pbEncoded = NULL;
|
|
}
|
|
cbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
*ppbEncoded = pbEncoded;
|
|
*pcbEncoded = cbEncoded;
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL CreateCRLReason(
|
|
OUT BYTE **ppbEncoded,
|
|
IN OUT DWORD *pcbEncoded
|
|
)
|
|
{
|
|
static int iReason = -1;
|
|
|
|
iReason += 1;
|
|
|
|
iReason = iReason % CRL_REASON_CERTIFICATE_HOLD;
|
|
return AllocAndEncodeObject(
|
|
X509_ENUMERATED,
|
|
(const void *) &iReason,
|
|
ppbEncoded,
|
|
pcbEncoded
|
|
);
|
|
}
|
|
|
|
static BOOL EncodeCert(DWORD dwCert, BYTE **ppbEncoded, DWORD *pcbEncoded)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbSubjectEncoded = NULL;
|
|
DWORD cbSubjectEncoded;
|
|
BYTE *pbIssuerEncoded = NULL;
|
|
DWORD cbIssuerEncoded;
|
|
PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
|
|
BYTE *pbCertEncoded = NULL;
|
|
DWORD cbCertEncoded;
|
|
|
|
BYTE *pbKeyIdEncoded = NULL;
|
|
DWORD cbKeyIdEncoded;
|
|
BYTE *pbKeyId2Encoded = NULL;
|
|
DWORD cbKeyId2Encoded;
|
|
BYTE *pbSubjectKeyIdEncoded = NULL;
|
|
DWORD cbSubjectKeyIdEncoded;
|
|
BYTE *pbAuthorityInfoAccessEncoded = NULL;
|
|
DWORD cbAuthorityInfoAccessEncoded;
|
|
BYTE *pbCrlDistPointsEncoded = NULL;
|
|
DWORD cbCrlDistPointsEncoded;
|
|
BYTE *pbKeyAttrEncoded = NULL;
|
|
DWORD cbKeyAttrEncoded;
|
|
BYTE *pbAltNameEncoded = NULL;
|
|
DWORD cbAltNameEncoded;
|
|
BYTE *pbIssuerAltNameEncoded = NULL;
|
|
DWORD cbIssuerAltNameEncoded;
|
|
BYTE *pbKeyUsageRestrictionEncoded = NULL;
|
|
DWORD cbKeyUsageRestrictionEncoded;
|
|
BYTE *pbBasicConstraintsEncoded = NULL;
|
|
DWORD cbBasicConstraintsEncoded;
|
|
BYTE *pbKeyUsageEncoded = NULL;
|
|
DWORD cbKeyUsageEncoded;
|
|
BYTE *pbBasicConstraints2Encoded = NULL;
|
|
DWORD cbBasicConstraints2Encoded;
|
|
BYTE *pbPoliciesEncoded = NULL;
|
|
DWORD cbPoliciesEncoded;
|
|
|
|
BYTE *pbSETAccountAliasEncoded = NULL;
|
|
DWORD cbSETAccountAliasEncoded;
|
|
BYTE *pbSETHashedRootKeyEncoded = NULL;
|
|
DWORD cbSETHashedRootKeyEncoded;
|
|
BYTE *pbSETCertificateTypeEncoded = NULL;
|
|
DWORD cbSETCertificateTypeEncoded;
|
|
BYTE *pbSETMerchantDataEncoded = NULL;
|
|
DWORD cbSETMerchantDataEncoded;
|
|
|
|
BYTE *pbSpcSpAgencyEncoded0 = NULL;
|
|
DWORD cbSpcSpAgencyEncoded0;
|
|
BYTE *pbSpcSpAgencyEncoded1 = NULL;
|
|
DWORD cbSpcSpAgencyEncoded1;
|
|
BYTE *pbSpcSpAgencyEncoded2 = NULL;
|
|
DWORD cbSpcSpAgencyEncoded2;
|
|
BYTE *pbSpcCommonNameEncoded = NULL;
|
|
DWORD cbSpcCommonNameEncoded;
|
|
|
|
BYTE *pbNetscapeCertType = NULL;
|
|
DWORD cbNetscapeCertType;
|
|
BYTE *pbNetscapeComment = NULL;
|
|
DWORD cbNetscapeComment;
|
|
BYTE *pbNetscapeBaseUrl = NULL;
|
|
DWORD cbNetscapeBaseUrl;
|
|
BYTE *pbNetscapeRevUrl = NULL;
|
|
DWORD cbNetscapeRevUrl;
|
|
|
|
BYTE *pbEnhancedKeyUsageEncoded = NULL;
|
|
DWORD cbEnhancedKeyUsageEncoded;
|
|
|
|
BYTE *pbSMIMECapabilitiesEncoded = NULL;
|
|
DWORD cbSMIMECapabilitiesEncoded;
|
|
|
|
BYTE *pbIDPEncoded = NULL;
|
|
DWORD cbIDPEncoded;
|
|
BYTE *pbNameConstraintsEncoded = NULL;
|
|
DWORD cbNameConstraintsEncoded;
|
|
|
|
BYTE *pbPolicyMappingsEncoded = NULL;
|
|
DWORD cbPolicyMappingsEncoded;
|
|
BYTE *pbPolicyConstraintsEncoded = NULL;
|
|
DWORD cbPolicyConstraintsEncoded;
|
|
BYTE *pbCrossCertDistPointsEncoded = NULL;
|
|
DWORD cbCrossCertDistPointsEncoded;
|
|
|
|
FILETIME SerialNumber;
|
|
|
|
CERT_RDN rgRDN[RDN_CNT];
|
|
CERT_RDN_ATTR rgAttr[ATTR_CNT];
|
|
CERT_NAME_INFO Name;
|
|
CERT_INFO Cert;
|
|
|
|
DWORD dwIssuer = CertPara[dwCert].dwIssuer;
|
|
|
|
DWORD dwCrlDistFlags;
|
|
|
|
#define CERT_EXTENSION_CNT 30
|
|
CERT_EXTENSION rgExt[CERT_EXTENSION_CNT];
|
|
|
|
// SUBJECT
|
|
CreateNameInfo(dwCert, &Name, rgRDN, rgAttr);
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&Name,
|
|
&pbSubjectEncoded,
|
|
&cbSubjectEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
// ISSUER
|
|
CreateNameInfo(dwIssuer, &Name, rgRDN, rgAttr);
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&Name,
|
|
&pbIssuerEncoded,
|
|
&cbIssuerEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
// PUBLIC KEY
|
|
if (!GetPublicKey(dwCert, &pPubKeyInfo)) goto ErrorReturn;
|
|
|
|
// CERT
|
|
memset(&Cert, 0, sizeof(Cert));
|
|
Cert.dwVersion = CERT_V3;
|
|
{
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
if (CertPara[dwCert].dwFlags & DUPLICATE_PARA_FLAG)
|
|
// Use same serial number as previous certificate
|
|
SystemTime.wMilliseconds += (WORD) (dwCert - 1);
|
|
else
|
|
SystemTime.wMilliseconds += (WORD) dwCert;
|
|
MySystemTimeToFileTime(&SystemTime, &SerialNumber);
|
|
}
|
|
Cert.SerialNumber.pbData = (BYTE *) &SerialNumber;
|
|
Cert.SerialNumber.cbData = sizeof(SerialNumber);
|
|
if (CertPara[dwIssuer].dwFlags & DSS_PARA_FLAG)
|
|
Cert.SignatureAlgorithm.pszObjId = DSS_SIGNATURE_ALG_OBJID;
|
|
else
|
|
Cert.SignatureAlgorithm.pszObjId = SIGNATURE_ALG_OBJID;
|
|
Cert.Issuer.pbData = pbIssuerEncoded;
|
|
Cert.Issuer.cbData = cbIssuerEncoded;
|
|
|
|
{
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
|
|
if (CertPara[dwCert].dwFlags & TIME_INVALID_PARA_FLAG) {
|
|
MySystemTimeToFileTime(&SystemTime, &Cert.NotAfter);
|
|
SystemTime.wYear--;
|
|
MySystemTimeToFileTime(&SystemTime, &Cert.NotBefore);
|
|
} else if (CertPara[dwCert].dwFlags & GENERALIZED_TIME_PARA_FLAG) {
|
|
SystemTime.wYear = 1920;
|
|
MySystemTimeToFileTime(&SystemTime, &Cert.NotBefore);
|
|
SystemTime.wYear = 2070;
|
|
|
|
if (CertPara[dwCert].dwFlags & CA_PARA_FLAG)
|
|
SystemTime.wHour = 1;
|
|
else
|
|
SystemTime.wHour = 0;
|
|
SystemTime.wMinute = 59 - (WORD) dwCert;
|
|
SystemTime.wSecond = 0;
|
|
MySystemTimeToFileTime(&SystemTime, &Cert.NotAfter);
|
|
} else if (0 == strcmp("ZeroNotAfter", CertPara[dwCert].pszName)) {
|
|
MySystemTimeToFileTime(&SystemTime, &Cert.NotBefore);
|
|
// NotAfter has already been zeroed
|
|
} else {
|
|
MySystemTimeToFileTime(&SystemTime, &Cert.NotBefore);
|
|
SystemTime.wYear++;
|
|
if (CertPara[dwCert].dwFlags & CA_PARA_FLAG)
|
|
SystemTime.wHour = 1;
|
|
else
|
|
SystemTime.wHour = 0;
|
|
if (dwCert < 60) {
|
|
SystemTime.wMinute = 59 - (WORD) dwCert;
|
|
SystemTime.wSecond = 0;
|
|
} else {
|
|
SystemTime.wMinute = 0;
|
|
SystemTime.wSecond = 0;
|
|
}
|
|
MySystemTimeToFileTime(&SystemTime, &Cert.NotAfter);
|
|
}
|
|
}
|
|
|
|
Cert.Subject.pbData = pbSubjectEncoded;
|
|
Cert.Subject.cbData = cbSubjectEncoded;
|
|
Cert.SubjectPublicKeyInfo = *pPubKeyInfo;
|
|
|
|
// Cert Extensions
|
|
if (!CreateAuthorityKeyId(
|
|
dwIssuer,
|
|
&pbKeyIdEncoded,
|
|
&cbKeyIdEncoded))
|
|
goto ErrorReturn;
|
|
if (!CreateAuthorityKeyId2(
|
|
dwCert,
|
|
dwIssuer,
|
|
&pbKeyId2Encoded,
|
|
&cbKeyId2Encoded))
|
|
goto ErrorReturn;
|
|
if (!CreateAuthorityInfoAccess(
|
|
dwCert,
|
|
&pbAuthorityInfoAccessEncoded,
|
|
&cbAuthorityInfoAccessEncoded))
|
|
goto ErrorReturn;
|
|
|
|
dwCrlDistFlags = 0;
|
|
if (CertPara[dwCert].dwFlags & DELTA_CRL_PARA_FLAG)
|
|
dwCrlDistFlags |= CRL_DIST_POINTS_DELTA_FLAG;
|
|
if (0 == strcmp(CertPara[dwCert].pszName, "UnsupportedCDP"))
|
|
dwCrlDistFlags |= CRL_DIST_POINTS_UNSUPPORTED_FLAG;
|
|
if (!CreateCrlDistPoints(
|
|
CertPara[dwCert].dwIssuer,
|
|
dwCrlDistFlags,
|
|
&pbCrlDistPointsEncoded,
|
|
&cbCrlDistPointsEncoded))
|
|
goto ErrorReturn;
|
|
|
|
if (!CreateKeyAttributes(
|
|
dwCert,
|
|
&pbKeyAttrEncoded,
|
|
&cbKeyAttrEncoded))
|
|
goto ErrorReturn;
|
|
if (!CreateAltName(
|
|
dwCert,
|
|
&pbAltNameEncoded,
|
|
&cbAltNameEncoded))
|
|
goto ErrorReturn;
|
|
if (!CreateKeyUsageRestriction(
|
|
dwCert,
|
|
&pbKeyUsageRestrictionEncoded,
|
|
&cbKeyUsageRestrictionEncoded))
|
|
goto ErrorReturn;
|
|
if (!CreateBasicConstraints(
|
|
dwCert,
|
|
&pbBasicConstraintsEncoded,
|
|
&cbBasicConstraintsEncoded))
|
|
goto ErrorReturn;
|
|
if (!CreateKeyUsage(
|
|
dwCert,
|
|
&pbKeyUsageEncoded,
|
|
&cbKeyUsageEncoded))
|
|
goto ErrorReturn;
|
|
if (!CreateBasicConstraints2(
|
|
dwCert,
|
|
&pbBasicConstraints2Encoded,
|
|
&cbBasicConstraints2Encoded))
|
|
goto ErrorReturn;
|
|
if (!CreatePolicies(
|
|
dwCert,
|
|
&pbPoliciesEncoded,
|
|
&cbPoliciesEncoded))
|
|
goto ErrorReturn;
|
|
|
|
if (CertPara[dwCert].dwFlags & SPC_AGENCY_INFO_PARA_FLAG) {
|
|
if (!CreateSpcSpAgency(
|
|
dwCert,
|
|
0, // dwLevel
|
|
&pbSpcSpAgencyEncoded0,
|
|
&cbSpcSpAgencyEncoded0))
|
|
goto ErrorReturn;
|
|
if (!CreateSpcSpAgency(
|
|
dwCert,
|
|
2, // dwLevel
|
|
&pbSpcSpAgencyEncoded1,
|
|
&cbSpcSpAgencyEncoded1))
|
|
goto ErrorReturn;
|
|
if (!CreateSpcSpAgency(
|
|
dwCert,
|
|
3, // dwLevel
|
|
&pbSpcSpAgencyEncoded2,
|
|
&cbSpcSpAgencyEncoded2))
|
|
goto ErrorReturn;
|
|
} else if (CertPara[dwCert].dwFlags & SPC_EXT_PARA_FLAG) {
|
|
if (!CreateSpcSpAgency(
|
|
dwCert,
|
|
1, // dwLevel
|
|
&pbSpcSpAgencyEncoded0,
|
|
&cbSpcSpAgencyEncoded0))
|
|
goto ErrorReturn;
|
|
if (!CreateSpcCommonName(
|
|
dwCert,
|
|
&pbSpcCommonNameEncoded,
|
|
&cbSpcCommonNameEncoded))
|
|
goto ErrorReturn;
|
|
} else {
|
|
if (!CreateSETAccountAlias(
|
|
dwCert,
|
|
&pbSETAccountAliasEncoded,
|
|
&cbSETAccountAliasEncoded))
|
|
goto ErrorReturn;
|
|
if (!CreateSETHashedRootKey(
|
|
dwCert,
|
|
&pbSETHashedRootKeyEncoded,
|
|
&cbSETHashedRootKeyEncoded))
|
|
goto ErrorReturn;
|
|
if (!CreateSETCertificateType(
|
|
dwCert,
|
|
&pbSETCertificateTypeEncoded,
|
|
&cbSETCertificateTypeEncoded))
|
|
goto ErrorReturn;
|
|
if (!CreateSETMerchantData(
|
|
dwCert,
|
|
&pbSETMerchantDataEncoded,
|
|
&cbSETMerchantDataEncoded))
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
|
|
rgExt[0].pszObjId = szOID_AUTHORITY_KEY_IDENTIFIER;
|
|
rgExt[0].fCritical = FALSE;
|
|
rgExt[0].Value.pbData = pbKeyIdEncoded;
|
|
rgExt[0].Value.cbData = cbKeyIdEncoded;
|
|
rgExt[1].pszObjId = szOID_KEY_ATTRIBUTES;
|
|
rgExt[1].fCritical = FALSE;
|
|
rgExt[1].Value.pbData = pbKeyAttrEncoded;
|
|
rgExt[1].Value.cbData = cbKeyAttrEncoded;
|
|
rgExt[2].pszObjId = szOID_BASIC_CONSTRAINTS;
|
|
rgExt[2].fCritical = FALSE;
|
|
rgExt[2].Value.pbData = pbBasicConstraintsEncoded;
|
|
rgExt[2].Value.cbData = cbBasicConstraintsEncoded;
|
|
rgExt[3].pszObjId = szOID_KEY_USAGE_RESTRICTION;
|
|
rgExt[3].fCritical = FALSE;
|
|
rgExt[3].Value.pbData = pbKeyUsageRestrictionEncoded;
|
|
rgExt[3].Value.cbData = cbKeyUsageRestrictionEncoded;
|
|
rgExt[4].pszObjId = szOID_KEY_USAGE;
|
|
rgExt[4].fCritical = FALSE;
|
|
rgExt[4].Value.pbData = pbKeyUsageEncoded;
|
|
rgExt[4].Value.cbData = cbKeyUsageEncoded;
|
|
rgExt[5].pszObjId = szOID_BASIC_CONSTRAINTS2;
|
|
rgExt[5].fCritical = FALSE;
|
|
rgExt[5].Value.pbData = pbBasicConstraints2Encoded;
|
|
rgExt[5].Value.cbData = cbBasicConstraints2Encoded;
|
|
rgExt[6].pszObjId = szOID_CERT_POLICIES;
|
|
rgExt[6].fCritical = FALSE;
|
|
rgExt[6].Value.pbData = pbPoliciesEncoded;
|
|
rgExt[6].Value.cbData = cbPoliciesEncoded;
|
|
|
|
rgExt[7].pszObjId = szOID_SUBJECT_ALT_NAME;
|
|
rgExt[7].fCritical = FALSE;
|
|
if (0 == strcmp(CertPara[dwCert].pszName, "InvalidNCEnd_AV")) {
|
|
static BYTE rgbExt[] = {5,0};
|
|
|
|
rgExt[7].Value.pbData = rgbExt;
|
|
rgExt[7].Value.cbData = 0; // sizeof(rgbExt);
|
|
} else {
|
|
rgExt[7].Value.pbData = pbAltNameEncoded;
|
|
rgExt[7].Value.cbData = cbAltNameEncoded;
|
|
}
|
|
|
|
if (CertPara[dwCert].dwFlags & NO_EXT_PARA_FLAG)
|
|
Cert.cExtension = 0;
|
|
else if (CertPara[dwCert].dwFlags & VALID_PARA_FLAG)
|
|
Cert.cExtension = 6;
|
|
else if (CertPara[dwCert].dwFlags & SPC_AGENCY_INFO_PARA_FLAG) {
|
|
rgExt[8].pszObjId = SPC_SP_AGENCY_INFO_OBJID;
|
|
rgExt[8].fCritical = TRUE;
|
|
rgExt[8].Value.pbData = pbSpcSpAgencyEncoded2;
|
|
rgExt[8].Value.cbData = cbSpcSpAgencyEncoded2;
|
|
rgExt[9].pszObjId = SPC_SP_AGENCY_INFO_OBJID;
|
|
rgExt[9].fCritical = FALSE;
|
|
rgExt[9].Value.pbData = pbSpcSpAgencyEncoded0;
|
|
rgExt[9].Value.cbData = cbSpcSpAgencyEncoded0;
|
|
rgExt[10].pszObjId = SPC_SP_AGENCY_INFO_OBJID;
|
|
rgExt[10].fCritical = FALSE;
|
|
rgExt[10].Value.pbData = pbSpcSpAgencyEncoded1;
|
|
rgExt[10].Value.cbData = cbSpcSpAgencyEncoded1;
|
|
Cert.cExtension = 11;
|
|
} else if (CertPara[dwCert].dwFlags & SPC_EXT_PARA_FLAG) {
|
|
rgExt[8].pszObjId = SPC_SP_AGENCY_INFO_OBJID;
|
|
rgExt[8].fCritical = FALSE;
|
|
rgExt[8].Value.pbData = pbSpcSpAgencyEncoded0;
|
|
rgExt[8].Value.cbData = cbSpcSpAgencyEncoded0;
|
|
if (CertPara[dwCert].dwFlags &
|
|
(SPC_AGENCY_PARA_FLAG | SPC_COM_PARA_FLAG)) {
|
|
rgExt[9].pszObjId = SPC_COMMON_NAME_OBJID;
|
|
rgExt[9].fCritical = FALSE;
|
|
rgExt[9].Value.pbData = pbSpcCommonNameEncoded;
|
|
rgExt[9].Value.cbData = cbSpcCommonNameEncoded;
|
|
Cert.cExtension = 10;
|
|
} else
|
|
Cert.cExtension = 9;
|
|
} else if (CertPara[dwCert].dwFlags & NETSCAPE_PARA_FLAG) {
|
|
BYTE bCertType;
|
|
CRYPT_BIT_BLOB BitBlob;
|
|
CERT_NAME_VALUE Comment;
|
|
CERT_NAME_VALUE RevUrl;
|
|
CERT_NAME_VALUE BaseUrl;
|
|
|
|
BitBlob.pbData = &bCertType;
|
|
BitBlob.cbData = 1;
|
|
BitBlob.cUnusedBits = 2;
|
|
if (CertPara[dwCert].dwFlags & CA_PARA_FLAG)
|
|
bCertType = NETSCAPE_SSL_CA_CERT_TYPE;
|
|
else
|
|
bCertType = NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_BITS,
|
|
&BitBlob,
|
|
&pbNetscapeCertType,
|
|
&cbNetscapeCertType))
|
|
goto ErrorReturn;
|
|
rgExt[8].pszObjId = szOID_NETSCAPE_CERT_TYPE;
|
|
rgExt[8].fCritical = FALSE;
|
|
rgExt[8].Value.pbData = pbNetscapeCertType;
|
|
rgExt[8].Value.cbData = cbNetscapeCertType;
|
|
|
|
memset(&Comment, 0, sizeof(Comment));
|
|
Comment.dwValueType = CERT_RDN_IA5_STRING;
|
|
Comment.Value.pbData = (BYTE *) L"This is an IA5 Netscape Comment";
|
|
if (!AllocAndEncodeObject(
|
|
X509_UNICODE_ANY_STRING,
|
|
&Comment,
|
|
&pbNetscapeComment,
|
|
&cbNetscapeComment))
|
|
goto ErrorReturn;
|
|
rgExt[9].pszObjId = szOID_NETSCAPE_COMMENT;
|
|
rgExt[9].fCritical = FALSE;
|
|
rgExt[9].Value.pbData = pbNetscapeComment;
|
|
rgExt[9].Value.cbData = cbNetscapeComment;
|
|
|
|
memset(&BaseUrl, 0, sizeof(BaseUrl));
|
|
BaseUrl.dwValueType = CERT_RDN_IA5_STRING;
|
|
#if 0
|
|
BaseUrl.Value.pbData = (BYTE *) L"http://status.verisign.com/";
|
|
#else
|
|
BaseUrl.Value.pbData = (BYTE *) L"https://www.netscape.com/";
|
|
#endif
|
|
if (!AllocAndEncodeObject(
|
|
X509_UNICODE_ANY_STRING,
|
|
&BaseUrl,
|
|
&pbNetscapeBaseUrl,
|
|
&cbNetscapeBaseUrl))
|
|
goto ErrorReturn;
|
|
rgExt[10].pszObjId = szOID_NETSCAPE_BASE_URL;
|
|
rgExt[10].fCritical = FALSE;
|
|
rgExt[10].Value.pbData = pbNetscapeBaseUrl;
|
|
rgExt[10].Value.cbData = cbNetscapeBaseUrl;
|
|
|
|
memset(&RevUrl, 0, sizeof(RevUrl));
|
|
RevUrl.dwValueType = CERT_RDN_IA5_STRING;
|
|
#if 0
|
|
RevUrl.Value.pbData = (BYTE *) L"status/check/ver/1/ID/";
|
|
#else
|
|
RevUrl.Value.pbData = (BYTE *) L"cgi-bin/check-rev.cgi?";
|
|
#endif
|
|
if (!AllocAndEncodeObject(
|
|
X509_UNICODE_ANY_STRING,
|
|
&RevUrl,
|
|
&pbNetscapeRevUrl,
|
|
&cbNetscapeRevUrl))
|
|
goto ErrorReturn;
|
|
if (CertPara[dwCert].dwFlags & CA_PARA_FLAG)
|
|
rgExt[11].pszObjId = szOID_NETSCAPE_CA_REVOCATION_URL;
|
|
else
|
|
rgExt[11].pszObjId = szOID_NETSCAPE_REVOCATION_URL;
|
|
rgExt[11].fCritical = FALSE;
|
|
rgExt[11].Value.pbData = pbNetscapeRevUrl;
|
|
rgExt[11].Value.cbData = cbNetscapeRevUrl;
|
|
|
|
Cert.cExtension = 12;
|
|
} else if (CertPara[dwCert].dwFlags & SET_PARA_FLAG) {
|
|
rgExt[8].pszObjId = szOID_SET_ACCOUNT_ALIAS;
|
|
rgExt[8].fCritical = FALSE;
|
|
rgExt[8].Value.pbData = pbSETAccountAliasEncoded;
|
|
rgExt[8].Value.cbData = cbSETAccountAliasEncoded;
|
|
rgExt[9].pszObjId = szOID_SET_HASHED_ROOT_KEY;
|
|
rgExt[9].fCritical = FALSE;
|
|
rgExt[9].Value.pbData = pbSETHashedRootKeyEncoded;
|
|
rgExt[9].Value.cbData = cbSETHashedRootKeyEncoded;
|
|
rgExt[10].pszObjId = szOID_SET_CERTIFICATE_TYPE;
|
|
rgExt[10].fCritical = FALSE;
|
|
rgExt[10].Value.pbData = pbSETCertificateTypeEncoded;
|
|
rgExt[10].Value.cbData = cbSETCertificateTypeEncoded;
|
|
rgExt[11].pszObjId = szOID_SET_MERCHANT_DATA;
|
|
rgExt[11].fCritical = FALSE;
|
|
rgExt[11].Value.pbData = pbSETMerchantDataEncoded;
|
|
rgExt[11].Value.cbData = cbSETMerchantDataEncoded;
|
|
Cert.cExtension = 12;
|
|
} else {
|
|
Cert.cExtension = 8;
|
|
}
|
|
|
|
if ((CertPara[dwCert].dwFlags & DELTA_CRL_PARA_FLAG) ||
|
|
(0 == (CertPara[dwCert].dwFlags &
|
|
(NO_EXT_PARA_FLAG | VALID_PARA_FLAG)))) {
|
|
DWORD cExt = Cert.cExtension;
|
|
|
|
if (0 == (CertPara[CertPara[dwCert].dwIssuer].dwFlags &
|
|
NO_CRL_EXT_PARA_FLAG)) {
|
|
if (0 != strncmp(CertPara[dwCert].pszName, "NoCDP", 5)) {
|
|
rgExt[cExt].pszObjId = szOID_CRL_DIST_POINTS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbCrlDistPointsEncoded;
|
|
rgExt[cExt].Value.cbData = cbCrlDistPointsEncoded;
|
|
cExt++;
|
|
}
|
|
}
|
|
|
|
if (0 == strcmp(CertPara[dwCert].pszName, "DeltaEndValid")) {
|
|
rgExt[cExt].pszObjId = szOID_FRESHEST_CRL;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbCrlDistPointsEncoded;
|
|
rgExt[cExt].Value.cbData = cbCrlDistPointsEncoded;
|
|
cExt++;
|
|
}
|
|
|
|
Cert.cExtension = cExt;
|
|
}
|
|
|
|
if (0 == strcmp(CertPara[dwCert].pszName, "DssCA") ||
|
|
0 == strcmp(CertPara[dwCert].pszName, "DssEnd")) {
|
|
DWORD cExt = Cert.cExtension;
|
|
PCTL_USAGE pCtlUsage;
|
|
|
|
rgExt[cExt].pszObjId = szOID_CERT_POLICIES;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbPoliciesEncoded;
|
|
rgExt[cExt].Value.cbData = cbPoliciesEncoded;
|
|
cExt++;
|
|
|
|
if (0 == strcmp(CertPara[dwCert].pszName, "DssCA"))
|
|
pCtlUsage = &rgCtlUsage[0];
|
|
else
|
|
pCtlUsage = &rgCtlUsage[2];
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_ENHANCED_KEY_USAGE,
|
|
(const void *) pCtlUsage,
|
|
&pbEnhancedKeyUsageEncoded,
|
|
&cbEnhancedKeyUsageEncoded))
|
|
goto ErrorReturn;
|
|
|
|
rgExt[cExt].pszObjId = szOID_ENHANCED_KEY_USAGE;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbEnhancedKeyUsageEncoded;
|
|
rgExt[cExt].Value.cbData = cbEnhancedKeyUsageEncoded;
|
|
cExt++;
|
|
|
|
Cert.cExtension = cExt;
|
|
} else if (0 == strcmp("TestAIAEnd", CertPara[dwCert].pszName)) {
|
|
DWORD cExt = Cert.cExtension;
|
|
|
|
rgExt[cExt].pszObjId = szOID_AUTHORITY_INFO_ACCESS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbAuthorityInfoAccessEncoded;
|
|
rgExt[cExt].Value.cbData = cbAuthorityInfoAccessEncoded;
|
|
cExt++;
|
|
|
|
Cert.cExtension = cExt;
|
|
} else if (0 == strcmp(CertPara[dwCert].pszName, "RolloverRoot") ||
|
|
0 == (CertPara[dwCert].dwFlags &
|
|
(NO_EXT_PARA_FLAG | VALID_PARA_FLAG))) {
|
|
DWORD cExt = Cert.cExtension;
|
|
|
|
rgExt[cExt].pszObjId = szOID_AUTHORITY_KEY_IDENTIFIER2;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbKeyId2Encoded;
|
|
rgExt[cExt].Value.cbData = cbKeyId2Encoded;
|
|
cExt++;
|
|
|
|
if (0 != strcmp(CertPara[dwCert].pszName, "RolloverRoot")) {
|
|
rgExt[cExt].pszObjId = szOID_AUTHORITY_INFO_ACCESS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbAuthorityInfoAccessEncoded;
|
|
rgExt[cExt].Value.cbData = cbAuthorityInfoAccessEncoded;
|
|
cExt++;
|
|
}
|
|
|
|
#if 1
|
|
if (TRUE) {
|
|
#else
|
|
if (CertPara[dwCert].dwFlags & CA_PARA_FLAG) {
|
|
#endif
|
|
if (!CreateKeyId(
|
|
dwCert,
|
|
&pbSubjectKeyIdEncoded,
|
|
&cbSubjectKeyIdEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_SUBJECT_KEY_IDENTIFIER;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbSubjectKeyIdEncoded;
|
|
rgExt[cExt].Value.cbData = cbSubjectKeyIdEncoded;
|
|
cExt++;
|
|
}
|
|
|
|
if (CertPara[dwCert].dwFlags & (USE1_PARA_FLAG | USE2_PARA_FLAG)) {
|
|
if (!CreateEnhancedKeyUsage(
|
|
CertPara[dwCert].dwFlags,
|
|
&pbEnhancedKeyUsageEncoded,
|
|
&cbEnhancedKeyUsageEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_ENHANCED_KEY_USAGE;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbEnhancedKeyUsageEncoded;
|
|
rgExt[cExt].Value.cbData = cbEnhancedKeyUsageEncoded;
|
|
cExt++;
|
|
}
|
|
|
|
Cert.cExtension = cExt;
|
|
} else if (0 == strcmp(CertPara[dwCert].pszName, "RolloverCA")) {
|
|
DWORD cExt = Cert.cExtension;
|
|
|
|
rgExt[cExt].pszObjId = szOID_AUTHORITY_INFO_ACCESS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbAuthorityInfoAccessEncoded;
|
|
rgExt[cExt].Value.cbData = cbAuthorityInfoAccessEncoded;
|
|
cExt++;
|
|
|
|
Cert.cExtension = cExt;
|
|
}
|
|
|
|
|
|
if (dwCert == POLICY_ROOT || dwCert == POLICY_CA) {
|
|
// 0 - Root
|
|
// 1 - CA
|
|
|
|
DWORD cExt = Cert.cExtension;
|
|
|
|
if (!CreatePolicyMappings(
|
|
dwCert,
|
|
&pbPolicyMappingsEncoded,
|
|
&cbPolicyMappingsEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_POLICY_MAPPINGS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbPolicyMappingsEncoded;
|
|
rgExt[cExt].Value.cbData = cbPolicyMappingsEncoded;
|
|
cExt++;
|
|
|
|
if (!CreatePolicyConstraints(
|
|
dwCert,
|
|
&pbPolicyConstraintsEncoded,
|
|
&cbPolicyConstraintsEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_POLICY_CONSTRAINTS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbPolicyConstraintsEncoded;
|
|
rgExt[cExt].Value.cbData = cbPolicyConstraintsEncoded;
|
|
cExt++;
|
|
|
|
if (!CreateNameConstraints(
|
|
dwCert,
|
|
&pbNameConstraintsEncoded,
|
|
&cbNameConstraintsEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_NAME_CONSTRAINTS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbNameConstraintsEncoded;
|
|
rgExt[cExt].Value.cbData = cbNameConstraintsEncoded;
|
|
cExt++;
|
|
|
|
Cert.cExtension = cExt;
|
|
|
|
} else if (dwCert == ROLLOVER_CROSS_CERT) {
|
|
DWORD cExt = Cert.cExtension;
|
|
|
|
if (!CreatePolicyConstraints(
|
|
dwCert,
|
|
&pbPolicyConstraintsEncoded,
|
|
&cbPolicyConstraintsEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_POLICY_CONSTRAINTS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbPolicyConstraintsEncoded;
|
|
rgExt[cExt].Value.cbData = cbPolicyConstraintsEncoded;
|
|
cExt++;
|
|
|
|
Cert.cExtension = cExt;
|
|
|
|
} else if (0 == strcmp(CertPara[dwCert].pszName, "MissingNCCA")) {
|
|
DWORD cExt = Cert.cExtension;
|
|
|
|
if (!CreateNameConstraints(
|
|
dwCert,
|
|
&pbNameConstraintsEncoded,
|
|
&cbNameConstraintsEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_NAME_CONSTRAINTS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbNameConstraintsEncoded;
|
|
rgExt[cExt].Value.cbData = cbNameConstraintsEncoded;
|
|
cExt++;
|
|
|
|
Cert.cExtension = cExt;
|
|
|
|
} else if (0 == strcmp(CertPara[dwCert].pszName, "InvalidNCCA_AV")) {
|
|
DWORD cExt = Cert.cExtension;
|
|
static BYTE rgbExt[] = {5,0};
|
|
|
|
rgExt[cExt].pszObjId = szOID_NAME_CONSTRAINTS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = rgbExt;
|
|
rgExt[cExt].Value.cbData = 0; // sizeof(rgbExt);
|
|
cExt++;
|
|
|
|
Cert.cExtension = cExt;
|
|
|
|
} else if (CertPara[dwCert].dwFlags & ALL_EXT_PARA_FLAG) {
|
|
DWORD cExt = Cert.cExtension;
|
|
|
|
if (!CreateSMIMECapabilities(
|
|
dwCert,
|
|
&pbSMIMECapabilitiesEncoded,
|
|
&cbSMIMECapabilitiesEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_RSA_SMIMECapabilities;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbSMIMECapabilitiesEncoded;
|
|
rgExt[cExt].Value.cbData = cbSMIMECapabilitiesEncoded;
|
|
cExt++;
|
|
|
|
if (!CreateCertIssuingDistPoint(
|
|
dwCert,
|
|
&pbIDPEncoded,
|
|
&cbIDPEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_ISSUING_DIST_POINT;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbIDPEncoded;
|
|
rgExt[cExt].Value.cbData = cbIDPEncoded;
|
|
cExt++;
|
|
|
|
if (!CreateCrossCertDistPoints(
|
|
dwCert,
|
|
&pbCrossCertDistPointsEncoded,
|
|
&cbCrossCertDistPointsEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_CROSS_CERT_DIST_POINTS;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbCrossCertDistPointsEncoded;
|
|
rgExt[cExt].Value.cbData = cbCrossCertDistPointsEncoded;
|
|
cExt++;
|
|
|
|
Cert.cExtension = cExt;
|
|
}
|
|
|
|
if (CertPara[dwCert].dwFlags & ALT_DIR_NAME_PARA_FLAG) {
|
|
DWORD cExt = Cert.cExtension;
|
|
|
|
if (!CreateAltName(
|
|
dwIssuer,
|
|
&pbIssuerAltNameEncoded,
|
|
&cbIssuerAltNameEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_ISSUER_ALT_NAME2;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbIssuerAltNameEncoded;
|
|
rgExt[cExt].Value.cbData = cbIssuerAltNameEncoded;
|
|
cExt++;
|
|
|
|
Cert.cExtension = cExt;
|
|
}
|
|
|
|
if (CertPara[dwCert].pszManifold) {
|
|
DWORD cExt = Cert.cExtension;
|
|
|
|
rgExt[cExt].pszObjId = szOID_CERT_MANIFOLD;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = (BYTE *) CertPara[dwCert].pszManifold;
|
|
rgExt[cExt].Value.cbData = strlen(CertPara[dwCert].pszManifold);
|
|
cExt++;
|
|
|
|
Cert.cExtension = cExt;
|
|
}
|
|
|
|
if (0 == strcmp("V1", CertPara[dwCert].pszName)) {
|
|
Cert.dwVersion = CERT_V1;
|
|
Cert.cExtension = 0;
|
|
} else if (0 == strcmp("V2", CertPara[dwCert].pszName)) {
|
|
Cert.dwVersion = CERT_V2;
|
|
Cert.cExtension = 0;
|
|
|
|
#define ISSUER_UNIQUE_ID "Issuer Unique Id"
|
|
#define SUBJECT_UNIQUE_ID "Subject Unique Id"
|
|
Cert.IssuerUniqueId.pbData = (BYTE *) ISSUER_UNIQUE_ID;
|
|
Cert.IssuerUniqueId.cbData = strlen(ISSUER_UNIQUE_ID);
|
|
Cert.IssuerUniqueId.cUnusedBits = 0;
|
|
|
|
Cert.SubjectUniqueId.pbData = (BYTE *) SUBJECT_UNIQUE_ID;
|
|
Cert.SubjectUniqueId.cbData = strlen(SUBJECT_UNIQUE_ID);
|
|
Cert.SubjectUniqueId.cUnusedBits = 0;
|
|
}
|
|
|
|
Cert.rgExtension = rgExt;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_CERT_TO_BE_SIGNED,
|
|
&Cert,
|
|
&pbCertEncoded,
|
|
&cbCertEncoded))
|
|
goto ErrorReturn;
|
|
|
|
if (!EncodeSignedContent(
|
|
dwIssuer,
|
|
pbCertEncoded,
|
|
cbCertEncoded,
|
|
ppbEncoded,
|
|
pcbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
*ppbEncoded = NULL;
|
|
*pcbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if (pbKeyIdEncoded)
|
|
TestFree(pbKeyIdEncoded);
|
|
if (pbKeyId2Encoded)
|
|
TestFree(pbKeyId2Encoded);
|
|
if (pbSubjectKeyIdEncoded)
|
|
TestFree(pbSubjectKeyIdEncoded);
|
|
if (pbAuthorityInfoAccessEncoded)
|
|
TestFree(pbAuthorityInfoAccessEncoded);
|
|
if (pbCrlDistPointsEncoded)
|
|
TestFree(pbCrlDistPointsEncoded);
|
|
if (pbKeyAttrEncoded)
|
|
TestFree(pbKeyAttrEncoded);
|
|
if (pbAltNameEncoded)
|
|
TestFree(pbAltNameEncoded);
|
|
if (pbIssuerAltNameEncoded)
|
|
TestFree(pbIssuerAltNameEncoded);
|
|
if (pbKeyUsageRestrictionEncoded)
|
|
TestFree(pbKeyUsageRestrictionEncoded);
|
|
if (pbBasicConstraintsEncoded)
|
|
TestFree(pbBasicConstraintsEncoded);
|
|
if (pbKeyUsageEncoded)
|
|
TestFree(pbKeyUsageEncoded);
|
|
if (pbBasicConstraints2Encoded)
|
|
TestFree(pbBasicConstraints2Encoded);
|
|
if (pbPoliciesEncoded)
|
|
TestFree(pbPoliciesEncoded);
|
|
if (pbSETAccountAliasEncoded)
|
|
TestFree(pbSETAccountAliasEncoded);
|
|
if (pbSETHashedRootKeyEncoded)
|
|
TestFree(pbSETHashedRootKeyEncoded);
|
|
if (pbSETCertificateTypeEncoded)
|
|
TestFree(pbSETCertificateTypeEncoded);
|
|
if (pbSETMerchantDataEncoded)
|
|
TestFree(pbSETMerchantDataEncoded);
|
|
if (pbSpcSpAgencyEncoded0)
|
|
TestFree(pbSpcSpAgencyEncoded0);
|
|
if (pbSpcSpAgencyEncoded1)
|
|
TestFree(pbSpcSpAgencyEncoded1);
|
|
if (pbSpcSpAgencyEncoded2)
|
|
TestFree(pbSpcSpAgencyEncoded2);
|
|
if (pbSpcCommonNameEncoded)
|
|
TestFree(pbSpcCommonNameEncoded);
|
|
if (pbNetscapeCertType)
|
|
TestFree(pbNetscapeCertType);
|
|
if (pbNetscapeComment)
|
|
TestFree(pbNetscapeComment);
|
|
if (pbNetscapeRevUrl)
|
|
TestFree(pbNetscapeRevUrl);
|
|
if (pbNetscapeBaseUrl)
|
|
TestFree(pbNetscapeBaseUrl);
|
|
|
|
if (pbSubjectEncoded)
|
|
TestFree(pbSubjectEncoded);
|
|
if (pbIssuerEncoded)
|
|
TestFree(pbIssuerEncoded);
|
|
if (pPubKeyInfo)
|
|
TestFree(pPubKeyInfo);
|
|
if (pbCertEncoded)
|
|
TestFree(pbCertEncoded);
|
|
if (pbEnhancedKeyUsageEncoded)
|
|
TestFree(pbEnhancedKeyUsageEncoded);
|
|
if (pbSMIMECapabilitiesEncoded)
|
|
TestFree(pbSMIMECapabilitiesEncoded);
|
|
if (pbIDPEncoded)
|
|
TestFree(pbIDPEncoded);
|
|
if (pbNameConstraintsEncoded)
|
|
TestFree(pbNameConstraintsEncoded);
|
|
if (pbPolicyMappingsEncoded)
|
|
TestFree(pbPolicyMappingsEncoded);
|
|
if (pbPolicyConstraintsEncoded)
|
|
TestFree(pbPolicyConstraintsEncoded);
|
|
if (pbCrossCertDistPointsEncoded)
|
|
TestFree(pbCrossCertDistPointsEncoded);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL EncodeCrl(
|
|
DWORD dwCert,
|
|
BYTE **ppbEncoded,
|
|
DWORD *pcbEncoded,
|
|
DWORD dwAki
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
BYTE *pbIssuerEncoded = NULL;
|
|
DWORD cbIssuerEncoded;
|
|
BYTE *pbCrlEncoded = NULL;
|
|
DWORD cbCrlEncoded;
|
|
BYTE *pbKeyId2Encoded = NULL;
|
|
DWORD cbKeyId2Encoded;
|
|
BYTE *pbIDPEncoded = NULL;
|
|
DWORD cbIDPEncoded;
|
|
DWORD i;
|
|
|
|
CERT_RDN rgRDN[RDN_CNT];
|
|
CERT_RDN_ATTR rgAttr[ATTR_CNT];
|
|
CERT_NAME_INFO Name;
|
|
|
|
CRL_ENTRY rgEntry[CERT_CNT];
|
|
CRL_INFO Crl;
|
|
|
|
FILETIME SerialNumber[CERT_CNT];
|
|
|
|
#define CRL_EXTENSION_CNT 2
|
|
CERT_EXTENSION rgExt[CRL_EXTENSION_CNT];
|
|
|
|
// Max of 1 extension per entry
|
|
CERT_EXTENSION rgEntryExt[CERT_CNT];
|
|
memset(rgEntryExt, 0, sizeof(rgEntryExt));
|
|
|
|
// ISSUER
|
|
CreateNameInfo(dwCert, &Name, rgRDN, rgAttr);
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&Name,
|
|
&pbIssuerEncoded,
|
|
&cbIssuerEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
// CRL
|
|
memset(&Crl, 0, sizeof(Crl));
|
|
Crl.dwVersion = CRL_V2;
|
|
if (CertPara[dwCert].dwFlags & DSS_PARA_FLAG)
|
|
Crl.SignatureAlgorithm.pszObjId = DSS_SIGNATURE_ALG_OBJID;
|
|
else
|
|
Crl.SignatureAlgorithm.pszObjId = SIGNATURE_ALG_OBJID;
|
|
Crl.Issuer.pbData = pbIssuerEncoded;
|
|
Crl.Issuer.cbData = cbIssuerEncoded;
|
|
|
|
{
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
|
|
if (CertPara[dwCert].dwFlags & GENERALIZED_TIME_PARA_FLAG) {
|
|
SystemTime.wYear = 1921;
|
|
MySystemTimeToFileTime(&SystemTime, &Crl.ThisUpdate);
|
|
SystemTime.wYear = 2071;
|
|
MySystemTimeToFileTime(&SystemTime, &Crl.NextUpdate);
|
|
} else {
|
|
MySystemTimeToFileTime(&SystemTime, &Crl.ThisUpdate);
|
|
if (0 == (CertPara[dwCert].dwFlags & NO_CRL_EXT_PARA_FLAG)) {
|
|
SystemTime.wYear++;
|
|
MySystemTimeToFileTime(&SystemTime, &Crl.NextUpdate);
|
|
}
|
|
}
|
|
}
|
|
|
|
Crl.cCRLEntry = 0;
|
|
Crl.rgCRLEntry = rgEntry;
|
|
for (i = 0; i < CERT_CNT; i++) {
|
|
if (CertPara[i].dwIssuer == dwCert &&
|
|
(CertPara[i].dwFlags & REVOKED_PARA_FLAG)) {
|
|
DWORD j;
|
|
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
|
|
j = Crl.cCRLEntry++;
|
|
memset(&rgEntry[j], 0, sizeof(rgEntry[j]));
|
|
|
|
SystemTime.wMilliseconds += (WORD) i;
|
|
MySystemTimeToFileTime(&SystemTime, &SerialNumber[j]);
|
|
|
|
rgEntry[j].SerialNumber.pbData = (BYTE *) &SerialNumber[j];
|
|
rgEntry[j].SerialNumber.cbData = sizeof(SerialNumber[j]);
|
|
if (CertPara[dwCert].dwFlags & GENERALIZED_TIME_PARA_FLAG) {
|
|
SystemTime.wYear = 1922;
|
|
MySystemTimeToFileTime(&SystemTime, &rgEntry[j].RevocationDate);
|
|
} else
|
|
MySystemTimeToFileTime(&SystemTime, &rgEntry[j].RevocationDate);
|
|
|
|
if (0 == (CertPara[dwCert].dwFlags & NO_CRL_EXT_PARA_FLAG)) {
|
|
if (!CreateCRLReason(
|
|
&rgEntryExt[j].Value.pbData,
|
|
&rgEntryExt[j].Value.cbData))
|
|
goto ErrorReturn;
|
|
rgEntryExt[j].pszObjId = szOID_CRL_REASON_CODE;
|
|
rgEntryExt[j].fCritical = FALSE;
|
|
rgEntry[j].cExtension = 1;
|
|
rgEntry[j].rgExtension = &rgEntryExt[j];
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (AKI2_NONE != dwAki &&
|
|
0 == (CertPara[dwCert].dwFlags & NO_CRL_EXT_PARA_FLAG)) {
|
|
// Crl Extensions
|
|
if (!CreateAuthorityKeyId2(
|
|
dwCert,
|
|
dwCert,
|
|
&pbKeyId2Encoded,
|
|
&cbKeyId2Encoded,
|
|
dwAki
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
rgExt[0].pszObjId = szOID_AUTHORITY_KEY_IDENTIFIER2;
|
|
rgExt[0].fCritical = FALSE;
|
|
rgExt[0].Value.pbData = pbKeyId2Encoded;
|
|
rgExt[0].Value.cbData = cbKeyId2Encoded;
|
|
|
|
if (!CreateCrlIssuingDistPoint(
|
|
&pbIDPEncoded,
|
|
&cbIDPEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
rgExt[1].pszObjId = szOID_ISSUING_DIST_POINT;
|
|
rgExt[1].fCritical = FALSE;
|
|
rgExt[1].Value.pbData = pbIDPEncoded;
|
|
rgExt[1].Value.cbData = cbIDPEncoded;
|
|
|
|
Crl.cExtension = CRL_EXTENSION_CNT;
|
|
Crl.rgExtension = rgExt;
|
|
}
|
|
|
|
if (0 == strcmp("V1", CertPara[dwCert].pszName)) {
|
|
Crl.dwVersion = CRL_V1;
|
|
Crl.cExtension = 0;
|
|
}
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_CERT_CRL_TO_BE_SIGNED,
|
|
&Crl,
|
|
&pbCrlEncoded,
|
|
&cbCrlEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
if (!EncodeSignedContent(
|
|
dwCert,
|
|
pbCrlEncoded,
|
|
cbCrlEncoded,
|
|
ppbEncoded,
|
|
pcbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
*ppbEncoded = NULL;
|
|
*pcbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if (pbKeyId2Encoded)
|
|
TestFree(pbKeyId2Encoded);
|
|
if (pbIDPEncoded)
|
|
TestFree(pbIDPEncoded);
|
|
if (pbIssuerEncoded)
|
|
TestFree(pbIssuerEncoded);
|
|
if (pbCrlEncoded)
|
|
TestFree(pbCrlEncoded);
|
|
for (i = 0; i < CERT_CNT; i++) {
|
|
if (rgEntryExt[i].Value.pbData)
|
|
TestFree(rgEntryExt[i].Value.pbData);
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL EncodeBaseOrDeltaCrl(
|
|
DWORD dwIssuer,
|
|
int iBase,
|
|
DWORD dwFlags,
|
|
BYTE **ppbEncoded,
|
|
DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
DWORD i;
|
|
BYTE *pbIssuerNameEncoded = NULL;
|
|
DWORD cbIssuerNameEncoded;
|
|
BYTE *pbCDPEncoded = NULL;
|
|
DWORD cbCDPEncoded;
|
|
BYTE *pbBaseEncoded;
|
|
DWORD cbBaseEncoded;
|
|
BYTE *pbIDPEncoded = NULL;
|
|
DWORD cbIDPEncoded;
|
|
BYTE *pbCrlEncoded = NULL;
|
|
DWORD cbCrlEncoded;
|
|
|
|
CERT_RDN rgRDN[RDN_CNT];
|
|
CERT_RDN_ATTR rgAttr[ATTR_CNT];
|
|
CERT_NAME_INFO Name;
|
|
FILETIME SerialNumber[CERT_CNT];
|
|
CRL_ENTRY rgEntry[CERT_CNT];
|
|
CRL_INFO Crl;
|
|
CERT_EXTENSION rgExt[10];
|
|
DWORD cExt = 0;
|
|
|
|
// Max of 1 extension per entry
|
|
CERT_EXTENSION rgEntryExt[CERT_CNT];
|
|
memset(rgEntryExt, 0, sizeof(rgEntryExt));
|
|
|
|
// ISSUER
|
|
CreateNameInfo(dwIssuer, &Name, rgRDN, rgAttr);
|
|
if (!AllocAndEncodeObject(
|
|
X509_NAME,
|
|
&Name,
|
|
&pbIssuerNameEncoded,
|
|
&cbIssuerNameEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
// CRL
|
|
memset(&Crl, 0, sizeof(Crl));
|
|
Crl.dwVersion = CRL_V2;
|
|
if (CertPara[dwIssuer].dwFlags & DSS_PARA_FLAG)
|
|
Crl.SignatureAlgorithm.pszObjId = DSS_SIGNATURE_ALG_OBJID;
|
|
else
|
|
Crl.SignatureAlgorithm.pszObjId = SIGNATURE_ALG_OBJID;
|
|
Crl.Issuer.pbData = pbIssuerNameEncoded;
|
|
Crl.Issuer.cbData = cbIssuerNameEncoded;
|
|
|
|
{
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
|
|
if (dwFlags & EXPIRED_CRL_FLAG) {
|
|
SystemTime.wYear = 1997;
|
|
MySystemTimeToFileTime(&SystemTime, &Crl.ThisUpdate);
|
|
SystemTime.wYear = 1998;
|
|
MySystemTimeToFileTime(&SystemTime, &Crl.NextUpdate);
|
|
} else if (CertPara[dwIssuer].dwFlags & GENERALIZED_TIME_PARA_FLAG) {
|
|
SystemTime.wYear = 1921;
|
|
MySystemTimeToFileTime(&SystemTime, &Crl.ThisUpdate);
|
|
SystemTime.wYear = 2071;
|
|
MySystemTimeToFileTime(&SystemTime, &Crl.NextUpdate);
|
|
} else {
|
|
MySystemTimeToFileTime(&SystemTime, &Crl.ThisUpdate);
|
|
if (0 == (CertPara[dwIssuer].dwFlags & NO_CRL_EXT_PARA_FLAG)) {
|
|
SystemTime.wYear++;
|
|
MySystemTimeToFileTime(&SystemTime, &Crl.NextUpdate);
|
|
}
|
|
}
|
|
}
|
|
|
|
Crl.cCRLEntry = 0;
|
|
Crl.rgCRLEntry = rgEntry;
|
|
if (0 == (dwFlags & NO_ENTRIES_CRL_FLAG)) {
|
|
for (i = 0; i < CERT_CNT; i++) {
|
|
if (CertPara[i].dwIssuer == dwIssuer &&
|
|
(CertPara[i].dwFlags & REVOKED_PARA_FLAG)) {
|
|
DWORD j;
|
|
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
|
|
j = Crl.cCRLEntry++;
|
|
memset(&rgEntry[j], 0, sizeof(rgEntry[j]));
|
|
|
|
SystemTime.wMilliseconds += (WORD) i;
|
|
MySystemTimeToFileTime(&SystemTime, &SerialNumber[j]);
|
|
|
|
rgEntry[j].SerialNumber.pbData = (BYTE *) &SerialNumber[j];
|
|
rgEntry[j].SerialNumber.cbData = sizeof(SerialNumber[j]);
|
|
if (CertPara[dwIssuer].dwFlags & GENERALIZED_TIME_PARA_FLAG) {
|
|
SystemTime.wYear = 1922;
|
|
MySystemTimeToFileTime(&SystemTime, &rgEntry[j].RevocationDate);
|
|
} else
|
|
MySystemTimeToFileTime(&SystemTime, &rgEntry[j].RevocationDate);
|
|
|
|
if (dwFlags & REMOVE_FROM_CRL_FLAG) {
|
|
int iReason = CRL_REASON_REMOVE_FROM_CRL;
|
|
if (!AllocAndEncodeObject(
|
|
X509_ENUMERATED,
|
|
(const void *) &iReason,
|
|
&rgEntryExt[j].Value.pbData,
|
|
&rgEntryExt[j].Value.cbData))
|
|
goto ErrorReturn;
|
|
rgEntryExt[j].pszObjId = szOID_CRL_REASON_CODE;
|
|
rgEntryExt[j].fCritical = TRUE;
|
|
rgEntry[j].cExtension = 1;
|
|
rgEntry[j].rgExtension = &rgEntryExt[j];
|
|
} else if (0 == (CertPara[dwIssuer].dwFlags & NO_CRL_EXT_PARA_FLAG)) {
|
|
if (dwFlags & HOLD_CRL_FLAG) {
|
|
int iReason = CRL_REASON_CERTIFICATE_HOLD;
|
|
if (!AllocAndEncodeObject(
|
|
X509_ENUMERATED,
|
|
(const void *) &iReason,
|
|
&rgEntryExt[j].Value.pbData,
|
|
&rgEntryExt[j].Value.cbData))
|
|
goto ErrorReturn;
|
|
} else {
|
|
if (!CreateCRLReason(
|
|
&rgEntryExt[j].Value.pbData,
|
|
&rgEntryExt[j].Value.cbData))
|
|
goto ErrorReturn;
|
|
}
|
|
rgEntryExt[j].pszObjId = szOID_CRL_REASON_CODE;
|
|
rgEntryExt[j].fCritical = FALSE;
|
|
rgEntry[j].cExtension = 1;
|
|
rgEntry[j].rgExtension = &rgEntryExt[j];
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
// Extensions
|
|
memset(&rgExt, 0, sizeof(rgExt));
|
|
if (!AllocAndEncodeObject(
|
|
X509_INTEGER,
|
|
(const void *) &iBase,
|
|
&pbBaseEncoded,
|
|
&cbBaseEncoded))
|
|
goto ErrorReturn;
|
|
if (dwFlags & FRESHEST_CRL_FLAG) {
|
|
rgExt[0].pszObjId = szOID_DELTA_CRL_INDICATOR;
|
|
rgExt[0].fCritical = TRUE;
|
|
} else {
|
|
rgExt[0].pszObjId = szOID_CRL_NUMBER;
|
|
rgExt[0].fCritical = FALSE;
|
|
}
|
|
rgExt[0].Value.pbData = pbBaseEncoded;
|
|
rgExt[0].Value.cbData = cbBaseEncoded;
|
|
cExt = 1;
|
|
|
|
if (dwFlags & UNSUPPORTED_CRITICAL_EXT_CRL_FLAG) {
|
|
rgExt[cExt].pszObjId = "1.2.3.4.1999.2000";
|
|
rgExt[cExt].fCritical = TRUE;
|
|
rgExt[cExt].Value.pbData = pbBaseEncoded;
|
|
rgExt[cExt].Value.cbData = cbBaseEncoded;
|
|
cExt++;
|
|
}
|
|
|
|
if (0 == (dwFlags & FRESHEST_CRL_FLAG) &&
|
|
0 == (dwFlags & NO_FRESHEST_CDP_CRL_FLAG)) {
|
|
if (!CreateCrlDistPoints(
|
|
dwIssuer,
|
|
CRL_DIST_POINTS_DELTA_FLAG,
|
|
&pbCDPEncoded,
|
|
&cbCDPEncoded))
|
|
goto ErrorReturn;
|
|
rgExt[cExt].pszObjId = szOID_FRESHEST_CRL;
|
|
rgExt[cExt].fCritical = FALSE;
|
|
rgExt[cExt].Value.pbData = pbCDPEncoded;
|
|
rgExt[cExt].Value.cbData = cbCDPEncoded;
|
|
cExt++;
|
|
}
|
|
|
|
|
|
|
|
if (0 == (dwFlags & NO_IDP_CRL_FLAG)) {
|
|
CRL_ISSUING_DIST_POINT IDP;
|
|
PCERT_ALT_NAME_INFO pIDPAltNameInfo;
|
|
|
|
CERT_ALT_NAME_ENTRY rgIDPAltNameEntry[8];
|
|
BYTE bOnlySomeReasonFlags;
|
|
|
|
memset(&IDP, 0, sizeof(IDP));
|
|
if (dwFlags & UNSUPPORTED_IDP_OPTIONS_CRL_FLAG) {
|
|
IDP.OnlySomeReasonFlags.cbData = 1;
|
|
IDP.OnlySomeReasonFlags.pbData = &bOnlySomeReasonFlags;
|
|
IDP.OnlySomeReasonFlags.cUnusedBits = 1;
|
|
bOnlySomeReasonFlags = CRL_REASON_KEY_COMPROMISE_FLAG |
|
|
CRL_REASON_CA_COMPROMISE_FLAG;
|
|
|
|
IDP.fIndirectCRL = TRUE;
|
|
}
|
|
|
|
if (dwFlags & ONLY_USERS_CRL_FLAG)
|
|
IDP.fOnlyContainsUserCerts = TRUE;
|
|
if (dwFlags & ONLY_CAS_CRL_FLAG)
|
|
IDP.fOnlyContainsCACerts = TRUE;
|
|
|
|
IDP.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
|
|
|
|
rgIDPAltNameEntry[0].dwAltNameChoice = CERT_ALT_NAME_OTHER_NAME;
|
|
rgIDPAltNameEntry[0].pOtherName = &CrlOtherName;
|
|
rgIDPAltNameEntry[1].dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
|
|
rgIDPAltNameEntry[1].DirectoryName.pbData = pbIssuerNameEncoded;
|
|
rgIDPAltNameEntry[1].DirectoryName.cbData = cbIssuerNameEncoded;
|
|
rgIDPAltNameEntry[2].dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
|
|
rgIDPAltNameEntry[2].pwszDNSName = CRL_DNS_NAME;
|
|
rgIDPAltNameEntry[3].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
|
|
rgIDPAltNameEntry[3].pwszRfc822Name = CRL_EMAIL_NAME;
|
|
rgIDPAltNameEntry[4].dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
|
|
rgIDPAltNameEntry[4].pszRegisteredID = CRL_REGISTERED_ID;
|
|
rgIDPAltNameEntry[5].dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
|
|
rgIDPAltNameEntry[5].IPAddress.pbData = CrlIPAddress;
|
|
rgIDPAltNameEntry[5].IPAddress.cbData = sizeof(CrlIPAddress);
|
|
rgIDPAltNameEntry[6].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgIDPAltNameEntry[6].pwszURL = CRL_URL_NAME2;
|
|
rgIDPAltNameEntry[7].dwAltNameChoice = CERT_ALT_NAME_URL;
|
|
rgIDPAltNameEntry[7].pwszURL = CRL_URL_NAME1;
|
|
|
|
pIDPAltNameInfo = &IDP.DistPointName.FullName;
|
|
switch (iBase) {
|
|
case 1:
|
|
pIDPAltNameInfo->cAltEntry = 1;
|
|
pIDPAltNameInfo->rgAltEntry = &rgIDPAltNameEntry[0];
|
|
break;
|
|
case 2:
|
|
pIDPAltNameInfo->cAltEntry = 1;
|
|
pIDPAltNameInfo->rgAltEntry = &rgIDPAltNameEntry[1];
|
|
break;
|
|
case 3:
|
|
pIDPAltNameInfo->cAltEntry = 2;
|
|
pIDPAltNameInfo->rgAltEntry = &rgIDPAltNameEntry[2];
|
|
break;
|
|
case 4:
|
|
pIDPAltNameInfo->cAltEntry = 2;
|
|
pIDPAltNameInfo->rgAltEntry = &rgIDPAltNameEntry[4];
|
|
break;
|
|
default:
|
|
pIDPAltNameInfo->cAltEntry = 2;
|
|
pIDPAltNameInfo->rgAltEntry = &rgIDPAltNameEntry[6];
|
|
break;
|
|
}
|
|
|
|
if (!AllocAndEncodeObject(
|
|
szOID_ISSUING_DIST_POINT,
|
|
&IDP,
|
|
&pbIDPEncoded,
|
|
&cbIDPEncoded))
|
|
goto ErrorReturn;
|
|
|
|
rgExt[cExt].pszObjId = szOID_ISSUING_DIST_POINT;
|
|
rgExt[cExt].fCritical = TRUE;
|
|
rgExt[cExt].Value.pbData = pbIDPEncoded;
|
|
rgExt[cExt].Value.cbData = cbIDPEncoded;
|
|
cExt++;
|
|
}
|
|
|
|
Crl.cExtension = cExt;
|
|
Crl.rgExtension = rgExt;
|
|
|
|
if (!AllocAndEncodeObject(
|
|
X509_CERT_CRL_TO_BE_SIGNED,
|
|
&Crl,
|
|
&pbCrlEncoded,
|
|
&cbCrlEncoded
|
|
))
|
|
goto ErrorReturn;
|
|
|
|
if (!EncodeSignedContent(
|
|
dwIssuer,
|
|
pbCrlEncoded,
|
|
cbCrlEncoded,
|
|
ppbEncoded,
|
|
pcbEncoded))
|
|
goto ErrorReturn;
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
*ppbEncoded = NULL;
|
|
*pcbEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if (pbIssuerNameEncoded)
|
|
TestFree(pbIssuerNameEncoded);
|
|
if (pbBaseEncoded)
|
|
TestFree(pbBaseEncoded);
|
|
if (pbCDPEncoded)
|
|
TestFree(pbCDPEncoded);
|
|
if (pbIDPEncoded)
|
|
TestFree(pbIDPEncoded);
|
|
if (pbCrlEncoded)
|
|
TestFree(pbCrlEncoded);
|
|
for (i = 0; i < CERT_CNT; i++) {
|
|
if (rgEntryExt[i].Value.pbData)
|
|
TestFree(rgEntryExt[i].Value.pbData);
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL EncodeCtl(DWORD dwCert, DWORD dwEncodeFlags, BYTE **ppbEncoded,
|
|
DWORD *pcbEncoded)
|
|
{
|
|
BOOL fResult;
|
|
|
|
BYTE *pbNextUpdateLoc = NULL;
|
|
DWORD cbNextUpdateLoc;
|
|
BYTE *pbCtlEncoded = NULL;
|
|
DWORD cbCtlEncoded;
|
|
|
|
DWORD dwFlags;
|
|
DWORD dwCtlFlags;
|
|
DWORD dwUseFlag;
|
|
DWORD i;
|
|
|
|
struct {
|
|
FILETIME ft;
|
|
DWORD dwCert;
|
|
} SequenceNumber;
|
|
|
|
PCTL_USAGE pCtlUsage; // not allocated
|
|
|
|
BYTE rgbHash[CERT_CNT][MAX_HASH_LEN];
|
|
BYTE rgbZero[1] = {0};
|
|
|
|
BYTE NullDer[] = {0x05, 0x00};
|
|
BYTE IntegerDer[] = {0x02, 0x01, 0x35};
|
|
CRYPT_ATTR_BLOB rgAttrBlob[2] = {
|
|
2, (BYTE *) NullDer,
|
|
3, (BYTE *) IntegerDer
|
|
};
|
|
CRYPT_ATTRIBUTE rgAttr[] = {
|
|
"1.2.3.4.5.0",
|
|
1, rgAttrBlob,
|
|
"1.2.1.1.1.1.1.1",
|
|
2, rgAttrBlob
|
|
};
|
|
|
|
CMSG_SIGNER_ENCODE_INFO SignerInfo;
|
|
CMSG_SIGNED_ENCODE_INFO SignInfo;
|
|
CRYPT_ATTRIBUTE SignerAttr;
|
|
CRYPT_ATTR_BLOB SignerAttrBlob;
|
|
CERT_BLOB CertBlob;
|
|
|
|
CTL_ENTRY rgEntry[CERT_CNT];
|
|
#define CTL_EXTENSION_CNT 1
|
|
CERT_EXTENSION rgExt[CTL_EXTENSION_CNT];
|
|
CTL_INFO Ctl;
|
|
|
|
if (NULL == rgpCertContext[dwCert])
|
|
goto ErrorReturn;
|
|
|
|
dwFlags = CertPara[dwCert].dwFlags;
|
|
|
|
// CTL
|
|
memset(&Ctl, 0, sizeof(Ctl));
|
|
Ctl.dwVersion = CTL_V1;
|
|
|
|
dwCtlFlags = dwFlags & (CTL1_PARA_FLAG | CTL2_PARA_FLAG);
|
|
dwUseFlag = 0;
|
|
switch (dwCtlFlags) {
|
|
case CTL1_PARA_FLAG:
|
|
if (dwFlags & NO_EXT_PARA_FLAG)
|
|
pCtlUsage = &rgCtlUsage[0];
|
|
else {
|
|
pCtlUsage = &rgCtlUsage[1];
|
|
dwUseFlag = USE1_PARA_FLAG;
|
|
}
|
|
break;
|
|
case CTL2_PARA_FLAG:
|
|
pCtlUsage = &rgCtlUsage[2];
|
|
dwUseFlag = USE2_PARA_FLAG;
|
|
break;
|
|
case CTL1_PARA_FLAG | CTL2_PARA_FLAG:
|
|
default:
|
|
pCtlUsage = &rgCtlUsage[3];
|
|
break;
|
|
}
|
|
Ctl.SubjectUsage = *pCtlUsage;
|
|
|
|
if (dwFlags & CTL2_PARA_FLAG) {
|
|
DWORD dwIdx;
|
|
if (dwFlags & TIME_INVALID_PARA_FLAG) {
|
|
assert(dwFlags & DUPLICATE_PARA_FLAG);
|
|
dwIdx = dwCert - 1;
|
|
} else
|
|
dwIdx = dwCert;
|
|
Ctl.ListIdentifier.pbData = (BYTE *) CertPara[dwIdx].pszName;
|
|
Ctl.ListIdentifier.cbData = strlen(CertPara[dwIdx].pszName);
|
|
|
|
MySystemTimeToFileTime(&TestTime, &SequenceNumber.ft);
|
|
SequenceNumber.dwCert = dwCert;
|
|
Ctl.SequenceNumber.pbData = (BYTE *) &SequenceNumber;
|
|
Ctl.SequenceNumber.cbData = sizeof(SequenceNumber);
|
|
}
|
|
|
|
|
|
{
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
|
|
if (dwFlags & TIME_INVALID_PARA_FLAG) {
|
|
SystemTime.wYear -=2;
|
|
MySystemTimeToFileTime(&SystemTime, &Ctl.ThisUpdate);
|
|
SystemTime.wYear++;
|
|
MySystemTimeToFileTime(&SystemTime, &Ctl.NextUpdate);
|
|
} else {
|
|
MySystemTimeToFileTime(&SystemTime, &Ctl.ThisUpdate);
|
|
if (dwUseFlag) {
|
|
SystemTime.wYear++;
|
|
MySystemTimeToFileTime(&SystemTime, &Ctl.NextUpdate);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ctl.SubjectAlgorithm.pszObjId = szOID_OIWSEC_sha1;
|
|
|
|
Ctl.cCTLEntry = 0;
|
|
Ctl.rgCTLEntry = rgEntry;
|
|
|
|
for (i = 0; i < CERT_CNT; i++) {
|
|
if (CertPara[i].dwFlags & dwUseFlag) {
|
|
DWORD j;
|
|
DWORD cbHash;
|
|
|
|
if (NULL == rgpCertContext[i])
|
|
continue;
|
|
|
|
j = Ctl.cCTLEntry++;
|
|
memset(&rgEntry[j], 0, sizeof(rgEntry[j]));
|
|
|
|
cbHash = MAX_HASH_LEN;
|
|
if (CertGetCertificateContextProperty(
|
|
rgpCertContext[i],
|
|
CERT_SHA1_HASH_PROP_ID,
|
|
rgbHash[j],
|
|
&cbHash)) {
|
|
rgEntry[j].SubjectIdentifier.pbData = rgbHash[j];
|
|
rgEntry[j].SubjectIdentifier.cbData = cbHash;
|
|
} else {
|
|
PrintLastError(
|
|
"CertGetCertificateContextProperty(SHA1_HASH)");
|
|
rgEntry[j].SubjectIdentifier.pbData = rgbZero;
|
|
rgEntry[j].SubjectIdentifier.cbData = sizeof(rgbZero);
|
|
}
|
|
|
|
if (CertPara[i].dwFlags & ALL_EXT_PARA_FLAG) {
|
|
rgEntry[j].cAttribute = sizeof(rgAttr) / sizeof(rgAttr[0]);
|
|
rgEntry[j].rgAttribute = rgAttr;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (!CreateNextUpdateLocation(
|
|
dwCert,
|
|
FALSE, // fProp
|
|
&pbNextUpdateLoc,
|
|
&cbNextUpdateLoc))
|
|
goto ErrorReturn;
|
|
|
|
// Ctl Extensions
|
|
|
|
rgExt[0].pszObjId = szOID_NEXT_UPDATE_LOCATION;
|
|
rgExt[0].fCritical = FALSE;
|
|
rgExt[0].Value.pbData = pbNextUpdateLoc;
|
|
rgExt[0].Value.cbData = cbNextUpdateLoc;
|
|
|
|
if (0 == (CertPara[dwCert].dwFlags & NO_EXT_PARA_FLAG)) {
|
|
Ctl.cExtension = 1;
|
|
Ctl.rgExtension = rgExt;
|
|
}
|
|
|
|
memset(&SignerInfo, 0, sizeof(SignerInfo));
|
|
SignerInfo.cbSize = sizeof(SignerInfo);
|
|
SignerInfo.pCertInfo = rgpCertContext[dwCert]->pCertInfo;
|
|
if (CertPara[dwCert].dwFlags & DSS_PARA_FLAG) {
|
|
if (CertPara[dwCert].dwFlags & DSS_512_PARA_FLAG)
|
|
SignerInfo.hCryptProv = hDSS512CryptProv;
|
|
else
|
|
SignerInfo.hCryptProv = hDSSCryptProv;
|
|
} else if (CertPara[dwCert].dwFlags & ENH_1024_PARA_FLAG)
|
|
SignerInfo.hCryptProv = hEnh1024CryptProv;
|
|
else if (CertPara[dwCert].dwFlags & ENH_2048_PARA_FLAG)
|
|
SignerInfo.hCryptProv = hEnh2048CryptProv;
|
|
else
|
|
SignerInfo.hCryptProv = hRSACryptProv;
|
|
SignerInfo.dwKeySpec = AT_SIGNATURE;
|
|
SignerInfo.HashAlgorithm.pszObjId = szOID_OIWSEC_sha1;
|
|
|
|
if (dwFlags & CTL2_PARA_FLAG) {
|
|
// Signer Attributes
|
|
memset(&SignerAttr, 0, sizeof(SignerAttr));
|
|
SignerAttr.pszObjId = szOID_NEXT_UPDATE_LOCATION;
|
|
SignerAttr.cValue = 1;
|
|
SignerAttr.rgValue = &SignerAttrBlob;
|
|
SignerAttrBlob.pbData = pbNextUpdateLoc;
|
|
SignerAttrBlob.cbData = cbNextUpdateLoc;
|
|
|
|
SignerInfo.cAuthAttr = 1;
|
|
SignerInfo.rgAuthAttr = &SignerAttr;
|
|
SignerInfo.cUnauthAttr = 1;
|
|
SignerInfo.rgUnauthAttr = &SignerAttr;
|
|
}
|
|
|
|
memset(&SignInfo, 0, sizeof(SignInfo));
|
|
SignInfo.cbSize = sizeof(SignInfo);
|
|
if (dwUseFlag) {
|
|
SignInfo.cSigners = 1;
|
|
SignInfo.rgSigners = &SignerInfo;
|
|
SignInfo.cCertEncoded = 1;
|
|
CertBlob.pbData = rgpCertContext[dwCert]->pbCertEncoded;
|
|
CertBlob.cbData = rgpCertContext[dwCert]->cbCertEncoded;
|
|
SignInfo.rgCertEncoded = &CertBlob;
|
|
}
|
|
|
|
cbCtlEncoded = 0;
|
|
if (!CryptMsgEncodeAndSignCTL(
|
|
dwMsgEncodingType,
|
|
&Ctl,
|
|
&SignInfo,
|
|
dwEncodeFlags,
|
|
NULL, // pbEncoded
|
|
&cbCtlEncoded
|
|
) || 0 == cbCtlEncoded) {
|
|
PrintLastError("EncodeCtl::CryptMsgEncodeAndSignCTL(cbEncoded == 0)");
|
|
goto ErrorReturn;
|
|
}
|
|
pbCtlEncoded = (BYTE *) TestAlloc(cbCtlEncoded);
|
|
if (pbCtlEncoded == NULL) goto ErrorReturn;
|
|
if (!CryptMsgEncodeAndSignCTL(
|
|
dwMsgEncodingType,
|
|
&Ctl,
|
|
&SignInfo,
|
|
dwEncodeFlags,
|
|
pbCtlEncoded,
|
|
&cbCtlEncoded
|
|
)) {
|
|
PrintLastError("EncodeCtl::CryptMsgEncodeAndSignCTL");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbCtlEncoded)
|
|
TestFree(pbCtlEncoded);
|
|
pbCtlEncoded = NULL;
|
|
cbCtlEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if (pbNextUpdateLoc)
|
|
TestFree(pbNextUpdateLoc);
|
|
*ppbEncoded = pbCtlEncoded;
|
|
*pcbEncoded = cbCtlEncoded;
|
|
|
|
return fResult;
|
|
}
|
|
|
|
static BOOL EncodeUpdateCtl(
|
|
BOOL fTimeInvalid,
|
|
LPSTR pszUsageObjId,
|
|
LPSTR pszListIdentifier,
|
|
LPWSTR pwszUrl,
|
|
BYTE **ppbEncoded,
|
|
DWORD *pcbEncoded
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
|
|
BYTE *pbNextUpdateLoc = NULL;
|
|
DWORD cbNextUpdateLoc;
|
|
BYTE *pbCtlEncoded = NULL;
|
|
DWORD cbCtlEncoded;
|
|
|
|
CERT_BLOB CertBlob;
|
|
CMSG_SIGNER_ENCODE_INFO SignerInfo;
|
|
CMSG_SIGNED_ENCODE_INFO SignInfo;
|
|
CERT_EXTENSION rgExt[1];
|
|
CTL_INFO Ctl;
|
|
|
|
if (NULL == rgpCertContext[UPDATE_CTL_SIGNER])
|
|
goto ErrorReturn;
|
|
|
|
// CTL
|
|
memset(&Ctl, 0, sizeof(Ctl));
|
|
Ctl.dwVersion = CTL_V1;
|
|
Ctl.SubjectUsage.cUsageIdentifier = 1;
|
|
Ctl.SubjectUsage.rgpszUsageIdentifier = &pszUsageObjId;
|
|
|
|
Ctl.ListIdentifier.pbData = (BYTE *) pszListIdentifier;
|
|
Ctl.ListIdentifier.cbData = strlen(pszListIdentifier);
|
|
|
|
|
|
{
|
|
SYSTEMTIME SystemTime = TestTime;
|
|
|
|
if (fTimeInvalid) {
|
|
SystemTime.wYear -=2;
|
|
MySystemTimeToFileTime(&SystemTime, &Ctl.ThisUpdate);
|
|
SystemTime.wYear++;
|
|
MySystemTimeToFileTime(&SystemTime, &Ctl.NextUpdate);
|
|
} else {
|
|
MySystemTimeToFileTime(&SystemTime, &Ctl.ThisUpdate);
|
|
SystemTime.wYear++;
|
|
MySystemTimeToFileTime(&SystemTime, &Ctl.NextUpdate);
|
|
}
|
|
}
|
|
|
|
Ctl.SubjectAlgorithm.pszObjId = szOID_OIWSEC_sha1;
|
|
|
|
if (!CreateNextUpdateLocation(
|
|
UPDATE_CTL_SIGNER, // dwCert
|
|
FALSE, // fProp
|
|
&pbNextUpdateLoc,
|
|
&cbNextUpdateLoc,
|
|
pwszUrl))
|
|
goto ErrorReturn;
|
|
|
|
// Ctl Extensions
|
|
|
|
rgExt[0].pszObjId = szOID_NEXT_UPDATE_LOCATION;
|
|
rgExt[0].fCritical = FALSE;
|
|
rgExt[0].Value.pbData = pbNextUpdateLoc;
|
|
rgExt[0].Value.cbData = cbNextUpdateLoc;
|
|
|
|
Ctl.cExtension = 1;
|
|
Ctl.rgExtension = rgExt;
|
|
|
|
memset(&SignerInfo, 0, sizeof(SignerInfo));
|
|
SignerInfo.cbSize = sizeof(SignerInfo);
|
|
SignerInfo.pCertInfo = rgpCertContext[UPDATE_CTL_SIGNER]->pCertInfo;
|
|
SignerInfo.hCryptProv = hRSACryptProv;
|
|
SignerInfo.dwKeySpec = AT_SIGNATURE;
|
|
SignerInfo.HashAlgorithm.pszObjId = szOID_OIWSEC_sha1;
|
|
|
|
memset(&SignInfo, 0, sizeof(SignInfo));
|
|
SignInfo.cbSize = sizeof(SignInfo);
|
|
SignInfo.cSigners = 1;
|
|
SignInfo.rgSigners = &SignerInfo;
|
|
SignInfo.cCertEncoded = 1;
|
|
CertBlob.pbData = rgpCertContext[UPDATE_CTL_SIGNER]->pbCertEncoded;
|
|
CertBlob.cbData = rgpCertContext[UPDATE_CTL_SIGNER]->cbCertEncoded;
|
|
SignInfo.rgCertEncoded = &CertBlob;
|
|
|
|
cbCtlEncoded = 0;
|
|
if (!CryptMsgEncodeAndSignCTL(
|
|
dwMsgEncodingType,
|
|
&Ctl,
|
|
&SignInfo,
|
|
0, // dwEncodeFlags
|
|
NULL, // pbEncoded
|
|
&cbCtlEncoded
|
|
) || 0 == cbCtlEncoded) {
|
|
PrintLastError("EncodeUpdateCtl::CryptMsgEncodeAndSignCTL(cbEncoded == 0)");
|
|
goto ErrorReturn;
|
|
}
|
|
pbCtlEncoded = (BYTE *) TestAlloc(cbCtlEncoded);
|
|
if (pbCtlEncoded == NULL) goto ErrorReturn;
|
|
if (!CryptMsgEncodeAndSignCTL(
|
|
dwMsgEncodingType,
|
|
&Ctl,
|
|
&SignInfo,
|
|
0, // dwEncodeFlags
|
|
pbCtlEncoded,
|
|
&cbCtlEncoded
|
|
)) {
|
|
PrintLastError("EncodeUpdateCtl::CryptMsgEncodeAndSignCTL");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
if (pbCtlEncoded)
|
|
TestFree(pbCtlEncoded);
|
|
pbCtlEncoded = NULL;
|
|
cbCtlEncoded = 0;
|
|
fResult = FALSE;
|
|
CommonReturn:
|
|
if (pbNextUpdateLoc)
|
|
TestFree(pbNextUpdateLoc);
|
|
*ppbEncoded = pbCtlEncoded;
|
|
*pcbEncoded = cbCtlEncoded;
|
|
|
|
return fResult;
|
|
}
|