/* * SfcValidateFileHeader * * Purpose: * * Verify fileheader from retL packet. * */ BOOL SfcValidateFileHeader( HCRYPTPROV hCryptoProv, HCRYPTKEY hCryptKey, ZA_FILEHEADER *FileHeader ) { BOOL bResult, cond = FALSE; HCRYPTHASH hCryptHash = 0; MD5_CTX ctx; bResult = FALSE; do { if (!CryptCreateHash(hCryptoProv, CALG_MD5, 0, 0, &hCryptHash)) break; MD5Init(&ctx); MD5Update(&ctx, (UCHAR*)FileHeader, (UINT)3 * sizeof(ULONG)); MD5Final(&ctx); if (!CryptSetHashParam(hCryptHash, HP_HASHVAL, (const BYTE *)&ctx.digest, 0)) break; bResult = CryptVerifySignatureW(hCryptHash, (const BYTE *)&FileHeader->Signature, sizeof(FileHeader->Signature), hCryptKey, 0, 0); } while (cond); if (hCryptHash != 0) { CryptDestroyHash(hCryptHash); } return bResult; }
BOOL kull_m_crypto_hmac(DWORD calgid, LPCVOID key, DWORD keyLen, LPCVOID message, DWORD messageLen, LPVOID hash, DWORD hashWanted) // for keyLen > 1 { BOOL status = FALSE; DWORD hashLen; HCRYPTPROV hProv; HCRYPTKEY hKey; HCRYPTHASH hHash; HMAC_INFO HmacInfo = {calgid, NULL, 0, NULL, 0}; PBYTE buffer; if(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { if(kull_m_crypto_hkey(hProv, CALG_RC2, key, keyLen, CRYPT_IPSEC_HMAC_KEY, &hKey, NULL)) { if(CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHash)) { if(CryptSetHashParam(hHash, HP_HMAC_INFO, (LPCBYTE) &HmacInfo, 0)) if(CryptHashData(hHash, (LPCBYTE) message, messageLen, 0)) if(CryptGetHashParam(hHash, HP_HASHVAL, NULL, &hashLen, 0)) { if(buffer = (PBYTE) LocalAlloc(LPTR, hashLen)) { status = CryptGetHashParam(hHash, HP_HASHVAL, buffer, &hashLen, 0); RtlCopyMemory(hash, buffer, KIWI_MINIMUM(hashLen, hashWanted)); LocalFree(buffer); } } CryptDestroyHash(hHash); } CryptDestroyKey(hKey); } CryptReleaseContext(hProv, 0); } return status; }
static int HCSP_setHashContext(void) { int result = TRUE; #ifdef DEBUG BIO_printf(err, "Call HCSP_setHashContext()\n"); #endif /* Create a hash object. */ if (!CryptCreateHash(hCryptProvider, Algid, 0, 0, &hHash)) { # ifdef DEBUG routine = "CryptCreateHash"; # endif goto error; } /* Set data to hash object. */ if (!CryptSetHashParam(hHash, HP_HASHVAL, pbBuffer, 0)) { # ifdef DEBUG routine = "CryptSetHashParam"; # endif goto error; } /* Determine size of signature. */ if (!CryptSignHash(hHash, dwKeySpec, NULL, 0, NULL, &dwSignatureLen)) { # ifdef DEBUG routine = "CryptSignHash"; # endif goto error; } #ifdef DEBUG BIO_printf(err, "size of signature %d\n", dwSignatureLen); #endif goto end; error: result = FALSE; end: #ifdef DEBUG BIO_printf(err, "Return HCSP_setHashContext(%d)\n", result); #endif return result; }
bool testVerifyHash(bool bVerbose){ BYTE bSignature[64]; strtobyte( "41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC049301456C64BA4642A1653C235A98A60249BCD6D3F746B631DF928014F6C5BF9C40" , bSignature ); DWORD dwSigLen = 64; HCRYPTHASH hHash; HCRYPTKEY hPub; BYTE bHashVal[32+1] = "\x2D\xFB\xC1\xB3\x72\xD8\x9A\x11\x88\xC0\x9C\x52\xE0\xEE\xC6\x1F\xCE\x52\x03\x2A\xB1\x02\x2E\x8E\x67\xEC\xE6\x67\x2B\x04\x3E\xE5"; if ( bVerbose ) std::cout << "Supplied hash value is: \n" << bHashVal << std::endl; if (!(CryptCreateHash(hProv, CALG_GOST_HASH, 0, 0, &hHash))) { if ( bVerbose ) printf("CryptCreateHash Failed\n"); return false; } if ( !CryptSetHashParam( hHash, HP_HASHVAL, bHashVal, 0)) { if ( bVerbose ) printf("CryptSetHashParam Failed\n"); return false; } if ( !CryptGetUserKey( hProv, AT_SIGNATURE, &hPub )) { if ( bVerbose ) printf("CryptGetUserKey Failed\n"); return false; } if (!CryptVerifySignature(hHash, bSignature, dwSigLen, hPub, NULL, 0)) { if ( bVerbose ) printf("Test Failed\n"); return false; } return true; }
/* * SfcVerifyFile * * Purpose: * * Verify file to be legit ZeroAccess signed binary. * */ BOOL SfcVerifyFile( _In_ HCRYPTPROV hProv, _In_ HCRYPTKEY hKey, _In_ MD5_CTX *ctx, _In_ PBYTE Image, _In_ DWORD ImageSize ) { HCRYPTHASH lh_hash = 0; ULONG CRC, SignSize = 0; BYTE e_sign[128]; PBYTE p_resource_sign; PIMAGE_NT_HEADERS32 phdr; BOOL bResult = FALSE; LDR_RESOURCE_INFO resInfo; phdr = (PIMAGE_NT_HEADERS32)RtlImageNtHeader(Image); while (phdr != NULL) { resInfo.Type = (ULONG_PTR)RT_RCDATA; //type resInfo.Name = 1; //id resInfo.Lang = 0; //lang p_resource_sign = SfLdrQueryResourceDataEx(Image, &resInfo, &SignSize); if (p_resource_sign == NULL) break; if (SignSize != 128) break; if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &lh_hash)) break; CRC = phdr->OptionalHeader.CheckSum; memcpy(e_sign, p_resource_sign, sizeof(e_sign)); memset(p_resource_sign, 0, sizeof(e_sign)); phdr->OptionalHeader.CheckSum = 0; MD5Update(ctx, Image, ImageSize); phdr->OptionalHeader.CheckSum = CRC; memcpy(p_resource_sign, e_sign, sizeof(e_sign)); MD5Final(ctx); if (!CryptSetHashParam(lh_hash, HP_HASHVAL, (const BYTE *)&ctx->digest, 0)) { CryptDestroyHash(lh_hash); break; } bResult = CryptVerifySignatureW(lh_hash, (const BYTE *)&e_sign, sizeof(e_sign), hKey, 0, 0); CryptDestroyHash(lh_hash); break; } return bResult; }
JNIEXPORT void JNICALL Java_org_company_security_csp_NativeCrypto_digestSetParameter( JNIEnv *env, jclass clazz, jlong hCryptHash, jint param, jbyteArray jBytes, jint offset, jint len) { if(hCryptHash) { jbyte *buffer = (jbyte*) malloc(len * sizeof(jbyte)); (*env)->GetByteArrayRegion(env, jBytes, offset, len, buffer); if(!CryptSetHashParam((HCRYPTHASH) hCryptHash, (DWORD) param, (BYTE*) buffer, 0)) { ThrowException(env, DIGEST_EXCEPTION, GetLastError()); } free(buffer); } }
//move to zacrypto.c //@@implemented in harusame VOID SfcZAVerifyFile( HCRYPTPROV hProv, HCRYPTKEY hKey, MD5_CTX *ctx, PBYTE Image, DWORD ImageSize ) { HCRYPTHASH lh_hash = 0; ULONG CRC, SignSize = 0; BYTE e_sign[128]; PBYTE p_resource_sign; PIMAGE_NT_HEADERS32 phdr; phdr = (PIMAGE_NT_HEADERS32)RtlImageNtHeader(Image); while (phdr != NULL) { p_resource_sign = SfuQueryResourceData(3, Image, &SignSize); if (p_resource_sign == NULL) break; if (SignSize != 128) break; if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &lh_hash)) break; CRC = phdr->OptionalHeader.CheckSum; memcpy(e_sign, p_resource_sign, sizeof(e_sign)); memset(p_resource_sign, 0, sizeof(e_sign)); phdr->OptionalHeader.CheckSum = 0; MD5Update(ctx, Image, ImageSize); phdr->OptionalHeader.CheckSum = CRC; memcpy(p_resource_sign, e_sign, sizeof(e_sign)); MD5Final(ctx); if (!CryptSetHashParam(lh_hash, HP_HASHVAL, (const BYTE *)&ctx->digest, 0)) { CryptDestroyHash(lh_hash); break; } CryptVerifySignatureW(lh_hash, (const BYTE *)&e_sign, sizeof(e_sign), hKey, 0, 0); break; } }
/////////////////////////////////////////////////////////////////////////////////////// // Function: SignHashString // Description: hash string signing ///////////////////////////////////////////////////////////////////////////////////////// BOOL SignHashString( ///////////////////////////////////////////////////////////////////////////////////////// HCRYPTPROV hProv, HCRYPTKEY hPubKey, DWORD dwKeySpec, LPBYTE pbHash, LPBYTE pbSignature, DWORD *dwSignature) { HCRYPTHASH hHash = NULL; BOOL fResult; BOOL fReturn = FALSE; __try { // Create Hash fResult = CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash); if (!fResult) __leave; // Set Hash fResult=CryptSetHashParam(hHash,HP_HASHVAL,pbHash,0); fResult = CryptSignHash(hHash, dwKeySpec, NULL, 0, pbSignature, dwSignature); if (!fResult) __leave; fReturn = TRUE; } __finally { if (hHash != NULL) CryptDestroyHash(hHash); } return fReturn; }
void checkSig(unsigned char *tucHashBuf, unsigned char *tucSignature, DWORD dwSignatureLen, unsigned char *tucPubKeyBlob, DWORD dwPubKeyBlobLen) { HCRYPTPROV hProv; HCRYPTKEY hPubKey; HCRYPTHASH hHash; DWORD err; int errors = 0; if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) ERR_LOG_RET("CryptAcquireContext()"); if (!CryptImportKey(hProv, tucPubKeyBlob, dwPubKeyBlobLen, 0, 0, &hPubKey)) ERR_LOG_RET("CryptImportKey()"); if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) ERR_LOG_RET("CryptCreateHash(CALG_MD5)"); if (!CryptSetHashParam(hHash, HP_HASHVAL, tucHashBuf, 0)) ERR_LOG_RET("CryptSetHashParam(HP_HASHVAL)"); if (!CryptVerifySignature(hHash, tucSignature, dwSignatureLen, hPubKey, NULL, 0)) { err = GetLastError(); printf("ERR (line %d): CryptVerifySignature() returned %s (0x%0x)\n", __LINE__, e2str(err), err); errors++; } if (!CryptDestroyHash(hHash)) ERR_LOG_RET("CryptDestroyHash()"); if (!CryptDestroyKey(hPubKey)) ERR_LOG_RET("CryptDestroyKey()"); CryptReleaseContext(hProv, 0); done: return; }
QByteArray QCSP::sign( int method, const QByteArray &digest ) { ALG_ID alg = 0; switch( method ) { case NID_sha1: alg = CALG_SHA1; break; case NID_sha256: alg = CALG_SHA_256; break; case NID_sha384: alg = CALG_SHA_384; break; case NID_sha512: alg = CALG_SHA_512; break; case NID_sha224: default: return QByteArray(); } HCRYPTHASH hash = 0; if( !CryptCreateHash( d->h, alg, 0, 0, &hash ) ) return QByteArray(); if( !CryptSetHashParam( hash, HP_HASHVAL, (BYTE*)digest.constData(), 0 ) ) { CryptDestroyHash( hash ); return QByteArray(); } DWORD size = 256; QByteArray sig; sig.resize( size ); if( !CryptSignHashW( hash, AT_SIGNATURE, 0, 0, (BYTE*)sig.data(), &size ) ) sig.clear(); CryptDestroyHash( hash ); QByteArray reverse; for( QByteArray::const_iterator i = sig.constEnd(); i != sig.constBegin(); ) { --i; reverse += *i; } return reverse; }
QByteArray QCSP::sign( int method, const QByteArray &digest ) { ALG_ID alg = 0; switch( method ) { case NID_sha1: alg = CALG_SHA1; break; case NID_sha256: alg = CALG_SHA_256; break; case NID_sha384: alg = CALG_SHA_384; break; case NID_sha512: alg = CALG_SHA_512; break; case NID_sha224: default: return QByteArray(); } HCRYPTHASH hash = 0; if( !CryptCreateHash( d->h, alg, 0, 0, &hash ) ) return QByteArray(); if( !CryptSetHashParam( hash, HP_HASHVAL, LPBYTE(digest.constData()), 0 ) ) { CryptDestroyHash( hash ); return QByteArray(); } DWORD size = 256; QByteArray sig( size, 0 ); if( CryptSignHashW( hash, AT_SIGNATURE, 0, 0, LPBYTE(sig.data()), &size ) ) sig.resize( size ); else sig.clear(); switch( GetLastError() ) { case ERROR_CANCELLED: d->error = PinCanceled; break; default: break; } CryptDestroyHash( hash ); return reverse( sig ); }
/** * Calculates the HMAC of the given message, hashtype, and hashkey. * dest must be at least the hash length. */ int create_hmac(int hashtype, const unsigned char *key, unsigned int keylen, const unsigned char *src, unsigned int srclen, unsigned char *dest, unsigned int *destlen) { // TODO: right now we reimport the hmac key each time. Test to see if this // is quick enough or if we need to cache an imported hmac key. HCRYPTKEY hmackey; HCRYPTHASH hash; char keyblob[BLOBLEN]; BLOBHEADER *bheader; DWORD *keysize; BYTE *keydata; HMAC_INFO info; ALG_ID alg; int bloblen, hashlen, rval; DWORD _destlen; hashlen = get_hash_len(hashtype); alg = get_hash(hashtype); bheader = (BLOBHEADER *)keyblob; keysize = (DWORD *)(keyblob + sizeof(BLOBHEADER)); keydata = (BYTE *)((char *)keysize + sizeof(DWORD)); memset(keyblob, 0, sizeof(keyblob)); bheader->bType = PLAINTEXTKEYBLOB; bheader->bVersion = CUR_BLOB_VERSION; bheader->aiKeyAlg = CALG_RC2; *keysize = keylen; memcpy(keydata, key, keylen); bloblen = sizeof(BLOBHEADER) + sizeof(DWORD) + hashlen; if (!CryptImportKey(base_prov, keyblob, bloblen, 0, CRYPT_IPSEC_HMAC_KEY, &hmackey)) { mserror("CryptImportKey failed"); return 0; } if (!CryptCreateHash(base_prov, CALG_HMAC, hmackey, 0, &hash)) { mserror("CryptCreateHash failed"); rval = 0; goto end1; } memset(&info, 0, sizeof(info)); info.HashAlgid = alg; if (!CryptSetHashParam(hash, HP_HMAC_INFO, (BYTE *)&info, 0)) { mserror("CryptSetHashParam failed"); rval = 0; goto end2; } if (!CryptHashData(hash, src, srclen, 0)) { mserror("CryptHashData failed"); rval = 0; goto end2; } _destlen = hashlen; if (!CryptGetHashParam(hash, HP_HASHVAL, dest, &_destlen, 0)) { mserror("CryptGetHashParam failed"); rval = 0; goto end2; } *destlen = _destlen; rval = 1; end2: if (!CryptDestroyHash(hash)) { mserror("CryptDestroyHash failed"); } end1: if (!CryptDestroyKey(hmackey)) { mserror("CryptDestroyKey failed"); } return rval; }
static SECStatus ssl3_CAPIPlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, PRBool isTLS, KeyType keyType) { SECStatus rv = SECFailure; PRBool doDerEncode = PR_FALSE; SECItem hashItem; DWORD argLen = 0; DWORD signatureLen = 0; ALG_ID hashAlg = 0; HCRYPTHASH hHash = 0; DWORD hashLen = 0; unsigned int i = 0; buf->data = NULL; switch (hash->hashAlg) { case SEC_OID_UNKNOWN: hashAlg = 0; break; case SEC_OID_SHA1: hashAlg = CALG_SHA1; break; case SEC_OID_SHA256: hashAlg = CALG_SHA_256; break; case SEC_OID_SHA384: hashAlg = CALG_SHA_384; break; case SEC_OID_SHA512: hashAlg = CALG_SHA_512; break; default: PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); return SECFailure; } switch (keyType) { case rsaKey: if (hashAlg == 0) { hashAlg = CALG_SSL3_SHAMD5; } hashItem.data = hash->u.raw; hashItem.len = hash->len; break; case dsaKey: case ecKey: if (keyType == ecKey) { doDerEncode = PR_TRUE; } else { doDerEncode = isTLS; } if (hashAlg == 0) { hashAlg = CALG_SHA1; hashItem.data = hash->u.s.sha; hashItem.len = sizeof(hash->u.s.sha); } else { hashItem.data = hash->u.raw; hashItem.len = hash->len; } break; default: PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len)); if (!CryptCreateHash(key->hCryptProv, hashAlg, 0, 0, &hHash)) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError()); goto done; } argLen = sizeof(hashLen); if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashLen, &argLen, 0)) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError()); goto done; } if (hashLen != hashItem.len) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, 0); goto done; } if (!CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)hashItem.data, 0)) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError()); goto done; } if (!CryptSignHash(hHash, key->dwKeySpec, NULL, 0, NULL, &signatureLen) || signatureLen == 0) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError()); goto done; } buf->data = (unsigned char *)PORT_Alloc(signatureLen); if (!buf->data) goto done; /* error code was set. */ if (!CryptSignHash(hHash, key->dwKeySpec, NULL, 0, (BYTE*)buf->data, &signatureLen)) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError()); goto done; } buf->len = signatureLen; /* CryptoAPI signs in little-endian, so reverse */ for (i = 0; i < buf->len / 2; ++i) { unsigned char tmp = buf->data[i]; buf->data[i] = buf->data[buf->len - 1 - i]; buf->data[buf->len - 1 - i] = tmp; } if (doDerEncode) { SECItem derSig = {siBuffer, NULL, 0}; /* This also works for an ECDSA signature */ rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len); if (rv == SECSuccess) { PORT_Free(buf->data); /* discard unencoded signature. */ *buf = derSig; /* give caller encoded signature. */ } else if (derSig.data) { PORT_Free(derSig.data); } } else { rv = SECSuccess; } PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len)); done: if (hHash) CryptDestroyHash(hHash); if (rv != SECSuccess && buf->data) { PORT_Free(buf->data); buf->data = NULL; } return rv; }
void WinCAPICryptoHashHMAC::setKey(XSECCryptoKey *key) { BOOL fResult; // Use this to initialise the ipadKeyed/opadKeyed values if (key->getKeyType() != XSECCryptoKey::KEY_HMAC) { throw XSECCryptoException(XSECCryptoException::MDError, "WinCAPI:HashHMAC - Non HMAC Key passed to HashHMAC"); } if (m_blockSize > XSEC_MAX_HASH_BLOCK_SIZE) { throw XSECCryptoException(XSECCryptoException::MDError, "WinCAPI:HashHMAC - Internal error - have got a blocksize bigger than I can handle"); } // Check to see if this is an internal Windows Key if (strEquals(key->getProviderName(), DSIGConstants::s_unicodeStrPROVWinCAPI) && ((WinCAPICryptoKeyHMAC *) key)->getWinKey() != 0) { // Over-ride the local provider for this HCRYPTPROV p = ((WinCAPICryptoKeyHMAC *) key)->getWinKeyProv(); HCRYPTKEY k = ((WinCAPICryptoKeyHMAC *) key)->getWinKey(); fResult = CryptCreateHash( p, CALG_HMAC, k, 0, &m_h); if (fResult == 0 || m_h == 0) { DWORD error = GetLastError(); throw XSECCryptoException(XSECCryptoException::MDError, "WinCAPI:Hash::setKey - Error creating internally keyed hash object"); } // Set the HMAC algorithm HMAC_INFO hi; hi.HashAlgid = m_algId; hi.pbInnerString = NULL; // Use default inner and outer strings hi.cbInnerString = 0; hi.pbOuterString = NULL; hi.cbOuterString = 0; fResult = CryptSetHashParam( m_h, HP_HMAC_INFO, (BYTE *) &hi, 0); if (fResult == 0 || m_h == 0) { DWORD error = GetLastError(); throw XSECCryptoException(XSECCryptoException::MDError, "WinCAPI:Hash::setKey - Error setting HASH_INFO object"); } return; } // Need to load from raw bit string safeBuffer keyBuf; unsigned int keyLen = ((XSECCryptoKeyHMAC *) key)->getKey(keyBuf); if (keyLen > m_blockSize) { HCRYPTHASH h; fResult = CryptCreateHash( m_p, m_algId, 0, 0, &h); if (fResult == 0 || h == 0) { throw XSECCryptoException(XSECCryptoException::MDError, "WinCAPI:Hash::setKey - Error creating hash object"); } fResult = CryptHashData( h, keyBuf.rawBuffer(), keyLen, 0); if (fResult == 0 || h == 0) { if (h) CryptDestroyHash(h); throw XSECCryptoException(XSECCryptoException::MDError, "WinCAPI:Hash::setKey - Error hashing key data"); } BYTE outData[XSEC_MAX_HASH_SIZE]; DWORD outDataLen = XSEC_MAX_HASH_SIZE; CryptGetHashParam( h, HP_HASHVAL, outData, &outDataLen, 0); if (fResult == 0 || h == 0) { if (h) CryptDestroyHash(h); throw XSECCryptoException(XSECCryptoException::MDError, "WinCAPI:Hash::setKey - Error getting hash result"); } keyBuf.sbMemcpyIn(outData, outDataLen); keyLen = outDataLen; if (h) CryptDestroyHash(h); } // Now create the ipad and opad keyed values memcpy(m_ipadKeyed, ipad, m_blockSize); memcpy(m_opadKeyed, opad, m_blockSize); // XOR with the key for (unsigned int i = 0; i < keyLen; ++i) { m_ipadKeyed[i] = keyBuf[i] ^ m_ipadKeyed[i]; m_opadKeyed[i] = keyBuf[i] ^ m_opadKeyed[i]; } // Now create the hash object, and start with the ipad operation fResult = CryptCreateHash( m_p, m_algId, 0, 0, &m_h); if (fResult == 0 || m_h == 0) { throw XSECCryptoException(XSECCryptoException::MDError, "WinCAPI:HashHMAC - Error creating hash object"); } fResult = CryptHashData( m_h, m_ipadKeyed, m_blockSize, 0); if (fResult == 0 || m_h == 0) { throw XSECCryptoException(XSECCryptoException::MDError, "WinCAPI:HashHMAC - Error performing initial ipad digest"); } }
bool testSignHash(bool bVerbose){ BYTE *pbSignature; DWORD dwSigLen; HCRYPTHASH hHash; BYTE bHashVal[32+1] = "\x2D\xFB\xC1\xB3\x72\xD8\x9A\x11\x88\xC0\x9C\x52\xE0\xEE\xC6\x1F\xCE\x52\x03\x2A\xB1\x02\x2E\x8E\x67\xEC\xE6\x67\x2B\x04\x3E\xE5"; if ( bVerbose ) std::cout << "Supplied hash value is: \n" << bHashVal << std::endl; if (!(CryptCreateHash(hProv, CALG_GOST_HASH, 0, 0, &hHash))) { if ( bVerbose ) printf("CryptCreateHash Failed\n"); return false; } if ( !CryptSetHashParam( hHash, HP_HASHVAL, bHashVal, 0)) { if ( bVerbose ) printf("CryptSetHashParam Failed\n"); return false; } if (!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSigLen)) { if ( bVerbose ) printf("First call to CryptSignHash Failed\n"); return false; } pbSignature = new BYTE[dwSigLen]; if (!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)) { if ( bVerbose ) printf("Second call to CryptSignHash Failed\n"); return false; } if ( bVerbose ) std::cout << "Signature:\n" << pbSignature << pbSignature + GOSTR34102001SigLen/2 << std::endl; BYTE bBenchmarkSignature[64]; strtobyte( "41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC049301456C64BA4642A1653C235A98A60249BCD6D3F746B631DF928014F6C5BF9C40" , bBenchmarkSignature ); if ( memcmp ( bBenchmarkSignature, pbSignature, 64 )==0 ) return TRUE; else return false; }
void CEstEIDIEPluginBHO::signWithCSP(BSTR id, BSTR hash, BSTR *signature) { LOG_LOCATION; HCRYPTPROV cryptoProvider = NULL; HCRYPTHASH _hash = NULL ; PCCERT_CONTEXT certContext = NULL; HCERTSTORE cert_store; BOOL must_release_provider; try{ if(!id || !strlen(CW2A(id))) { throw CryptoException(ESTEID_CERT_NOT_FOUND_ERROR); } EstEID_log("signing started, selected certificate id = %s", CW2A(id)); #define VALID_HASH_LENGTH 40 if (_bstr_t(hash).length() != VALID_HASH_LENGTH) { throw CryptoException("invalid hash"); } cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG, L"MY"); if(!cert_store) throw CryptoException(); while(certContext = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext)) { if(certificateMatchesId(certContext, id)) { DWORD key_type = 0; if (CryptAcquireCertificatePrivateKey(certContext, CRYPT_ACQUIRE_CACHE_FLAG, NULL, &cryptoProvider, &key_type, &must_release_provider)) { BYTE hashBytes[21]; DWORD hashBytesLength = 20; CryptStringToBinary(hash, VALID_HASH_LENGTH, CRYPT_STRING_HEX, hashBytes, &hashBytesLength, 0, 0); hashBytes[hashBytesLength] = '\0'; EstEID_log("Number of bytes stored in hashBytes buffer = %u", hashBytesLength); CryptoErrorHandler(CryptCreateHash(cryptoProvider, CALG_SHA1, 0, 0, &_hash)); EstEID_log("CryptCreateHash() set hash object pointer to %p", _hash); CryptoErrorHandler(CryptSetHashParam(_hash, HP_HASHVAL, hashBytes, 0)); #define SIGNATURE_LENGTH 1024 BYTE _signature[SIGNATURE_LENGTH]; DWORD signatureLength = SIGNATURE_LENGTH; INT retCode = CryptSignHash(_hash, AT_SIGNATURE, NULL, 0, _signature, &signatureLength); DWORD lastError = GetLastError(); EstEID_log("CryptSignHash() return code: %u (%s) %x", retCode, retCode ? "SUCCESS" : "FAILURE", lastError); if(!retCode) throw CryptoException(lastError); CryptDestroyHash(_hash); CryptReleaseContext(cryptoProvider, 0); CertFreeCertificateContext(certContext); if(must_release_provider) CertCloseStore(cert_store, 0); std::stringstream ss; for (DWORD i = 0; i < signatureLength; i++) { ss << std::hex << std::setfill('0') << std::setw(2) << (short)_signature[signatureLength - i - 1]; } *signature = _bstr_t(ss.str().c_str()).Detach(); } else { INT lastError = GetLastError(); EstEID_log("ERROR: CryptAcquireCertificatePrivateKey() failed, error code = %lXh", GetLastError()); switch(lastError) { case NTE_BAD_PUBLIC_KEY: EstEID_log(" error code %lXh: NTE_BAD_PUBLIC_KEY", lastError); break; case NTE_SILENT_CONTEXT: EstEID_log(" error code %lXh: NTE_SILENT_CONTEXT", lastError); } } break; } } } catch(CryptoException e) { *signature = _bstr_t("").Detach(); if(_hash) CryptDestroyHash(_hash); if(cryptoProvider) CryptReleaseContext(cryptoProvider, 0); if(certContext) CertFreeCertificateContext(certContext); if(must_release_provider && cert_store) CertCloseStore(cert_store, 0); throw(CryptoException(e.windowsErrorCode)); } }
/* sign arbitrary data */ static int rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data; HCRYPTHASH hash; DWORD hash_size, len, i; unsigned char *buf; if (cd == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (padding != RSA_PKCS1_PADDING) { /* AFAICS, CryptSignHash() *always* uses PKCS1 padding. */ RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); return 0; } /* Unfortunately, there is no "CryptSign()" function in CryptoAPI, that would * be way to straightforward for M$, I guess... So we have to do it this * tricky way instead, by creating a "Hash", and load the already-made hash * from 'from' into it. */ /* For now, we only support NID_md5_sha1 */ if (flen != SSL_SIG_LENGTH) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); return 0; } if (!CryptCreateHash(cd->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash)) { CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_CREATE_HASH); return 0; } len = sizeof(hash_size); if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len, 0)) { CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_GET_HASH_PARAM); CryptDestroyHash(hash); return 0; } if ((int) hash_size != flen) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); CryptDestroyHash(hash); return 0; } if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) { CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_SET_HASH_PARAM); CryptDestroyHash(hash); return 0; } len = RSA_size(rsa); buf = malloc(len); if (buf == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); CryptDestroyHash(hash); return 0; } if (!CryptSignHash(hash, cd->key_spec, NULL, 0, buf, &len)) { CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_SIGN_HASH); CryptDestroyHash(hash); free(buf); return 0; } /* and now, we have to reverse the byte-order in the result from CryptSignHash()... */ for (i = 0; i < len; i++) to[i] = buf[len - i - 1]; free(buf); CryptDestroyHash(hash); return len; }
/* * Compute the Base64-encoded HmacSha256 for the given key and content, optionally URL * encoding the Base64 result. */ CharHolder HmacSha256::getEncodedHMAC(const std::string& secretKey, const std::string& signContent, bool urlEncode) { // get the crypt provider CryptProviderHolder provider; if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) throw FormattedException(GetLastError(), "CryptAcquireContext: %08x", GetLastError()); // import the supplied key into a crypt library key object using PLAINTEXTKEYBLOB typedef struct _PLAINTEXTKEYBLOBSTRUCT { BLOBHEADER hdr; DWORD dwKeyLen; } PLAINTEXTKEYBLOBSTRUCT; UCharHolder keyImport(sizeof(PLAINTEXTKEYBLOBSTRUCT) + secretKey.length()); ((PLAINTEXTKEYBLOBSTRUCT*) keyImport.get())->hdr.bType = PLAINTEXTKEYBLOB; ((PLAINTEXTKEYBLOBSTRUCT*) keyImport.get())->hdr.bVersion = CUR_BLOB_VERSION; ((PLAINTEXTKEYBLOBSTRUCT*) keyImport.get())->hdr.reserved = 0; ((PLAINTEXTKEYBLOBSTRUCT*) keyImport.get())->hdr.aiKeyAlg = CALG_RC2; ((PLAINTEXTKEYBLOBSTRUCT*) keyImport.get())->dwKeyLen = secretKey.length(); CopyMemory(keyImport.get() + sizeof(PLAINTEXTKEYBLOBSTRUCT), secretKey.c_str(), secretKey.length()); CryptKeyHolder key; if (!CryptImportKey(provider.get(), (const BYTE *) keyImport.get(), sizeof(PLAINTEXTKEYBLOBSTRUCT), 0, CRYPT_IPSEC_HMAC_KEY, &key)) throw FormattedException(GetLastError(), "CryptImportKey(key): %08x", GetLastError()); // create the hash object using the imported key CryptHashHolder hash; if (!CryptCreateHash(provider.get(), CALG_HMAC, key.get(), 0, &hash)) throw FormattedException(GetLastError(), "CryptCreateHash(data): %08x", GetLastError()); HMAC_INFO hmacInfo; ZeroMemory(&hmacInfo, sizeof(HMAC_INFO)); hmacInfo.HashAlgid = CALG_SHA_256; if (!CryptSetHashParam(hash.get(), HP_HMAC_INFO, (BYTE *) &hmacInfo, 0)) throw FormattedException(GetLastError(), "CryptSetHashParam(data): %08x", GetLastError()); // hash the content data if (!CryptHashData(hash.get(), (const BYTE *) signContent.c_str(), signContent.length(), 0)) throw FormattedException("CryptHashData(data): %08x", GetLastError()); // query the size of the hash that will be returned DWORD hashSize = 0; if (!CryptGetHashParam(hash.get(), HP_HASHVAL, NULL, &hashSize, 0)) throw FormattedException(GetLastError(), "CryptGetHashParam(data): %08x", GetLastError()); // create a managed buffer to receive the hash value and then store it there UCharHolder buffer(hashSize); if (!CryptGetHashParam(hash.get(), HP_HASHVAL, (BYTE *) buffer.get(), &hashSize, 0)) throw FormattedException(GetLastError(), "CryptGetHashParam(data): %08x", GetLastError()); // convert hash to Base64, store that in a managed buffer size_t base64Size; Base64Codec base64Codec; char* base64 = base64Codec.base64_encode((const unsigned char *) buffer.get(), buffer.getSize(), &base64Size); CharHolder base64Holder(base64, base64Size); if (!urlEncode) return base64Holder; // poor-man's URL encoding for Base64'd data -- only need to worry about + / and = int count = 0; for (unsigned int i=0; i<base64Holder.getSize(); i++) { if ((base64Holder.get()[i] == '+') || (base64Holder.get()[i] == '/') || (base64Holder.get()[i] == '=')) count++; } CharHolder urlHolder(base64Holder.getSize() + 2 * count); // 2 additional characters for each + / or = int j = 0; for (unsigned int i=0; i<base64Holder.getSize(); i++) { if (base64Holder.get()[i] == '+') { urlHolder.get()[j++] = '%'; urlHolder.get()[j++] = '2'; urlHolder.get()[j++] = 'B'; } else if (base64Holder.get()[i] == '/') { urlHolder.get()[j++] = '%'; urlHolder.get()[j++] = '2'; urlHolder.get()[j++] = 'F'; } else if (base64Holder.get()[i] == '=') { urlHolder.get()[j++] = '%'; urlHolder.get()[j++] = '3'; urlHolder.get()[j++] = 'D'; } else { urlHolder.get()[j++] = base64Holder.get()[i]; } } return urlHolder; }
struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) { struct crypto_hash *ctx; ALG_ID calg; struct { BLOBHEADER hdr; DWORD len; BYTE key[32]; } key_blob; os_memset(&key_blob, 0, sizeof(key_blob)); switch (alg) { case CRYPTO_HASH_ALG_MD5: calg = CALG_MD5; break; case CRYPTO_HASH_ALG_SHA1: calg = CALG_SHA; break; case CRYPTO_HASH_ALG_HMAC_MD5: case CRYPTO_HASH_ALG_HMAC_SHA1: calg = CALG_HMAC; key_blob.hdr.bType = PLAINTEXTKEYBLOB; key_blob.hdr.bVersion = CUR_BLOB_VERSION; key_blob.hdr.reserved = 0; /* * Note: RC2 is not really used, but that can be used to * import HMAC keys of up to 16 byte long. * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to * be able to import longer keys (HMAC-SHA1 uses 20-byte key). */ key_blob.hdr.aiKeyAlg = CALG_RC2; key_blob.len = key_len; if (key_len > sizeof(key_blob.key)) return NULL; os_memcpy(key_blob.key, key, key_len); break; default: return NULL; } ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->alg = alg; if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) { cryptoapi_report_error("CryptAcquireContext"); os_free(ctx); return NULL; } if (calg == CALG_HMAC) { #ifndef CRYPT_IPSEC_HMAC_KEY #define CRYPT_IPSEC_HMAC_KEY 0x00000100 #endif if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY, &ctx->key)) { cryptoapi_report_error("CryptImportKey"); CryptReleaseContext(ctx->prov, 0); os_free(ctx); return NULL; } } if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) { cryptoapi_report_error("CryptCreateHash"); CryptReleaseContext(ctx->prov, 0); os_free(ctx); return NULL; } if (calg == CALG_HMAC) { HMAC_INFO info; os_memset(&info, 0, sizeof(info)); switch (alg) { case CRYPTO_HASH_ALG_HMAC_MD5: info.HashAlgid = CALG_MD5; break; case CRYPTO_HASH_ALG_HMAC_SHA1: info.HashAlgid = CALG_SHA; break; default: /* unreachable */ break; } if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info, 0)) { cryptoapi_report_error("CryptSetHashParam"); CryptDestroyHash(ctx->hash); CryptReleaseContext(ctx->prov, 0); os_free(ctx); return NULL; } } return ctx; }
//----------------------------------------------------------------------------- // swPBKDF2() : implémentation de PBKDF2 RFC 2898 (http://www.ietf.org/rfc/rfc2898.txt) // Limitée à 2 blocs de 160 bits en sortie, dont seuls les 256 premiers sont // fournis à l'appelant. Ce résultat est utilisé pour : // 1) Alimenter la fonction de dérivation de clé AES-256 (CryptDeriveKey) // 2) Stocker le mot de passe maître //----------------------------------------------------------------------------- // Avec 2 blocs, l'algo proposé par la RFC donne : // DK = T_1 || T_2 // T_1 = F (P, S, c, 1) // T_2 = F (P, S, c, 2) // où : // P = password, an octet string // S = salt, an octet string // c = iteration count, a positive integer // F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c // U_1 = PRF (P, S || INT (i)) // U_2 = PRF (P, U_1) // ... // U_c = PRF (P, U_{c-1}) //----------------------------------------------------------------------------- // MERCI A GUILLAUME POUR SA PROPOSITION D'IMPLEMENTATION ! //----------------------------------------------------------------------------- // [out]bufResult = pointeur vers un buffer de bytes (alloué par l'appelant) // [in] bufResultLen = taille de clé souhaitée (max HASH_LENx2) // [in] szPwd = mot de passe maitre a deriver // [in] bufSalt = buffer contenant le sel // [in] bufSaltLen = taille du buffer de sel (PBKDF2_SALT_LEN) // [in] iNbIterations = nombre d'itérations //----------------------------------------------------------------------------- int swPBKDF2(BYTE *bufResult,int bufResultLen,const char *szPwd,const BYTE *bufSalt,int bufSaltLen,int iNbIterations) { TRACE((TRACE_ENTER,_F_,"bufResultLen=%d iNbIterations=%d",bufResultLen,iNbIterations)); //TRACE((TRACE_PWD,_F_,"szPwd=%s",szPwd)); TRACE_BUFFER((TRACE_DEBUG,_F_,(BYTE*)bufSalt,bufSaltLen,"sel")); int brc; int c; // itérations int rc=-1; HCRYPTKEY hKey=NULL; HCRYPTHASH hHMAC=NULL; HMAC_INFO hmacinfo; KEYBLOB *pKey=NULL; int iKeySize; DWORD dwLenHash; BYTE bufU_c[HASH_LEN]; // stocke successivement U_1, U_2, ..., U_c BYTE bufT[HASH_LEN*2]; // stocke le résultat final : T_1 à l'index 0 et T_2 à l'index HASH_LEN BYTE bufSaltWithBlocIndex[PBKDF2_SALT_LEN+4]; int iBloc; if (bufResultLen>HASH_LEN*2) { TRACE((TRACE_ERROR,_F_,"bufResultLen=%d > valeur autorisée HASH_LEN*2=%d",bufResultLen,HASH_LEN*2)); goto end; } if (bufSaltLen!=PBKDF2_SALT_LEN) { TRACE((TRACE_ERROR,_F_,"bufSaltLen=%d != valeur imposée PBKDF2_SALT_LEN=%d",bufSaltLen,PBKDF2_SALT_LEN)); goto end; } // Création de la clé HMAC en mode PLAINTEXTKEYBLOB, à partir du mot de passe iKeySize=sizeof(KEYBLOB)+strlen(szPwd); pKey=(KEYBLOB*)malloc(iKeySize); if (pKey==NULL) { TRACE((TRACE_ERROR,_F_,"malloc(%d)",iKeySize)); goto end; } ZeroMemory(pKey,iKeySize); // Création de la clé symétrique pour le HMAC // cf. doc de CryptImportKey() -> http://msdn.microsoft.com/en-us/library/aa380207(v=vs.85).aspx : // "When importing a Hash-Based Message Authentication Code (HMAC) key, the caller must identify // the imported key as a PLAINTEXTKEYBLOB type" // "The HMAC algorithms do not have their own algorithm identifiers; use CALG_RC2 instead. // CRYPT_IPSEC_HMAC_KEY allows the import of RC2 keys longer than 16 bytes." // cf. tests vectors de la RFC 2202 HMAC-SHA1 pKey->header.bType=PLAINTEXTKEYBLOB; pKey->header.bVersion=CUR_BLOB_VERSION; pKey->header.reserved=0; pKey->header.aiKeyAlg=CALG_RC2; pKey->dwKeySize=strlen(szPwd); memcpy(pKey->KeyData,szPwd,pKey->dwKeySize); // test case 1 RFC 2202 HMAC-SHA1 /*pKey->dwKeySize=20; memset(pKey->KeyData,0x0b,pKey->dwKeySize);*/ // fin test case 1 RFC 2202 HMAC-SHA1 // test case 7 RFC 2202 HMAC-SHA1 /*pKey->dwKeySize=80; memset(pKey->KeyData,0xaa,pKey->dwKeySize);*/ // fin test case 7 RFC 2202 HMAC-SHA1 //TRACE_BUFFER((TRACE_PWD,_F_,(BYTE*)pKey,iKeySize,"pKey (iKeySize=%d)",iKeySize)); brc= CryptImportKey(ghProv,(LPBYTE)pKey,iKeySize,NULL,CRYPT_IPSEC_HMAC_KEY,&hKey); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptImportKey()=0x%08lx",GetLastError())); goto end; } // Initialisation du buffer resultat a zero ZeroMemory(bufT,HASH_LEN*2); // Itération pour sortir 2 blocs de 160 bits chacun (T_1 et T_2) for (iBloc=1;iBloc<=2;iBloc++) { // concaténation de l'index de bloc au sel memcpy(bufSaltWithBlocIndex,bufSalt,PBKDF2_SALT_LEN); bufSaltWithBlocIndex[bufSaltLen]=0x00; bufSaltWithBlocIndex[bufSaltLen+1]=0x00; bufSaltWithBlocIndex[bufSaltLen+2]=0x00; bufSaltWithBlocIndex[bufSaltLen+3]=(BYTE)iBloc; TRACE_BUFFER((TRACE_DEBUG,_F_,bufSaltWithBlocIndex,bufSaltLen+4,"bufSaltWithBlocIndex")); // Création du HMAC // cf. http://msdn.microsoft.com/en-us/library/aa382379(VS.85).aspx brc=CryptCreateHash(ghProv,CALG_HMAC,hKey,0,&hHMAC); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptCreateHash()=0x%08lx",GetLastError())); goto end; } // Initialisation des paramètres du HMAC ZeroMemory(&hmacinfo,sizeof(hmacinfo)); hmacinfo.HashAlgid=CALG_SHA1; brc=CryptSetHashParam(hHMAC,HP_HMAC_INFO, (BYTE*)&hmacinfo,0); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptSetHashParam()=0x%08lx",GetLastError())); goto end; } // test case 1 RFC 2202 HMAC-SHA1 /*brc=CryptHashData(hHMAC,(const BYTE*)"Hi There",8, 0); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptCreateHash()=0x%08lx",GetLastError())); goto end; } brc=CryptGetHashParam(hHMAC,HP_HASHVAL,bufU_c,&dwLenHash,0); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptGetHashParam()=0x%08lx",GetLastError())); goto end; } TRACE_BUFFER((TRACE_DEBUG,_F_,bufU_c,HASH_LEN,"Test case 1 RFC 2202 HMAC-SHA1")); if (brc) goto end;*/ // fin test case 1 RFC 2202 HMAC-SHA1 // test case 7 RFC 2202 HMAC-SHA1 /*brc=CryptHashData(hHMAC,(const BYTE*)"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",73, 0); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptCreateHash()=0x%08lx",GetLastError())); goto end; } brc=CryptGetHashParam(hHMAC,HP_HASHVAL,bufU_c,&dwLenHash,0); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptGetHashParam()=0x%08lx",GetLastError())); goto end; } TRACE_BUFFER((TRACE_DEBUG,_F_,bufU_c,HASH_LEN,"Test case 1 RFC 2202 HMAC-SHA1")); if (brc) goto end;*/ // fin test case 7 RFC 2202 HMAC-SHA1 // HMAC du sel enrichi de l'id de bloc brc=CryptHashData(hHMAC,bufSaltWithBlocIndex,bufSaltLen+4, 0); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptHashData(bufSaltWithBlocIndex)=0x%08lx",GetLastError())); goto end; } // Récupération du hash dwLenHash=sizeof(bufU_c); brc=CryptGetHashParam(hHMAC,HP_HASHVAL,bufU_c,&dwLenHash,0); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptGetHashParam(bufU_1)=0x%08lx",GetLastError())); goto end; } TRACE_BUFFER((TRACE_DEBUG,_F_,bufU_c,HASH_LEN,"bufU_1")); // Destruction du HMAC brc=CryptDestroyHash(hHMAC); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptDestroyHash()=0x%08lx",GetLastError())); goto end; } hHMAC=NULL; // XOR dans le buffer résultat swXORBuff(bufT+(iBloc-1)*HASH_LEN,bufU_c,HASH_LEN); // Iterations for (c=2;c<=iNbIterations;c++) // on démarre à 1, la 1ère itération étant faite précédemment hors de la boucle { // Création du HMAC brc=CryptCreateHash(ghProv,CALG_HMAC,hKey,0,&hHMAC); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptCreateHash()=0x%08lx",GetLastError())); goto end; } // Initialisation des paramètres du HMAC ZeroMemory(&hmacinfo,sizeof(hmacinfo)); hmacinfo.HashAlgid=CALG_SHA1; brc=CryptSetHashParam(hHMAC,HP_HMAC_INFO,(BYTE*)&hmacinfo,0); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptSetHashParam()=0x%08lx",GetLastError())); goto end; } // HMAC du résultat de l'itération précédente brc=CryptHashData(hHMAC,bufU_c,HASH_LEN,0); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptHashData(bufU_%d)=0x%08lx",c,GetLastError())); goto end; } // Recup du hash brc=CryptGetHashParam(hHMAC,HP_HASHVAL,bufU_c,&dwLenHash,0); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptGetHashParam(bufU_%d)=0x%08lx",c,GetLastError())); goto end; } // Détruire le HMAC brc=CryptDestroyHash(hHMAC); if (!brc) { TRACE((TRACE_ERROR,_F_,"CryptDestroyHash()=0x%08lx",GetLastError())); goto end; } hHMAC=NULL; // XOR dans le resultat swXORBuff(bufT+(iBloc-1)*HASH_LEN,bufU_c,HASH_LEN); } TRACE_BUFFER((TRACE_DEBUG,_F_,bufT+(iBloc-1)*HASH_LEN,HASH_LEN,"bufT_%d",iBloc)); } // Les 2 blocs sont alimentés, on extrait les bufResultLen pour alimenter bufResult memcpy(bufResult,bufT,bufResultLen); TRACE_BUFFER((TRACE_DEBUG,_F_,bufResult,bufResultLen,"bufResult")); rc=0; end: if (hHMAC!=NULL) CryptDestroyHash(hHMAC); if (hKey!=NULL) CryptDestroyKey(hKey); if (pKey!=NULL) free(pKey); TRACE((TRACE_LEAVE,_F_,"rc=%d",rc)); return rc; }
static int capi_sign(gnutls_privkey_t key, void *userdata, const gnutls_datum_t * raw_data, gnutls_datum_t * signature) { priv_st *priv = (priv_st *) userdata; ALG_ID Algid; HCRYPTHASH hHash = NULL; uint8_t digest[MAX_HASH_SIZE]; unsigned int digest_size; gnutls_digest_algorithm_t algo; DWORD size1 = 0, sizesize = sizeof(DWORD); DWORD ret_sig = 0; int ret; signature->data = NULL; signature->size = 0; digest_size = raw_data->size; switch (digest_size) { case 16: Algid = CALG_MD5; break; //case 35: size=20; // DigestInfo SHA1 case 20: Algid = CALG_SHA1; break; //case 51: size=32; // DigestInto SHA-256 case 32: Algid = CALG_SHA_256; break; case 36: Algid = CALG_SSL3_SHAMD5; break; case 48: Algid = CALG_SHA_384; break; case 64: Algid = CALG_SHA_512; break; default: digest_size = sizeof(digest); ret = decode_ber_digest_info(raw_data, &algo, digest, &digest_size); if (ret < 0) return gnutls_assert_val(ret); switch (algo) { case GNUTLS_DIG_SHA1: Algid = CALG_SHA1; break; #ifdef NCRYPT_SHA224_ALGORITHM case GNUTLS_DIG_SHA224: Algid = CALG_SHA_224; break; #endif case GNUTLS_DIG_SHA256: Algid = CALG_SHA_256; break; case GNUTLS_DIG_SHA384: Algid = CALG_SHA_384; break; case GNUTLS_DIG_SHA512: Algid = CALG_SHA_512; break; default: return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM); } } if (!CryptCreateHash(priv->hCryptProv, Algid, 0, 0, &hHash)) { gnutls_assert(); _gnutls_debug_log("error in create hash: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } if (!CryptSetHashParam(hHash, HP_HASHVAL, digest, 0)) { gnutls_assert(); _gnutls_debug_log("error in set hash val: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } if (!CryptGetHashParam (hHash, HP_HASHSIZE, (BYTE *) & size1, &sizesize, 0) || digest_size != size1) { gnutls_assert(); _gnutls_debug_log("error in hash size: %d\n", (int)size1); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } if (!CryptSignHash(hHash, priv->dwKeySpec, NULL, 0, NULL, &ret_sig)) { gnutls_assert(); _gnutls_debug_log("error in pre-signing: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } signature->size = ret_sig; signature->data = (unsigned char *)gnutls_malloc(signature->size); if (signature->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); if (!CryptSignHash (hHash, priv->dwKeySpec, NULL, 0, signature->data, &ret_sig)) { gnutls_assert(); _gnutls_debug_log("error in signing: %d\n", (int)GetLastError()); ret = GNUTLS_E_PK_SIGN_FAILED; goto fail; } memrev(signature->data, signature->size); CryptDestroyHash(hHash); signature->size = ret_sig; return 0; fail: if (hHash != 0) CryptDestroyHash(hHash); gnutls_free(signature->data); return ret; }
int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, const RSA *rsa) { ALG_ID alg; HCRYPTHASH hash; DWORD slen; unsigned int i; int ret = -1; CAPI_KEY *capi_key; CAPI_CTX *ctx; ctx = ENGINE_get_ex_data(rsa->engine, capi_idx); CAPI_trace(ctx, "Called CAPI_rsa_sign()\n"); capi_key = RSA_get_ex_data(rsa, rsa_capi_idx); if (!capi_key) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY); return -1; } /* Convert the signature type to a CryptoAPI algorithm ID */ switch(dtype) { case NID_sha1: alg = CALG_SHA1; break; case NID_md5: alg = CALG_MD5; break; case NID_md5_sha1: alg = CALG_SSL3_SHAMD5; break; default: { char algstr[10]; BIO_snprintf(algstr, 10, "%lx", dtype); CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID); ERR_add_error_data(2, "NID=0x", algstr); return -1; } } /* Create the hash object */ if(!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); capi_addlasterror(); return -1; } /* Set the hash value to the value passed */ if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE); capi_addlasterror(); goto err; } /* Finally sign it */ slen = RSA_size(rsa); if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); goto err; } else { ret = 1; /* Inplace byte reversal of signature */ for(i = 0; i < slen / 2; i++) { unsigned char c; c = sigret[i]; sigret[i] = sigret[slen - i - 1]; sigret[slen - i - 1] = c; } *siglen = slen; } /* Now cleanup */ err: CryptDestroyHash(hash); return ret; }
static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, DSA *dsa) { HCRYPTHASH hash; DWORD slen; DSA_SIG *ret = NULL; CAPI_KEY *capi_key; CAPI_CTX *ctx; unsigned char csigbuf[40]; ctx = ENGINE_get_ex_data(dsa->engine, capi_idx); CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n"); capi_key = DSA_get_ex_data(dsa, dsa_capi_idx); if (!capi_key) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY); return NULL; } if (dlen != 20) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH); return NULL; } /* Create the hash object */ if(!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash)) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT); capi_addlasterror(); return NULL; } /* Set the hash value to the value passed */ if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0)) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE); capi_addlasterror(); goto err; } /* Finally sign it */ slen = sizeof(csigbuf); if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); goto err; } else { ret = DSA_SIG_new(); if (!ret) goto err; ret->r = BN_new(); ret->s = BN_new(); if (!ret->r || !ret->s) goto err; if (!lend_tobn(ret->r, csigbuf, 20) || !lend_tobn(ret->s, csigbuf + 20, 20)) { DSA_SIG_free(ret); ret = NULL; goto err; } } /* Now cleanup */ err: OPENSSL_cleanse(csigbuf, 40); CryptDestroyHash(hash); return ret; }
static int xmlSecMSCryptoHmacSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { xmlSecMSCryptoHmacCtxPtr ctx; xmlSecKeyDataPtr value; xmlSecBufferPtr buffer; HMAC_INFO hmacInfo; int ret; xmlSecAssert2(xmlSecMSCryptoHmacCheckId(transform), -1); xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1); xmlSecAssert2(key != NULL, -1); ctx = xmlSecMSCryptoHmacGetCtx(transform); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->ctxInitialized == 0, -1); xmlSecAssert2(ctx->provider != 0, -1); xmlSecAssert2(ctx->pubPrivKey != 0, -1); xmlSecAssert2(ctx->cryptKey == 0, -1); xmlSecAssert2(ctx->mscHash == 0, -1); value = xmlSecKeyGetValue(key); xmlSecAssert2(xmlSecKeyDataCheckId(value, xmlSecMSCryptoKeyDataHmacId), -1); buffer = xmlSecKeyDataBinaryValueGetBuffer(value); xmlSecAssert2(buffer != NULL, -1); if(xmlSecBufferGetSize(buffer) == 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), NULL, XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, "keySize=0"); return(-1); } xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1); /* Import this key and get an HCRYPTKEY handle. * * HACK!!! HACK!!! HACK!!! * * Using CALG_RC2 instead of CALG_HMAC for the key algorithm so we don't want to check key length */ if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->provider, ctx->pubPrivKey, CALG_RC2, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), FALSE, &(ctx->cryptKey) ) || (ctx->cryptKey == 0)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecMSCryptoImportPlainSessionBlob", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } /* create hash */ ret = CryptCreateHash(ctx->provider, CALG_HMAC, ctx->cryptKey, 0, &(ctx->mscHash)); if((ret == 0) || (ctx->mscHash == 0)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "CryptCreateHash", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } /* set parameters */ memset(&hmacInfo, 0, sizeof(hmacInfo)); hmacInfo.HashAlgid = ctx->alg_id; ret = CryptSetHashParam(ctx->mscHash, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0); if(ret == 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "CryptSetHashParam", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } /* done */ ctx->ctxInitialized = 1; return(0); }