int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { HCRYPTPROV prov; HCRYPTHASH hash; size_t i; DWORD hlen; int ret = 0; /* if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) { cryptoapi_report_error("CryptAcquireContext"); return -1; } */ BOOL r = CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0); if (!r) { if (GetLastError() == NTE_BAD_KEYSET) { r = CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET); } } if (!r) { cryptoapi_report_error("CryptAcquireContext"); return -1; } if (!CryptCreateHash(prov, alg, 0, 0, &hash)) { cryptoapi_report_error("CryptCreateHash"); CryptReleaseContext(prov, 0); return -1; } for (i = 0; i < num_elem; i++) { if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) { cryptoapi_report_error("CryptHashData"); CryptDestroyHash(hash); CryptReleaseContext(prov, 0); } } hlen = hash_len; if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) { cryptoapi_report_error("CryptGetHashParam"); ret = -1; } CryptDestroyHash(hash); CryptReleaseContext(prov, 0); return ret; }
int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) { int ret = 0; DWORD hlen; if (ctx == NULL) return -2; if (mac == NULL || len == NULL) goto done; if (ctx->error) { ret = -2; goto done; } hlen = *len; if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) { cryptoapi_report_error("CryptGetHashParam"); ret = -2; } *len = hlen; done: if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 || ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5) CryptDestroyKey(ctx->key); os_free(ctx); return ret; }
void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) { if (ctx == NULL || ctx->error) return; if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) { cryptoapi_report_error("CryptHashData"); ctx->error = 1; } }
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; }
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { DWORD dlen; os_memcpy(plain, crypt, len); dlen = len; if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) { cryptoapi_report_error("CryptDecrypt"); return -1; } return 0; }
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; struct { BLOBHEADER hdr; DWORD len; BYTE key[32]; } key_blob; DWORD mode = CRYPT_MODE_CBC; key_blob.hdr.bType = PLAINTEXTKEYBLOB; key_blob.hdr.bVersion = CUR_BLOB_VERSION; key_blob.hdr.reserved = 0; key_blob.len = key_len; if (key_len > sizeof(key_blob.key)) return NULL; os_memcpy(key_blob.key, key, key_len); switch (alg) { case CRYPTO_CIPHER_ALG_AES: if (key_len == 32) key_blob.hdr.aiKeyAlg = CALG_AES_256; else if (key_len == 24) key_blob.hdr.aiKeyAlg = CALG_AES_192; else key_blob.hdr.aiKeyAlg = CALG_AES_128; break; case CRYPTO_CIPHER_ALG_3DES: key_blob.hdr.aiKeyAlg = CALG_3DES; break; case CRYPTO_CIPHER_ALG_DES: key_blob.hdr.aiKeyAlg = CALG_DES; break; case CRYPTO_CIPHER_ALG_RC2: key_blob.hdr.aiKeyAlg = CALG_RC2; break; case CRYPTO_CIPHER_ALG_RC4: key_blob.hdr.aiKeyAlg = CALG_RC4; break; default: return NULL; } ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { cryptoapi_report_error("CryptAcquireContext"); goto fail1; } if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, &ctx->key)) { cryptoapi_report_error("CryptImportKey"); goto fail2; } if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) { cryptoapi_report_error("CryptSetKeyParam(KP_MODE)"); goto fail3; } if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) { cryptoapi_report_error("CryptSetKeyParam(KP_IV)"); goto fail3; } return ctx; fail3: CryptDestroyKey(ctx->key); fail2: CryptReleaseContext(ctx->prov, 0); fail1: os_free(ctx); return NULL; }
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; }