/** * Obtains the public key for the passed in cert data * * @param provider The crypto provider * @param certData Data of the certificate to extract the public key from * @param sizeOfCertData The size of the certData buffer * @param certStore Pointer to the handle of the certificate store to use * @param CryptoX_Success on success */ CryptoX_Result CryptoAPI_LoadPublicKey(HCRYPTPROV provider, BYTE *certData, DWORD sizeOfCertData, HCRYPTKEY *publicKey) { CRYPT_DATA_BLOB blob; CERT_CONTEXT *context; if (!provider || !certData || !publicKey) { return CryptoX_Error; } blob.cbData = sizeOfCertData; blob.pbData = certData; if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_CERT, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, NULL, NULL, (const void **)&context)) { return CryptoX_Error; } if (!CryptImportPublicKeyInfo(provider, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, &context->pCertInfo->SubjectPublicKeyInfo, publicKey)) { CertFreeCertificateContext(context); return CryptoX_Error; } CertFreeCertificateContext(context); return CryptoX_Success; }
/** * * 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; }
struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, size_t len) { struct crypto_public_key *pk; PCCERT_CONTEXT cc; pk = os_zalloc(sizeof(*pk)); if (pk == NULL) return NULL; cc = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, buf, len); if (!cc) { cryptoapi_report_error("CryptCreateCertificateContext"); os_free(pk); return NULL; } if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0)) { cryptoapi_report_error("CryptAcquireContext"); os_free(pk); CertFreeCertificateContext(cc); return NULL; } if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &cc->pCertInfo->SubjectPublicKeyInfo, &pk->rsa)) { cryptoapi_report_error("CryptImportPublicKeyInfo"); CryptReleaseContext(pk->prov, 0); os_free(pk); CertFreeCertificateContext(cc); return NULL; } CertFreeCertificateContext(cc); return pk; }
// Get functions XSECCryptoKey * WinCAPICryptoX509::clonePublicKey() const { if (mp_certContext == NULL) { throw XSECCryptoException(XSECCryptoException::X509Error, "WinCAPI:X509 - clonePublicKey called before X509 loaded"); } // Import the key into the provider to get a pointer to the key HCRYPTKEY key; BOOL fResult; if (getPublicKeyType() == XSECCryptoKey::KEY_DSA_PUBLIC) { fResult= CryptImportPublicKeyInfo( m_pDSS, X509_ASN_ENCODING, &(mp_certContext->pCertInfo->SubjectPublicKeyInfo), &key); if (fResult == FALSE) { throw XSECCryptoException(XSECCryptoException::X509Error, "WinCAPI:X509 - Error loading public key info from certificate"); } // Now that we have a handle for the DSA key, create a DSA Key object to // wrap it in WinCAPICryptoKeyDSA * ret; XSECnew(ret, WinCAPICryptoKeyDSA(m_pDSS, key)); return ret; } if (getPublicKeyType() == XSECCryptoKey::KEY_RSA_PUBLIC) { fResult= CryptImportPublicKeyInfo( m_pRSA, X509_ASN_ENCODING, &(mp_certContext->pCertInfo->SubjectPublicKeyInfo), &key); if (fResult == FALSE) { throw XSECCryptoException(XSECCryptoException::X509Error, "WinCAPI:X509 - Error loading public key info from certificate"); } // Now that we have a handle for the DSA key, create a DSA Key object to // wrap it in WinCAPICryptoKeyRSA * ret; XSECnew(ret, WinCAPICryptoKeyRSA(m_pRSA, key)); return ret; } return NULL; // Unknown key type, but not necessarily an error }
BOOL AcquireAndGetRSAKey(PCCERT_CONTEXT pCertContext, HCRYPTPROV *phProv, HCRYPTKEY *phRSAKey, BOOL fEncrypt, BOOL *pfCallerFreeProv) { BOOL fSuccess = FALSE; DWORD dwKeySpec = 0; __try { *phProv = NULL; *phRSAKey = NULL; *pfCallerFreeProv = FALSE; if (fEncrypt) { // Acquire context for RSA key fSuccess = CryptAcquireContext(phProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!fSuccess) { MyPrintf(_T("CryptAcquireContext failed with %X\n"), GetLastError()); __leave; } // Import the RSA public key from the certificate context fSuccess = CryptImportPublicKeyInfo(*phProv, MY_ENCODING, &(pCertContext->pCertInfo->SubjectPublicKeyInfo), phRSAKey); if (!fSuccess) { MyPrintf(_T("CryptImportPublicKeyInfo failed with %X\n"), GetLastError()); __leave; } *pfCallerFreeProv = TRUE; } else { // Acquire the RSA private key fSuccess = CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_USE_PROV_INFO_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, phProv, &dwKeySpec, pfCallerFreeProv); if (!fSuccess) { MyPrintf(_T("CryptAcquireCertificatePrivateKey failed with %X\n"), GetLastError()); __leave; } // Get the RSA key handle fSuccess = CryptGetUserKey(*phProv, dwKeySpec, phRSAKey); if (!fSuccess) { MyPrintf(_T("CryptGetUserKey failed with %X\n"), GetLastError()); __leave; } } } __finally { if (fSuccess == FALSE) { if (phProv && *phProv != NULL) { CryptReleaseContext(*phProv, 0); *phProv = NULL; } if (phRSAKey && *phRSAKey != NULL) { CryptDestroyKey(*phRSAKey); *phRSAKey = NULL; } } } return fSuccess; }
int KSI_PKITruststore_verifyRawSignature(KSI_CTX *ctx, const unsigned char *data, unsigned data_len, const char *algoOid, const unsigned char *signature, unsigned signature_len, const KSI_PKICertificate *certificate) { int res = KSI_UNKNOWN_ERROR; ALG_ID algorithm=0; HCRYPTPROV hCryptProv = 0; PCCERT_CONTEXT subjectCert = NULL; HCRYPTKEY publicKey = 0; DWORD i=0; BYTE *little_endian_pkcs1= NULL; DWORD pkcs1_len = 0; HCRYPTHASH hash = 0; char buf[1024]; KSI_ERR_clearErrors(ctx); if (ctx == NULL || data == NULL || signature == NULL || signature_len >= UINT_MAX || algoOid == NULL || certificate == NULL){ res = KSI_INVALID_ARGUMENT; goto cleanup; } algorithm = algIdFromOID(algoOid); if (algorithm == 0) { KSI_pushError(ctx, res = KSI_UNAVAILABLE_HASH_ALGORITHM, NULL); goto cleanup; } // Get the CSP context if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get cryptographic provider."); goto cleanup; } // Get the public key from the issuer certificate subjectCert = certificate->x509; if (!CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,&subjectCert->pCertInfo->SubjectPublicKeyInfo,&publicKey)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, "Failed to read PKI public key."); goto cleanup; } /*Convert big-endian to little-endian PKCS#1 signature*/ pkcs1_len = signature_len; little_endian_pkcs1 = (BYTE*)KSI_malloc(pkcs1_len); if (little_endian_pkcs1 == NULL){ KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } for (i=0; i<pkcs1_len; i++){ little_endian_pkcs1[pkcs1_len-1-i] = signature[i]; } // Create the hash object and hash input data. if (!CryptCreateHash(hCryptProv, algorithm, 0, 0, &hash)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to create hasher."); goto cleanup; } if (!CryptHashData(hash, (BYTE*)data, data_len,0)){ KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to hash data."); goto cleanup; } /*Verify the signature. The format MUST be PKCS#1*/ if (!CryptVerifySignature(hash, (BYTE*)little_endian_pkcs1, pkcs1_len, publicKey, NULL, 0)){ DWORD error = GetLastError(); const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf)); KSI_LOG_debug(ctx, "%s", errmsg); if (error == NTE_BAD_SIGNATURE) KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, "Invalid PKI signature."); else if (error == NTE_NO_MEMORY) KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, "Unable to verify PKI signature. CSP out of memory."); else KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, errmsg); goto cleanup; } KSI_LOG_debug(certificate->ctx, "CryptoAPI: PKI signature verified successfully."); res = KSI_OK; cleanup: KSI_free(little_endian_pkcs1); if (hCryptProv) CryptReleaseContext(hCryptProv, 0); if (hash) CryptDestroyHash(hash); return res; }
int VerifyDataSignWithHashAlg(const char * userData, const char * hashAlg, const char * certDataB64, const char * signatureDataB64) { int rv = -1; int ulHashAlg = 0; HCRYPTHASH hHash = NULL; char * pbCert = NULL; char * pbSignature = NULL; unsigned int ulCert = 0; unsigned int ulSignature = 0; PCCERT_CONTEXT pCertContext = NULL; HCRYPTPROV hProv = NULL; HCRYPTKEY hPubKey = NULL; { ulCert = modp_b64_decode_len(strlen(certDataB64)); ulSignature = modp_b64_decode_len(strlen(signatureDataB64)); pbCert = (char *)malloc(ulCert); pbSignature = (char *) malloc(ulSignature); if (NULL == pbCert || NULL == pbSignature) { sprintf(m_errMsg, "%s","memroy less.\n" ); goto err; } ulCert = modp_b64_decode(pbCert, certDataB64,strlen(certDataB64)); ulSignature = modp_b64_decode(pbSignature, signatureDataB64,strlen(signatureDataB64)); } if (0 == strcmp(hashAlg, "MD5")) { ulHashAlg = CALG_MD5; } else if (0 == strcmp(hashAlg, "SHA")) { ulHashAlg = CALG_SHA; } else if (0 == strcmp(hashAlg, "SHA1")) { ulHashAlg = CALG_SHA1; } else if (0 == strcmp(hashAlg, "SHA_256")) { ulHashAlg = CALG_SHA_256; } else if (0 == strcmp(hashAlg, "SHA_384")) { ulHashAlg = CALG_SHA_384; } pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (BYTE *)pbCert,ulCert); if (!pCertContext) { sprintf(m_errMsg, "%s","Select Certificate UI failed.\n" ); goto err; } //Ò»¡¢»ñµÃÒ»¸öCSP¾ä±ú if(!CryptAcquireContext( &hProv, NULL, //ÃÜÔ¿ÈÝÆ÷Ãû£¬NULL±íʾʹÓÃĬÈÏÈÝÆ÷ NULL, //CSP_NAME PROV_RSA_FULL, 0 )) { if(!CryptAcquireContext( &hProv, NULL, //ÃÜÔ¿ÈÝÆ÷Ãû£¬NULL±íʾʹÓÃĬÈÏÈÝÆ÷ NULL, //CSP_NAME PROV_RSA_FULL, CRYPT_NEWKEYSET //´´½¨ÃÜÔ¿ÈÝÆ÷ )) { sprintf(m_errMsg, "%s","CryptAcquireContext fail.\n"); goto err; } } if(CryptImportPublicKeyInfo( hProv, X509_ASN_ENCODING, &(pCertContext->pCertInfo->SubjectPublicKeyInfo), &hPubKey )) { sprintf(m_errMsg,"CryptImportPublicKeyInfo OK. \n"); } else { sprintf(m_errMsg,"Error CryptImportPublicKeyInfo.\n"); goto err; } //if(CryptImportKey(hProv,pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData, pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData, NULL, 0, &hPubKey)) //{ // sprintf(m_errMsg,"CryptImportKey OK. \n"); //} //else //{ // sprintf(m_errMsg,"Error CryptImportKey.\n"); // goto err; //} if(CryptCreateHash( hProv, ulHashAlg, 0, 0, &hHash)) { sprintf(m_errMsg, "%s","An empty hash object has been created. \n"); } else { sprintf(m_errMsg, "%s","Error during CryptBeginHash!\n"); goto err; } //-------------------------------------------------------------------- // This code assumes that the handle of a cryptographic context // has been acquired and that a hash object has been created // and its handle (hHash) is available. if(CryptHashData( hHash, (unsigned char *)userData, strlen(userData), 0)) { sprintf(m_errMsg, "%s","The data buffer has been added to the hash.\n"); } else { sprintf(m_errMsg, "%s","Error during CryptHashData.\n"); goto err; } if(CryptVerifySignature(hHash, (const BYTE *)pbSignature, ulSignature,hPubKey,NULL,0)) { sprintf(m_errMsg,"verify OK.\n"); } else { sprintf(m_errMsg,"Error during CryptVerifySignature.\n"); goto err; } rv = 0; err: if(hHash) { CryptDestroyHash(hHash); } if (pbSignature) { free(pbSignature); } if (pbCert) { free(pbCert); } if (pCertContext) { CertFreeCertificateContext(pCertContext); } if(hProv) { CryptReleaseContext(hProv,0); } return rv; }
BOOL GetRSAKeyFromCert(PCCERT_CONTEXT pCertContext, BOOL fSign, HCRYPTPROV *hProv, HCRYPTKEY *hPubKey, DWORD *dwKeySpec, BOOL *fFreeProv) { BOOL fResult; BOOL fReturn = FALSE; __try { if (hProv == NULL || hPubKey == NULL || dwKeySpec == NULL || fFreeProv == NULL) { __leave; } *hProv = 0; *hPubKey = 0; *fFreeProv = FALSE; if (fSign) { // Acquire the certificate's private key fResult = CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_USE_PROV_INFO_FLAG| CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, hProv, dwKeySpec, fFreeProv); if (!fResult) { MyPrintf(_T("CryptAcquireCertificatePrivateKey failed with %x\n"), GetLastError()); __leave; } } else { fResult = CryptAcquireContext(hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!fResult) { MyPrintf(_T("CryptAcquireContext failed with %x\n"), GetLastError()); __leave; } *fFreeProv = TRUE; // Import the public key from the certificate so we can verify fResult = CryptImportPublicKeyInfo(*hProv, ENCODING, &(pCertContext->pCertInfo->SubjectPublicKeyInfo), hPubKey); if (!fResult) { MyPrintf(_T("CryptImportPublicKeyInfo failed with %x\n"), GetLastError()); __leave; } } fReturn = TRUE; } __finally { if (!fReturn) { if (*hPubKey != NULL) { CryptDestroyKey(*hPubKey); *hPubKey = NULL; } if ((*fFreeProv == TRUE) && (*hProv != NULL)) { CryptReleaseContext(*hProv, 0); *hProv = NULL; *fFreeProv = FALSE; } } } return fReturn; }