hmacsha.c revision acbb301e648b82fcc38b876a44403cf0fe539cc9
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer/*
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2005-2007, 2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and/or distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * copyright notice and this permission notice appear in all copies.
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer *
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
821644d49b73b49f2abc5463bc53a3132f612478Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
821644d49b73b49f2abc5463bc53a3132f612478Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt * PERFORMANCE OF THIS SOFTWARE.
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt */
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer/* $Id$ */
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt/*
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt * This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384
5a77e9620a0b2f7417469c98be374de49d0eccc6Andreas Gustafsson * and HMAC-SHA512 keyed hash algorithm described in RFC 2104 and
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer * draft-ietf-dnsext-tsig-sha-01.txt.
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer */
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer#include "config.h"
e2f470bebb3a0c107bc4ac86c6920c21e50e83e0Brian Wellington
e2f470bebb3a0c107bc4ac86c6920c21e50e83e0Brian Wellington#include <isc/assertions.h>
4eb998928b9aef0ceda42d7529980d658138698aEvan Hunt#include <isc/hmacsha.h>
e2f470bebb3a0c107bc4ac86c6920c21e50e83e0Brian Wellington#include <isc/platform.h>
e2f470bebb3a0c107bc4ac86c6920c21e50e83e0Brian Wellington#include <isc/safe.h>
e2f470bebb3a0c107bc4ac86c6920c21e50e83e0Brian Wellington#include <isc/sha1.h>
e2f470bebb3a0c107bc4ac86c6920c21e50e83e0Brian Wellington#include <isc/sha2.h>
e2f470bebb3a0c107bc4ac86c6920c21e50e83e0Brian Wellington#include <isc/string.h>
e2f470bebb3a0c107bc4ac86c6920c21e50e83e0Brian Wellington#include <isc/types.h>
ac21f918f23ce95fd5be807428ee9e2c42319878Evan Hunt#include <isc/util.h>
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews#if PKCS11CRYPTO
ac21f918f23ce95fd5be807428ee9e2c42319878Evan Hunt#include <pk11/internal.h>
ac21f918f23ce95fd5be807428ee9e2c42319878Evan Hunt#include <pk11/pk11.h>
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt#endif
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer#ifdef ISC_PLATFORM_OPENSSLHASH
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyervoid
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyerisc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
2c15fcdeac4c2402258867fbac24d7475ef98259Mark Andrews unsigned int len)
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt{
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha1());
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt}
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Huntvoid
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Huntisc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
35f6a21f5f8114542c050bfcb484b39ce513d4bdEvan Hunt HMAC_CTX_cleanup(ctx);
35f6a21f5f8114542c050bfcb484b39ce513d4bdEvan Hunt}
35f6a21f5f8114542c050bfcb484b39ce513d4bdEvan Hunt
35f6a21f5f8114542c050bfcb484b39ce513d4bdEvan Huntvoid
35f6a21f5f8114542c050bfcb484b39ce513d4bdEvan Huntisc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
35f6a21f5f8114542c050bfcb484b39ce513d4bdEvan Hunt unsigned int len)
35f6a21f5f8114542c050bfcb484b39ce513d4bdEvan Hunt{
35f6a21f5f8114542c050bfcb484b39ce513d4bdEvan Hunt HMAC_Update(ctx, buf, (int) len);
35f6a21f5f8114542c050bfcb484b39ce513d4bdEvan Hunt}
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Huntvoid
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Huntisc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt
222d38735f97f771054e223b03f84c5858252332Evan Hunt REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer HMAC_Final(ctx, newdigest, NULL);
c5272fb3303425f794dab68f734f6a2a45dce01eMichael Sawyer HMAC_CTX_cleanup(ctx);
ac21f918f23ce95fd5be807428ee9e2c42319878Evan Hunt memmove(digest, newdigest, len);
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews memset(newdigest, 0, sizeof(newdigest));
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews}
ac21f918f23ce95fd5be807428ee9e2c42319878Evan Hunt
ac21f918f23ce95fd5be807428ee9e2c42319878Evan Huntvoid
c5272fb3303425f794dab68f734f6a2a45dce01eMichael Sawyerisc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
c5272fb3303425f794dab68f734f6a2a45dce01eMichael Sawyer unsigned int len)
c5272fb3303425f794dab68f734f6a2a45dce01eMichael Sawyer{
2c15fcdeac4c2402258867fbac24d7475ef98259Mark Andrews HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha224());
c5272fb3303425f794dab68f734f6a2a45dce01eMichael Sawyer}
c5272fb3303425f794dab68f734f6a2a45dce01eMichael Sawyer
ac21f918f23ce95fd5be807428ee9e2c42319878Evan Huntvoid
c5272fb3303425f794dab68f734f6a2a45dce01eMichael Sawyerisc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews HMAC_CTX_cleanup(ctx);
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews}
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrewsvoid
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrewsisc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews unsigned int len)
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews{
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews HMAC_Update(ctx, buf, (int) len);
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews}
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews
7318bbc26262a66a0d740ceefed769961ef7e476Evan Huntvoid
7318bbc26262a66a0d740ceefed769961ef7e476Evan Huntisc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt HMAC_Final(ctx, newdigest, NULL);
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt HMAC_CTX_cleanup(ctx);
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt memmove(digest, newdigest, len);
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt memset(newdigest, 0, sizeof(newdigest));
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt}
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Huntvoid
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Huntisc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt unsigned int len)
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt{
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha256());
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews}
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrewsvoid
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrewsisc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews HMAC_CTX_cleanup(ctx);
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews}
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrewsvoid
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrewsisc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews unsigned int len)
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt{
74717eef53ba5d6aefc80eb262bbb090ff4bb3b5Mark Andrews HMAC_Update(ctx, buf, (int) len);
74717eef53ba5d6aefc80eb262bbb090ff4bb3b5Mark Andrews}
948c80ffa8f4efbade049f49d9751675f6937cf4Tinderbox User
948c80ffa8f4efbade049f49d9751675f6937cf4Tinderbox Uservoid
948c80ffa8f4efbade049f49d9751675f6937cf4Tinderbox Userisc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
74717eef53ba5d6aefc80eb262bbb090ff4bb3b5Mark Andrews unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
HMAC_Final(ctx, newdigest, NULL);
HMAC_CTX_cleanup(ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
void
isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
unsigned int len)
{
HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha384());
}
void
isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
HMAC_CTX_cleanup(ctx);
}
void
isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
unsigned int len)
{
HMAC_Update(ctx, buf, (int) len);
}
void
isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
HMAC_Final(ctx, newdigest, NULL);
HMAC_CTX_cleanup(ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
void
isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
unsigned int len)
{
HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha512());
}
void
isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
HMAC_CTX_cleanup(ctx);
}
void
isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
unsigned int len)
{
HMAC_Update(ctx, buf, (int) len);
}
void
isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
HMAC_Final(ctx, newdigest, NULL);
HMAC_CTX_cleanup(ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
#elif PKCS11CRYPTO
static CK_BBOOL truevalue = TRUE;
static CK_BBOOL falsevalue = FALSE;
void
isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
unsigned int len)
{
CK_RV rv;
CK_MECHANISM mech = { CKM_SHA_1_HMAC, NULL, 0 };
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
CK_KEY_TYPE keyType = CKK_SHA_1_HMAC;
CK_ATTRIBUTE keyTemplate[] =
{
{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
{ CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
{ CKA_VALUE, NULL, (CK_ULONG) len }
};
DE_CONST(key, keyTemplate[5].pValue);
RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
ctx->object = CK_INVALID_HANDLE;
PK11_FATALCHECK(pkcs_C_CreateObject,
(ctx->session, keyTemplate,
(CK_ULONG) 6, &ctx->object));
INSIST(ctx->object != CK_INVALID_HANDLE);
PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
}
void
isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
CK_BYTE garbage[ISC_SHA1_DIGESTLENGTH];
CK_ULONG len = ISC_SHA1_DIGESTLENGTH;
if (ctx->handle == NULL)
return;
(void) pkcs_C_SignFinal(ctx->session, garbage, &len);
memset(garbage, 0, sizeof(garbage));
if (ctx->object != CK_INVALID_HANDLE)
(void) pkcs_C_DestroyObject(ctx->session, ctx->object);
ctx->object = CK_INVALID_HANDLE;
pk11_return_session(ctx);
}
void
isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
unsigned int len)
{
CK_RV rv;
CK_BYTE_PTR pPart;
DE_CONST(buf, pPart);
PK11_FATALCHECK(pkcs_C_SignUpdate,
(ctx->session, pPart, (CK_ULONG) len));
}
void
isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
CK_RV rv;
CK_BYTE newdigest[ISC_SHA1_DIGESTLENGTH];
CK_ULONG psl = ISC_SHA1_DIGESTLENGTH;
REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl));
if (ctx->object != CK_INVALID_HANDLE)
(void) pkcs_C_DestroyObject(ctx->session, ctx->object);
ctx->object = CK_INVALID_HANDLE;
pk11_return_session(ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
void
isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
unsigned int len)
{
CK_RV rv;
CK_MECHANISM mech = { CKM_SHA224_HMAC, NULL, 0 };
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
CK_KEY_TYPE keyType = CKK_SHA224_HMAC;
CK_ATTRIBUTE keyTemplate[] =
{
{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
{ CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
{ CKA_VALUE, NULL, (CK_ULONG) len }
};
DE_CONST(key, keyTemplate[5].pValue);
RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
ctx->object = CK_INVALID_HANDLE;
PK11_FATALCHECK(pkcs_C_CreateObject,
(ctx->session, keyTemplate,
(CK_ULONG) 6, &ctx->object));
INSIST(ctx->object != CK_INVALID_HANDLE);
PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
}
void
isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
CK_BYTE garbage[ISC_SHA224_DIGESTLENGTH];
CK_ULONG len = ISC_SHA224_DIGESTLENGTH;
if (ctx->handle == NULL)
return;
(void) pkcs_C_SignFinal(ctx->session, garbage, &len);
memset(garbage, 0, sizeof(garbage));
if (ctx->object != CK_INVALID_HANDLE)
(void) pkcs_C_DestroyObject(ctx->session, ctx->object);
ctx->object = CK_INVALID_HANDLE;
pk11_return_session(ctx);
}
void
isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
unsigned int len)
{
CK_RV rv;
CK_BYTE_PTR pPart;
DE_CONST(buf, pPart);
PK11_FATALCHECK(pkcs_C_SignUpdate,
(ctx->session, pPart, (CK_ULONG) len));
}
void
isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
CK_RV rv;
CK_BYTE newdigest[ISC_SHA224_DIGESTLENGTH];
CK_ULONG psl = ISC_SHA224_DIGESTLENGTH;
REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl));
if (ctx->object != CK_INVALID_HANDLE)
(void) pkcs_C_DestroyObject(ctx->session, ctx->object);
ctx->object = CK_INVALID_HANDLE;
pk11_return_session(ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
void
isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
unsigned int len)
{
CK_RV rv;
CK_MECHANISM mech = { CKM_SHA256_HMAC, NULL, 0 };
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
CK_KEY_TYPE keyType = CKK_SHA256_HMAC;
CK_ATTRIBUTE keyTemplate[] =
{
{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
{ CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
{ CKA_VALUE, NULL, (CK_ULONG) len }
};
DE_CONST(key, keyTemplate[5].pValue);
RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
ctx->object = CK_INVALID_HANDLE;
PK11_FATALCHECK(pkcs_C_CreateObject,
(ctx->session, keyTemplate,
(CK_ULONG) 6, &ctx->object));
INSIST(ctx->object != CK_INVALID_HANDLE);
PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
}
void
isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
CK_BYTE garbage[ISC_SHA256_DIGESTLENGTH];
CK_ULONG len = ISC_SHA256_DIGESTLENGTH;
if (ctx->handle == NULL)
return;
(void) pkcs_C_SignFinal(ctx->session, garbage, &len);
memset(garbage, 0, sizeof(garbage));
if (ctx->object != CK_INVALID_HANDLE)
(void) pkcs_C_DestroyObject(ctx->session, ctx->object);
ctx->object = CK_INVALID_HANDLE;
pk11_return_session(ctx);
}
void
isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
unsigned int len)
{
CK_RV rv;
CK_BYTE_PTR pPart;
DE_CONST(buf, pPart);
PK11_FATALCHECK(pkcs_C_SignUpdate,
(ctx->session, pPart, (CK_ULONG) len));
}
void
isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
CK_RV rv;
CK_BYTE newdigest[ISC_SHA256_DIGESTLENGTH];
CK_ULONG psl = ISC_SHA256_DIGESTLENGTH;
REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl));
if (ctx->object != CK_INVALID_HANDLE)
(void) pkcs_C_DestroyObject(ctx->session, ctx->object);
ctx->object = CK_INVALID_HANDLE;
pk11_return_session(ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
void
isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
unsigned int len)
{
CK_RV rv;
CK_MECHANISM mech = { CKM_SHA384_HMAC, NULL, 0 };
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
CK_KEY_TYPE keyType = CKK_SHA384_HMAC;
CK_ATTRIBUTE keyTemplate[] =
{
{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
{ CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
{ CKA_VALUE, NULL, (CK_ULONG) len }
};
DE_CONST(key, keyTemplate[5].pValue);
RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
ctx->object = CK_INVALID_HANDLE;
PK11_FATALCHECK(pkcs_C_CreateObject,
(ctx->session, keyTemplate,
(CK_ULONG) 6, &ctx->object));
INSIST(ctx->object != CK_INVALID_HANDLE);
PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
}
void
isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
CK_BYTE garbage[ISC_SHA384_DIGESTLENGTH];
CK_ULONG len = ISC_SHA384_DIGESTLENGTH;
if (ctx->handle == NULL)
return;
(void) pkcs_C_SignFinal(ctx->session, garbage, &len);
memset(garbage, 0, sizeof(garbage));
if (ctx->object != CK_INVALID_HANDLE)
(void) pkcs_C_DestroyObject(ctx->session, ctx->object);
ctx->object = CK_INVALID_HANDLE;
pk11_return_session(ctx);
}
void
isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
unsigned int len)
{
CK_RV rv;
CK_BYTE_PTR pPart;
DE_CONST(buf, pPart);
PK11_FATALCHECK(pkcs_C_SignUpdate,
(ctx->session, pPart, (CK_ULONG) len));
}
void
isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
CK_RV rv;
CK_BYTE newdigest[ISC_SHA384_DIGESTLENGTH];
CK_ULONG psl = ISC_SHA384_DIGESTLENGTH;
REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl));
if (ctx->object != CK_INVALID_HANDLE)
(void) pkcs_C_DestroyObject(ctx->session, ctx->object);
ctx->object = CK_INVALID_HANDLE;
pk11_return_session(ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
void
isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
unsigned int len)
{
CK_RV rv;
CK_MECHANISM mech = { CKM_SHA512_HMAC, NULL, 0 };
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
CK_KEY_TYPE keyType = CKK_SHA512_HMAC;
CK_ATTRIBUTE keyTemplate[] =
{
{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
{ CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
{ CKA_VALUE, NULL, (CK_ULONG) len }
};
DE_CONST(key, keyTemplate[5].pValue);
RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
ctx->object = CK_INVALID_HANDLE;
PK11_FATALCHECK(pkcs_C_CreateObject,
(ctx->session, keyTemplate,
(CK_ULONG) 6, &ctx->object));
INSIST(ctx->object != CK_INVALID_HANDLE);
PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
}
void
isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
CK_BYTE garbage[ISC_SHA512_DIGESTLENGTH];
CK_ULONG len = ISC_SHA512_DIGESTLENGTH;
if (ctx->handle == NULL)
return;
(void) pkcs_C_SignFinal(ctx->session, garbage, &len);
memset(garbage, 0, sizeof(garbage));
if (ctx->object != CK_INVALID_HANDLE)
(void) pkcs_C_DestroyObject(ctx->session, ctx->object);
ctx->object = CK_INVALID_HANDLE;
pk11_return_session(ctx);
}
void
isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
unsigned int len)
{
CK_RV rv;
CK_BYTE_PTR pPart;
DE_CONST(buf, pPart);
PK11_FATALCHECK(pkcs_C_SignUpdate,
(ctx->session, pPart, (CK_ULONG) len));
}
void
isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
CK_RV rv;
CK_BYTE newdigest[ISC_SHA512_DIGESTLENGTH];
CK_ULONG psl = ISC_SHA512_DIGESTLENGTH;
REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl));
if (ctx->object != CK_INVALID_HANDLE)
(void) pkcs_C_DestroyObject(ctx->session, ctx->object);
ctx->object = CK_INVALID_HANDLE;
pk11_return_session(ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
#else
#define IPAD 0x36
#define OPAD 0x5C
/*
* Start HMAC-SHA1 process. Initialize an sha1 context and digest the key.
*/
void
isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
unsigned int len)
{
unsigned char ipad[ISC_SHA1_BLOCK_LENGTH];
unsigned int i;
memset(ctx->key, 0, sizeof(ctx->key));
if (len > sizeof(ctx->key)) {
isc_sha1_t sha1ctx;
isc_sha1_init(&sha1ctx);
isc_sha1_update(&sha1ctx, key, len);
isc_sha1_final(&sha1ctx, ctx->key);
} else
memmove(ctx->key, key, len);
isc_sha1_init(&ctx->sha1ctx);
memset(ipad, IPAD, sizeof(ipad));
for (i = 0; i < ISC_SHA1_BLOCK_LENGTH; i++)
ipad[i] ^= ctx->key[i];
isc_sha1_update(&ctx->sha1ctx, ipad, sizeof(ipad));
}
void
isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
isc_sha1_invalidate(&ctx->sha1ctx);
memset(ctx, 0, sizeof(*ctx));
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void
isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
unsigned int len)
{
isc_sha1_update(&ctx->sha1ctx, buf, len);
}
/*
* Compute signature - finalize SHA1 operation and reapply SHA1.
*/
void
isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
unsigned char opad[ISC_SHA1_BLOCK_LENGTH];
unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
unsigned int i;
REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
isc_sha1_final(&ctx->sha1ctx, newdigest);
memset(opad, OPAD, sizeof(opad));
for (i = 0; i < ISC_SHA1_BLOCK_LENGTH; i++)
opad[i] ^= ctx->key[i];
isc_sha1_init(&ctx->sha1ctx);
isc_sha1_update(&ctx->sha1ctx, opad, sizeof(opad));
isc_sha1_update(&ctx->sha1ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
isc_sha1_final(&ctx->sha1ctx, newdigest);
isc_hmacsha1_invalidate(ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
/*
* Start HMAC-SHA224 process. Initialize an sha224 context and digest the key.
*/
void
isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
unsigned int len)
{
unsigned char ipad[ISC_SHA224_BLOCK_LENGTH];
unsigned int i;
memset(ctx->key, 0, sizeof(ctx->key));
if (len > sizeof(ctx->key)) {
isc_sha224_t sha224ctx;
isc_sha224_init(&sha224ctx);
isc_sha224_update(&sha224ctx, key, len);
isc_sha224_final(ctx->key, &sha224ctx);
} else
memmove(ctx->key, key, len);
isc_sha224_init(&ctx->sha224ctx);
memset(ipad, IPAD, sizeof(ipad));
for (i = 0; i < ISC_SHA224_BLOCK_LENGTH; i++)
ipad[i] ^= ctx->key[i];
isc_sha224_update(&ctx->sha224ctx, ipad, sizeof(ipad));
}
void
isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
memset(ctx, 0, sizeof(*ctx));
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void
isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
unsigned int len)
{
isc_sha224_update(&ctx->sha224ctx, buf, len);
}
/*
* Compute signature - finalize SHA224 operation and reapply SHA224.
*/
void
isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
unsigned char opad[ISC_SHA224_BLOCK_LENGTH];
unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
unsigned int i;
REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
isc_sha224_final(newdigest, &ctx->sha224ctx);
memset(opad, OPAD, sizeof(opad));
for (i = 0; i < ISC_SHA224_BLOCK_LENGTH; i++)
opad[i] ^= ctx->key[i];
isc_sha224_init(&ctx->sha224ctx);
isc_sha224_update(&ctx->sha224ctx, opad, sizeof(opad));
isc_sha224_update(&ctx->sha224ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
isc_sha224_final(newdigest, &ctx->sha224ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
/*
* Start HMAC-SHA256 process. Initialize an sha256 context and digest the key.
*/
void
isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
unsigned int len)
{
unsigned char ipad[ISC_SHA256_BLOCK_LENGTH];
unsigned int i;
memset(ctx->key, 0, sizeof(ctx->key));
if (len > sizeof(ctx->key)) {
isc_sha256_t sha256ctx;
isc_sha256_init(&sha256ctx);
isc_sha256_update(&sha256ctx, key, len);
isc_sha256_final(ctx->key, &sha256ctx);
} else
memmove(ctx->key, key, len);
isc_sha256_init(&ctx->sha256ctx);
memset(ipad, IPAD, sizeof(ipad));
for (i = 0; i < ISC_SHA256_BLOCK_LENGTH; i++)
ipad[i] ^= ctx->key[i];
isc_sha256_update(&ctx->sha256ctx, ipad, sizeof(ipad));
}
void
isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
memset(ctx, 0, sizeof(*ctx));
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void
isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
unsigned int len)
{
isc_sha256_update(&ctx->sha256ctx, buf, len);
}
/*
* Compute signature - finalize SHA256 operation and reapply SHA256.
*/
void
isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
unsigned char opad[ISC_SHA256_BLOCK_LENGTH];
unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
unsigned int i;
REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
isc_sha256_final(newdigest, &ctx->sha256ctx);
memset(opad, OPAD, sizeof(opad));
for (i = 0; i < ISC_SHA256_BLOCK_LENGTH; i++)
opad[i] ^= ctx->key[i];
isc_sha256_init(&ctx->sha256ctx);
isc_sha256_update(&ctx->sha256ctx, opad, sizeof(opad));
isc_sha256_update(&ctx->sha256ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
isc_sha256_final(newdigest, &ctx->sha256ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
/*
* Start HMAC-SHA384 process. Initialize an sha384 context and digest the key.
*/
void
isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
unsigned int len)
{
unsigned char ipad[ISC_SHA384_BLOCK_LENGTH];
unsigned int i;
memset(ctx->key, 0, sizeof(ctx->key));
if (len > sizeof(ctx->key)) {
isc_sha384_t sha384ctx;
isc_sha384_init(&sha384ctx);
isc_sha384_update(&sha384ctx, key, len);
isc_sha384_final(ctx->key, &sha384ctx);
} else
memmove(ctx->key, key, len);
isc_sha384_init(&ctx->sha384ctx);
memset(ipad, IPAD, sizeof(ipad));
for (i = 0; i < ISC_SHA384_BLOCK_LENGTH; i++)
ipad[i] ^= ctx->key[i];
isc_sha384_update(&ctx->sha384ctx, ipad, sizeof(ipad));
}
void
isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
memset(ctx, 0, sizeof(*ctx));
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void
isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
unsigned int len)
{
isc_sha384_update(&ctx->sha384ctx, buf, len);
}
/*
* Compute signature - finalize SHA384 operation and reapply SHA384.
*/
void
isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
unsigned char opad[ISC_SHA384_BLOCK_LENGTH];
unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
unsigned int i;
REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
isc_sha384_final(newdigest, &ctx->sha384ctx);
memset(opad, OPAD, sizeof(opad));
for (i = 0; i < ISC_SHA384_BLOCK_LENGTH; i++)
opad[i] ^= ctx->key[i];
isc_sha384_init(&ctx->sha384ctx);
isc_sha384_update(&ctx->sha384ctx, opad, sizeof(opad));
isc_sha384_update(&ctx->sha384ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
isc_sha384_final(newdigest, &ctx->sha384ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
/*
* Start HMAC-SHA512 process. Initialize an sha512 context and digest the key.
*/
void
isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
unsigned int len)
{
unsigned char ipad[ISC_SHA512_BLOCK_LENGTH];
unsigned int i;
memset(ctx->key, 0, sizeof(ctx->key));
if (len > sizeof(ctx->key)) {
isc_sha512_t sha512ctx;
isc_sha512_init(&sha512ctx);
isc_sha512_update(&sha512ctx, key, len);
isc_sha512_final(ctx->key, &sha512ctx);
} else
memmove(ctx->key, key, len);
isc_sha512_init(&ctx->sha512ctx);
memset(ipad, IPAD, sizeof(ipad));
for (i = 0; i < ISC_SHA512_BLOCK_LENGTH; i++)
ipad[i] ^= ctx->key[i];
isc_sha512_update(&ctx->sha512ctx, ipad, sizeof(ipad));
}
void
isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
memset(ctx, 0, sizeof(*ctx));
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void
isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
unsigned int len)
{
isc_sha512_update(&ctx->sha512ctx, buf, len);
}
/*
* Compute signature - finalize SHA512 operation and reapply SHA512.
*/
void
isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
unsigned char opad[ISC_SHA512_BLOCK_LENGTH];
unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
unsigned int i;
REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
isc_sha512_final(newdigest, &ctx->sha512ctx);
memset(opad, OPAD, sizeof(opad));
for (i = 0; i < ISC_SHA512_BLOCK_LENGTH; i++)
opad[i] ^= ctx->key[i];
isc_sha512_init(&ctx->sha512ctx);
isc_sha512_update(&ctx->sha512ctx, opad, sizeof(opad));
isc_sha512_update(&ctx->sha512ctx, newdigest, ISC_SHA512_DIGESTLENGTH);
isc_sha512_final(newdigest, &ctx->sha512ctx);
memmove(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
#endif /* !ISC_PLATFORM_OPENSSLHASH */
/*
* Verify signature - finalize SHA1 operation and reapply SHA1, then
* compare to the supplied digest.
*/
isc_boolean_t
isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
return (isc_safe_memcmp(digest, newdigest, len));
}
/*
* Verify signature - finalize SHA224 operation and reapply SHA224, then
* compare to the supplied digest.
*/
isc_boolean_t
isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
return (isc_safe_memcmp(digest, newdigest, len));
}
/*
* Verify signature - finalize SHA256 operation and reapply SHA256, then
* compare to the supplied digest.
*/
isc_boolean_t
isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
return (isc_safe_memcmp(digest, newdigest, len));
}
/*
* Verify signature - finalize SHA384 operation and reapply SHA384, then
* compare to the supplied digest.
*/
isc_boolean_t
isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
return (isc_safe_memcmp(digest, newdigest, len));
}
/*
* Verify signature - finalize SHA512 operation and reapply SHA512, then
* compare to the supplied digest.
*/
isc_boolean_t
isc_hmacsha512_verify(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
isc_hmacsha512_sign(ctx, newdigest, ISC_SHA512_DIGESTLENGTH);
return (isc_safe_memcmp(digest, newdigest, len));
}