Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 1 | /* |
| 2 | Copyright (C) 2012-2013 Werner Dittmann |
| 3 | |
| 4 | This library is free software; you can redistribute it and/or |
| 5 | modify it under the terms of the GNU Lesser General Public |
| 6 | License as published by the Free Software Foundation; either |
| 7 | version 2.1 of the License, or (at your option) any later version. |
| 8 | |
| 9 | This library is distributed in the hope that it will be useful, |
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | Lesser General Public License for more details. |
| 13 | |
| 14 | You should have received a copy of the GNU Lesser General Public |
| 15 | License along with this library; if not, write to the Free Software |
| 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 | |
| 18 | * In addition, as a special exception, the copyright holders give |
| 19 | * permission to link the code of portions of this program with the |
| 20 | * OpenSSL library under certain conditions as described in each |
| 21 | * individual source file, and distribute linked combinations |
| 22 | * including the two. |
| 23 | * You must obey the GNU General Public License in all respects |
| 24 | * for all of the code used other than OpenSSL. If you modify |
| 25 | * file(s) with this exception, you may extend this exception to your |
| 26 | * version of the file(s), but you are not obligated to do so. If you |
| 27 | * do not wish to do so, delete this exception statement from your |
| 28 | * version. If you delete this exception statement from all source |
| 29 | * files in the program, then also delete it here. |
| 30 | */ |
| 31 | |
| 32 | /* |
| 33 | * Authors: Werner Dittmann |
| 34 | */ |
| 35 | |
| 36 | #include <stdint.h> |
| 37 | #include <string.h> |
| 38 | #include <stdio.h> |
| 39 | #include "zrtp/crypto/sha2.h" |
| 40 | #include "zrtp/crypto/hmac256.h" |
| 41 | |
| 42 | typedef struct _hmacSha256Context { |
| 43 | sha256_ctx ctx; |
| 44 | sha256_ctx innerCtx; |
| 45 | sha256_ctx outerCtx; |
| 46 | } hmacSha256Context; |
| 47 | |
| 48 | static int32_t hmacSha256Init(hmacSha256Context *ctx, const uint8_t *key, uint32_t kLength) |
| 49 | { |
| 50 | int32_t i; |
| 51 | uint8_t localPad[SHA256_BLOCK_SIZE] = {0}; |
| 52 | uint8_t localKey[SHA256_BLOCK_SIZE] = {0}; |
| 53 | |
| 54 | if (key == NULL) |
| 55 | return 0; |
| 56 | |
| 57 | memset(ctx, 0, sizeof(hmacSha256Context)); |
| 58 | |
| 59 | /* check key length and reduce it if necessary */ |
| 60 | if (kLength > SHA256_BLOCK_SIZE) { |
| 61 | sha256_begin(&ctx->ctx); |
| 62 | sha256_hash(key, kLength, &ctx->ctx); |
| 63 | sha256_end(localKey, &ctx->ctx); |
| 64 | } |
| 65 | else { |
| 66 | memcpy(localKey, key, kLength); |
| 67 | } |
| 68 | /* prepare inner hash and hold the context */ |
| 69 | for (i = 0; i < SHA256_BLOCK_SIZE; i++) |
| 70 | localPad[i] = localKey[i] ^ 0x36; |
| 71 | |
| 72 | sha256_begin(&ctx->innerCtx); |
| 73 | sha256_hash(localPad, SHA256_BLOCK_SIZE, &ctx->innerCtx); |
| 74 | |
| 75 | /* prepare outer hash and hold the context */ |
| 76 | for (i = 0; i < SHA256_BLOCK_SIZE; i++) |
| 77 | localPad[i] = localKey[i] ^ 0x5c; |
| 78 | |
| 79 | sha256_begin(&ctx->outerCtx); |
| 80 | sha256_hash(localPad, SHA256_BLOCK_SIZE, &ctx->outerCtx); |
| 81 | |
| 82 | /* copy prepared inner hash to work hash - ready to process data */ |
| 83 | memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha256_ctx)); |
| 84 | |
| 85 | memset(localKey, 0, sizeof(localKey)); |
| 86 | |
| 87 | return 1; |
| 88 | } |
| 89 | |
| 90 | static void hmacSha256Reset(hmacSha256Context *ctx) |
| 91 | { |
| 92 | /* copy prepared inner hash to work hash context */ |
| 93 | memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha256_ctx)); |
| 94 | } |
| 95 | |
| 96 | static void hmacSha256Update(hmacSha256Context *ctx, const uint8_t *data, uint32_t dLength) |
| 97 | { |
| 98 | /* hash new data to work hash context */ |
| 99 | sha256_hash(data, dLength, &ctx->ctx); |
| 100 | } |
| 101 | |
| 102 | static void hmacSha256Final(hmacSha256Context *ctx, uint8_t *mac) |
| 103 | { |
| 104 | uint8_t tmpDigest[SHA256_DIGEST_SIZE]; |
| 105 | |
| 106 | /* finalize work hash context */ |
| 107 | sha256_end(tmpDigest, &ctx->ctx); |
| 108 | |
| 109 | /* copy prepared outer hash to work hash */ |
| 110 | memcpy(&ctx->ctx, &ctx->outerCtx, sizeof(sha256_ctx)); |
| 111 | |
| 112 | /* hash inner digest to work (outer) hash context */ |
| 113 | sha256_hash(tmpDigest, SHA256_DIGEST_SIZE, &ctx->ctx); |
| 114 | |
| 115 | /* finalize work hash context to get the hmac*/ |
| 116 | sha256_end(mac, &ctx->ctx); |
| 117 | } |
| 118 | |
| 119 | |
| 120 | void hmac_sha256(uint8_t *key, uint32_t keyLength, uint8_t* data, int32_t dataLength, uint8_t* mac, uint32_t* macLength) |
| 121 | { |
| 122 | hmacSha256Context ctx; |
| 123 | |
| 124 | hmacSha256Init(&ctx, key, keyLength); |
| 125 | hmacSha256Update(&ctx, data, dataLength); |
| 126 | hmacSha256Final(&ctx, mac); |
| 127 | *macLength = SHA256_DIGEST_SIZE; |
| 128 | } |
| 129 | |
| 130 | void hmac_sha256(uint8_t* key, uint32_t keyLength, uint8_t* dataChunks[], uint32_t dataChunckLength[], |
| 131 | uint8_t* mac, uint32_t* macLength ) |
| 132 | { |
| 133 | hmacSha256Context ctx; |
| 134 | |
| 135 | hmacSha256Init(&ctx, key, keyLength); |
| 136 | |
| 137 | while (*dataChunks) { |
| 138 | hmacSha256Update(&ctx, *dataChunks, *dataChunckLength); |
| 139 | dataChunks ++; |
| 140 | dataChunckLength ++; |
| 141 | } |
| 142 | hmacSha256Final(&ctx, mac); |
| 143 | *macLength = SHA256_DIGEST_SIZE; |
| 144 | } |
| 145 | |
| 146 | void* createSha256HmacContext(uint8_t* key, int32_t keyLength) |
| 147 | { |
| 148 | hmacSha256Context *ctx = reinterpret_cast<hmacSha256Context*>(malloc(sizeof(hmacSha256Context))); |
| 149 | |
| 150 | hmacSha256Init(ctx, key, keyLength); |
| 151 | return ctx; |
| 152 | } |
| 153 | |
| 154 | void hmacSha256Ctx(void* ctx, const uint8_t* data, uint32_t dataLength, |
| 155 | uint8_t* mac, int32_t* macLength) |
| 156 | { |
| 157 | hmacSha256Context *pctx = (hmacSha256Context*)ctx; |
| 158 | |
| 159 | hmacSha256Reset(pctx); |
| 160 | hmacSha256Update(pctx, data, dataLength); |
| 161 | hmacSha256Final(pctx, mac); |
| 162 | *macLength = SHA256_DIGEST_SIZE; |
| 163 | } |
| 164 | |
| 165 | void hmacSha256Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], |
| 166 | uint8_t* mac, int32_t* macLength ) |
| 167 | { |
| 168 | hmacSha256Context *pctx = (hmacSha256Context*)ctx; |
| 169 | |
| 170 | hmacSha256Reset(pctx); |
| 171 | while (*data) { |
| 172 | hmacSha256Update(pctx, *data, *dataLength); |
| 173 | data++; |
| 174 | dataLength++; |
| 175 | } |
| 176 | hmacSha256Final(pctx, mac); |
| 177 | *macLength = SHA256_DIGEST_SIZE; |
| 178 | } |
| 179 | |
| 180 | void freeSha256HmacContext(void* ctx) |
| 181 | { |
| 182 | if (ctx) { |
| 183 | memset(ctx, 0, sizeof(hmacSha256Context)); |
| 184 | free(ctx); |
| 185 | } |
| 186 | } |