hmacmd5.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2007, 2009, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000, 2001  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: hmacmd5.c,v 1.16 2009/02/06 23:47:42 tbox Exp $ */
00019 
00020 /*! \file
00021  * This code implements the HMAC-MD5 keyed hash algorithm
00022  * described in RFC2104.
00023  */
00024 
00025 #include "config.h"
00026 
00027 #include <isc/assertions.h>
00028 #include <isc/hmacmd5.h>
00029 #include <isc/md5.h>
00030 #include <isc/platform.h>
00031 #include <isc/safe.h>
00032 #include <isc/string.h>
00033 #include <isc/types.h>
00034 #include <isc/util.h>
00035 
00036 #if PKCS11CRYPTO || PKCS11CRYPTOWITHHMAC
00037 #include <pk11/internal.h>
00038 #include <pk11/pk11.h>
00039 #endif
00040 
00041 #ifdef ISC_PLATFORM_OPENSSLHASH
00042 
00043 void
00044 isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
00045                  unsigned int len)
00046 {
00047 #ifdef HMAC_RETURN_INT
00048         RUNTIME_CHECK(HMAC_Init(ctx, (const void *) key,
00049                                 (int) len, EVP_md5()) == 1);
00050 #else
00051         HMAC_Init(ctx, (const void *) key, (int) len, EVP_md5());
00052 #endif
00053 }
00054 
00055 void
00056 isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
00057         HMAC_CTX_cleanup(ctx);
00058 }
00059 
00060 void
00061 isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
00062                    unsigned int len)
00063 {
00064 #ifdef HMAC_RETURN_INT
00065         RUNTIME_CHECK(HMAC_Update(ctx, buf, (int) len) == 1);
00066 #else
00067         HMAC_Update(ctx, buf, (int) len);
00068 #endif
00069 }
00070 
00071 void
00072 isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
00073 #ifdef HMAC_RETURN_INT
00074         RUNTIME_CHECK(HMAC_Final(ctx, digest, NULL) == 1);
00075 #else
00076         HMAC_Final(ctx, digest, NULL);
00077 #endif
00078         HMAC_CTX_cleanup(ctx);
00079 }
00080 
00081 #elif PKCS11CRYPTOWITHHMAC
00082 
00083 static CK_BBOOL truevalue = TRUE;
00084 static CK_BBOOL falsevalue = FALSE;
00085 
00086 void
00087 isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
00088                  unsigned int len)
00089 {
00090         CK_RV rv;
00091         CK_MECHANISM mech = { CKM_MD5_HMAC, NULL, 0 };
00092         CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
00093         CK_KEY_TYPE keyType = CKK_MD5_HMAC;
00094         CK_ATTRIBUTE keyTemplate[] =
00095         {
00096                 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
00097                 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00098                 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00099                 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00100                 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
00101                 { CKA_VALUE, NULL, (CK_ULONG) len }
00102         };
00103 
00104         DE_CONST(key, keyTemplate[5].pValue);
00105         RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
00106                                        ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
00107         ctx->object = CK_INVALID_HANDLE;
00108         PK11_FATALCHECK(pkcs_C_CreateObject,
00109                         (ctx->session, keyTemplate,
00110                          (CK_ULONG) 6, &ctx->object));
00111         INSIST(ctx->object != CK_INVALID_HANDLE);
00112         PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
00113 }
00114 
00115 void
00116 isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
00117         CK_BYTE garbage[ISC_MD5_DIGESTLENGTH];
00118         CK_ULONG len = ISC_MD5_DIGESTLENGTH;
00119 
00120         if (ctx->handle == NULL)
00121                 return;
00122         (void) pkcs_C_SignFinal(ctx->session, garbage, &len);
00123         memset(garbage, 0, sizeof(garbage));
00124         if (ctx->object != CK_INVALID_HANDLE)
00125                 (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
00126         ctx->object = CK_INVALID_HANDLE;
00127         pk11_return_session(ctx);
00128 }
00129 
00130 void
00131 isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
00132                    unsigned int len)
00133 {
00134         CK_RV rv;
00135         CK_BYTE_PTR pPart;
00136 
00137         DE_CONST(buf, pPart);
00138         PK11_FATALCHECK(pkcs_C_SignUpdate,
00139                         (ctx->session, pPart, (CK_ULONG) len));
00140 }
00141 
00142 void
00143 isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
00144         CK_RV rv;
00145         CK_ULONG len = ISC_MD5_DIGESTLENGTH;
00146 
00147         PK11_FATALCHECK(pkcs_C_SignFinal,
00148                         (ctx->session, (CK_BYTE_PTR) digest, &len));
00149         if (ctx->object != CK_INVALID_HANDLE)
00150                 (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
00151         ctx->object = CK_INVALID_HANDLE;
00152         pk11_return_session(ctx);
00153 }
00154 
00155 #elif PKCS11CRYPTO
00156 
00157 #define PADLEN 64
00158 #define IPAD 0x36
00159 #define OPAD 0x5C
00160 
00161 void
00162 isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
00163                  unsigned int len)
00164 {
00165         CK_RV rv;
00166         CK_MECHANISM mech = { CKM_MD5, NULL, 0 };
00167         unsigned char ipad[PADLEN];
00168         unsigned int i;
00169 
00170         RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
00171                                        ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
00172         RUNTIME_CHECK((ctx->key = pk11_mem_get(PADLEN)) != NULL);
00173         if (len > PADLEN) {
00174                 CK_BYTE_PTR kPart;
00175                 CK_ULONG kl;
00176 
00177                 PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
00178                 DE_CONST(key, kPart);
00179                 PK11_FATALCHECK(pkcs_C_DigestUpdate,
00180                                 (ctx->session, kPart, (CK_ULONG) len));
00181                 kl = ISC_MD5_DIGESTLENGTH;
00182                 PK11_FATALCHECK(pkcs_C_DigestFinal,
00183                                 (ctx->session, (CK_BYTE_PTR) ctx->key, &kl));
00184         } else
00185                 memmove(ctx->key, key, len);
00186         PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
00187         memset(ipad, IPAD, PADLEN);
00188         for (i = 0; i < PADLEN; i++)
00189                 ipad[i] ^= ctx->key[i];
00190         PK11_FATALCHECK(pkcs_C_DigestUpdate,
00191                         (ctx->session, ipad, (CK_ULONG) PADLEN));
00192 }
00193 
00194 void
00195 isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
00196         if (ctx->key != NULL)
00197                 pk11_mem_put(ctx->key, PADLEN);
00198         ctx->key = NULL;
00199         isc_md5_invalidate(ctx);
00200 }
00201 
00202 void
00203 isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
00204                    unsigned int len)
00205 {
00206         CK_RV rv;
00207         CK_BYTE_PTR pPart;
00208 
00209         DE_CONST(buf, pPart);
00210         PK11_FATALCHECK(pkcs_C_DigestUpdate,
00211                         (ctx->session, pPart, (CK_ULONG) len));
00212 }
00213 
00214 void
00215 isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
00216         CK_RV rv;
00217         CK_MECHANISM mech = { CKM_MD5, NULL, 0 };
00218         CK_ULONG len = ISC_MD5_DIGESTLENGTH;
00219         CK_BYTE opad[PADLEN];
00220         unsigned int i;
00221 
00222         PK11_FATALCHECK(pkcs_C_DigestFinal,
00223                         (ctx->session, (CK_BYTE_PTR) digest,
00224                          (CK_ULONG_PTR) &len));
00225         memset(opad, OPAD, PADLEN);
00226         for (i = 0; i < PADLEN; i++)
00227                 opad[i] ^= ctx->key[i];
00228         pk11_mem_put(ctx->key, PADLEN);
00229         ctx->key = NULL;
00230         PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
00231         PK11_FATALCHECK(pkcs_C_DigestUpdate,
00232                         (ctx->session, opad, (CK_ULONG) PADLEN));
00233         PK11_FATALCHECK(pkcs_C_DigestUpdate,
00234                         (ctx->session, (CK_BYTE_PTR) digest, len));
00235         PK11_FATALCHECK(pkcs_C_DigestFinal,
00236                         (ctx->session,
00237                          (CK_BYTE_PTR) digest,
00238                          (CK_ULONG_PTR) &len));
00239         pk11_return_session(ctx);
00240 }
00241 
00242 #else
00243 
00244 #define PADLEN 64
00245 #define IPAD 0x36
00246 #define OPAD 0x5C
00247 
00248 /*!
00249  * Start HMAC-MD5 process.  Initialize an md5 context and digest the key.
00250  */
00251 void
00252 isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
00253                  unsigned int len)
00254 {
00255         unsigned char ipad[PADLEN];
00256         int i;
00257 
00258         memset(ctx->key, 0, sizeof(ctx->key));
00259         if (len > sizeof(ctx->key)) {
00260                 isc_md5_t md5ctx;
00261                 isc_md5_init(&md5ctx);
00262                 isc_md5_update(&md5ctx, key, len);
00263                 isc_md5_final(&md5ctx, ctx->key);
00264         } else
00265                 memmove(ctx->key, key, len);
00266 
00267         isc_md5_init(&ctx->md5ctx);
00268         memset(ipad, IPAD, sizeof(ipad));
00269         for (i = 0; i < PADLEN; i++)
00270                 ipad[i] ^= ctx->key[i];
00271         isc_md5_update(&ctx->md5ctx, ipad, sizeof(ipad));
00272 }
00273 
00274 void
00275 isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
00276         isc_md5_invalidate(&ctx->md5ctx);
00277         memset(ctx->key, 0, sizeof(ctx->key));
00278 }
00279 
00280 /*!
00281  * Update context to reflect the concatenation of another buffer full
00282  * of bytes.
00283  */
00284 void
00285 isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
00286                    unsigned int len)
00287 {
00288         isc_md5_update(&ctx->md5ctx, buf, len);
00289 }
00290 
00291 /*!
00292  * Compute signature - finalize MD5 operation and reapply MD5.
00293  */
00294 void
00295 isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
00296         unsigned char opad[PADLEN];
00297         int i;
00298 
00299         isc_md5_final(&ctx->md5ctx, digest);
00300 
00301         memset(opad, OPAD, sizeof(opad));
00302         for (i = 0; i < PADLEN; i++)
00303                 opad[i] ^= ctx->key[i];
00304 
00305         isc_md5_init(&ctx->md5ctx);
00306         isc_md5_update(&ctx->md5ctx, opad, sizeof(opad));
00307         isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH);
00308         isc_md5_final(&ctx->md5ctx, digest);
00309         isc_hmacmd5_invalidate(ctx);
00310 }
00311 
00312 #endif /* !ISC_PLATFORM_OPENSSLHASH */
00313 
00314 /*!
00315  * Verify signature - finalize MD5 operation and reapply MD5, then
00316  * compare to the supplied digest.
00317  */
00318 isc_boolean_t
00319 isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) {
00320         return (isc_hmacmd5_verify2(ctx, digest, ISC_MD5_DIGESTLENGTH));
00321 }
00322 
00323 isc_boolean_t
00324 isc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len) {
00325         unsigned char newdigest[ISC_MD5_DIGESTLENGTH];
00326 
00327         REQUIRE(len <= ISC_MD5_DIGESTLENGTH);
00328         isc_hmacmd5_sign(ctx, newdigest);
00329         return (isc_safe_memcmp(digest, newdigest, len));
00330 }

Generated on Tue Apr 28 17:41:04 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha