/* MUST BE THREAD-SAFE */ static PK11SymKey *pk11_extract_derive_wrapper_lsw(PK11SymKey *base, CK_EXTRACT_PARAMS bs, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize) { SECItem param; param.data = (unsigned char*)&bs; param.len = sizeof(bs); return PK11_Derive_lsw(base, CKM_EXTRACT_KEY_FROM_KEY, ¶m, target, operation, keySize); }
void hmac_init(struct hmac_ctx *ctx, const struct hash_desc *h, const u_char *key, size_t key_len) { ctx->h = h; ctx->hmac_digest_len = h->hash_digest_len; /* DBG(DBG_CRYPT, DBG_log("NSS: hmac init")); */ SECStatus status; PK11SymKey *symkey = NULL, *tkey1 = NULL; /* PK11SymKey *tkey1=NULL; */ unsigned int klen; chunk_t hmac_opad, hmac_ipad, hmac_pad; memcpy(&symkey, key, key_len); klen = PK11_GetKeyLength(symkey); hmac_opad = hmac_pads(HMAC_OPAD, h->hash_block_size); hmac_ipad = hmac_pads(HMAC_IPAD, h->hash_block_size); hmac_pad = hmac_pads(0x00, h->hash_block_size - klen); if (klen > h->hash_block_size) { tkey1 = PK11_Derive_lsw(symkey, nss_key_derivation_mech( h), NULL, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, 0); } else { tkey1 = symkey; } PK11SymKey *tkey2 = pk11_derive_wrapper_lsw(tkey1, CKM_CONCATENATE_BASE_AND_DATA, hmac_pad, CKM_XOR_BASE_AND_DATA, CKA_DERIVE, h->hash_block_size); PR_ASSERT(tkey2 != NULL); ctx->ikey = pk11_derive_wrapper_lsw(tkey2, CKM_XOR_BASE_AND_DATA, hmac_ipad, nss_hash_mech( h), CKA_DIGEST, 0); PR_ASSERT(ctx->ikey != NULL); ctx->okey = pk11_derive_wrapper_lsw(tkey2, CKM_XOR_BASE_AND_DATA, hmac_opad, nss_hash_mech( h), CKA_DIGEST, 0); PR_ASSERT(ctx->okey != NULL); if (tkey1 != symkey) PK11_FreeSymKey(tkey1); PK11_FreeSymKey(tkey2); freeanychunk(hmac_opad); freeanychunk(hmac_ipad); freeanychunk(hmac_pad); ctx->ctx_nss = PK11_CreateDigestContext(nss_hash_oid(h)); PR_ASSERT(ctx->ctx_nss != NULL); status = PK11_DigestBegin(ctx->ctx_nss); PR_ASSERT(status == SECSuccess); status = PK11_DigestKey(ctx->ctx_nss, ctx->ikey); PR_ASSERT(status == SECSuccess); }