00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00282
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
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
00313
00314
00315
00316
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 }