static void setup_x509_schannel_create_ecc_mocks(void) { STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); /*this is creating the handle storage space*/ STRICT_EXPECTED_CALL(CryptStringToBinaryA("certificate", 0, CRYPT_STRING_ANY, NULL, IGNORED_PTR_ARG, NULL, NULL)); /*this is asking for "how big is the certificate binary size?"*/ STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); /*this is creating the binary storage for the certificate*/ STRICT_EXPECTED_CALL(CryptStringToBinaryA("certificate", 0, CRYPT_STRING_ANY, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, NULL)); /*this is asking for "fill in the certificate in this binary buffer"*/ STRICT_EXPECTED_CALL(CryptStringToBinaryA("private key", 0, CRYPT_STRING_ANY, NULL, IGNORED_PTR_ARG, NULL, NULL)); /*this is asking for "how big is the private key binary size?"*/ STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); /*this is creating the binary storage for the private key*/ STRICT_EXPECTED_CALL(CryptStringToBinaryA("private key", 0, CRYPT_STRING_ANY, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, NULL)); /*this is asking for "fill in the private key in this binary buffer"*/ STRICT_EXPECTED_CALL(CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, IGNORED_PTR_ARG, IGNORED_NUM_ARG, 0, NULL, NULL, IGNORED_PTR_ARG)).SetReturn(FALSE); /*this is asking "how big is the decoded private key? (from binary)*/ STRICT_EXPECTED_CALL(CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_ECC_PRIVATE_KEY, IGNORED_PTR_ARG, IGNORED_NUM_ARG, 0, NULL, NULL, IGNORED_PTR_ARG)); /*this is asking "how big is the decoded private key? (from binary)*/ STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); /*this is allocating space for the decoded private key*/ STRICT_EXPECTED_CALL(CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_ECC_PRIVATE_KEY, IGNORED_PTR_ARG, IGNORED_NUM_ARG, 0, NULL, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); /*this is asking "how big is the decoded private key? (from binary)*/ STRICT_EXPECTED_CALL(CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); /*create a certificate context from an encoded certificate*/ STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(NCryptOpenStorageProvider(IGNORED_PTR_ARG, MS_KEY_STORAGE_PROVIDER, 0)) .IgnoreArgument_pszProviderName(); STRICT_EXPECTED_CALL(NCryptImportKey((NCRYPT_PROV_HANDLE)IGNORED_PTR_ARG, (NCRYPT_KEY_HANDLE)IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, NCRYPT_OVERWRITE_KEY_FLAG)) .IgnoreArgument_hProvider() .IgnoreArgument_hImportKey(); STRICT_EXPECTED_CALL(NCryptFreeObject((HCRYPTKEY)IGNORED_PTR_ARG)) .IgnoreArgument_hObject(); STRICT_EXPECTED_CALL(NCryptFreeObject((HCRYPTKEY)IGNORED_PTR_ARG)) .IgnoreArgument_hObject(); STRICT_EXPECTED_CALL(CertSetCertificateContextProperty(IGNORED_PTR_ARG, CERT_KEY_PROV_INFO_PROP_ID, 0, IGNORED_PTR_ARG)); /*give the private key*/ STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); }
/** * * save public or private key to PEM format * * ifile : name of file to write PEM encoded key * pemType : type of key being saved * rsa : RSA object with public and private keys * */ int rsa_read_key(RSA* rsa, const char* ifile, int pemType) { LPVOID derData, keyData; PCRYPT_PRIVATE_KEY_INFO pki = 0; DWORD pkiLen, derLen, keyLen; BOOL ok = FALSE; // decode base64 string ignoring headers derData = rsa_read_pem(ifile, &derLen); if (derData != NULL) { // decode DER // is it a public key? if (pemType == RSA_PUBLIC_KEY) { if (CryptDecodeObjectEx( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, derData, derLen, CRYPT_DECODE_ALLOC_FLAG, NULL, &keyData, &keyLen)) { // if decode ok, import it ok = CryptImportPublicKeyInfo(rsa->prov, X509_ASN_ENCODING, (PCERT_PUBLIC_KEY_INFO)keyData, &rsa->pubkey); // release allocated memory LocalFree(keyData); } } else { // convert the PKCS#8 data to private key info if (CryptDecodeObjectEx( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_PRIVATE_KEY_INFO, derData, derLen, CRYPT_DECODE_ALLOC_FLAG, NULL, &pki, &pkiLen)) { // then convert the private key to private key blob if (CryptDecodeObjectEx( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pki->PrivateKey.pbData, pki->PrivateKey.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &keyData, &keyLen)) { // if decode ok, import it ok = CryptImportKey(rsa->prov, keyData, keyLen, 0, CRYPT_EXPORTABLE, &rsa->privkey); // release data LocalFree(keyData); } // release private key info LocalFree(pki); } } xfree(derData); } return ok; }
BOOL WINAPI CertIsValidCRLForCertificate(PCCERT_CONTEXT pCert, PCCRL_CONTEXT pCrl, DWORD dwFlags, void *pvReserved) { PCERT_EXTENSION ext; BOOL ret; TRACE("(%p, %p, %08x, %p)\n", pCert, pCrl, dwFlags, pvReserved); if (!pCert) return TRUE; if ((ext = CertFindExtension(szOID_ISSUING_DIST_POINT, pCrl->pCrlInfo->cExtension, pCrl->pCrlInfo->rgExtension))) { CRL_ISSUING_DIST_POINT *idp; DWORD size; if ((ret = CryptDecodeObjectEx(pCrl->dwCertEncodingType, X509_ISSUING_DIST_POINT, ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &idp, &size))) { if ((ext = CertFindExtension(szOID_CRL_DIST_POINTS, pCert->pCertInfo->cExtension, pCert->pCertInfo->rgExtension))) { CRL_DIST_POINTS_INFO *distPoints; if ((ret = CryptDecodeObjectEx(pCert->dwCertEncodingType, X509_CRL_DIST_POINTS, ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &distPoints, &size))) { DWORD i; ret = FALSE; for (i = 0; !ret && i < distPoints->cDistPoint; i++) ret = match_dist_point_with_issuing_dist_point( &distPoints->rgDistPoint[i], idp); if (!ret) SetLastError(CRYPT_E_NO_MATCH); LocalFree(distPoints); } } else { /* no CRL dist points extension in cert, can't match the CRL * (which has an issuing dist point extension) */ ret = FALSE; SetLastError(CRYPT_E_NO_MATCH); } LocalFree(idp); } } else ret = TRUE; return ret; }
static BOOL CRYPT_FormatCPS(DWORD dwCertEncodingType, DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded, WCHAR *str, DWORD *pcchStr) { BOOL ret; DWORD size, charsNeeded = 1; CERT_NAME_VALUE *cpsValue; if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &cpsValue, &size))) { LPCWSTR sep; DWORD sepLen; if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) sep = crlf; else sep = commaSep; sepLen = strlenW(sep); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { charsNeeded += 3 * strlenW(indent); if (str && *pcchStr >= charsNeeded) { strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); } } charsNeeded += cpsValue->Value.cbData / sizeof(WCHAR); if (str && *pcchStr >= charsNeeded) { strcpyW(str, (LPWSTR)cpsValue->Value.pbData); str += cpsValue->Value.cbData / sizeof(WCHAR); } charsNeeded += sepLen; if (str && *pcchStr >= charsNeeded) { strcpyW(str, sep); str += sepLen; } LocalFree(cpsValue); if (!str) *pcchStr = charsNeeded; else if (*pcchStr < charsNeeded) { *pcchStr = charsNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else *pcchStr = charsNeeded; } return ret; }
/* Searches cert's extensions for the alternate name extension with OID * altNameOID, and if found, searches it for the alternate name type entryType. * If found, returns a pointer to the entry, otherwise returns NULL. * Regardless of whether an entry of the desired type is found, if the * alternate name extension is present, sets *info to the decoded alternate * name extension, which you must free using LocalFree. * The return value is a pointer within *info, so don't free *info before * you're done with the return value. */ static PCERT_ALT_NAME_ENTRY cert_find_alt_name_entry(PCCERT_CONTEXT cert, LPCSTR altNameOID, DWORD entryType, PCERT_ALT_NAME_INFO *info) { PCERT_ALT_NAME_ENTRY entry = NULL; PCERT_EXTENSION ext = CertFindExtension(altNameOID, cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension); if (ext) { DWORD bytes = 0; if (CryptDecodeObjectEx(cert->dwCertEncodingType, X509_ALTERNATE_NAME, ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, info, &bytes)) { DWORD i; for (i = 0; !entry && i < (*info)->cAltEntry; i++) if ((*info)->rgAltEntry[i].dwAltNameChoice == entryType) entry = &(*info)->rgAltEntry[i]; } } else *info = NULL; return entry; }
static const char *get_cert_common_name(PCCERT_CONTEXT cert) { static char buf[1024]; const char *name = NULL; CERT_NAME_INFO *nameInfo; DWORD size; BOOL ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, cert->pCertInfo->Subject.pbData, cert->pCertInfo->Subject.cbData, CRYPT_DECODE_NOCOPY_FLAG | CRYPT_DECODE_ALLOC_FLAG, NULL, &nameInfo, &size); if (ret) { PCERT_RDN_ATTR commonName = CertFindRDNAttr(szOID_COMMON_NAME, nameInfo); if (commonName) { CertRDNValueToStrA(commonName->dwValueType, &commonName->Value, buf, sizeof(buf)); name = buf; } LocalFree(nameInfo); } return name; }
static BOOL WINTRUST_GetTimeFromCounterSigner( const CMSG_CMS_SIGNER_INFO *counterSignerInfo, FILETIME *time) { DWORD i; BOOL foundTimeStamp = FALSE; for (i = 0; !foundTimeStamp && i < counterSignerInfo->AuthAttrs.cAttr; i++) { if (!strcmp(counterSignerInfo->AuthAttrs.rgAttr[i].pszObjId, szOID_RSA_signingTime)) { const CRYPT_ATTRIBUTE *attr = &counterSignerInfo->AuthAttrs.rgAttr[i]; DWORD j; for (j = 0; !foundTimeStamp && j < attr->cValue; j++) { static const DWORD encoding = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; DWORD size = sizeof(FILETIME); foundTimeStamp = CryptDecodeObjectEx(encoding, X509_CHOICE_OF_TIME, attr->rgValue[j].pbData, attr->rgValue[j].cbData, 0, NULL, time, &size); } } } return foundTimeStamp; }
static void setup_x509_schannel_create_mocks(void) { STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); /*this is creating the handle storage space*/ STRICT_EXPECTED_CALL(CryptStringToBinaryA("certificate", 0, CRYPT_STRING_ANY, NULL, IGNORED_PTR_ARG, NULL, NULL)); /*this is asking for "how big is the certificate binary size?"*/ STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); /*this is creating the binary storage for the certificate*/ STRICT_EXPECTED_CALL(CryptStringToBinaryA("certificate", 0, CRYPT_STRING_ANY, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, NULL)); /*this is asking for "fill in the certificate in this binary buffer"*/ STRICT_EXPECTED_CALL(CryptStringToBinaryA("private key", 0, CRYPT_STRING_ANY, NULL, IGNORED_PTR_ARG, NULL, NULL)); /*this is asking for "how big is the private key binary size?"*/ STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); /*this is creating the binary storage for the private key*/ STRICT_EXPECTED_CALL(CryptStringToBinaryA("private key", 0, CRYPT_STRING_ANY, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, NULL)); /*this is asking for "fill in the private key in this binary buffer"*/ STRICT_EXPECTED_CALL(CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, IGNORED_PTR_ARG, IGNORED_NUM_ARG, 0, NULL, NULL, IGNORED_PTR_ARG)); /*this is asking "how big is the decoded private key? (from binary)*/ STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); /*this is allocating space for the decoded private key*/ STRICT_EXPECTED_CALL(CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, IGNORED_PTR_ARG, IGNORED_NUM_ARG, 0, NULL, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); /*this is asking "how big is the decoded private key? (from binary)*/ STRICT_EXPECTED_CALL(CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, IGNORED_PTR_ARG, IGNORED_NUM_ARG)); /*create a certificate context from an encoded certificate*/ STRICT_EXPECTED_CALL(CryptAcquireContextA(IGNORED_PTR_ARG, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)); /*this is acquire a handle to a key container within a cryptographic service provider*/ STRICT_EXPECTED_CALL(CryptImportKey((HCRYPTPROV)IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, (HCRYPTKEY)NULL, 0, IGNORED_PTR_ARG)) /*tranferring the key from the blob to the cryptrographic key provider*/ .IgnoreArgument_hProv(); STRICT_EXPECTED_CALL(CertSetCertificateContextProperty(IGNORED_PTR_ARG, CERT_KEY_PROV_HANDLE_PROP_ID, 0, IGNORED_PTR_ARG)); /*give the private key*/ STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); }
static int _libssh2_wincng_asn_decode(unsigned char *pbEncoded, unsigned long cbEncoded, LPCSTR lpszStructType, unsigned char **ppbDecoded, unsigned long *pcbDecoded) { unsigned char *pbDecoded = NULL; unsigned long cbDecoded = 0; int ret; ret = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, lpszStructType, pbEncoded, cbEncoded, 0, NULL, NULL, &cbDecoded); if (!ret) { return -1; } pbDecoded = malloc(cbDecoded); if (!pbDecoded) { return -1; } ret = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, lpszStructType, pbEncoded, cbEncoded, 0, NULL, pbDecoded, &cbDecoded); if (!ret) { free(pbDecoded); return -1; } *ppbDecoded = pbDecoded; *pcbDecoded = cbDecoded; return 0; }
static DWORD cert_get_name_from_rdn_attr(DWORD encodingType, const CERT_NAME_BLOB *name, LPCSTR oid, LPWSTR pszNameString, DWORD cchNameString) { CERT_NAME_INFO *nameInfo; DWORD bytes = 0, ret = 0; if (CryptDecodeObjectEx(encodingType, X509_NAME, name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &nameInfo, &bytes)) { PCERT_RDN_ATTR nameAttr = CertFindRDNAttr(oid, nameInfo); if (nameAttr) ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value, pszNameString, cchNameString); LocalFree(nameInfo); } return ret; }
static FILETIME WINTRUST_GetTimeFromSigner(const CRYPT_PROVIDER_DATA *data, const CMSG_SIGNER_INFO *signerInfo) { DWORD i; FILETIME time; BOOL foundTimeStamp = FALSE; for (i = 0; !foundTimeStamp && i < signerInfo->UnauthAttrs.cAttr; i++) { if (!strcmp(signerInfo->UnauthAttrs.rgAttr[i].pszObjId, szOID_RSA_counterSign)) { const CRYPT_ATTRIBUTE *attr = &signerInfo->UnauthAttrs.rgAttr[i]; DWORD j; for (j = 0; j < attr->cValue; j++) { static const DWORD encoding = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; CMSG_CMS_SIGNER_INFO *counterSignerInfo; DWORD size; BOOL ret = CryptDecodeObjectEx(encoding, CMS_SIGNER_INFO, attr->rgValue[j].pbData, attr->rgValue[j].cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &counterSignerInfo, &size); if (ret) { /* FIXME: need to verify countersigner signature too */ foundTimeStamp = WINTRUST_GetTimeFromCounterSigner( counterSignerInfo, &time); LocalFree(counterSignerInfo); } } } } if (!foundTimeStamp) { TRACE("returning system time %s\n", filetime_to_str(&data->sftSystemTime)); time = data->sftSystemTime; } else TRACE("returning time from message %s\n", filetime_to_str(&time)); return time; }
PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType, const BYTE* pbCrlEncoded, DWORD cbCrlEncoded) { PCRL_CONTEXT crl = NULL; BOOL ret; PCRL_INFO crlInfo = NULL; DWORD size = 0; TRACE("(%08x, %p, %d)\n", dwCertEncodingType, pbCrlEncoded, cbCrlEncoded); if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING) { SetLastError(E_INVALIDARG); return NULL; } ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED, pbCrlEncoded, cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &crlInfo, &size); if (ret) { BYTE *data = NULL; crl = Context_CreateDataContext(sizeof(CRL_CONTEXT)); if (!crl) goto end; data = CryptMemAlloc(cbCrlEncoded); if (!data) { CertFreeCRLContext(crl); crl = NULL; goto end; } memcpy(data, pbCrlEncoded, cbCrlEncoded); crl->dwCertEncodingType = dwCertEncodingType; crl->pbCrlEncoded = data; crl->cbCrlEncoded = cbCrlEncoded; crl->pCrlInfo = crlInfo; crl->hCertStore = 0; } end: return crl; }
PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType, const BYTE* pbCrlEncoded, DWORD cbCrlEncoded) { crl_t *crl = NULL; BOOL ret; PCRL_INFO crlInfo = NULL; BYTE *data = NULL; DWORD size = 0; TRACE("(%08x, %p, %d)\n", dwCertEncodingType, pbCrlEncoded, cbCrlEncoded); if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING) { SetLastError(E_INVALIDARG); return NULL; } ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED, pbCrlEncoded, cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &crlInfo, &size); if (!ret) return NULL; crl = (crl_t*)Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl, &empty_store); if (!crl) return NULL; data = CryptMemAlloc(cbCrlEncoded); if (!data) { Context_Release(&crl->base); return NULL; } memcpy(data, pbCrlEncoded, cbCrlEncoded); crl->ctx.dwCertEncodingType = dwCertEncodingType; crl->ctx.pbCrlEncoded = data; crl->ctx.cbCrlEncoded = cbCrlEncoded; crl->ctx.pCrlInfo = crlInfo; crl->ctx.hCertStore = &empty_store; return &crl->ctx; }
static context_t *CRL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link) { crl_t *crl; if(use_link) { crl = (crl_t*)Context_CreateLinkContext(sizeof(CRL_CONTEXT), context, store); if(!crl) return NULL; }else { const crl_t *cloned = (const crl_t*)context; DWORD size = 0; BOOL res; crl = (crl_t*)Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl, store); if(!crl) return NULL; Context_CopyProperties(&crl->ctx, &cloned->ctx); crl->ctx.dwCertEncodingType = cloned->ctx.dwCertEncodingType; crl->ctx.pbCrlEncoded = CryptMemAlloc(cloned->ctx.cbCrlEncoded); memcpy(crl->ctx.pbCrlEncoded, cloned->ctx.pbCrlEncoded, cloned->ctx.cbCrlEncoded); crl->ctx.cbCrlEncoded = cloned->ctx.cbCrlEncoded; /* FIXME: We don't need to decode the object here, we could just clone crl info. */ res = CryptDecodeObjectEx(crl->ctx.dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED, crl->ctx.pbCrlEncoded, crl->ctx.cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &crl->ctx.pCrlInfo, &size); if(!res) { CertFreeCRLContext(&crl->ctx); return NULL; } } crl->ctx.hCertStore = store; return &crl->base; }
static BOOL compare_crl_issued_by(PCCRL_CONTEXT pCrlContext, DWORD dwType, DWORD dwFlags, const void *pvPara) { BOOL ret; if (pvPara) { PCCERT_CONTEXT issuer = pvPara; ret = CertCompareCertificateName(issuer->dwCertEncodingType, &issuer->pCertInfo->Subject, &pCrlContext->pCrlInfo->Issuer); if (ret && (dwFlags & CRL_FIND_ISSUED_BY_SIGNATURE_FLAG)) ret = CryptVerifyCertificateSignatureEx(0, issuer->dwCertEncodingType, CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL, (void *)pCrlContext, CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)issuer, 0, NULL); if (ret && (dwFlags & CRL_FIND_ISSUED_BY_AKI_FLAG)) { PCERT_EXTENSION ext = CertFindExtension( szOID_AUTHORITY_KEY_IDENTIFIER2, pCrlContext->pCrlInfo->cExtension, pCrlContext->pCrlInfo->rgExtension); if (ext) { CERT_AUTHORITY_KEY_ID2_INFO *info; DWORD size; if ((ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size))) { if (info->AuthorityCertIssuer.cAltEntry && info->AuthorityCertSerialNumber.cbData) { PCERT_ALT_NAME_ENTRY directoryName = NULL; DWORD i; for (i = 0; !directoryName && i < info->AuthorityCertIssuer.cAltEntry; i++) if (info->AuthorityCertIssuer.rgAltEntry[i]. dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME) directoryName = &info->AuthorityCertIssuer.rgAltEntry[i]; if (directoryName) { ret = CertCompareCertificateName( issuer->dwCertEncodingType, &issuer->pCertInfo->Subject, &directoryName->u.DirectoryName); if (ret) ret = CertCompareIntegerBlob( &issuer->pCertInfo->SerialNumber, &info->AuthorityCertSerialNumber); } else { FIXME("no supported name type in authority key id2\n"); ret = FALSE; } } else if (info->KeyId.cbData) { DWORD size; ret = CertGetCertificateContextProperty(issuer, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); if (ret && size == info->KeyId.cbData) { LPBYTE buf = CryptMemAlloc(size); if (buf) { CertGetCertificateContextProperty(issuer, CERT_KEY_IDENTIFIER_PROP_ID, buf, &size); ret = !memcmp(buf, info->KeyId.pbData, size); CryptMemFree(buf); } else ret = FALSE; } else ret = FALSE; } else { FIXME("unsupported value for AKI extension\n"); ret = FALSE; } LocalFree(info); } } /* else: a CRL without an AKI matches any cert */ } } else ret = TRUE; return ret; }
DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString) { DWORD ret = 0; PCERT_NAME_BLOB name; LPCSTR altNameOID; TRACE("(%p, %d, %08x, %p, %p, %d)\n", pCertContext, dwType, dwFlags, pvTypePara, pszNameString, cchNameString); if (dwFlags & CERT_NAME_ISSUER_FLAG) { name = &pCertContext->pCertInfo->Issuer; altNameOID = szOID_ISSUER_ALT_NAME; } else { name = &pCertContext->pCertInfo->Subject; altNameOID = szOID_SUBJECT_ALT_NAME; } switch (dwType) { case CERT_NAME_EMAIL_TYPE: { CERT_ALT_NAME_INFO *info; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_RFC822_NAME, &info); if (entry) { if (!pszNameString) ret = strlenW(entry->u.pwszRfc822Name) + 1; else if (cchNameString) { ret = min(strlenW(entry->u.pwszRfc822Name), cchNameString - 1); memcpy(pszNameString, entry->u.pwszRfc822Name, ret * sizeof(WCHAR)); pszNameString[ret++] = 0; } } if (info) LocalFree(info); if (!ret) ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType, name, szOID_RSA_emailAddr, pszNameString, cchNameString); break; } case CERT_NAME_RDN_TYPE: if (name->cbData) ret = CertNameToStrW(pCertContext->dwCertEncodingType, name, *(DWORD *)pvTypePara, pszNameString, cchNameString); else { CERT_ALT_NAME_INFO *info; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_DIRECTORY_NAME, &info); if (entry) ret = CertNameToStrW(pCertContext->dwCertEncodingType, &entry->u.DirectoryName, *(DWORD *)pvTypePara, pszNameString, cchNameString); if (info) LocalFree(info); } break; case CERT_NAME_ATTR_TYPE: ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType, name, pvTypePara, pszNameString, cchNameString); if (!ret) { CERT_ALT_NAME_INFO *altInfo; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_DIRECTORY_NAME, &altInfo); if (entry) ret = cert_name_to_str_with_indent(X509_ASN_ENCODING, 0, &entry->u.DirectoryName, 0, pszNameString, cchNameString); if (altInfo) LocalFree(altInfo); } break; case CERT_NAME_SIMPLE_DISPLAY_TYPE: { static const LPCSTR simpleAttributeOIDs[] = { szOID_COMMON_NAME, szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME, szOID_RSA_emailAddr }; CERT_NAME_INFO *nameInfo = NULL; DWORD bytes = 0, i; if (CryptDecodeObjectEx(pCertContext->dwCertEncodingType, X509_NAME, name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &nameInfo, &bytes)) { PCERT_RDN_ATTR nameAttr = NULL; for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) / sizeof(simpleAttributeOIDs[0]); i++) nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], nameInfo); if (nameAttr) ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value, pszNameString, cchNameString); LocalFree(nameInfo); } if (!ret) { CERT_ALT_NAME_INFO *altInfo; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_RFC822_NAME, &altInfo); if (altInfo) { if (!entry && altInfo->cAltEntry) entry = &altInfo->rgAltEntry[0]; if (entry) { if (!pszNameString) ret = strlenW(entry->u.pwszRfc822Name) + 1; else if (cchNameString) { ret = min(strlenW(entry->u.pwszRfc822Name), cchNameString - 1); memcpy(pszNameString, entry->u.pwszRfc822Name, ret * sizeof(WCHAR)); pszNameString[ret++] = 0; } } LocalFree(altInfo); } } break; } case CERT_NAME_FRIENDLY_DISPLAY_TYPE: { DWORD cch = cchNameString; if (CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pszNameString, &cch)) ret = cch; else ret = CertGetNameStringW(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, dwFlags, pvTypePara, pszNameString, cchNameString); break; } case CERT_NAME_DNS_TYPE: { CERT_ALT_NAME_INFO *info; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_DNS_NAME, &info); if (entry) { if (!pszNameString) ret = strlenW(entry->u.pwszDNSName) + 1; else if (cchNameString) { ret = min(strlenW(entry->u.pwszDNSName), cchNameString - 1); memcpy(pszNameString, entry->u.pwszDNSName, ret * sizeof(WCHAR)); pszNameString[ret++] = 0; } } if (info) LocalFree(info); if (!ret) ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType, name, szOID_COMMON_NAME, pszNameString, cchNameString); break; } case CERT_NAME_URL_TYPE: { CERT_ALT_NAME_INFO *info; PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, altNameOID, CERT_ALT_NAME_URL, &info); if (entry) { if (!pszNameString) ret = strlenW(entry->u.pwszURL) + 1; else if (cchNameString) { ret = min(strlenW(entry->u.pwszURL), cchNameString - 1); memcpy(pszNameString, entry->u.pwszURL, ret * sizeof(WCHAR)); pszNameString[ret++] = 0; } } if (info) LocalFree(info); break; } default: FIXME("unimplemented for type %d\n", dwType); ret = 0; } if (!ret) { if (!pszNameString) ret = 1; else if (cchNameString) { pszNameString[0] = 0; ret = 1; } } return ret; }
void ca_generate_root_ca_cert_t::generate_ca_cert_clicked(){ GIE_QT_DEF_EXCEPTION_GUARD_BEGIN stcrypt::cert_name_t cert_subject_name; #define STCRYPT_TOYCA_CP_NAME(x) { auto str = ui.x##_edit->text().toStdWString(); cert_subject_name.set_##x( std::move(str) ); } STCRYPT_TOYCA_CP_NAME(common_name); STCRYPT_TOYCA_CP_NAME(country_name); STCRYPT_TOYCA_CP_NAME(locality_name); STCRYPT_TOYCA_CP_NAME(organization_name); STCRYPT_TOYCA_CP_NAME(organization_unit_name); STCRYPT_TOYCA_CP_NAME(state_or_province_name); STCRYPT_TOYCA_CP_NAME(email_name); #undef STCRYPT_TOYCA_CP_NAME // generate key pair NCRYPT_PROV_HANDLE cng_provider=0; NCRYPT_KEY_HANDLE cng_n_key_pair=0; auto status = NCryptOpenStorageProvider(&cng_provider, CNG_STCRYPT_KEYSTORAGE, 0); STCRYPT_CHECK(!FAILED(status)); BOOST_SCOPE_EXIT((&cng_provider)) { auto const status = NCryptFreeObject (cng_provider); assert( !FAILED(status) ); } BOOST_SCOPE_EXIT_END boost::uuids::uuid const key_container_id( (boost::uuids::random_generator()()) ); auto const& key_pair_container_name = boost::lexical_cast<std::wstring>( key_container_id ); status = NCryptCreatePersistedKey(cng_provider, &cng_n_key_pair, NCNG_DSTU4145, key_pair_container_name.c_str(), AT_KEYEXCHANGE, 0/*NCRYPT_OVERWRITE_KEY_FLAG*/); STCRYPT_CHECK(!FAILED(status)); BOOST_SCOPE_EXIT((&cng_n_key_pair)) { auto const status = NCryptFreeObject (cng_n_key_pair); assert( !FAILED(status) ); } BOOST_SCOPE_EXIT_END status = NCryptFinalizeKey(cng_n_key_pair, 0); STCRYPT_CHECK(!FAILED(status)); auto const& to_be_signed_cert_blob = ms_cert::create_req_blob(cert_subject_name, cng_n_key_pair, cert_subject_name); DWORD size; STCRYPT_CHECK( CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, reinterpret_cast<BYTE const*> (to_be_signed_cert_blob.data()), to_be_signed_cert_blob.size(), CRYPT_DECODE_TO_BE_SIGNED_FLAG, 0, 0, &size) ); STCRYPT_CHECK(size!=0); std::vector<unsigned char> to_be_signed_cert_blob_combined(size); STCRYPT_CHECK( CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, reinterpret_cast<BYTE const*> (to_be_signed_cert_blob.data()), to_be_signed_cert_blob.size(), CRYPT_DECODE_TO_BE_SIGNED_FLAG, 0, to_be_signed_cert_blob_combined.data(), &size) ); to_be_signed_cert_blob_combined.resize(size); CERT_INFO* const cert_to_be_signed = static_cast<CERT_INFO*>( static_cast<void*>( to_be_signed_cert_blob_combined.data() ) ); // do sign CRYPT_ALGORITHM_IDENTIFIER signature_alg={OID_G34311_DSTU4145_SIGN,0}; DWORD encoded_cert_size = 0; if( !CryptSignAndEncodeCertificate(cng_n_key_pair, 0, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, cert_to_be_signed, &signature_alg, 0, 0, &encoded_cert_size) ){ //TODO: this CryptSignAndEncodeCertificate leaks memory STCRYPT_UNEXPECTED(); } STCRYPT_CHECK(encoded_cert_size!=0); std::vector<BYTE> signed_certificate(encoded_cert_size); if( !CryptSignAndEncodeCertificate(cng_n_key_pair, 0, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, cert_to_be_signed, &signature_alg, 0, signed_certificate.data(), &encoded_cert_size) ){ STCRYPT_UNEXPECTED(); } signed_certificate.resize(encoded_cert_size); // context from signed blob ms_cert::pccert_context_t signed_cert_context( CertCreateCertificateContext (X509_ASN_ENCODING, reinterpret_cast<BYTE const*>( signed_certificate.data() ), signed_certificate.size() ) ); STCRYPT_CHECK( signed_cert_context ); // assign private key container name CRYPT_KEY_PROV_INFO key_prov_info = {0}; key_prov_info.pwszContainerName = const_cast<wchar_t*>( key_pair_container_name.c_str() ); key_prov_info.pwszProvName = CNG_STCRYPT_KEYSTORAGE; key_prov_info.dwProvType = 0; key_prov_info.dwFlags = 0; key_prov_info.cProvParam = 0; key_prov_info.rgProvParam = 0; key_prov_info.dwKeySpec = 0; STCRYPT_CHECK( CertSetCertificateContextProperty(signed_cert_context.handle(), CERT_KEY_PROV_INFO_PROP_ID, 0, &key_prov_info) ); STCRYPT_CHECK( CryptUIDlgViewContext (CERT_STORE_CERTIFICATE_CONTEXT, signed_cert_context.handle(), this->winId(), L"Generated CA certificate [NOT YET INSTALLED]", 0, 0) ); ms_cert::import_into_ms_store2(signed_cert_context.handle(), L"ROOT"); STCRYPT_CHECK( CryptUIDlgViewContext (CERT_STORE_CERTIFICATE_CONTEXT, signed_cert_context.handle(), this->winId(), L"Generated CA certificate", 0, 0) ); toy_ca::initialize_accept_requests_mode( dynamic_cast<QMainWindow*>( this->parent() ), std::move(signed_cert_context) ); GIE_QT_DEF_EXCEPTION_GUARD_END }
DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString) { DWORD ret; PCERT_NAME_BLOB name; LPCSTR altNameOID; TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext, dwType, dwFlags, pvTypePara, pszNameString, cchNameString); if (dwFlags & CERT_NAME_ISSUER_FLAG) { name = &pCertContext->pCertInfo->Issuer; altNameOID = szOID_ISSUER_ALT_NAME; } else { name = &pCertContext->pCertInfo->Subject; altNameOID = szOID_SUBJECT_ALT_NAME; } switch (dwType) { case CERT_NAME_SIMPLE_DISPLAY_TYPE: { static const LPCSTR simpleAttributeOIDs[] = { szOID_COMMON_NAME, szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME, szOID_RSA_emailAddr }; CERT_NAME_INFO *info = NULL; PCERT_RDN_ATTR nameAttr = NULL; DWORD bytes = 0, i; if (CryptDecodeObjectEx(pCertContext->dwCertEncodingType, X509_NAME, name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes)) { for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) / sizeof(simpleAttributeOIDs[0]); i++) nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info); } else ret = 0; if (!nameAttr) { PCERT_EXTENSION ext = CertFindExtension(altNameOID, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension); if (ext) { for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) / sizeof(simpleAttributeOIDs[0]); i++) nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info); if (!nameAttr) { /* FIXME: gotta then look for a rfc822Name choice in ext. * Failing that, look for the first attribute. */ FIXME("CERT_NAME_SIMPLE_DISPLAY_TYPE: stub\n"); ret = 0; } } } ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value, pszNameString, cchNameString); if (info) LocalFree(info); break; } case CERT_NAME_FRIENDLY_DISPLAY_TYPE: { DWORD cch = cchNameString; if (CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pszNameString, &cch)) ret = cch; else ret = CertGetNameStringW(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, dwFlags, pvTypePara, pszNameString, cchNameString); break; } default: FIXME("unimplemented for type %ld\n", dwType); ret = 0; } return ret; }
DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, DWORD dwStrType, LPWSTR psz, DWORD csz) { static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG; static const WCHAR commaSep[] = { ',',' ',0 }; static const WCHAR semiSep[] = { ';',' ',0 }; static const WCHAR crlfSep[] = { '\r','\n',0 }; static const WCHAR plusSep[] = { ' ','+',' ',0 }; static const WCHAR spaceSep[] = { ' ',0 }; DWORD ret = 0, bytes = 0; BOOL bRet; CERT_NAME_INFO *info; TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType, psz, csz); if (dwStrType & unsupportedFlags) FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags); bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData, pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes); if (bRet) { DWORD i, j, sepLen, rdnSepLen; LPCWSTR sep, rdnSep; if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG) sep = semiSep; else if (dwStrType & CERT_NAME_STR_CRLF_FLAG) sep = crlfSep; else sep = commaSep; sepLen = lstrlenW(sep); if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG) rdnSep = spaceSep; else rdnSep = plusSep; rdnSepLen = lstrlenW(rdnSep); for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++) { for (j = 0; (!psz || ret < csz) && j < info->rgRDN[i].cRDNAttr; j++) { DWORD chars; LPCSTR prefixA = NULL; LPCWSTR prefixW = NULL; if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR) prefixA = info->rgRDN[i].rgRDNAttr[j].pszObjId; else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR) { PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, info->rgRDN[i].rgRDNAttr[j].pszObjId, CRYPT_RDN_ATTR_OID_GROUP_ID); if (oidInfo) prefixW = oidInfo->pwszName; else prefixA = info->rgRDN[i].rgRDNAttr[j].pszObjId; } if (prefixW) { /* - 1 is needed to account for the NULL terminator. */ chars = CRYPT_AddPrefixW(prefixW, psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0); ret += chars; csz -= chars; } else if (prefixA) { /* - 1 is needed to account for the NULL terminator. */ chars = CRYPT_AddPrefixAToW(prefixA, psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0); ret += chars; csz -= chars; } /* FIXME: handle quoting */ chars = CertRDNValueToStrW( info->rgRDN[i].rgRDNAttr[j].dwValueType, &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL, psz ? csz - ret : 0); if (chars) ret += chars - 1; if (j < info->rgRDN[i].cRDNAttr - 1) { if (psz && ret < csz - rdnSepLen - 1) memcpy(psz + ret, rdnSep, rdnSepLen * sizeof(WCHAR)); ret += rdnSepLen; } } if (i < info->cRDN - 1) { if (psz && ret < csz - sepLen - 1) memcpy(psz + ret, sep, sepLen * sizeof(WCHAR)); ret += sepLen; } } LocalFree(info); } if (psz && csz) { *(psz + ret) = '\0'; csz--; ret++; } else ret++; TRACE("Returning %s\n", debugstr_w(psz)); return ret; }
DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, DWORD dwStrType, LPSTR psz, DWORD csz) { static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG; static const char commaSep[] = ", "; static const char semiSep[] = "; "; static const char crlfSep[] = "\r\n"; static const char plusSep[] = " + "; static const char spaceSep[] = " "; DWORD ret = 0, bytes = 0; BOOL bRet; CERT_NAME_INFO *info; TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType, psz, csz); if (dwStrType & unsupportedFlags) FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags); bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData, pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes); if (bRet) { DWORD i, j, sepLen, rdnSepLen; LPCSTR sep, rdnSep; if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG) sep = semiSep; else if (dwStrType & CERT_NAME_STR_CRLF_FLAG) sep = crlfSep; else sep = commaSep; sepLen = strlen(sep); if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG) rdnSep = spaceSep; else rdnSep = plusSep; rdnSepLen = strlen(rdnSep); for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++) { for (j = 0; (!psz || ret < csz) && j < info->rgRDN[i].cRDNAttr; j++) { DWORD chars; char prefixBuf[10]; /* big enough for GivenName */ LPCSTR prefix = NULL; if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR) prefix = info->rgRDN[i].rgRDNAttr[j].pszObjId; else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR) { PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, info->rgRDN[i].rgRDNAttr[j].pszObjId, CRYPT_RDN_ATTR_OID_GROUP_ID); if (oidInfo) { WideCharToMultiByte(CP_ACP, 0, oidInfo->pwszName, -1, prefixBuf, sizeof(prefixBuf), NULL, NULL); prefix = prefixBuf; } else prefix = info->rgRDN[i].rgRDNAttr[j].pszObjId; } if (prefix) { /* - 1 is needed to account for the NULL terminator. */ chars = CRYPT_AddPrefixA(prefix, psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0); ret += chars; csz -= chars; } /* FIXME: handle quoting */ chars = CertRDNValueToStrA( info->rgRDN[i].rgRDNAttr[j].dwValueType, &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL, psz ? csz - ret : 0); if (chars) ret += chars - 1; if (j < info->rgRDN[i].cRDNAttr - 1) { if (psz && ret < csz - rdnSepLen - 1) memcpy(psz + ret, rdnSep, rdnSepLen); ret += rdnSepLen; } } if (i < info->cRDN - 1) { if (psz && ret < csz - sepLen - 1) memcpy(psz + ret, sep, sepLen); ret += sepLen; } } LocalFree(info); } if (psz && csz) { *(psz + ret) = '\0'; csz--; ret++; } else ret++; TRACE("Returning %s\n", debugstr_a(psz)); return ret; }
/*********************************************************************** * TrustIsCertificateSelfSigned (WINTRUST.@) */ BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert ) { PCERT_EXTENSION ext; DWORD size; BOOL ret; TRACE("%p\n", cert); if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2, cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension))) { CERT_AUTHORITY_KEY_ID2_INFO *info; ret = CryptDecodeObjectEx(cert->dwCertEncodingType, X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, &info, &size); if (ret) { if (info->AuthorityCertIssuer.cAltEntry && info->AuthorityCertSerialNumber.cbData) { PCERT_ALT_NAME_ENTRY directoryName = NULL; DWORD i; for (i = 0; !directoryName && i < info->AuthorityCertIssuer.cAltEntry; i++) if (info->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME) directoryName = &info->AuthorityCertIssuer.rgAltEntry[i]; if (directoryName) { ret = CertCompareCertificateName(cert->dwCertEncodingType, &directoryName->u.DirectoryName, &cert->pCertInfo->Issuer) && CertCompareIntegerBlob(&info->AuthorityCertSerialNumber, &cert->pCertInfo->SerialNumber); } else { FIXME("no supported name type in authority key id2\n"); ret = FALSE; } } else if (info->KeyId.cbData) { ret = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); if (ret && size == info->KeyId.cbData) { LPBYTE buf = CryptMemAlloc(size); if (buf) { CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, buf, &size); ret = !memcmp(buf, info->KeyId.pbData, size); CryptMemFree(buf); } else ret = FALSE; } else ret = FALSE; } LocalFree(info); } } else if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER, cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension))) { CERT_AUTHORITY_KEY_ID_INFO *info; ret = CryptDecodeObjectEx(cert->dwCertEncodingType, X509_AUTHORITY_KEY_ID, ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, &info, &size); if (ret) { if (info->CertIssuer.cbData && info->CertSerialNumber.cbData) { ret = CertCompareCertificateName(cert->dwCertEncodingType, &info->CertIssuer, &cert->pCertInfo->Issuer) && CertCompareIntegerBlob(&info->CertSerialNumber, &cert->pCertInfo->SerialNumber); } else if (info->KeyId.cbData) { ret = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); if (ret && size == info->KeyId.cbData) { LPBYTE buf = CryptMemAlloc(size); if (buf) { CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, buf, &size); ret = !memcmp(buf, info->KeyId.pbData, size); CryptMemFree(buf); } else ret = FALSE; } else ret = FALSE; } else ret = FALSE; LocalFree(info); } } else ret = CertCompareCertificateName(cert->dwCertEncodingType, &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer); return ret; }
void SchannelCertificate::parse() { // // Subject name // DWORD requiredSize = CertNameToStr(X509_ASN_ENCODING, &m_cert->pCertInfo->Subject, CERT_OID_NAME_STR, NULL, 0); if (requiredSize > 1) { vector<char> rawSubjectName(requiredSize); CertNameToStr(X509_ASN_ENCODING, &m_cert->pCertInfo->Subject, CERT_OID_NAME_STR, &rawSubjectName[0], rawSubjectName.size()); m_subjectName = std::string(&rawSubjectName[0]); } // // Common name // // Note: We only pull out one common name from the cert. requiredSize = CertGetNameString(m_cert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, 0); if (requiredSize > 1) { vector<char> rawCommonName(requiredSize); requiredSize = CertGetNameString(m_cert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, &rawCommonName[0], rawCommonName.size()); m_commonNames.push_back( std::string(&rawCommonName[0]) ); } // // Subject alternative names // PCERT_EXTENSION pExtensions = CertFindExtension(szOID_SUBJECT_ALT_NAME2, m_cert->pCertInfo->cExtension, m_cert->pCertInfo->rgExtension); if (pExtensions) { CRYPT_DECODE_PARA decodePara = {0}; decodePara.cbSize = sizeof(decodePara); CERT_ALT_NAME_INFO* pAltNameInfo = NULL; DWORD altNameInfoSize = 0; BOOL status = CryptDecodeObjectEx( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_SUBJECT_ALT_NAME2, pExtensions->Value.pbData, pExtensions->Value.cbData, CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, &decodePara, &pAltNameInfo, &altNameInfoSize); if (status && pAltNameInfo) { for (int i = 0; i < pAltNameInfo->cAltEntry; i++) { if (pAltNameInfo->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) addDNSName( wstrToStr( pAltNameInfo->rgAltEntry[i].pwszDNSName ) ); } } } // if (pExtensions) // { // vector<wchar_t> subjectAlt // CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_SUBJECT_ALT_NAME, pExtensions->Value->pbData, pExtensions->Value->cbData, ) // } // // // subjectAltNames // int subjectAltNameLoc = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); // if(subjectAltNameLoc != -1) { // X509_EXTENSION* extension = X509_get_ext(cert.get(), subjectAltNameLoc); // std::shared_ptr<GENERAL_NAMES> generalNames(reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(extension)), GENERAL_NAMES_free); // std::shared_ptr<ASN1_OBJECT> xmppAddrObject(OBJ_txt2obj(ID_ON_XMPPADDR_OID, 1), ASN1_OBJECT_free); // std::shared_ptr<ASN1_OBJECT> dnsSRVObject(OBJ_txt2obj(ID_ON_DNSSRV_OID, 1), ASN1_OBJECT_free); // for (int i = 0; i < sk_GENERAL_NAME_num(generalNames.get()); ++i) { // GENERAL_NAME* generalName = sk_GENERAL_NAME_value(generalNames.get(), i); // if (generalName->type == GEN_OTHERNAME) { // OTHERNAME* otherName = generalName->d.otherName; // if (OBJ_cmp(otherName->type_id, xmppAddrObject.get()) == 0) { // // XmppAddr // if (otherName->value->type != V_ASN1_UTF8STRING) { // continue; // } // ASN1_UTF8STRING* xmppAddrValue = otherName->value->value.utf8string; // addXMPPAddress(ByteArray(ASN1_STRING_data(xmppAddrValue), ASN1_STRING_length(xmppAddrValue)).toString()); // } // else if (OBJ_cmp(otherName->type_id, dnsSRVObject.get()) == 0) { // // SRVName // if (otherName->value->type != V_ASN1_IA5STRING) { // continue; // } // ASN1_IA5STRING* srvNameValue = otherName->value->value.ia5string; // addSRVName(ByteArray(ASN1_STRING_data(srvNameValue), ASN1_STRING_length(srvNameValue)).toString()); // } // } // else if (generalName->type == GEN_DNS) { // // DNSName // addDNSName(ByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)).toString()); // } // } // } }
my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, CERT_CONTEXT *ctx, char *key_file) { DWORD der_buffer_len= 0; LPBYTE der_buffer= NULL; DWORD priv_key_len= 0; LPBYTE priv_key= NULL; HCRYPTPROV crypt_prov= 0; HCRYPTKEY crypt_key= 0; CERT_KEY_CONTEXT kpi={ 0 }; my_bool rc= 0; /* load private key into der binary object */ if (!(der_buffer= ma_schannel_load_pem(pvio, key_file, &der_buffer_len))) return 0; /* determine required buffer size for decoded private key */ if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, der_buffer, der_buffer_len, 0, NULL, NULL, &priv_key_len)) { ma_schannel_set_win_error(pvio); goto end; } /* allocate buffer for decoded private key */ if (!(priv_key= LocalAlloc(0, priv_key_len))) { pvio->set_error(pvio->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, NULL); goto end; } /* decode */ if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, der_buffer, der_buffer_len, 0, NULL, priv_key, &priv_key_len)) { ma_schannel_set_win_error(pvio); goto end; } /* Acquire context */ if (!CryptAcquireContext(&crypt_prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { ma_schannel_set_win_error(pvio); goto end; } /* ... and import the private key */ if (!CryptImportKey(crypt_prov, priv_key, priv_key_len, 0, 0, (HCRYPTKEY *)&crypt_key)) { ma_schannel_set_win_error(pvio); goto end; } kpi.hCryptProv= crypt_prov; kpi.dwKeySpec = AT_KEYEXCHANGE; kpi.cbSize= sizeof(kpi); /* assign private key to certificate context */ if (CertSetCertificateContextProperty(ctx, CERT_KEY_CONTEXT_PROP_ID, 0, &kpi)) rc= 1; else ma_schannel_set_win_error(pvio); end: if (der_buffer) LocalFree(der_buffer); if (priv_key) { if (crypt_key) CryptDestroyKey(crypt_key); LocalFree(priv_key); if (!rc) if (crypt_prov) CryptReleaseContext(crypt_prov, 0); } return rc; }
static BOOL CRYPT_FormatUserNotice(DWORD dwCertEncodingType, DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded, WCHAR *str, DWORD *pcchStr) { BOOL ret; DWORD size, charsNeeded = 1; CERT_POLICY_QUALIFIER_USER_NOTICE *notice; if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_PKIX_POLICY_QUALIFIER_USERNOTICE, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, ¬ice, &size))) { static const WCHAR numFmt[] = { '%','d',0 }; CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *pNoticeRef = notice->pNoticeReference; LPCWSTR headingSep, sep; DWORD headingSepLen, sepLen; LPWSTR noticeRef, organization, noticeNum, noticeText; DWORD noticeRefLen, organizationLen, noticeNumLen, noticeTextLen; WCHAR noticeNumStr[11]; noticeRefLen = LoadStringW(hInstance, IDS_NOTICE_REF, (LPWSTR)¬iceRef, 0); organizationLen = LoadStringW(hInstance, IDS_ORGANIZATION, (LPWSTR)&organization, 0); noticeNumLen = LoadStringW(hInstance, IDS_NOTICE_NUM, (LPWSTR)¬iceNum, 0); noticeTextLen = LoadStringW(hInstance, IDS_NOTICE_TEXT, (LPWSTR)¬iceText, 0); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { headingSep = colonCrlf; sep = crlf; } else { headingSep = colonSpace; sep = commaSep; } sepLen = strlenW(sep); headingSepLen = strlenW(headingSep); if (pNoticeRef) { DWORD k; LPCSTR src; if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { charsNeeded += 3 * strlenW(indent); if (str && *pcchStr >= charsNeeded) { strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); } } charsNeeded += noticeRefLen; if (str && *pcchStr >= charsNeeded) { memcpy(str, noticeRef, noticeRefLen * sizeof(WCHAR)); str += noticeRefLen; } charsNeeded += headingSepLen; if (str && *pcchStr >= charsNeeded) { strcpyW(str, headingSep); str += headingSepLen; } if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { charsNeeded += 4 * strlenW(indent); if (str && *pcchStr >= charsNeeded) { strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); } } charsNeeded += organizationLen; if (str && *pcchStr >= charsNeeded) { memcpy(str, organization, organizationLen * sizeof(WCHAR)); str += organizationLen; } charsNeeded += strlen(pNoticeRef->pszOrganization); if (str && *pcchStr >= charsNeeded) for (src = pNoticeRef->pszOrganization; src && *src; src++, str++) *str = *src; charsNeeded += sepLen; if (str && *pcchStr >= charsNeeded) { strcpyW(str, sep); str += sepLen; } for (k = 0; k < pNoticeRef->cNoticeNumbers; k++) { if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { charsNeeded += 4 * strlenW(indent); if (str && *pcchStr >= charsNeeded) { strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); } } charsNeeded += noticeNumLen; if (str && *pcchStr >= charsNeeded) { memcpy(str, noticeNum, noticeNumLen * sizeof(WCHAR)); str += noticeNumLen; } sprintfW(noticeNumStr, numFmt, k + 1); charsNeeded += strlenW(noticeNumStr); if (str && *pcchStr >= charsNeeded) { strcpyW(str, noticeNumStr); str += strlenW(noticeNumStr); } charsNeeded += sepLen; if (str && *pcchStr >= charsNeeded) { strcpyW(str, sep); str += sepLen; } } } if (notice->pszDisplayText) { if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { charsNeeded += 3 * strlenW(indent); if (str && *pcchStr >= charsNeeded) { strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); } } charsNeeded += noticeTextLen; if (str && *pcchStr >= charsNeeded) { memcpy(str, noticeText, noticeTextLen * sizeof(WCHAR)); str += noticeTextLen; } charsNeeded += strlenW(notice->pszDisplayText); if (str && *pcchStr >= charsNeeded) { strcpyW(str, notice->pszDisplayText); str += strlenW(notice->pszDisplayText); } charsNeeded += sepLen; if (str && *pcchStr >= charsNeeded) { strcpyW(str, sep); str += sepLen; } } LocalFree(notice); if (!str) *pcchStr = charsNeeded; else if (*pcchStr < charsNeeded) { *pcchStr = charsNeeded; SetLastError(ERROR_MORE_DATA); ret = FALSE; } else *pcchStr = charsNeeded; } return ret; }
/*********************************************************************** * FormatVerisignExtension (CRYPTDLG.@) */ BOOL WINAPI FormatVerisignExtension(DWORD dwCertEncodingType, DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat) { CERT_POLICIES_INFO *policies; DWORD size; BOOL ret = FALSE; if (!cbEncoded) { SetLastError(E_INVALIDARG); return FALSE; } if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_POLICIES, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &policies, &size))) { static const WCHAR numFmt[] = { '%','d',0 }; DWORD charsNeeded = 1; /* space for NULL terminator */ LPCWSTR headingSep, sep; DWORD headingSepLen, sepLen; WCHAR policyNum[11], policyQualifierNum[11]; LPWSTR certPolicy, policyId, policyQualifierInfo, policyQualifierId; LPWSTR cps, userNotice, qualifier; DWORD certPolicyLen, policyIdLen, policyQualifierInfoLen; DWORD policyQualifierIdLen, cpsLen, userNoticeLen, qualifierLen; DWORD i; LPWSTR str = pbFormat; certPolicyLen = LoadStringW(hInstance, IDS_CERT_POLICY, (LPWSTR)&certPolicy, 0); policyIdLen = LoadStringW(hInstance, IDS_POLICY_ID, (LPWSTR)&policyId, 0); policyQualifierInfoLen = LoadStringW(hInstance, IDS_POLICY_QUALIFIER_INFO, (LPWSTR)&policyQualifierInfo, 0); policyQualifierIdLen = LoadStringW(hInstance, IDS_POLICY_QUALIFIER_ID, (LPWSTR)&policyQualifierId, 0); cpsLen = LoadStringW(hInstance, IDS_CPS, (LPWSTR)&cps, 0); userNoticeLen = LoadStringW(hInstance, IDS_USER_NOTICE, (LPWSTR)&userNotice, 0); qualifierLen = LoadStringW(hInstance, IDS_QUALIFIER, (LPWSTR)&qualifier, 0); if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { headingSep = colonCrlf; sep = crlf; } else { headingSep = colonSpace; sep = commaSep; } sepLen = strlenW(sep); headingSepLen = strlenW(headingSep); for (i = 0; ret && i < policies->cPolicyInfo; i++) { CERT_POLICY_INFO *policy = &policies->rgPolicyInfo[i]; DWORD j; LPCSTR src; charsNeeded += 1; /* '['*/ if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) *str++ = '['; sprintfW(policyNum, numFmt, i + 1); charsNeeded += strlenW(policyNum); if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, policyNum); str += strlenW(policyNum); } charsNeeded += 1; /* ']'*/ if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) *str++ = ']'; charsNeeded += certPolicyLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { memcpy(str, certPolicy, certPolicyLen * sizeof(WCHAR)); str += certPolicyLen; } charsNeeded += headingSepLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, headingSep); str += headingSepLen; } if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { charsNeeded += strlenW(indent); if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, indent); str += strlenW(indent); } } charsNeeded += policyIdLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { memcpy(str, policyId, policyIdLen * sizeof(WCHAR)); str += policyIdLen; } charsNeeded += strlen(policy->pszPolicyIdentifier); if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { for (src = policy->pszPolicyIdentifier; src && *src; src++, str++) *str = *src; } charsNeeded += sepLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, sep); str += sepLen; } for (j = 0; j < policy->cPolicyQualifier; j++) { CERT_POLICY_QUALIFIER_INFO *qualifierInfo = &policy->rgPolicyQualifier[j]; DWORD sizeRemaining; if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { charsNeeded += strlenW(indent); if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, indent); str += strlenW(indent); } } charsNeeded += 1; /* '['*/ if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) *str++ = '['; charsNeeded += strlenW(policyNum); if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, policyNum); str += strlenW(policyNum); } charsNeeded += 1; /* ','*/ if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) *str++ = ','; sprintfW(policyQualifierNum, numFmt, j + 1); charsNeeded += strlenW(policyQualifierNum); if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, policyQualifierNum); str += strlenW(policyQualifierNum); } charsNeeded += 1; /* ']'*/ if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) *str++ = ']'; charsNeeded += policyQualifierInfoLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { memcpy(str, policyQualifierInfo, policyQualifierInfoLen * sizeof(WCHAR)); str += policyQualifierInfoLen; } charsNeeded += headingSepLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, headingSep); str += headingSepLen; } if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { charsNeeded += 2 * strlenW(indent); if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); } } charsNeeded += policyQualifierIdLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { memcpy(str, policyQualifierId, policyQualifierIdLen * sizeof(WCHAR)); str += policyQualifierIdLen; } if (!strcmp(qualifierInfo->pszPolicyQualifierId, szOID_PKIX_POLICY_QUALIFIER_CPS)) { charsNeeded += cpsLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { memcpy(str, cps, cpsLen * sizeof(WCHAR)); str += cpsLen; } } else if (!strcmp(qualifierInfo->pszPolicyQualifierId, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE)) { charsNeeded += userNoticeLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { memcpy(str, userNotice, userNoticeLen * sizeof(WCHAR)); str += userNoticeLen; } } else { charsNeeded += strlen(qualifierInfo->pszPolicyQualifierId); if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { for (src = qualifierInfo->pszPolicyQualifierId; src && *src; src++, str++) *str = *src; } } charsNeeded += sepLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, sep); str += sepLen; } if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) { charsNeeded += 2 * strlenW(indent); if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, indent); str += strlenW(indent); strcpyW(str, indent); str += strlenW(indent); } } charsNeeded += qualifierLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { memcpy(str, qualifier, qualifierLen * sizeof(WCHAR)); str += qualifierLen; } charsNeeded += headingSepLen; if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) { strcpyW(str, headingSep); str += headingSepLen; } /* This if block is deliberately redundant with the same if * block above, in order to keep the code more readable (the * code flow follows the order in which the strings are output.) */ if (!strcmp(qualifierInfo->pszPolicyQualifierId, szOID_PKIX_POLICY_QUALIFIER_CPS)) { if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR)) { /* Insufficient space, determine how much is needed. */ ret = CRYPT_FormatCPS(dwCertEncodingType, dwFormatStrType, qualifierInfo->Qualifier.pbData, qualifierInfo->Qualifier.cbData, NULL, &size); if (ret) charsNeeded += size - 1; } else { sizeRemaining = *pcbFormat / sizeof(WCHAR); sizeRemaining -= str - (LPWSTR)pbFormat; ret = CRYPT_FormatCPS(dwCertEncodingType, dwFormatStrType, qualifierInfo->Qualifier.pbData, qualifierInfo->Qualifier.cbData, str, &sizeRemaining); if (ret || GetLastError() == ERROR_MORE_DATA) { charsNeeded += sizeRemaining - 1; str += sizeRemaining - 1; } } } else if (!strcmp(qualifierInfo->pszPolicyQualifierId, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE)) { if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR)) { /* Insufficient space, determine how much is needed. */ ret = CRYPT_FormatUserNotice(dwCertEncodingType, dwFormatStrType, qualifierInfo->Qualifier.pbData, qualifierInfo->Qualifier.cbData, NULL, &size); if (ret) charsNeeded += size - 1; } else { sizeRemaining = *pcbFormat / sizeof(WCHAR); sizeRemaining -= str - (LPWSTR)pbFormat; ret = CRYPT_FormatUserNotice(dwCertEncodingType, dwFormatStrType, qualifierInfo->Qualifier.pbData, qualifierInfo->Qualifier.cbData, str, &sizeRemaining); if (ret || GetLastError() == ERROR_MORE_DATA) { charsNeeded += sizeRemaining - 1; str += sizeRemaining - 1; } } } else { if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR)) { /* Insufficient space, determine how much is needed. */ ret = CRYPT_FormatHexString( qualifierInfo->Qualifier.pbData, qualifierInfo->Qualifier.cbData, NULL, &size); if (ret) charsNeeded += size - 1; } else { sizeRemaining = *pcbFormat / sizeof(WCHAR); sizeRemaining -= str - (LPWSTR)pbFormat; ret = CRYPT_FormatHexString( qualifierInfo->Qualifier.pbData, qualifierInfo->Qualifier.cbData, str, &sizeRemaining); if (ret || GetLastError() == ERROR_MORE_DATA) { charsNeeded += sizeRemaining - 1; str += sizeRemaining - 1; } } } } } LocalFree(policies); if (ret) { if (!pbFormat) *pcbFormat = charsNeeded * sizeof(WCHAR); else if (*pcbFormat < charsNeeded * sizeof(WCHAR)) { *pcbFormat = charsNeeded * sizeof(WCHAR); SetLastError(ERROR_MORE_DATA); ret = FALSE; } else *pcbFormat = charsNeeded * sizeof(WCHAR); } } return ret; }
PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded) { PCTL_CONTEXT ctl = NULL; HCRYPTMSG msg; BOOL ret; BYTE *content = NULL; DWORD contentSize = 0, size; PCTL_INFO ctlInfo = NULL; TRACE("(%08x, %p, %d)\n", dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded); if (GET_CERT_ENCODING_TYPE(dwMsgAndCertEncodingType) != X509_ASN_ENCODING) { SetLastError(E_INVALIDARG); return NULL; } if (!pbCtlEncoded || !cbCtlEncoded) { SetLastError(ERROR_INVALID_DATA); return NULL; } msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, 0, NULL, NULL); if (!msg) return NULL; ret = CryptMsgUpdate(msg, pbCtlEncoded, cbCtlEncoded, TRUE); if (!ret) { SetLastError(ERROR_INVALID_DATA); goto end; } /* Check that it's really a CTL */ ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL, &size); if (ret) { char *innerContent = CryptMemAlloc(size); if (innerContent) { ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, innerContent, &size); if (ret) { if (strcmp(innerContent, szOID_CTL)) { SetLastError(ERROR_INVALID_DATA); ret = FALSE; } } CryptMemFree(innerContent); } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } if (!ret) goto end; ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &contentSize); if (!ret) goto end; content = CryptMemAlloc(contentSize); if (content) { ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, content, &contentSize); if (ret) { ret = CryptDecodeObjectEx(dwMsgAndCertEncodingType, PKCS_CTL, content, contentSize, CRYPT_DECODE_ALLOC_FLAG, NULL, &ctlInfo, &size); if (ret) { ctl = Context_CreateDataContext(sizeof(CTL_CONTEXT)); if (ctl) { BYTE *data = CryptMemAlloc(cbCtlEncoded); if (data) { memcpy(data, pbCtlEncoded, cbCtlEncoded); ctl->dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; ctl->pbCtlEncoded = data; ctl->cbCtlEncoded = cbCtlEncoded; ctl->pCtlInfo = ctlInfo; ctl->hCertStore = NULL; ctl->hCryptMsg = msg; ctl->pbCtlContext = content; ctl->cbCtlContext = contentSize; } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } } } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } end: if (!ret) { CryptMemFree(ctl); ctl = NULL; LocalFree(ctlInfo); CryptMemFree(content); CryptMsgClose(msg); } return ctl; }