Return to hmacsha.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / lib / isc |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2005-2007 Internet Systems Consortium, Inc. ("ISC") ! 3: * ! 4: * Permission to use, copy, modify, and/or distribute this software for any ! 5: * purpose with or without fee is hereby granted, provided that the above ! 6: * copyright notice and this permission notice appear in all copies. ! 7: * ! 8: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH ! 9: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ! 10: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, ! 11: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ! 12: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ! 13: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ! 14: * PERFORMANCE OF THIS SOFTWARE. ! 15: */ ! 16: ! 17: /* $Id: hmacsha.c,v 1.8 2007/08/27 03:27:53 marka Exp $ */ ! 18: ! 19: /* ! 20: * This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384 ! 21: * and HMAC-SHA512 keyed hash algorithm described in RFC 2104 and ! 22: * draft-ietf-dnsext-tsig-sha-01.txt. ! 23: */ ! 24: ! 25: #include "config.h" ! 26: ! 27: #include <isc/assertions.h> ! 28: #include <isc/hmacsha.h> ! 29: #include <isc/sha1.h> ! 30: #include <isc/sha2.h> ! 31: #include <isc/string.h> ! 32: #include <isc/types.h> ! 33: #include <isc/util.h> ! 34: ! 35: #define IPAD 0x36 ! 36: #define OPAD 0x5C ! 37: ! 38: /* ! 39: * Start HMAC-SHA1 process. Initialize an sha1 context and digest the key. ! 40: */ ! 41: void ! 42: isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key, ! 43: unsigned int len) ! 44: { ! 45: unsigned char ipad[ISC_SHA1_BLOCK_LENGTH]; ! 46: unsigned int i; ! 47: ! 48: memset(ctx->key, 0, sizeof(ctx->key)); ! 49: if (len > sizeof(ctx->key)) { ! 50: isc_sha1_t sha1ctx; ! 51: isc_sha1_init(&sha1ctx); ! 52: isc_sha1_update(&sha1ctx, key, len); ! 53: isc_sha1_final(&sha1ctx, ctx->key); ! 54: } else ! 55: memcpy(ctx->key, key, len); ! 56: ! 57: isc_sha1_init(&ctx->sha1ctx); ! 58: memset(ipad, IPAD, sizeof(ipad)); ! 59: for (i = 0; i < ISC_SHA1_BLOCK_LENGTH; i++) ! 60: ipad[i] ^= ctx->key[i]; ! 61: isc_sha1_update(&ctx->sha1ctx, ipad, sizeof(ipad)); ! 62: } ! 63: ! 64: void ! 65: isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) { ! 66: isc_sha1_invalidate(&ctx->sha1ctx); ! 67: memset(ctx->key, 0, sizeof(ctx->key)); ! 68: memset(ctx, 0, sizeof(ctx)); ! 69: } ! 70: ! 71: /* ! 72: * Update context to reflect the concatenation of another buffer full ! 73: * of bytes. ! 74: */ ! 75: void ! 76: isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf, ! 77: unsigned int len) ! 78: { ! 79: isc_sha1_update(&ctx->sha1ctx, buf, len); ! 80: } ! 81: ! 82: /* ! 83: * Compute signature - finalize SHA1 operation and reapply SHA1. ! 84: */ ! 85: void ! 86: isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) { ! 87: unsigned char opad[ISC_SHA1_BLOCK_LENGTH]; ! 88: unsigned char newdigest[ISC_SHA1_DIGESTLENGTH]; ! 89: unsigned int i; ! 90: ! 91: REQUIRE(len <= ISC_SHA1_DIGESTLENGTH); ! 92: isc_sha1_final(&ctx->sha1ctx, newdigest); ! 93: ! 94: memset(opad, OPAD, sizeof(opad)); ! 95: for (i = 0; i < ISC_SHA1_BLOCK_LENGTH; i++) ! 96: opad[i] ^= ctx->key[i]; ! 97: ! 98: isc_sha1_init(&ctx->sha1ctx); ! 99: isc_sha1_update(&ctx->sha1ctx, opad, sizeof(opad)); ! 100: isc_sha1_update(&ctx->sha1ctx, newdigest, ISC_SHA1_DIGESTLENGTH); ! 101: isc_sha1_final(&ctx->sha1ctx, newdigest); ! 102: isc_hmacsha1_invalidate(ctx); ! 103: memcpy(digest, newdigest, len); ! 104: memset(newdigest, 0, sizeof(newdigest)); ! 105: } ! 106: ! 107: /* ! 108: * Verify signature - finalize SHA1 operation and reapply SHA1, then ! 109: * compare to the supplied digest. ! 110: */ ! 111: isc_boolean_t ! 112: isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) { ! 113: unsigned char newdigest[ISC_SHA1_DIGESTLENGTH]; ! 114: ! 115: REQUIRE(len <= ISC_SHA1_DIGESTLENGTH); ! 116: isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH); ! 117: return (ISC_TF(memcmp(digest, newdigest, len) == 0)); ! 118: } ! 119: ! 120: /* ! 121: * Start HMAC-SHA224 process. Initialize an sha224 context and digest the key. ! 122: */ ! 123: void ! 124: isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key, ! 125: unsigned int len) ! 126: { ! 127: unsigned char ipad[ISC_SHA224_BLOCK_LENGTH]; ! 128: unsigned int i; ! 129: ! 130: memset(ctx->key, 0, sizeof(ctx->key)); ! 131: if (len > sizeof(ctx->key)) { ! 132: isc_sha224_t sha224ctx; ! 133: isc_sha224_init(&sha224ctx); ! 134: isc_sha224_update(&sha224ctx, key, len); ! 135: isc_sha224_final(ctx->key, &sha224ctx); ! 136: } else ! 137: memcpy(ctx->key, key, len); ! 138: ! 139: isc_sha224_init(&ctx->sha224ctx); ! 140: memset(ipad, IPAD, sizeof(ipad)); ! 141: for (i = 0; i < ISC_SHA224_BLOCK_LENGTH; i++) ! 142: ipad[i] ^= ctx->key[i]; ! 143: isc_sha224_update(&ctx->sha224ctx, ipad, sizeof(ipad)); ! 144: } ! 145: ! 146: void ! 147: isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) { ! 148: memset(ctx->key, 0, sizeof(ctx->key)); ! 149: memset(ctx, 0, sizeof(ctx)); ! 150: } ! 151: ! 152: /* ! 153: * Update context to reflect the concatenation of another buffer full ! 154: * of bytes. ! 155: */ ! 156: void ! 157: isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf, ! 158: unsigned int len) ! 159: { ! 160: isc_sha224_update(&ctx->sha224ctx, buf, len); ! 161: } ! 162: ! 163: /* ! 164: * Compute signature - finalize SHA224 operation and reapply SHA224. ! 165: */ ! 166: void ! 167: isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) { ! 168: unsigned char opad[ISC_SHA224_BLOCK_LENGTH]; ! 169: unsigned char newdigest[ISC_SHA224_DIGESTLENGTH]; ! 170: unsigned int i; ! 171: ! 172: REQUIRE(len <= ISC_SHA224_DIGESTLENGTH); ! 173: isc_sha224_final(newdigest, &ctx->sha224ctx); ! 174: ! 175: memset(opad, OPAD, sizeof(opad)); ! 176: for (i = 0; i < ISC_SHA224_BLOCK_LENGTH; i++) ! 177: opad[i] ^= ctx->key[i]; ! 178: ! 179: isc_sha224_init(&ctx->sha224ctx); ! 180: isc_sha224_update(&ctx->sha224ctx, opad, sizeof(opad)); ! 181: isc_sha224_update(&ctx->sha224ctx, newdigest, ISC_SHA224_DIGESTLENGTH); ! 182: isc_sha224_final(newdigest, &ctx->sha224ctx); ! 183: memcpy(digest, newdigest, len); ! 184: memset(newdigest, 0, sizeof(newdigest)); ! 185: } ! 186: ! 187: /* ! 188: * Verify signature - finalize SHA224 operation and reapply SHA224, then ! 189: * compare to the supplied digest. ! 190: */ ! 191: isc_boolean_t ! 192: isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) { ! 193: unsigned char newdigest[ISC_SHA224_DIGESTLENGTH]; ! 194: ! 195: REQUIRE(len <= ISC_SHA224_DIGESTLENGTH); ! 196: isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH); ! 197: return (ISC_TF(memcmp(digest, newdigest, len) == 0)); ! 198: } ! 199: ! 200: /* ! 201: * Start HMAC-SHA256 process. Initialize an sha256 context and digest the key. ! 202: */ ! 203: void ! 204: isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key, ! 205: unsigned int len) ! 206: { ! 207: unsigned char ipad[ISC_SHA256_BLOCK_LENGTH]; ! 208: unsigned int i; ! 209: ! 210: memset(ctx->key, 0, sizeof(ctx->key)); ! 211: if (len > sizeof(ctx->key)) { ! 212: isc_sha256_t sha256ctx; ! 213: isc_sha256_init(&sha256ctx); ! 214: isc_sha256_update(&sha256ctx, key, len); ! 215: isc_sha256_final(ctx->key, &sha256ctx); ! 216: } else ! 217: memcpy(ctx->key, key, len); ! 218: ! 219: isc_sha256_init(&ctx->sha256ctx); ! 220: memset(ipad, IPAD, sizeof(ipad)); ! 221: for (i = 0; i < ISC_SHA256_BLOCK_LENGTH; i++) ! 222: ipad[i] ^= ctx->key[i]; ! 223: isc_sha256_update(&ctx->sha256ctx, ipad, sizeof(ipad)); ! 224: } ! 225: ! 226: void ! 227: isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) { ! 228: memset(ctx->key, 0, sizeof(ctx->key)); ! 229: memset(ctx, 0, sizeof(ctx)); ! 230: } ! 231: ! 232: /* ! 233: * Update context to reflect the concatenation of another buffer full ! 234: * of bytes. ! 235: */ ! 236: void ! 237: isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf, ! 238: unsigned int len) ! 239: { ! 240: isc_sha256_update(&ctx->sha256ctx, buf, len); ! 241: } ! 242: ! 243: /* ! 244: * Compute signature - finalize SHA256 operation and reapply SHA256. ! 245: */ ! 246: void ! 247: isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) { ! 248: unsigned char opad[ISC_SHA256_BLOCK_LENGTH]; ! 249: unsigned char newdigest[ISC_SHA256_DIGESTLENGTH]; ! 250: unsigned int i; ! 251: ! 252: REQUIRE(len <= ISC_SHA256_DIGESTLENGTH); ! 253: isc_sha256_final(newdigest, &ctx->sha256ctx); ! 254: ! 255: memset(opad, OPAD, sizeof(opad)); ! 256: for (i = 0; i < ISC_SHA256_BLOCK_LENGTH; i++) ! 257: opad[i] ^= ctx->key[i]; ! 258: ! 259: isc_sha256_init(&ctx->sha256ctx); ! 260: isc_sha256_update(&ctx->sha256ctx, opad, sizeof(opad)); ! 261: isc_sha256_update(&ctx->sha256ctx, newdigest, ISC_SHA256_DIGESTLENGTH); ! 262: isc_sha256_final(newdigest, &ctx->sha256ctx); ! 263: memcpy(digest, newdigest, len); ! 264: memset(newdigest, 0, sizeof(newdigest)); ! 265: } ! 266: ! 267: /* ! 268: * Verify signature - finalize SHA256 operation and reapply SHA256, then ! 269: * compare to the supplied digest. ! 270: */ ! 271: isc_boolean_t ! 272: isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) { ! 273: unsigned char newdigest[ISC_SHA256_DIGESTLENGTH]; ! 274: ! 275: REQUIRE(len <= ISC_SHA256_DIGESTLENGTH); ! 276: isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH); ! 277: return (ISC_TF(memcmp(digest, newdigest, len) == 0)); ! 278: } ! 279: ! 280: /* ! 281: * Start HMAC-SHA384 process. Initialize an sha384 context and digest the key. ! 282: */ ! 283: void ! 284: isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key, ! 285: unsigned int len) ! 286: { ! 287: unsigned char ipad[ISC_SHA384_BLOCK_LENGTH]; ! 288: unsigned int i; ! 289: ! 290: memset(ctx->key, 0, sizeof(ctx->key)); ! 291: if (len > sizeof(ctx->key)) { ! 292: isc_sha384_t sha384ctx; ! 293: isc_sha384_init(&sha384ctx); ! 294: isc_sha384_update(&sha384ctx, key, len); ! 295: isc_sha384_final(ctx->key, &sha384ctx); ! 296: } else ! 297: memcpy(ctx->key, key, len); ! 298: ! 299: isc_sha384_init(&ctx->sha384ctx); ! 300: memset(ipad, IPAD, sizeof(ipad)); ! 301: for (i = 0; i < ISC_SHA384_BLOCK_LENGTH; i++) ! 302: ipad[i] ^= ctx->key[i]; ! 303: isc_sha384_update(&ctx->sha384ctx, ipad, sizeof(ipad)); ! 304: } ! 305: ! 306: void ! 307: isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) { ! 308: memset(ctx->key, 0, sizeof(ctx->key)); ! 309: memset(ctx, 0, sizeof(ctx)); ! 310: } ! 311: ! 312: /* ! 313: * Update context to reflect the concatenation of another buffer full ! 314: * of bytes. ! 315: */ ! 316: void ! 317: isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf, ! 318: unsigned int len) ! 319: { ! 320: isc_sha384_update(&ctx->sha384ctx, buf, len); ! 321: } ! 322: ! 323: /* ! 324: * Compute signature - finalize SHA384 operation and reapply SHA384. ! 325: */ ! 326: void ! 327: isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) { ! 328: unsigned char opad[ISC_SHA384_BLOCK_LENGTH]; ! 329: unsigned char newdigest[ISC_SHA384_DIGESTLENGTH]; ! 330: unsigned int i; ! 331: ! 332: REQUIRE(len <= ISC_SHA384_DIGESTLENGTH); ! 333: isc_sha384_final(newdigest, &ctx->sha384ctx); ! 334: ! 335: memset(opad, OPAD, sizeof(opad)); ! 336: for (i = 0; i < ISC_SHA384_BLOCK_LENGTH; i++) ! 337: opad[i] ^= ctx->key[i]; ! 338: ! 339: isc_sha384_init(&ctx->sha384ctx); ! 340: isc_sha384_update(&ctx->sha384ctx, opad, sizeof(opad)); ! 341: isc_sha384_update(&ctx->sha384ctx, newdigest, ISC_SHA384_DIGESTLENGTH); ! 342: isc_sha384_final(newdigest, &ctx->sha384ctx); ! 343: memcpy(digest, newdigest, len); ! 344: memset(newdigest, 0, sizeof(newdigest)); ! 345: } ! 346: ! 347: /* ! 348: * Verify signature - finalize SHA384 operation and reapply SHA384, then ! 349: * compare to the supplied digest. ! 350: */ ! 351: isc_boolean_t ! 352: isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) { ! 353: unsigned char newdigest[ISC_SHA384_DIGESTLENGTH]; ! 354: ! 355: REQUIRE(len <= ISC_SHA384_DIGESTLENGTH); ! 356: isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH); ! 357: return (ISC_TF(memcmp(digest, newdigest, len) == 0)); ! 358: } ! 359: ! 360: /* ! 361: * Start HMAC-SHA512 process. Initialize an sha512 context and digest the key. ! 362: */ ! 363: void ! 364: isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key, ! 365: unsigned int len) ! 366: { ! 367: unsigned char ipad[ISC_SHA512_BLOCK_LENGTH]; ! 368: unsigned int i; ! 369: ! 370: memset(ctx->key, 0, sizeof(ctx->key)); ! 371: if (len > sizeof(ctx->key)) { ! 372: isc_sha512_t sha512ctx; ! 373: isc_sha512_init(&sha512ctx); ! 374: isc_sha512_update(&sha512ctx, key, len); ! 375: isc_sha512_final(ctx->key, &sha512ctx); ! 376: } else ! 377: memcpy(ctx->key, key, len); ! 378: ! 379: isc_sha512_init(&ctx->sha512ctx); ! 380: memset(ipad, IPAD, sizeof(ipad)); ! 381: for (i = 0; i < ISC_SHA512_BLOCK_LENGTH; i++) ! 382: ipad[i] ^= ctx->key[i]; ! 383: isc_sha512_update(&ctx->sha512ctx, ipad, sizeof(ipad)); ! 384: } ! 385: ! 386: void ! 387: isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) { ! 388: memset(ctx->key, 0, sizeof(ctx->key)); ! 389: memset(ctx, 0, sizeof(ctx)); ! 390: } ! 391: ! 392: /* ! 393: * Update context to reflect the concatenation of another buffer full ! 394: * of bytes. ! 395: */ ! 396: void ! 397: isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf, ! 398: unsigned int len) ! 399: { ! 400: isc_sha512_update(&ctx->sha512ctx, buf, len); ! 401: } ! 402: ! 403: /* ! 404: * Compute signature - finalize SHA512 operation and reapply SHA512. ! 405: */ ! 406: void ! 407: isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) { ! 408: unsigned char opad[ISC_SHA512_BLOCK_LENGTH]; ! 409: unsigned char newdigest[ISC_SHA512_DIGESTLENGTH]; ! 410: unsigned int i; ! 411: ! 412: REQUIRE(len <= ISC_SHA512_DIGESTLENGTH); ! 413: isc_sha512_final(newdigest, &ctx->sha512ctx); ! 414: ! 415: memset(opad, OPAD, sizeof(opad)); ! 416: for (i = 0; i < ISC_SHA512_BLOCK_LENGTH; i++) ! 417: opad[i] ^= ctx->key[i]; ! 418: ! 419: isc_sha512_init(&ctx->sha512ctx); ! 420: isc_sha512_update(&ctx->sha512ctx, opad, sizeof(opad)); ! 421: isc_sha512_update(&ctx->sha512ctx, newdigest, ISC_SHA512_DIGESTLENGTH); ! 422: isc_sha512_final(newdigest, &ctx->sha512ctx); ! 423: memcpy(digest, newdigest, len); ! 424: memset(newdigest, 0, sizeof(newdigest)); ! 425: } ! 426: ! 427: /* ! 428: * Verify signature - finalize SHA512 operation and reapply SHA512, then ! 429: * compare to the supplied digest. ! 430: */ ! 431: isc_boolean_t ! 432: isc_hmacsha512_verify(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) { ! 433: unsigned char newdigest[ISC_SHA512_DIGESTLENGTH]; ! 434: ! 435: REQUIRE(len <= ISC_SHA512_DIGESTLENGTH); ! 436: isc_hmacsha512_sign(ctx, newdigest, ISC_SHA512_DIGESTLENGTH); ! 437: return (ISC_TF(memcmp(digest, newdigest, len) == 0)); ! 438: }