/* MUST BE THREAD-SAFE */ static PK11SymKey *calc_dh_shared(const chunk_t g, /* converted to SECItem */ /*const*/ SECKEYPrivateKey *privk, /* NSS doesn't do const */ const struct oakley_group_desc *group, const SECKEYPublicKey *local_pubk) { struct timeval tv0; SECKEYPublicKey *remote_pubk; SECItem nss_g; PK11SymKey *dhshared; PRArenaPool *arena; SECStatus status; unsigned int dhshared_len; DBG(DBG_CRYPT, DBG_log("Started DH shared-secret computation in NSS:")); gettimeofday(&tv0, NULL); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); passert(arena != NULL); remote_pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); remote_pubk->arena = arena; remote_pubk->keyType = dhKey; remote_pubk->pkcs11Slot = NULL; remote_pubk->pkcs11ID = CK_INVALID_HANDLE; nss_g.data = g.ptr; nss_g.len = (unsigned int)g.len; nss_g.type = siBuffer; status = SECITEM_CopyItem(remote_pubk->arena, &remote_pubk->u.dh.prime, &local_pubk->u.dh.prime); passert(status == SECSuccess); status = SECITEM_CopyItem(remote_pubk->arena, &remote_pubk->u.dh.base, &local_pubk->u.dh.base); passert(status == SECSuccess); status = SECITEM_CopyItem(remote_pubk->arena, &remote_pubk->u.dh.publicValue, &nss_g); passert(status == SECSuccess); dhshared = PK11_PubDerive(privk, remote_pubk, PR_FALSE, NULL, NULL, CKM_DH_PKCS_DERIVE, CKM_CONCATENATE_DATA_AND_BASE, CKA_DERIVE, group->bytes, lsw_return_nss_password_file_info()); passert(dhshared != NULL); dhshared_len = PK11_GetKeyLength(dhshared); if (group->bytes > dhshared_len) { DBG(DBG_CRYPT, DBG_log("Dropped %lu leading zeros", group->bytes - dhshared_len)); chunk_t zeros; PK11SymKey *newdhshared; CK_KEY_DERIVATION_STRING_DATA string_params; SECItem params; zeros = hmac_pads(0x00, group->bytes - dhshared_len); params.data = (unsigned char *)&string_params; params.len = sizeof(string_params); string_params.pData = zeros.ptr; string_params.ulLen = zeros.len; newdhshared = PK11_Derive(dhshared, CKM_CONCATENATE_DATA_AND_BASE, ¶ms, CKM_CONCATENATE_DATA_AND_BASE, CKA_DERIVE, 0); passert(newdhshared != NULL); PK11_FreeSymKey(dhshared); dhshared = newdhshared; freeanychunk(zeros); } else { DBG(DBG_CRYPT, DBG_log("Dropped no leading zeros %d", dhshared_len)); } /* nss_symkey_log(dhshared, "dhshared"); */ DBG(DBG_CRYPT, { struct timeval tv1; unsigned long tv_diff; gettimeofday(&tv1, NULL); tv_diff = (tv1.tv_sec - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec); DBG_log("calc_dh_shared(): time elapsed (%s): %ld usec", enum_show(&oakley_group_names, group->group), tv_diff); });
void hmac_init(struct hmac_ctx *ctx, const struct hash_desc *h, const u_char *key, size_t key_len) { #ifndef HAVE_LIBNSS int k; #endif ctx->h = h; ctx->hmac_digest_len = h->hash_digest_len; #ifdef HAVE_LIBNSS /* 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,HMAC_BUFSIZE); hmac_ipad = hmac_pads(HMAC_IPAD,HMAC_BUFSIZE); hmac_pad = hmac_pads(0x00,HMAC_BUFSIZE-klen); if(klen > HMAC_BUFSIZE) { tkey1 = PK11_Derive_osw(symkey, nss_key_derivation_mech(h) , NULL, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, 0); } else { tkey1 = symkey; } PK11SymKey *tkey2 = pk11_derive_wrapper_osw(tkey1, CKM_CONCATENATE_BASE_AND_DATA , hmac_pad,CKM_XOR_BASE_AND_DATA, CKA_DERIVE, HMAC_BUFSIZE); PR_ASSERT(tkey2!=NULL); ctx->ikey = pk11_derive_wrapper_osw(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_osw(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); #else /* Prepare the two pads for the HMAC */ memset(ctx->buf1, '\0', HMAC_BUFSIZE); if (key_len <= HMAC_BUFSIZE) { memcpy(ctx->buf1, key, key_len); } else { h->hash_init(&ctx->hash_ctx); h->hash_update(&ctx->hash_ctx, key, key_len); h->hash_final(ctx->buf1, &ctx->hash_ctx); } memcpy(ctx->buf2, ctx->buf1, HMAC_BUFSIZE); for (k = 0; k < HMAC_BUFSIZE; k++) { ctx->buf1[k] ^= HMAC_IPAD; ctx->buf2[k] ^= HMAC_OPAD; } hmac_reinit(ctx); #endif }
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); }