security/nss/lib/freebl/alghmac.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #ifdef FREEBL_NO_DEPEND
michael@0 6 #include "stubs.h"
michael@0 7 #endif
michael@0 8
michael@0 9 #include "secport.h"
michael@0 10 #include "hasht.h"
michael@0 11 #include "blapit.h"
michael@0 12 #include "alghmac.h"
michael@0 13 #include "secerr.h"
michael@0 14
michael@0 15 #define HMAC_PAD_SIZE HASH_BLOCK_LENGTH_MAX
michael@0 16
michael@0 17 struct HMACContextStr {
michael@0 18 void *hash;
michael@0 19 const SECHashObject *hashobj;
michael@0 20 PRBool wasAllocated;
michael@0 21 unsigned char ipad[HMAC_PAD_SIZE];
michael@0 22 unsigned char opad[HMAC_PAD_SIZE];
michael@0 23 };
michael@0 24
michael@0 25 void
michael@0 26 HMAC_Destroy(HMACContext *cx, PRBool freeit)
michael@0 27 {
michael@0 28 if (cx == NULL)
michael@0 29 return;
michael@0 30
michael@0 31 PORT_Assert(!freeit == !cx->wasAllocated);
michael@0 32 if (cx->hash != NULL) {
michael@0 33 cx->hashobj->destroy(cx->hash, PR_TRUE);
michael@0 34 PORT_Memset(cx, 0, sizeof *cx);
michael@0 35 }
michael@0 36 if (freeit)
michael@0 37 PORT_Free(cx);
michael@0 38 }
michael@0 39
michael@0 40 SECStatus
michael@0 41 HMAC_Init( HMACContext * cx, const SECHashObject *hash_obj,
michael@0 42 const unsigned char *secret, unsigned int secret_len, PRBool isFIPS)
michael@0 43 {
michael@0 44 unsigned int i;
michael@0 45 unsigned char hashed_secret[HASH_LENGTH_MAX];
michael@0 46
michael@0 47 /* required by FIPS 198 Section 3 */
michael@0 48 if (isFIPS && secret_len < hash_obj->length/2) {
michael@0 49 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 50 return SECFailure;
michael@0 51 }
michael@0 52 if (cx == NULL) {
michael@0 53 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 54 return SECFailure;
michael@0 55 }
michael@0 56 cx->wasAllocated = PR_FALSE;
michael@0 57 cx->hashobj = hash_obj;
michael@0 58 cx->hash = cx->hashobj->create();
michael@0 59 if (cx->hash == NULL)
michael@0 60 goto loser;
michael@0 61
michael@0 62 if (secret_len > cx->hashobj->blocklength) {
michael@0 63 cx->hashobj->begin( cx->hash);
michael@0 64 cx->hashobj->update(cx->hash, secret, secret_len);
michael@0 65 PORT_Assert(cx->hashobj->length <= sizeof hashed_secret);
michael@0 66 cx->hashobj->end( cx->hash, hashed_secret, &secret_len,
michael@0 67 sizeof hashed_secret);
michael@0 68 if (secret_len != cx->hashobj->length) {
michael@0 69 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
michael@0 70 goto loser;
michael@0 71 }
michael@0 72 secret = (const unsigned char *)&hashed_secret[0];
michael@0 73 }
michael@0 74
michael@0 75 PORT_Memset(cx->ipad, 0x36, cx->hashobj->blocklength);
michael@0 76 PORT_Memset(cx->opad, 0x5c, cx->hashobj->blocklength);
michael@0 77
michael@0 78 /* fold secret into padding */
michael@0 79 for (i = 0; i < secret_len; i++) {
michael@0 80 cx->ipad[i] ^= secret[i];
michael@0 81 cx->opad[i] ^= secret[i];
michael@0 82 }
michael@0 83 PORT_Memset(hashed_secret, 0, sizeof hashed_secret);
michael@0 84 return SECSuccess;
michael@0 85
michael@0 86 loser:
michael@0 87 PORT_Memset(hashed_secret, 0, sizeof hashed_secret);
michael@0 88 if (cx->hash != NULL)
michael@0 89 cx->hashobj->destroy(cx->hash, PR_TRUE);
michael@0 90 return SECFailure;
michael@0 91 }
michael@0 92
michael@0 93 HMACContext *
michael@0 94 HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret,
michael@0 95 unsigned int secret_len, PRBool isFIPS)
michael@0 96 {
michael@0 97 SECStatus rv;
michael@0 98 HMACContext * cx = PORT_ZNew(HMACContext);
michael@0 99 if (cx == NULL)
michael@0 100 return NULL;
michael@0 101 rv = HMAC_Init(cx, hash_obj, secret, secret_len, isFIPS);
michael@0 102 cx->wasAllocated = PR_TRUE;
michael@0 103 if (rv != SECSuccess) {
michael@0 104 PORT_Free(cx); /* contains no secret info */
michael@0 105 cx = NULL;
michael@0 106 }
michael@0 107 return cx;
michael@0 108 }
michael@0 109
michael@0 110 void
michael@0 111 HMAC_Begin(HMACContext *cx)
michael@0 112 {
michael@0 113 /* start inner hash */
michael@0 114 cx->hashobj->begin(cx->hash);
michael@0 115 cx->hashobj->update(cx->hash, cx->ipad, cx->hashobj->blocklength);
michael@0 116 }
michael@0 117
michael@0 118 void
michael@0 119 HMAC_Update(HMACContext *cx, const unsigned char *data, unsigned int data_len)
michael@0 120 {
michael@0 121 cx->hashobj->update(cx->hash, data, data_len);
michael@0 122 }
michael@0 123
michael@0 124 SECStatus
michael@0 125 HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len,
michael@0 126 unsigned int max_result_len)
michael@0 127 {
michael@0 128 if (max_result_len < cx->hashobj->length) {
michael@0 129 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 130 return SECFailure;
michael@0 131 }
michael@0 132
michael@0 133 cx->hashobj->end(cx->hash, result, result_len, max_result_len);
michael@0 134 if (*result_len != cx->hashobj->length)
michael@0 135 return SECFailure;
michael@0 136
michael@0 137 cx->hashobj->begin(cx->hash);
michael@0 138 cx->hashobj->update(cx->hash, cx->opad, cx->hashobj->blocklength);
michael@0 139 cx->hashobj->update(cx->hash, result, *result_len);
michael@0 140 cx->hashobj->end(cx->hash, result, result_len, max_result_len);
michael@0 141 return SECSuccess;
michael@0 142 }
michael@0 143
michael@0 144 HMACContext *
michael@0 145 HMAC_Clone(HMACContext *cx)
michael@0 146 {
michael@0 147 HMACContext *newcx;
michael@0 148
michael@0 149 newcx = (HMACContext*)PORT_ZAlloc(sizeof(HMACContext));
michael@0 150 if (newcx == NULL)
michael@0 151 goto loser;
michael@0 152
michael@0 153 newcx->wasAllocated = PR_TRUE;
michael@0 154 newcx->hashobj = cx->hashobj;
michael@0 155 newcx->hash = cx->hashobj->clone(cx->hash);
michael@0 156 if (newcx->hash == NULL)
michael@0 157 goto loser;
michael@0 158 PORT_Memcpy(newcx->ipad, cx->ipad, cx->hashobj->blocklength);
michael@0 159 PORT_Memcpy(newcx->opad, cx->opad, cx->hashobj->blocklength);
michael@0 160 return newcx;
michael@0 161
michael@0 162 loser:
michael@0 163 HMAC_Destroy(newcx, PR_TRUE);
michael@0 164 return NULL;
michael@0 165 }

mercurial